电子邮件主题中的错误标题?

3

我有一个非常简单的发送电子邮件的功能。我开始实现电子邮件的翻译版本,并出现了特殊字符,例如é和ó。每当我在电子邮件主题中包含这些字符时,它就会导致我的amavis出现BAD_HEADER错误。

显然,它不是8位编码的,这一点起初是有道理的。然而,我找不到任何关于如何正确编码主题的指南或说明。

只是为了好玩,我尝试使用é代替é,当然问题被解决了。但同时,电子邮件的主题中出现了é,而不是é。

这是我目前拥有的脚本:

function sendEmail() {

    // Build HTML version
    ob_start();
    include('emailhtml.php');
    $msgHTML = ob_get_contents();
    ob_end_clean();

    // Build TXT version
    ob_start();
    include('email.php');
    $msgTxt = ob_get_contents();
    ob_end_clean();


    // Subject & headers
    $subject = "áéíóú";
    $boundary = md5(uniqid(rand())); 
    $headers   = array();
    $headers[] = "MIME-Version: 1.0";
    $headers[] = "Content-Type: multipart/alternative; boundary = ".$boundary;
    $headers[] = "From: ".$from." <".$from_email.">";
    $headers[] = "Reply-To: ".$reply2_email;

    // Plain text version of message
    $body = "--$boundary\r\n" .
       "Content-Type: text/plain; charset=UTF-8\r\n" .
       "Content-Transfer-Encoding: base64\r\n\r\n";
    $body .= chunk_split(base64_encode($msgTxt));

    // HTML version of message
    $body .= "--$boundary\r\n" .
       "Content-Type: text/html; charset=UTF-8\r\n" .
       "Content-Transfer-Encoding: base64\r\n\r\n";
    $body .= chunk_split(base64_encode($msgHTML));
    $body .= "--$boundary--\r\n";

    // BAM! Shoot it off...
    mail($receiver, $subject, $body, implode("\r\n", $headers));
}

1
你需要使用quoted printable或base64对主题进行编码。这是一个例子:https://dev59.com/6GYr5IYBdhLWcg3wdqGw - grebneke
@grebneke 谢谢,我正在尝试这个解决方案。 - Kolja
@grebneke 我尝试使用你提供链接中的quoted_printable_encode()函数,但是当我使用它时,我的脚本完全停止工作了。 :/ - Kolja
4个回答

5

邮件头编码

如果Subject: header包含任何ASCII字符集之外的字符,就需要进行编码。

编码类型

有两种编码可供选择:Quoted PrintableBase64。对于内容为áéíóú的典型编码主题头,看起来像这样:

// Using Quoted Printable encoding:
Subject: =?ISO-8859-1?Q?=C3=A1=C3=A9=C3=AD=C3=B3=C3=BA?=

// Using Base64 encoding:
Subject: =?ISO-8859-1?B?w6HDqcOtw7PDug==?=

首选方式

如果您的PHP使用了多字节字符串函数,您应该使用mb_encode_mimeheader()

$subject = "áéíóú";
$encoded_subject = mb_encode_mimeheader($subject);
print $encoded_subject;
// output: =?UTF-8?B?w4PCocODwqnDg8Ktw4PCs8ODwro=?=

手动方式

如果您无法使用mb_encode_mimeheader(),可以使用一些第三方PHP库或创建自己的编码函数。

$subject = "áéíóú";
$encoded_subject = "=?ISO-8859-1?Q?" . quoted_printable_encode($subject) . "?=";
print $encoded_subject;
// Output: =?ISO-8859-1?Q?=C3=A1=C3=A9=C3=AD=C3=B3=C3=BA?=

可怕的细节

正确执行MIME编码并不容易。如果您想了解关于它的一切,应该开始学习RFC 2047RFC 2045


谢谢,这个解决了我的问题。我先尝试了可引用打印(quoted printable),但后来发现我的提供商只运行在 PHP 5.2.17 上,而根据文档,可引用打印是在 5.3 版本中添加的。现在我使用 Base64,它非常好用。 - Kolja

1
我的做法是:$Subject = "=?UTF-8?B?". base64_encode($Subject). "?=";,这可以实现反向操作。
function Subject($subject) {
    $prefix = "=?UTF-8?B?";
    return (stristr($subject,$prefix) === false ? 
                                    $subject : 
        base64_decode(substr(substr($subject,10),0,-2) ));
}

0
你有这样一行代码:$subject = $subject;,但你实际上并没有设置变量$subject。因此,你传递了一个未初始化的值给mail(),这被视为null并会引起问题。

-1

$asuntoUFT8 = "Example wishes you a Happy Birthday!!";

$asunto = "=?UTF-8?B?".base64_encode($asuntoUFT8)."=?=";


1
请花点时间阅读[编辑帮助](//stackoverflow.com/editing-help)中的内容。在Stack Overflow上进行格式设置与其他网站不同。 - Dharman
这个主题中已经有一个非常相似的答案了,请解释一下你的答案与之不同。 - Dharman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接