Zend_Mailで日本語のFrom情報を扱う

以前の記事で、Fromの名前の部分が化けてしまうということを書きましたが、
解決方法がわかったので、ここに残しておきます。

参考になったのは http://iandeth.dyndns.org/mt/ian/archives/000628.html です。
ここに、日本語のヘッダーを扱うためには、ISO-2022-JPに文字コードを変換して、
さらにbase64でエンコードして、さらに “=?ISO-2022-JP?B?”と”?=”で囲む必要があると。
今まで、mb_encode_mimeheaderを何も考えずに使っていましたが、
内部では上記のbase64エンコード以降のことをやってくれていたんですね。

ここまでを踏まえて、Zend_Mailのソースを見たところ、メールヘッダーはすべて、
base64ではなく、printableでエンコードされていました。
文字化けの原因はここでした。日本語に対応した処理でなかったとうことです。

しかし、printableでエンコードしている部分( _encodeHeaderメソッド)を、
base64でエンコードするようにしてしまうと、送信日時等の日本語が入ることがない
ヘッダーが受信側で正確にデコードされなくなってしまいます。

base64でエンコードしないとおかしくなるのは、Fromです。(場合によっては、Subjectも)
なので、setFromメソッドで、_encodeHeaderメソッドを呼び出している部分を、
mb_encode_mimeheaderを使ってエンコードするように変更したらOKです。

$this->_encodeHeader(‘”‘.$name.'”‘)

  ↓

mb_encode_mimeheader(‘”‘.$name.'”‘, ‘ISO-2022-JP’)

mb_encode_mimeheaderについては、下記をご参照ください。
http://phpspot.net/php/man/php/function.mb-encode-mimeheader.html

プログラムを設置しているサーバからZend_Mailだけを使って送信する場合は、
必ず文字化けするようなので、この対応は必須です。
メールサーバにSMTP認証して送信する場合(Zend_Mail_Transport_Smtp利用)は、
上記対応をしなくても、文字化けしていない場合もありました。
メールサーバ側で、うまいことやってくれているのかもしれません。

メールヘッダーのデコード(Zend_Mail)

Zend_Mail_Storage_Imapを利用して、メッセージを取得する場合、
Zend_Mail_Storage_ImapのgetMessageメソッドにて、メッセージデータを
取得したタイミングで、メールヘッダーもデコードされて、オブジェクトに設定されます。

この際のデコードは、iconv_mime_decode_headersというphp5から使える
phpライブラリで行われています。Zend_Mime_Decodeクラスの中で。
しかし、このとき文字コードが、iconv.internal_encoding(default “ISO-8859-1″)
にてデコードされるため、日本語を含んでいる場合は、正常にデコードされません。

iconv_mime_decode_headersの第3パラメタに’UTF-8’を指定したら、
日本語もUTF-8にて、正常にデコードされて取得することができます。

この対応策にたどり着くまでに、4,5時間悩んでましたが、解決策は1行修正。
Zendのソースには、あまり修正を入れたくないと思っていたので、手間取りました。

メール受信の注意点(Zend_Mail)

例えばPop3でメールを取得する場合、以前書いたこの記事のような方法で取得します。

取得した際、件名などのヘッダー情報は、
$message->subject
としてとりだすことが可能です。

しかし、取り出そうとしたヘッダー情報がない場合は、
nullが返ってくるわけではなく、exceptionが発生します。

そのため、try catchを大きなくくりでしか行っていないと、
大部分の処理が実行されないという結果になります。

件名、本文がないメールも存在するので、ここは注意が必要です。
私もこれで、しばらく作りかけのプログラムが止まっていました。