title_parttitle_parttitle_part
静岡県浜松市であれこれソフトを開発している A.K.I Software のブログです。日々の開発日記やサーバー・セキュリティ関連の話題なども掲載。
<< 2024/03 >>12345678910111213141516171819202122232425262728293031
《《《 ネットワーク機器の購入は Amazon で! 》》》
Powered by BLOM IMAP4 コマンドとエンコード問題について
小さくも大きくも閉じたりもしません
15/12/12 15:19 / PMailServer2

少し珍しいケースでのお問い合わせを頂いたので、その対策を行っているのですが、この問題は色々な仕様が絡み合って発生する問題で、お問い合わせを頂くまで想定もしていなかったこともあり、メモ代わりに記事にしておきます。


以下は IMAP4 サーバーを作っている人(殆ど居ないと思いますが)または IMAP4 クライアントを作っている人、メールの送信を行うプログラムを作成している方に、ホンのわずかーーーに有用かもしれない情報です。

まず文字コードの話からとなりますが、メールの件名などで日本語を扱う場合は、昔ながらの JISコード(ISO-2022-JPと言う奴です)が多く、最近では Unicode、UTF-8 / UTF-16 なども増えてきています。

そしてこの JIS コードなんですが、色々あるのですが 2byteコードの「、」を JIS コードに変換すると以下のようになります。

[0x1B]$B!"[0x1B](B

[0x1B] は ASCII では無く、0x1B というバイナリで、いわゆるエスケープシーケンスという物でして「ここから変換するよ」とか「ここで変換は終わりだよ」などを指定する場合に利用します。

もう1個、メールの本文などは Content-Type で「メールの本文は、こういう形式でエンコードはこれを使っています」と指定できますが、件名の場合は、そのセクションのみで完結させる為に、MIME エンコードと言う方式を使います。

=?文字コード?エンコード方式?エンコードデータ?=

みたいな奴です。上記だけではピンときませんが
上記の、[0x1B]$B!"[0x1B](B をこの形式にすると

=?iso-2022-jp?Q?=1B$B!"=1B(B?=

こんな風になります。メールヘッダを見たことがある人は、なんとなく見たことがあるよ!と思われると思います。

ちなみに、エンコード方式に B が指定されていると Base64 、Q が指定されていると Quoted-Printable という形式になります。

ここまでが前提となります。

さて IMAP4 のコマンドに FETCH というコマンドがありサーバー側にあるメールの情報などを取得します。

telnet で IMAP4 サーバーにログインしてから適当なメールボックスに移動した後に

FETCH 1 ENVELOPE

とやると「1番のメールのエンベロープを返せ」となります。

結果は(便宜省略と改行をしますが)

* 1 FETCH (UID 228118 ENVELOPE ("Stu, 12 Dec 2015 11:42:50 +0900" "Test Mail" 〜(省略)〜))

と応答が返って来ます。(実際にはもっと複雑です)
ENVELOPE コマンドはメールヘッダーの「解析結果」をエンベローブ構造体という形で返しています。

んで、構造体にもいくつかルール(データが無い場合は NIL を設定するとか)があるのですが「スペースを含む場合はダブルクォートで囲う」とあります。

上記の例でも日付部分や件名にスペースが含まれていますので「ダブルクォート」で囲っています。
というかダブルクォートで囲っておかないと一部メーラーは解析に失敗してくれます。(ダブルクォートで囲われているのが前提となっている)

さて、ここで先ほど作った「、という件名を MIME に変換しエンコードタイプは Quoted-Printable にした」奴を当てはめてみます。

* 1 FETCH (UID 228118 ENVELOPE ("Stu, 12 Dec 2015 11:42:50 +0900" "=?iso-2022-jp?Q?=1B$B!"=1B(B?=" 〜(省略)〜))

もう一目瞭然ですが、途中にダブルクォートが含まれる為、誤認識します。

さて、誰が悪いんでしょう?

まず「、」を JIS(ISO-2022-JP)でエンコードした際にダブルクォートが入るのはそのまんま「エンコードのルール」なので悪くありません。

ENVELOPE でダブルクォートを使うことですが「スペースが入らないのにダブルクォートで囲うほうが悪い」と思うかもしれませんが、実際、仕様上は問題ありませんし、むしろ囲わないと認識しないクライアントが現実問題として存在するので囲わざる得ません。

JIS と Quoted-Printable でエンコードして送信するクライアントが悪いんじゃない?ってとこに行き着くのですが、そもそも、JIS と Quoted-Printable の組み合わせはやってはいけない組み合わせではありません。
IMAP4 じゃなくて POP3 のようにメールヘッダ又は全体を受信してから単独でデコードすれば正常にデコードできる訳ですので。

つまり誰も悪くなく、組み合わせが悪かったということになります。

まぁ、しいて言えば、送信時に Quoted-Printable を使わずに Base64 でエンコードすれば問題ないのですが。

ちなみに Base64 でエンコードすると

=?iso-2022-jp?B?GyRCISIbKEI=?=

このようになります。
Base64 で利用される記号は /+= の3種類だけですので、問題の出ようがありません。

なにか RFC で見忘れている仕様があるのかもしれないと思い、RFC 読み返してみたり(見落としている可能性はあります・・・)、ダブルクォートを外してみたり、エスケープしてみたり、CSV のようにダブルクォートを重ねてみたりしてみましたが、認識しないクライアント続出なので、その辺りの問題では無い気もします。

で、最終的には PMail Server2 側で、Quoted-Printable で MIME エンコードされている場合にダブルクォートが含まれている場合は、Base64 で再エンコードしてから応答する。
というオプションをつけることにしました。

(FETCH の応答のみ再変換し、元データは加工しません。元データを加工すると POP3 で読み出した場合に元のデータと違うことになってしまいますし、DKIM 等で確認範囲に Subject が含まれている場合、偽装判定される可能性が出てくるからです。)

結論としては「メールの送信プログラムを作る場合は、Quoted-Printable は止めて、Base64 にしておけば確実だよ!」ってことです。

[更新日付:2015/12/12 16:44:51]
トラックバックを見る(0)
Log Link [https://akisoftware.com/cgi-bin/blom.exe?akisoft+sl+c0291ca5e472738f610f010097bd73f593acfd63]
TB Link [https://akisoftware.com/cgi-bin/blom.exe?akisoft+tb+c0291ca5e472738f610f010097bd73f593acfd63]

記事へのコメント

コメントはありません

名前
コメントキー
 
コメントする時はキーを正確に入力して下さい
コメント
アドレスを含んだコメントはできません
© 2008-10 A.K.I Software all rights reserved.