saturn 发表于 2010-10-14 13:37:23

Codeigniter中使用Email库中文标题乱码的通用解决方案

这是一篇总结性的文章,其撰写目的是:彻底解决在Codeigniter中使用内置Email库时,出现的中文标题(Subject)乱码问题。对于此问题的探讨很多,比如这里,这里还有这里。

和某些动作片会打上马赛克一样,乱码的根源在于编码。中文汉字,与其日语,韩语这样的东亚字符集兄弟姐妹一样,均属于非ASCII字符集。邮件系统由于产生较早,设计之初并没有完全考虑到拉丁语系之外的字符集。所以,如果需要在邮件中支持中文这样的非ASCII字符集,则必须要对其中的内容进行编码,否则邮件服务器将会无法识别。主要的编码方式有两种,后面我们会提到。

需要注意,我这里的解决方案主旨在于通用一词,亦即:在不做任何编码转换的情况(即保持CI默认的utf-8编码)下,完美解决邮件中中文标题的乱码问题。

先说解决方案,再说问题原因。

创建一个MY_Email.php拓展类,丢到./application/libraries.html文件夹中,内容如下:

<?php

class MY_Email extends CI_Email
{
    /**
   * Set Email Subject
   *
   * @access    public
   * @param   string
   * @return    void
   */
    function subject($subject)
    {
      $subject = '=?'. $this->charset .'?B?'. base64_encode($subject) .'?=';
      $this->_set_header('Subject', $subject);
    }
}

修改完成之后,发个带中文标题的邮件试试。整个Hack过程非常简单,但需要了解下原理。

上面的解决方案,我将CI默认的对邮件标题(Subject)的编码方式从 Q-Encoding (简称 Q编码)变成了 Base64 (简称 B编码)。Q编码和B编码也就是上面我们所提到的对非ASCII所需的两种编码格式。标准文件 MIME RFC2047 对邮件的编码和格式信息有非常明确的定义和建议,其中有句话需要我们仔细研究:

Initially, the legal values for "encoding" are "Q" and "B". These encodings are described below. The "Q" encoding is recommended for use when most of the characters to be encoded are in the ASCII character set; otherwise, the "B" encoding should be used.

更深入的内容,大家可以参考PHP官方上提到的一系列与邮件MIME相关的RFC文档。

拓展阅读:

“UTF-8下mail header中的换行符 \r\n可能会产生乱码问题” - PHP 官方

原文地址:http://www.cnsaturn.com/posts/62
页: [1]
查看完整版本: Codeigniter中使用Email库中文标题乱码的通用解决方案