Some solution for using national chars and have problem with UTF-8 for example in mail subject. Before you use mb_encode_mimeheader with UTF-8 set mb_internal_encoding('UTF-8').
(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)
mb_encode_mimeheader — Кодирует строку для заголовка MIME
$string
,$charset
= null
,$transfer_encoding
= null
,$newline
= "\r\n",$indent
= 0
Функция кодирует строку (string), которую передали
в аргументе string
, по схеме кодирования MIME-заголовка.
string
Строка (string), которую требуется закодировать. Параметр принимает строку, кодировка которой совпадает с кодировкой, которую возвращает функция mb_internal_encoding().
charset
Параметр charset
определяет название набора символов,
в котором представляется строка string
.
Значение по умолчанию определяется настройкой национального языка по умолчанию
(англ. NLS, National Language Setting), которую устанавливает директива mbstring.language
.
transfer_encoding
Параметр transfer_encoding
определяет схему MIME-кодирования.
Параметр принимает либо значение «B»
, которое указывает кодировку Base64,
либо значение «Q»
, которое указывает кодировку Quoted-Printable.
Значение по умолчанию равно «B»
.
newline
Параметр newline
определяет EOL-метку конца строки (англ. end-of-line),
которой функция mb_encode_mimeheader()
переносит строки (англ. line-folding). Line-folding — термин стандарта » RFC 2822,
который означает разбиение строки, длина которой превышает конкретную величину, на несколько строк.
Длину разбиения строки жёстко закодировали и установили значение в 74 символа.
Значение по умолчанию определили последовательностью символов «\r\n»
, или CRLF.
indent
Отступ первой строки — количество символов в заголовке перед параметром string
.
Функция возвращает версию строки (string), которую преобразовала в ASCII-представление.
Версия | Описание |
---|---|
8.3.0 |
NUL -байты больше не отбрасываются при кодировании
строк по правилам синтаксиса QP-кодировки (англ. Quoted-Printable),
а кодируются как =00 . Нулевой байт — байт со значением 0,
который в наборах символов назначают нулевой кодовой точке.
|
8.0.0 |
Параметры charset и transfer_encoding
теперь принимают значение null .
|
Пример #1 Пример кодировки строки для заголовка MIME функцией mb_encode_mimeheader()
<?php
$name = "太郎"; // kanji
$mbox = "kru";
$doma = "gtinn.mon";
$addr = '"' . addcslashes(mb_encode_mimeheader($name, "UTF-7", "Q"), '"') . '" <' . $mbox . "@" . $doma . ">";
echo $addr;
?>
Результат выполнения приведённого примера:
"=?UTF-7?Q?+WSqQzg-?=" <kru@gtinn.mon>
Замечание:
Функция не переносит строки в высокоуровневых точках разрыва строк на основе контекста наподобие границ слов и аналогичных. Такое поведение иногда загромождает исходную строку неожиданными пробелами.
Some solution for using national chars and have problem with UTF-8 for example in mail subject. Before you use mb_encode_mimeheader with UTF-8 set mb_internal_encoding('UTF-8').
True, function is broken (PHP5.1, encoding from UTF-8 with pl_PL charset). Below is about 15% faster version of proposed _mb_mime_encode. Also it has header more like othe mb_* functions and doesn't trigger any errors/warnings/notices.<?phpfunction mb_mime_header($string, $encoding=null, $linefeed="\r\n") { if(!$encoding) $encoding = mb_internal_encoding(); $encoded = ''; while($length = mb_strlen($string)) { $encoded .= "=?$encoding?B?" . base64_encode(mb_substr($string,0,24,$encoding)) . "?=$linefeed"; $string = mb_substr($string,24,$length,$encoding); } return $encoded;}?>
Read this FIRST: http://bugs.php.net/bug.php?id=23192 because mb_encode_mimeheaders is BUGGY!a work around for the multibyte broken error for too long subjects for ISO-2022-JP:$pos=0;$split=36; // after 36 single bytes characters, if then comes MB, it is brokenwhile ($pos<mb_strlen($string,$encoding)){ $output=mb_strimwidth($string,$pos,$split,"",$encoding); $pos+=mb_strlen($output,$encoding); $_string.=(($_string)?' ':'').mb_encode_mimeheader($output,$encoding);}$string=$_string;is not the best, but it works
I could not find a PHP function to MIME encode the name for a n email address.
Input = "Karl Müller<kmueller@gmx.de>"
Output = "Karl%20M%FCller<kmueller@gmx.de>"
I wrote it on my own:
<?php
// required to encode names in email addresses
// replace " " with "%20"
// replace "ü" with "%FC"
// replace "%" with "%25" etc....
// Use "%" as Delimiter for MIME
// Use "=" as Delimiter for Quoted Printable
// Input string must be UTF8 encoded
public static function EncodeMime($Text, $Delimiter)
{
$Text = utf8_decode($Text);
$Len = strlen($Text);
$Out = "";
for ($i=0; $i<$Len; $i++)
{
$Chr = substr($Text, $i, 1);
$Asc = ord($Chr);
if ($Asc > 0x255) // Unicode not allowed
{
$Out .= "?";
}
else if ($Chr == " " || $Chr == $Delimiter || $Asc > 127)
{
$Out .= $Delimiter . strtoupper(bin2hex($Chr));
}
else $Out .= $Chr;
}
return $Out;
}
?>
mb_encode_mimeheader() depends on correct mbstring.internal_encoding setting. It tries to convert $str from internal encoding to $charset. If you ignore mbstring internal encoding, function might encode strings incorrectly even when $str character set matches $charset
My first post was around 2003, and still the mb_mime_header is broken. It is *NOT* usable with longer subjects, and mostly unusable with anything else than japanese.iwakura at junx dot org is also not working for me, it produces also some gargabe.I updated my old function (the one I posted 2003) and I tested it with overlong subjects in UTF-8, ISO-2022-JP (japanese), GB2312 (simplified chinese) and EUC-KR (korean) and I got readable results in thunderbird, mail.app, outlook, etc.<?phpfunction _mb_mime_encode($string, $encoding){ $pos = 0; // after 36 single bytes characters if then comes MB, it is broken // but I trimmed it down to 24, to stay 100% < 76 chars per line $split = 24; while ($pos < mb_strlen($string, $encoding)) { $output = mb_strimwidth($string, $pos, $split, "", $encoding); $pos += mb_strlen($output, $encoding); $_string_encoded = "=?".$encoding."?B?".base64_encode($output)."?="; if ($_string) $_string .= "\r\n"; $_string .= $_string_encoded; } $string = $_string; return $string;}?>
If mb_ version doesn't work for you in MIME-B mode:function encode_mimeheader($string, $charset=null, $linefeed="\r\n") { if (!$charset) $charset = mb_internal_encoding(); $start = "=?$charset?B?"; $end = "?="; $encoded = ''; /* Each line must have length <= 75, including $start and $end */ $length = 75 - strlen($start) - strlen($end); /* Average multi-byte ratio */ $ratio = mb_strlen($string, $charset) / strlen($string); /* Base64 has a 4:3 ratio */ $magic = $avglength = floor(3 * $length * $ratio / 4); for ($i=0; $i <= mb_strlen($string, $charset); $i+=$magic) { $magic = $avglength; $offset = 0; /* Recalculate magic for each line to be 100% sure */ do { $magic -= $offset; $chunk = mb_substr($string, $i, $magic, $charset); $chunk = base64_encode($chunk); $offset++; } while (strlen($chunk) > $length); if ($chunk) $encoded .= ' '.$start.$chunk.$end.$linefeed; } /* Chomp the first space and the last linefeed */ $encoded = substr($encoded, 1, -strlen($linefeed)); return $encoded;}
In countries where there's non-us ASCII, it's a very good example, for sending mail:mb_internal_encoding('iso-8859-2');setlocale(LC_CTYPE, 'hu_HU');function encode($str,$charset){ $str=mb_encode_mimeheader(trim($str),$charset, 'Q', "\n\t"); return $str;}print encode('the text with spec. chars: ő Ű Ő ű, ?','iso-8859-2');It creates a 7bit string
i think mb_encode_mimeheader still have bug. here is sample code:function mb_encode_mimeheader2($string, $encoding = "ISO-2022-JP") { $string_array = array(); $pos = 0; $row = 0; $mode = 0; while ($pos < mb_strlen($string)) { $word = mb_strimwidth($string, $pos, 1); if (!$word) { $word = mb_strimwidth($string, $pos, 2); } if (mb_ereg_match("[ -~]", $word)) { // ascii if ($mode != 1) { $row++; $mode = 1; $string_array[$row] = NULL; } } else { // multibyte if ($mode != 2) { $row++; $mode = 2; $string_array[$row] = NULL; } } $string_array[$row] .= $word; $pos++; } //echo "<pre>"; //print_r($string_array); //echo "</pre>"; foreach ($string_array as $key => $value) { $value = mb_convert_encoding($value, $encoding); $string_array[$key] = mb_encode_mimeheader($value, $encoding); } //echo "<pre>"; //print_r($string_array); //echo "</pre>"; return implode("", $string_array);}is not the best, but it works
At least for Q encoding, this function is unsafe and does not encode correctly. Raw characters which appear as RFC2047 sequences are simply left as is.Ex:mb_encode_mimeheader( '=?iso-8859-1?q?this=20is=20some=20text?=' );returns '=?iso-8859-1?q?this=20is=20some=20text?='The exact same string, which is obviously not the encoding for the source string. That is, mb_encode_mimeheader does not do any type of escaping.That is, the following condition is not always true: mb_decode_mimeheader( mb_encode_mimeheader( $text ) ) == $text