PHPMailer类发送中文邮件兼谈解决XOOPS中文发送邮件乱码

xoops.org.cn论坛上又有人问xoops发送中文邮件乱码的问题。domecc给出了一个临时办法,还提供一个网址http://www.thedevlog.com/dev/log-29.html来对utf8编码系统做修正。

其实PHPMailer已经是非常成熟的PHP类了(当然需要打上前一段时间出现的bug的补丁),对于邮件头和邮件体的编码处理已经非常好了,http://www.thedevlog.com/dev/log-29.html中提到修改EncodeHeader并编码,实际上EncodeHeader后面的代码就是完成将头部编码的功能,所以不需要修改该函数。

要成功实现发送中文邮件,设置phpmailer类两个值即可。

$mail = new PHPMailer();

$mail->CharSet = “UTF-8”; // 设置字符集编码,GB2312 GBK

$mail->Encoding = “base64”;//设置文本编码方式

……
这样保证了邮件标题和正文内容全部不会乱码,当然邮件内容的字符集需要和给定的CharSet内容一致。

回过头来看看xoops中为什么邮件乱码,在xoops中发送邮件首先我们使用了具体语言的xoopsmailerlocal.php文件中XoopsMailerLocal类,而XoopsMailerLocal类继承自class\xoopsmailer.php中的XoopsMailer类,而XoopsMailer类的multimailer成员指向自class\mail\xoopsmultimailer.php中的XoopsMultiMailer类的实体,XoopsMultiMailer类是从PHPMailer派生的。

问题就出在XoopsMailer的构造函数上。在XoopsMultiMailer类的构造函数中(xoopsmultimailer.php中177行)指定了CharSet值为strtolower( _CHARSET ),这样做本来在绝大多数邮件系统中均不会出现乱码,但在XoopsMailer类的sendMail方法(xoopsmailer.php中378行)却重新指定了字符集和文本编码方式:

$this->multimailer->CharSet = $this->charSet;

$this->multimailer->Encoding = $this->encoding;

这样导致前面在构造multimailer的时候指定了字符集为XOOPS系统字符集strtolower( _CHARSET )(utf-8或者gb2312),到sendMail方法中却换成了XoopsMailer的成员charSet的值,而XoopsMailer的构造函数并没有让charSet随系统变化,而是取默认值:iso-8859-1。邮件客户端收到邮件按照iso-8859-1来显示邮件内容当然会乱码。所以我们只要正确的给XoopsMailer类实体赋给正确字符集(_CHARSET)即可。

解决办法是:

打开htdocs\class\xoopsmailer.php ,137行附近

$this->multimailer = new XoopsMultiMailer();

$this->reset();

后面添加一行:

$this->charSet = strtolower( _CHARSET );

$this->encoding = ‘base64’;
更完美的解决办法是:
打开htdocs\language\schinese\xoopsmailerlocal.php和htdocs\language\schinese_utf8\xoopsmailerlocal.php 修改为:

<?php

class XoopsMailerLocal extends XoopsMailer {

function XoopsMailerLocal(){

    $this-&gt;XoopsMailer();

    $this-&gt;charSet = strtolower( _CHARSET );

    $this-&gt;encoding = 'base64';

}

}

?>
实则是xoops 中文版bug。

另外,为什么要指定encoding呢,这里涉及到email的原理,email产生的年代用7bit就足够表示所有ASCII字符可打印字符了,email发展到全世界之后,多字节语种的需要,需要使用8bit或者16bit或者更多bit来表示一个完整的字,但老式的网络设备和一些邮件系统并不能很好的处理不是7bit的内容或者并不能很好处理多字节的文本内容,这样就需要将文本做一个编码,base64和quoted-printable便是email中用来解决这个问题的最流行方法。email中附件都是用base64来编码具体内容的,用base64编码之后的邮件除非文本内容和指定字符集不一致或者本身就是乱码,否则不会出现乱码的。

当时给ceiea做Windows下邮件系统时候对email做了全面的分析,还是有些用处的。

[tags]PHPMailer,中文,邮件,XOOPS[/tags]