转换内联指定的UTF-8邮件主题

时间:2012-02-19 16:28:44

标签: php email encoding utf-8

想要将以下原始邮件转换为正常的UTF-8文本:

  

=?utf-8?Q?Schuker_hat_sich_vom_ = C3 = 9Cbungsabend_(01.01.2012)_abgem?= =?utf-8?Q?eldet?=

真实的文字是:

  

Schuker hat sichvomÜbungsabend(01.01.2012)abgemeldet

我的第一种转换方法:

$mime = '=?utf-8?Q?Schuker_hat_sich_vom_=C3=9Cbungsabend_(01.01.2012)_abgem?=  =?utf-8?Q?eldet?=';
mb_internal_encoding("UTF-8");
echo mb_decode_mimeheader($mime);

这给了我以下结果:

  

Schuker_hat_sich_vom_Übungsabend_(01.01.2012)_abgemeldet

(问题在这里:我做错了什么?为什么会出现这些下划线?)

我转换它的第二种方法:

$mime = '=?utf-8?Q?Schuker_hat_sich_vom_=C3=9Cbungsabend_(01.01.2012)_abgem?=  =?utf-8?Q?eldet?=';
echo imap_utf8($mime);

这给了我以下(正确)结果:

  

Schuker hat sichvomÜbungsabend(01.01.2012)abgemeldet

为什么这样做?我应该依靠哪种方法?

我问的原因是我之前曾问过另一个mail subject decoding related question mb_decode_mimeheader解决方案,而imap_utf8就是这样。我怎样才能确保为这两个例子解码所有正确的内容:

  

=?utf-8?Q?Schuker_hat_sich_vom_ = C3 = 9Cbungsabend_(01.01.2012)_abgem?= =?utf-8?Q?eldet?

  

=?UTF-8 2 B 4 UmU6ICMyLUZpbmFsIEFjY2VwdGFuY2UgdGVzdCB3aXRoIG5ldyB0ZXh0IHdpdGggU2xvdg ==?=           =?UTF-8 2 B 4 YWsgaW50ZXJwdW5jdGlvbnMgIivEvsWhxI3FpcW + w73DocOtw6khxYgi?=

应该给我预期的结果:

  

Schuker hat sichvomÜbungsabend(01.01.2012)abgemeldet

  

回复:#2 - 最终验收测试,带有斯洛伐克语中间节点的新文本“+ľščťžýáíé!”

4 个答案:

答案 0 :(得分:7)

根据hbit响应,我改进了imapUtf8()功能,使用charset信息将主题文本转换为UTF-8。结果如下:

function imapUtf8($str){
    $convStr = '';
    $subLines = preg_split('/[\r\n]+/', $str);
    for ($i=0; $i < count($subLines); $i++) {
        $convLine = '';
        $linePartArr = imap_mime_header_decode($subLines[$i]);
        for ($j=0; $j < count($linePartArr); $j++) {
            if ($linePartArr[$j]->charset === 'default') {
                if ($linePartArr[$j]->text != " ") {
                    $convLine .= ($linePartArr[$j]->text);
                }
            } else {
                $convLine .= iconv($linePartArr[$j]->charset, 'UTF-8', $linePartArr[$j]->text);
            }
        }
        $convStr .= $convLine;
    }

    return $convStr;
}

答案 1 :(得分:1)

这也在mb_decode_mimeheader手册的评论中,我实际上认为这是一个错误。数据库中没有,所以我将其作为新文件提交。

但是,AFAIK imap_mime_header_decode会毫无问题地处理您的编码,这样可以保持代码的正常运行。

答案 2 :(得分:1)

此功能适用于两个示例:

function imapUtf8($str){
    $convStr = '';
    $subLines = preg_split('/[\r\n]+/',$str); // split multi-line subjects
    for($i=0; $i < count($subLines); $i++){ // go through lines
        $convLine = '';
        $linePartArr = imap_mime_header_decode(trim($subLines[$i])); // split and decode by charset
        for($j=0; $j < count($linePartArr); $j++){
            $convLine .= ($linePartArr[$j]->text); // append sub-parts of line together
        }
        $convStr .= $convLine; // append to whole subject
    }
    return $convStr; // return converted subject
} 

试验:

$sub1 = '=?utf-8?Q?Schuker_hat_sich_vom_=C3=9Cbungsabend_(01.01.2012)_abgem?=  =?utf-8?Q?eldet?=';
$sub2 = '=?UTF-8?B?UmU6ICMyLUZpbmFsIEFjY2VwdGFuY2UgdGVzdCB3aXRoIG5ldyB0ZXh0IHdpdGggU2xvdg==?= =?UTF-8?B?YWsgaW50ZXJwdW5jdGlvbnMgIivEvsWhxI3FpcW+w73DocOtw6khxYgi?=';
echo imapUtf8($sub1);
echo imapUtf8($sub2);

结果:

  

Schuker hat sichvomÜbungsabend(01.01.2012)abgemeldet

     

回复:#2 - 最终验收测试,带有斯洛伐克语中间节点的新文本“+ľščťžýáíé!”

答案 3 :(得分:0)

关于主题标题字段中的神秘下划线:

RFC2047 4.2(2)明确说明:

  

8位十六进制值20(例如,ISO-8859-1 SPACE)可以是          表示为&#34; _&#34; (下划线,ASCII 95.)。 (这个角色可能会          不通过一些互联网邮件网关,但它的使用          将大大提高&#34; Q&#34;的可读性。邮件编码数据          不支持此编码的读者。)请注意&#34; _&#34;          始终表示十六进制20,即使是SPACE字符          在使用的字符集中占用不同的代码位置。

主题行的编码规则记录在RFC2047中。