いわゆる機種依存文字をPHPでメールする

よく判らん。


先日仕事で作ったケータイサイトで、クレームがついた。
別にクレームでもないか。


要するにいわゆる「機種依存文字」が化けるんだけど?って。


ケータイサイトなんで、HTML側はShift-JISで、PHPUTF-8です。
SJISのサイトからSJISで受け取った文字列をUTF-8に変換して、各種処理(入力チェックとか、内容の確認)をして、HTMLで表示する直前にSJISに戻すことをしている。


で、メールを送信する際に

mb_language('ja');

を実行しているので、ISO-2022-JPで扱われることになる。

e-mail メッセージのエンコーディングとして使用します。有効な言語は、"Japanese", "ja","English","en", "uni" (UTF-8) です。 mb_send_mail() は、e-mail をエンコードする際にこの設定を使用します。

言語とその設定は、Japanese の場合は ISO-2022-JP/Base64、uni の場合は UTF-8/Base64、English の場合は ISO-8859-1/quoted printable です。

PHP: mb_language - Manual

はぁ…
フツーにメーラーを使ってメール送ると「ISO-2022-JP」じゃん!って思ってたのもあって、このあたりのテストを怠ってたわ。ケータイサイトだし、自由入力って住所氏名くらいのもんだから、そんな機種依存文字の問題が出るとは想定してなかったなぁ。*1
でもよく考えればマンション名にローマ数字を使ってるところもあるな(そういうマンションに住んでたのを忘れてた)。そうすると文字化けするな。


いや、そもそもSJISUTF-8の変換では問題がないのに、mb_send_mail()に限らずmbstring系の処理でUTF-8からISO-2022-JPSJISに変換すると機種依存文字が化けるっつーのはどういうこった!?


一応入力内容ってのはデータベースに入れてるからいいんだけど、と思ったら管理画面いらないってゆーから、作ってないわ(一応僕のローカルのテスト環境にはあるけど)。


色々考えた結果、まずはメールのエンコードUTF-8にする方法を考えた。
でもそれにはmb_send_mail()を捨てる必要がある。
件名($subject)は自前で変換する必要があるので、mb_encode_mimeheader()をはさむ。本文($body)はUTF-8なので、対応する必要はない。


少なくともPC宛てには問題がなかった。

mb_language('uni');
mb_internal_encoding('UTF-8');
(中略)
$mail_header .= "Content-Type: text/plain; charset=utf-8\r\n";
$mail_header .= "Content-Transfer-Encoding: 7bit";
(中略)
mail($mail, mb_encode_mimeheader($subject), $body, $mail_header);


しかし、ケータイってUTF-8メールって受け取れるの?
ググッってみたけど確証はなし。


そしてたどり着いたのが、「ISO-2022-JP-MS」という文字コード
今度は本文($body)も変換する必要が出てくるので、mb_convert_encoding()を実行することになる。
でもって、以下のようにしてみた。*2

mb_language('ja');
mb_internal_encoding('UTF-8');
$e_subject = mb_encode_mimeheader($subject);
$e_body    = mb_convert_encoding($body, 'ISO-2022-JP-MS');
(中略)
$mail_header .= "Content-Type: text/plain; charset=ISO-2022-JP\r\n";
$mail_header .= "Content-Transfer-Encoding: 7bit";
(中略)
mail($order_email, $e_subject, $e_body, $mail_header);

ここで「e_」とつけるのはエンコード済みですよって印。完全な個人的趣味。だってどこで変換したのか忘れるんだもん。


Becky!も、Hotmail経由のWindows Live Mailも機種依存文字を正しく表示してくれた。
一応自分のアドエスW-ZERO3メールも正常に受け取ってくれた。


他のケータイは大丈夫だろうか?(WILLCOMユーザで悪かったね)*3
そして、ヘッダにもISO-2022-JP-MSと指定しなくてもいいのか?


誰か教えてください。


(追記)
SJIS-winというのもあるんだね。

*1:一応補足しておくと、別にテキトーな仕事をしたワケではない。どちらかというとプライベートな集まりで使うためのものに近い性質を持っていたため、仕事というより社長からの個人的な依頼っぽい雰囲気だったし、あまり時間をかけるなと…というのは完全なる言い訳か。

*2:mb_convert_encodingの第三引数の'UTF-8'を省略したのは、このときはナゼか第三引数があると正しい結果が得られなかったから。最近テストしたら第三引数ありでも正常に変換できていた。ナゼだろう??

*3:一応二〜三年位前のauのカメラなし機種では正常に受け取れました。