使用 utf-8 文件名发送 MIME 编码的电子邮件附件

Posted

技术标签:

【中文标题】使用 utf-8 文件名发送 MIME 编码的电子邮件附件【英文标题】:Sending MIME-encoded email attachments with utf-8 filenames 【发布时间】:2015-02-10 15:47:24 【问题描述】:

亲爱的朋友们,

过去 3 天我在网上搜索了答案,但找不到任何答案。 我发现了很多“几乎”的案例,但没有一个是我想要的。

我可以获取希伯来语的主题和正文,但无法获取希伯来语的附件名。

顺便说一句,我对 phpMailer 等第三方程序不感兴趣。

这是我得到的:

W_W(W'W_W_.pdf

这是我想要的:

שלום.pdf

这是我的代码,很简单..

$boundary = uniqid("htmlEMAIL");
$separator = md5(time());
$eol = PHP_EOL;

// attachment name
$fileName = "שלום.pdf";
var_dump($fileName);

$pdfdoc = $pdf->Output("", "S");
$attachment = chunk_split(base64_encode($pdfdoc));

// main header (multipart mandatory)
$headers = [];
$headers[] = "From: $from";
$headers[] = "MIME-Version: 1.0";
$headers[] = "Content-Type: multipart/mixed; boundary=\"".$separator."\"";
$headers[] = "This is a MIME encoded message.";

// message
$msg = "--".$separator.$eol;
$msg .= "Content-Type: text/html; charset=UTF-8".$eol;
$msg .= "Content-Transfer-Encoding: base64".$eol.$eol;
$msg .= chunk_split(base64_encode($message)).$eol.$eol; 

// attachment
$msg .= "--".$separator.$eol;
$msg .= "Content-Type: application/pdf; name=\"".$fileName."\"".$eol; 
$msg .= "Content-Transfer-Encoding: base64".$eol.$eol;
$msg .= "Content-Disposition: attachment".$eol;
$msg .= $attachment.$eol;
$msg .= "--".$separator."--";

mail($to,'=?UTF-8?B?'.base64_encode($subject).'?=', $msg, implode("\n\r", $headers));

【问题讨论】:

看看this answer to a similar question - 它使用 RFC5987 urlencoding 作为文件名。 感谢您的快速回放,但这不是我想要的,它应该更容易.. 我几乎没有刮擦那里的表面。有很多相关的 RFC。我检查了雷鸟的行为,看起来它使用了编码词:Content-Type: application/pdf; name="=?UTF-8?B?16nXnNeV150ucGRm?=" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename*=utf-8''%D7%A9%D7%9C%D7%95%D7%9D%2E%70%64%66 但是 rfc 2047 说 An 'encoded-word' MUST NOT be used in parameter of a MIME Content-Type or Content-Disposition field, or in any structured field body except within a 'comment' or 'phrase'. 并且到目前为止我还没有发现其他 rfc 另有说明 Outlook 的编码方式如下:Content-Type: application/pdf; name="=?windows-1255?B?+ezl7S5wZGY=?=" Content-Description: =?windows-1255?B?+ezl7S5wZGY=?= Content-Disposition: attachment; filename="=?windows-1255?B?+ezl7S5wZGY=?="; 【参考方案1】:

根据 RFC2047,您不能在 Content-Type 标头的参数中使用除 ascii 以外的编码。

根据 RFC2231 你可以尝试定义扩展参数: Content-Type: application/pdf; name*=utf-8''%D7%A9%D7%9C%D7%95%D7%9D%2E%70%64%66

我不知道它的支持程度。

我想不出oneliner,但你可以尝试改编这个PHP convert string to hex and hex to string

根据 cmets 更新: 虽然规范明确禁止这样做,但大多数邮件客户端应该理解以下格式 'name="?UTF-8?B?' . base64_encode($filename) . '?='

我建议你为了理智而使用它。

【讨论】:

这取决于您用来检查的邮件客户端。如果它不能处理它,那么......

以上是关于使用 utf-8 文件名发送 MIME 编码的电子邮件附件的主要内容,如果未能解决你的问题,请参考以下文章

无法在python中使用MIME发送带有pdf附件的电子邮件

包含扩展字符的 MIME 附件名称失败

如何发送 utf-8 的电子邮件?

将 DOCX 编码为通过电子邮件发送

ajax的post方法怎么设置mime编码

在 perl 中使用电子邮件 :: MIME 发送多个文件?