让phpmailer支持中文名称的附件

phpmailer设置使用utf-8编码发送邮件以后,已经能够正常的发送中文邮件了,当然你调用时传进去的中文参数必须也是utf-8编码才行,但是我发现,即使这样,发送中文文件名的附件的时候,附件名称不能正确的显示。

比如我们要发送的附件是“测试.txt”,如果在添加附件的时候强制使用指定文件名的方式:

$mail->AddAttachment($attach, $attach);

那么发送过去的附件文件名将会是乱码,如果不指定:

$mail->AddAttachment($attach, $attach);

那么发送过去的文件名中的中文干脆没了,成了“.txt”。

究其原因,打开class.phpmailer.php,在大概第1007行左右,函数AddAttachment中,有一句

$filename = basename($path);

原因就在这里,现在我们使用的php 5.1.2,包括他以前的很多版本,basename函数和dirname函数都是不支持中文文件名的,所以一解析就把中文给过滤掉了。而如果强行指定文件名为什么还乱码呢,这是因为phpmailer虽然会自动根据你设定的编码方式给主题、正文进行utf-8编码化,但是却不会给附件的文件名编码。现在,只需要修改上面这一句,就能够同时解决这两方面的问题了。修改结果如下:

//$filename = basename($path);
if (false === strpos($path, '/'))
    $filename = $this->EncodeHeader($path);
else
    $filename = $this->EncodeHeader(substr($path, strrpos($path, '/') + 1));

不使用basename函数了,改用自己的方法来得到文件名,并且借用了主题Subject的编码函数EncodeHeader来生成utf-8编码形式的附件名称,搞定。

Update @ 2008-04-14

在phpMailer 2.1.0 Beta 2中,这个问题依然没有得到处理,需要作的修改还是一样,不过代码的位置在1018行附近。

另外在发送中文邮件的时候,中文会出现乱码,看了网上有处理的方式,没有讲原因,也粗暴了点,直接把函数截断了,还要改两个地方。

我看了一下源码,乱码的产生大概是在将邮件标题转成几个小的=?utf-8?B?...?=时,可能是无意中把中文给截断了产生的,所以我的修改更简单而又略微温柔一点,修改第1185行:

$maxlen = 75 - 7 - strlen($this->CharSet);
改成:
$maxlen = 75000 - 7 - strlen($this->CharSet);

就行了,把字符串的值设大点,让它不分段就行了。

6 thoughts on “让phpmailer支持中文名称的附件”

  1. 核心思想是在生成邮件的时候, 附件的名称要生成类似=?utf-8?B?...?=这样的形式,才能成功的保存非ascii字符的附件名称。 phpmailer现在的版本应该更新了,但一般做法不会变动太多, 可以在我说的行数附近找找类似代码。 希望能够帮到你。

    Reply

  2. 谢谢,我按照这个思路再试一下,我试着输出了文件名看了,确实是=?utf-8?B?…?=了。

    我再试下。

    Reply

  3. 又试了下,发出去后用foxmail收的时候附件是可以显示中文名,在WEB页面上的附件名还是乱码。不知你那里有没有完好的例子给我参考下? 再次感谢!

    Reply

    Fwolf reply on July 17th, 2009 0:29:02:

    首先要避免出现多个=?utf-8?B?…?=段,只能有一个, 其次的,就是看各种客户端或者webmail程序对附件格式如何兼容和处理了。

    我以前遇到过一种,比如mutt坚持发信附件采用rfc2231格式,倒是能读rfc2047格式的, 而gmail却只能用rfc2047格式,所以用mutt发送中文附件之后,在gmail中看附件名称就是乱码,或者说是未经解析的裸编码。

    考虑到客户端太多种了,所以最好的办法,就是避免在附件文件名里使用中文。 若再有别的问题可以邮件联系,地址见页面右上角部分。

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *