http://wordpress.pastebin.ca/1015650
に、ISO-2022-JP 専用の MIME B エンコード関数を作ってみましたが、mb_strcut()
の仕様なのかバグなのか、全部がマルチバイト文字の場合、最後の2文字が出てきません。空白を2文字追加しておくという荒技もありますが、どうすればよいでしょうか……。
http://wordpress.pastebin.ca/1015713
切り出す部分が $length より短い場合は mb_strcut()
を使わないことにして改善しました。
ぜひテストをお願いします。
lilyfan さん、こんばんは。
送信するメールの Subject がうまく表示できません (特に nkf -m がダメ)。
nkf -m ですか。参考までに他に MUA でデコードに難があったものはありますでしょうか?
またもし可能であれば問題となったMIMEエンコードされた行もペーストして頂けないでしょうか。
メソッド名がモロ encode_mimeheader_b_uncut() となっているので、あえて「76文字を越えてエンコードする」という方針なのだと思いますが、そうされている意図は何でしょう??
MIMEエンコードのバグは素の本家版含む多くのケースで分割方法の問題に起因していることが多いので、あえてテスト的に無分割にして様子を見ていました。プラグイン公開後約半年の間にここに関するバグ報告は一件もなかったので恐らくほとんどのケースで問題はないのかと思いますが、RFC違反ではありますし実際にデコードできないケースがあることが分かりましたので分割する方向で直してみたいと思います。
http://wordpress.pastebin.ca/1015713
切り出す部分が $length より短い場合は mb_strcut() を使わないことにして改善しました。
ぜひテストをお願いします。
ありがとうございます。テストしてみます。
nkf -m ですか。参考までに他に MUA でデコードに難があったものはありますでしょうか?
他の MUA としては、GyazMail しか使っていませんが、こちらは問題なしです。Mail.app は最近使ってなくて不明です。
ここんところ spam だらけで、メールサーバーのスプール (Maildir/) から spam を消していますが、そのとき、Subject が長くて何も表示されません。以下のものは全滅です……。
Subject: =?ISO-2022-JP?B?W1l1cmlrby5OZXRdIBskQiUzJWElcyVIGyhCOiAiV29yZFByZXNzIBs
kQiVhITwla0VqOUYlVyVpJTAlJCVzGyhCIEt0YWkgRW50cnkgMC44LjIgGyRCJWolaiE8JTkbKEIi?=
Subject: =?ISO-2022-JP?B?W1l1cmlrby5OZXRdIBskQiVIJWklQyUvJVAlQyUvGyhCOiAiV29yZFB
yZXNzIBskQjdIQlNCUDF+JVclaSUwJSQlcxsoQiBLdGFpIFN0eWxlIDEuMDAgGyRCJWolaiE8JTkbKEI
i?=
Subject: =?ISO-2022-JP?B?W1l1cmlrby5OZXRdIBskQiUzJWElcyVIGyhCOiAiGyRCOiNHLyRiGyh
CV29yZFByZXNzGyRCJVclaSUwJSQlcyUzJXMlWjMrOkUbKEIi?=
Subject: =?ISO-2022-JP?B?W1l1cmlrby5OZXRdIBskQiUzJWElcyVIGyhCOiAiV29yZFByZXNzIEp
hcGFuIBskQkpEOj8kSBsoQldvcmRQcmVzcyAbJEJGfEtcOGwlVSUpITwlaSVgMytAXxsoQiI=?=
MIMEエンコードのバグは素の本家版含む多くのケースで分割方法の問題に起因していることが多いので、
たしかに、本家版は 76 文字を越えないように分割していますが、マルチバイト文字の途中で分割したり、改行コードを2つ入れてしまってヘッダを終了させてしまうなど、問題が多いですね。
http://wordpress.pastebin.ca/1015713
実際に組み込んでみたのですが、MIME エンコードは 76 文字を越えないのですが、改行コードが反映されませんでした。nkf 等でのデコードは OK になりましたが、RFC 準拠にはなっていません。おそらく PHPmailer の方で改行を消してしまうようです。となると、本パッチではなく PHPmailer の方も対策が必要です。
本当ならば PHPmailer の MIME エンコーダーを直せばいいのでしょうが、これはいろんなエンコーディングを知らないといけないので、なかなか大変ですね。とりあえず ISO-2022-JP の場合を検出して特別処理をやらせる手はあると思います。
よく考えたら mbstring 拡張が入っているなら <a href="http://jp2.php.net/manual/ja/function.mb-encode-mimeheader.php">mb_encode_mimeheader()</a>
を使う手がありました。これの方がよりマトモな処理をしてくれそうです。
mb_encode_mimeheader() は PHPのバージョン依存のバグがあるようなので利用を見合わせています。
また詳細は改めて確認しないといけませんが PHPmailer 内部に改行を変換してしまうフィルターが存在するのは確かでそれも無分割にしたことの理由の一つだったかと思います。
PHPmailer は前もってMIMEエンコードを行った入力を想定して作られていないのだと思います。
MIME エンコードは 76 文字を越えないのですが、改行コードが反映されませんでした。nkf 等でのデコードは OK になりましたが、RFC 準拠にはなっていません。
ということはスペース区切りで一行になっているような状態(Gmailのフォームメールがこれ)でしょうか?
またそれであれば nkf のデコードは OK なのでしょうか?
mb_encode_mimeheader() は PHPのバージョン依存のバグがあるようなので利用を見合わせています。
なるほど。mb_internal_encoding の設定によっても結果が異なるようで、そういう状況だと使いにくいのもうなづけます。
PHPmailer は前もってMIMEエンコードを行った入力を想定して作られていないのだと思います。
このへんは PHPmailer へのパッチを trac に投げるという方向で改善をすすめればいいかと思います。可能ならば、PHPmailer の encodeHeader() を完全に直してしまう手もありますが、ちょっと大変でしょうし。
スペース区切りで一行になっているような状態(Gmailのフォームメールがこれ)でしょうか?
はい、そういう状態です。なぜか、この状態だとうまくデコードできます。「MIME エンコードされた部分が76文字を越えない」ので OK になっているという気がします。実装としては納得できますが、ちょっと変ですね。
わたしのコードは ISO-2022-JP のエスケープシーケンスの処理が泥臭くなっていて、そのために汎用的ではありません。もうちょっと工夫すれば ISO-2022 系の他のエンコーディング (KR とか CN) にも対応させられそうですが、かの国では使ってなさそうですから、対応しなくてもいいかもしれません。
UTF-8 の場合は tenpura さんの処理そのままですが、こちらも 76 文字対応した方がいいかもしれません。こちらはエスケープシーケンスの処理がないので、だいぶ楽になりそうです。