localdisk

PHP とか Java とか Web とか好きなことを書きます。

Zend_Mail を頑張って日本語対応してみた

タイトル通りがんばってみました。問題になってた長いSubjectでも文字化けはしません。
長いSubjectが文字化けするのは Zend_Mime::encodeBase64Header の第3引数の Zend_Mime::LINELENGTH(72) と第4引数のZend_Mime::LINEEND(\n)に問題があります。ヘッダを Base64エンコードする際に 72文字ごとに「\n」が入ってしまうことが原因でした。なので LINELENGTH の数を増やしてやるか、LINEEND を空文字を指定してやれば解決します。
解決できてない問題が1つあって、漢字の「松」が「毫」になるんですよねぇ。これは Zend_Mail::_filterName が余計なことをしやがってるせいです。
漢字の「松」は ISO-2022-JP では「e$B>>e(B」なのですが、これを「e$B]]e(B」に変換しやがるせいで化けてしまいます。これは正直どうしたものかと思ってて保留中。誰か詳しい方教えて下さい。
以下ソース

<?php
require_once 'Zend/Mail.php';
class Japanese_Mail extends Zend_Mail {
    protected $_headerEncoding = Zend_Mime::ENCODING_BASE64;
    public function __construct($charset = 'iso-8859-1') {
        parent::__construct('ISO-2022-JP');
    }
    public function addTo($email, $name='') {
        parent::addTo($email, mb_convert_encoding($name, 'ISO-2022-JP', mb_detect_encoding($name)));
    }
    public function addCc($email, $name='') {
        parent::addCc($email, mb_convert_encoding($name, 'ISO-2022-JP', mb_detect_encoding($name)));
    }
    public function setFrom($email, $name = null) {
        parent::setFrom($email, mb_convert_encoding($name, 'ISO-2022-JP', mb_detect_encoding($name)));
    }
    public function setSubject($subject) {
        parent::setSubject(mb_convert_encoding($subject, 'ISO-2022-JP', mb_detect_encoding($subject)));
    }
    public function setBodyText($txt, $charset = null, $encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE) {
        parent::setBodyText($txt, mb_convert_encoding($txt, 'ISO-2022-JP', mb_detect_encoding($txt)), Zend_Mime::ENCODING_7BIT);
    }
    public function setBodyHtml($html, $charset = null, $encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE) {
        parent::setBodyHtml($html, mb_convert_encoding($html, 'ISO-2022-JP', mb_detect_encoding($html)), Zend_Mime::ENCODING_7BIT);
    }
    protected function _encodeHeader($value) {
    	if (Zend_Mime::isPrintable($value) === false) {
            if ($this->getHeaderEncoding() === Zend_Mime::ENCODING_QUOTEDPRINTABLE) {
                $value = Zend_Mime::encodeQuotedPrintableHeader($value, $this->getCharset(), Zend_Mime::LINELENGTH, '');
            } else {
                $value = Zend_Mime::encodeBase64Header($value, $this->getCharset(), Zend_Mime::LINELENGTH, '');
            }
        }

        return $value;
    }
    protected function _formatAddress($email, $name) {
        if ($name === '' || $name === null || $name === $email) {
            return $email;
        } else {
            $encodedName = $this->_encodeHeader($name);
            $format = '"%s" <%s>';
            return sprintf($format, $encodedName, $email);
        }
    }
}

Free source code hosting for Git and Mercurial by Bitbucket に置きました。