PHP Conference Japan 2024

mb_encode_mimeheader

(PHP 4 >= 4.0.6,PHP 5,PHP 7,PHP 8)

mb_encode_mimeheader為 MIME 標頭編碼字串

描述

mb_encode_mimeheader(
    字串 $string,
    字串 $charset = null,
    字串 $transfer_encoding = null,
    字串 $newline = "\r\n",
    整數 $indent = 0
):字串

依 MIME 標頭編碼架構,編碼給定的 字串 string

參數

string

要編碼的 字串。其編碼應與 mb_internal_encoding() 相同。

charset

charset 指定 string 所表示的字元集名稱。預設值由目前的 NLS 設定 ( mbstring.language ) 決定。

transfer_encoding

transfer_encoding 指定 MIME 編碼的架構。它應該是 "B" (Base64) 或 "Q" (Quoted-Printable)。如果未指定,則會回退到 "B"

newline

newline 指定 EOL(行尾)標記,mb_encode_mimeheader() 使用此標記執行換行(» RFC 術語,將長度超過特定長度的行分割成多行的動作。長度目前硬式編碼為 74 個字元)。如果未指定,則會回退到 "\r\n" (CRLF)。

indent

第一行的縮排(string 前標頭中的字元數)。

傳回值

以 ASCII 表示的 字串 轉換版本。

變更記錄

版本 描述
8.3.0 使用 Quoted-Printable 編碼時,NUL (0) 位元組不再被捨棄,而是編碼為 =00
8.0.0 charsettransfer_encoding 現在可以為 null。

範例

範例 #1 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>

注意事項

注意:

此函式並非設計為在高層次上下文斷點(單字邊界等)處斷行。此行為可能會使原始字串與非預期的空格混雜。

參見

新增註解

使用者貢獻的註解 10 則註解

7
stormflyCUT at hyh dot pl
18 年前
一些使用國家字元並在郵件主旨中使用 UTF-8 時遇到問題的解決方案。在使用 mb_encode_mimeheader 與 UTF-8 之前,請設定 mb_internal_encoding('UTF-8')。
1
nigrez at nius dot waw dot pl
18 年前
確實,函式已損壞(PHP5.1,來自 UTF-8 具有 pl_PL 字元集的編碼)。以下是所建議的 _mb_mime_encode 的快約 15% 的版本。它也具有更像其他 mb_* 函式的標頭,並且不會觸發任何錯誤/警告/通知。

<?php

function 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;
}

?>
2
gullevek at gullevek dot org
21 年前
請先閱讀此內容:http://bugs.php.net/bug.php?id=23192,因為 mb_encode_mimeheaders 有錯誤!

針對 ISO-2022-JP 主旨過長的多位元組損壞錯誤的解決方法

$pos=0;
$split=36; // 在 36 個單一位元組字元後,如果接著出現 MB,則會損壞
while ($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;

並非最佳方式,但它有效
2
匿名
15 年前
我找不到 PHP 函式來 MIME 編碼電子郵件地址的名稱。

輸入 = "Karl Müller<kmueller@gmx.de>"
輸出 = "Karl%20M%FCller<kmueller@gmx.de>"

我自己寫的

<?php
// 郵件地址中編碼名稱時需要
// 將 " " 取代為 "%20"
// 將 "ü" 取代為 "%FC"
// 將 "%" 取代為 "%25" 等...
// 使用 "%" 作為 MIME 的分隔符號
// 使用 "=" 作為 Quoted Printable 的分隔符號
// 輸入字串必須是 UTF8 編碼
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
{
$Out .= "?";
}
else if (
$Chr == " " || $Chr == $Delimiter || $Asc > 127)
{
$Out .= $Delimiter . strtoupper(bin2hex($Chr));
}
else
$Out .= $Chr;
}
return
$Out;
}
?>
1
tokul at users dot sourceforge dot net
16 年前
mb_encode_mimeheader() 取決於正確的 mbstring.internal_encoding 設定。它嘗試將 $str 從內部編碼轉換為 $charset。如果您忽略 mbstring 內部編碼,即使 $str 字元集與 $charset 匹配,函式也可能會錯誤地編碼字串。
1
gullevek at gullevek dot org
19 年前
我的第一篇文章大約在 2003 年,而 mb_mime_header 仍然是壞的。它*不*適用於較長的主題,而且幾乎不適用於日語以外的任何內容。

iwakura at junx dot org 對我來說也無法運作,它也會產生一些垃圾字元。

我更新了我的舊函式(我 2003 年發布的那個),並用 UTF-8、ISO-2022-JP(日語)、GB2312(簡體中文)和 EUC-KR(韓語)中的過長主題測試了它,我在 thunderbird、mail.app、outlook 等中得到了可讀的結果。

<?php

function _mb_mime_encode($string, $encoding)
{
$pos = 0;
// 如果在 36 個單位元組字元之後出現多位元組字元,它就會壞掉
// 但我將其修剪為 24,以保持每行 100% < 76 個字元
$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;
}

?>
0
paravoid
18 年前
如果 mb_ 版本在 MIME-B 模式下對您不起作用

function encode_mimeheader($string, $charset=null, $linefeed="\r\n") {
if (!$charset)
$charset = mb_internal_encoding();

$start = "=?$charset?B?";
$end = "?=";
$encoded = '';

/* 每行長度必須 <= 75,包括 $start 和 $end */
$length = 75 - strlen($start) - strlen($end);
/* 平均多位元組比率 */
$ratio = mb_strlen($string, $charset) / strlen($string);
/* Base64 的比例為 4:3 */
$magic = $avglength = floor(3 * $length * $ratio / 4);

for ($i=0; $i <= mb_strlen($string, $charset); $i+=$magic) {
$magic = $avglength;
$offset = 0;
/* 重新計算每行的 magic 以 100% 確定 */
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;
}
/* 移除第一個空格和最後一個換行符 */
$encoded = substr($encoded, 1, -strlen($linefeed));

return $encoded;
}
0
chappy at citromail dot hu
19 年前
在有非美式 ASCII 的國家/地區,這是一個很好的寄送郵件範例

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: &#337; &#368; &#336; &#369;, ?','iso-8859-2');

它會建立一個 7 位元的字串
-1
iwakura at junx dot org
19 年前
我認為 mb_encode_mimeheader 仍然有錯誤。這是範例程式碼

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 { // 多位元組
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);
}

並非最佳方式,但它有效
-3
mortoray at ecircle-ag dot com
19 年前
至少對於 Q 編碼,此函式是不安全的,並且無法正確編碼。以 RFC2047 序列形式出現的原始字元會直接保留原樣。

例如

mb_encode_mimeheader( '=?iso-8859-1?q?this=20is=20some=20text?=' );

傳回 '=?iso-8859-1?q?this=20is=20some=20text?='

完全相同的字串,這顯然不是來源字串的編碼。也就是說,mb_encode_mimeheader 不會進行任何類型的跳脫。

也就是說,以下條件並不總是成立
mb_decode_mimeheader( mb_encode_mimeheader( $text ) ) == $text
To Top