サポート » バグ報告と提案 » WP-Multibyte-Patch が 76 文字を越えるメールヘッダを生成する

  • モデレーター IKEDA Yuriko

    (@lilyfan)


    WordPress 2.5.1 日本語版同梱の WP-Multibyte-Patch (バージョン 1.0) を利用していますが、これが送信するメールの Subject がうまく表示できません (特に nkf -m がダメ)。どうやら、MIME B エンコードするとき「1行76文字を越えるエンコード」を行なっているようです。

    wp-multibyte-patch/ext/ja/class.php の42行目 encode_mimeheader_b_uncut() が以下のようになっています。

    function encode_mimeheader_b_uncut($string, $charset = 'UTF8') {
    	return "=?$charset?B?" . base64_encode($string) . '?=';
    }

    これは、RFC2047 (日本語訳) で定義されている「1つ以上の ‘encoded-word’ を含むそれぞれの行は、76文字に制限される」に違反しています。$string を、floor( (76 - strlen("=?$charset?B??=")) * 3 / 4) 文字ごとに mb_strcut() してから、base64_encode() すれば、うまく適合させることが可能なのではないでしょうか?

    メソッド名がモロ encode_mimeheader_b_uncut() となっているので、あえて「76文字を越えてエンコードする」という方針なのだと思いますが、そうされている意図は何でしょう??

    (追記) ちょっと試してみましたが、mb_strcut() は、カットした文字列にエスケープシーケンスを補わないんですね……。そのへんを考慮したコード案を提示してみます。

6件の返信を表示中 - 1 - 6件目 (全6件中)
  • モデレーター IKEDA Yuriko

    (@lilyfan)

    http://wordpress.pastebin.ca/1015650
    に、ISO-2022-JP 専用の MIME B エンコード関数を作ってみましたが、mb_strcut() の仕様なのかバグなのか、全部がマルチバイト文字の場合、最後の2文字が出てきません。空白を2文字追加しておくという荒技もありますが、どうすればよいでしょうか……。

    モデレーター IKEDA Yuriko

    (@lilyfan)

    http://wordpress.pastebin.ca/1015713
    切り出す部分が $length より短い場合は mb_strcut() を使わないことにして改善しました。
    ぜひテストをお願いします。

    モデレーター Seisuke Kuraishi

    (@tenpura)

    lilyfan さん、こんばんは。

    送信するメールの Subject がうまく表示できません (特に nkf -m がダメ)。

    nkf -m ですか。参考までに他に MUA でデコードに難があったものはありますでしょうか?
    またもし可能であれば問題となったMIMEエンコードされた行もペーストして頂けないでしょうか。

    メソッド名がモロ encode_mimeheader_b_uncut() となっているので、あえて「76文字を越えてエンコードする」という方針なのだと思いますが、そうされている意図は何でしょう??

    MIMEエンコードのバグは素の本家版含む多くのケースで分割方法の問題に起因していることが多いので、あえてテスト的に無分割にして様子を見ていました。プラグイン公開後約半年の間にここに関するバグ報告は一件もなかったので恐らくほとんどのケースで問題はないのかと思いますが、RFC違反ではありますし実際にデコードできないケースがあることが分かりましたので分割する方向で直してみたいと思います。

    http://wordpress.pastebin.ca/1015713
    切り出す部分が $length より短い場合は mb_strcut() を使わないことにして改善しました。
    ぜひテストをお願いします。

    ありがとうございます。テストしてみます。

    モデレーター IKEDA Yuriko

    (@lilyfan)

    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> を使う手がありました。これの方がよりマトモな処理をしてくれそうです。

    モデレーター Seisuke Kuraishi

    (@tenpura)

    mb_encode_mimeheader() は PHPのバージョン依存のバグがあるようなので利用を見合わせています。
    また詳細は改めて確認しないといけませんが PHPmailer 内部に改行を変換してしまうフィルターが存在するのは確かでそれも無分割にしたことの理由の一つだったかと思います。
    PHPmailer は前もってMIMEエンコードを行った入力を想定して作られていないのだと思います。

    MIME エンコードは 76 文字を越えないのですが、改行コードが反映されませんでした。nkf 等でのデコードは OK になりましたが、RFC 準拠にはなっていません。

    ということはスペース区切りで一行になっているような状態(Gmailのフォームメールがこれ)でしょうか?
    またそれであれば nkf のデコードは OK なのでしょうか?

    モデレーター IKEDA Yuriko

    (@lilyfan)

    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 文字対応した方がいいかもしれません。こちらはエスケープシーケンスの処理がないので、だいぶ楽になりそうです。

6件の返信を表示中 - 1 - 6件目 (全6件中)
  • トピック「WP-Multibyte-Patch が 76 文字を越えるメールヘッダを生成する」には新たに返信することはできません。