MIMEヘッダエンコーディングは複雑すぎてつらい

2021-06-22

とみたまさひろ

別にしらなくてもいい
役に立つか立たないかわからない
技術について語るコーナー

MIMEヘッダエンコーディング

メールのヘッダでよく見る
=?ISO-2022-JP?B?GyRCRnxLXDhsGyhC?=
みたいなやつ

RFC 2047

Message Header Extensions for Non-ASCII Text
https://tools.ietf.org/html/rfc2047

メールのヘッダは ASCII のみ
ASCII以外の文字列をヘッダに書けるようにするために作られた規格

Bエンコーディング:

=?[文字コード]?B?[Base64化されたデータ]?=

Qエンコーディング:

=?[文字コード]?Q?[そのまま書けない文字を=XXに変換したデータ]?=

「日本語ABC」を変換すると:

=?ISO-2022-JP?B?GyRCRnxLXDhsGyhCQUJD?=
=?ISO-2022-JP?Q?=1B$BF|K\8l=1B(BABC?=
=?UTF-8?B?5pel5pys6KqeQUJD?=
=?UTF-8?Q?=E6=97=A5=E6=9C=AC=E8=AA=9EABC?=

エンコードのつらみ

Bエンコーディングは基本的には文字列をBase64化して前後に文字列をつけるだけ

日本語5pel5pys6Kqe=?UTF-8?B?5pel5pys6Kqe?=

つらくない

Subject: MIMEヘッダエンコーディングは複雑すぎてつらい

Subject: =?UTF-8?B?TUlNReODmOODg+ODgOOCqOODs+OCs+ODvOODh+OCo+ODs+OCsOOBr+ikh+mbkeOBmeOBjuOBpuOBpOOCieOBhA==?=

長い…

メールのヘッダだから折り返しちゃえ!

Subject: =?UTF-8?B?TUlNReODmOODg+ODgOOCqOODs+OCs+ODvOODh+OCo+ODs+OCsOOBr+ik
 h+mbkeOBmeOBjuOBpuOBpOOCieOBhA==?=

ダメ

折り返せるのは空白文字の箇所だけ

複数のエンコーディング文字列に分割する

Subject: =?UTF-8?B?TUlNReODmOODg+ODgOOCqOODs+OCs+ODvOODh+OCo+ODs+OCsOOBr+ik?=
 =?UTF-8?B?h+mbkeOBmeOBjuOBpuOBpOOCieOBhA==?=

エンコーディング文字列間の空白は取り除かれる仕様
だからよさそう

でも実はこれでもダメ

文字を分割しちゃダメ

=?UTF-8?B?TUlNReODmOODg+ODgOOCqOODs+OCs+ODvOODh+OCo+ODs+OCsOOBr+ik?=
→ MIMEヘッダエンコーディングは<E8><A4>

=?UTF-8?B?h+mbkeOBmeOBjuOBpuOBpOOCieOBhA==?=
→ <87>雑すぎてつらい

「複」(E8 A4 87) が分割されてしまっている

文字単位で処理しないといけない

=?UTF-8?B?TUlNReODmOODg+ODgOOCqOODs+OCs+ODvOODh+OCo+ODs+OCsOOBr+==?=
→ MIMEヘッダエンコーディングは

=?UTF-8?B?6KSH6ZuR44GZ44GO44Gm44Gk44KJ44GE?=
→ 複雑すぎてつらい

さらに
ISO-2022-JP のような状態を持つ文字コードの場合は ASCII で終了しないといけない

日本語ABCあいう

→ <ESC>$BF|K\8l<ESC>(BABC<ESC>$B$"$$$&<ESC>(B

<ESC>$B : JIS X 0208

<ESC>(B : US-ASCII 

これは OK

<ESC>$BF|K\8l<ESC>(BABC⏎    日本語ABC
<ESC>$B$"$$$&<ESC>(B        あいう

これはNG

<ESC>$BF|K\8l<ESC>(BABC<ESC>$B$"⏎  日本語ABCあ
$$$&<ESC>(B                        いう

やるならエンコーディング文字列の最後にASCIIに戻す

<ESC>$BF|K\8l<ESC>(BABC<ESC>$B$"<ESC>(B⏎  日本語ABCあ
<ESC>$B$$$&<ESC>(B                        いう

デコードのつらみ

文字が分割されている

=?UTF-8?B?44GC44GE44GG44GI44E=?=⏎       あいうえ<E3><81>
=?UTF-8?B?iuOBi+OBjeOBj+OBkeOBkw==?=    <8A>かきくけこ
↓
あいうえ???かきくけこ

エンコーディング文字列がつながってる

=?UTF-8?B?44GC44GE44GG44GI44GK?==?UTF-8?B?44GL44GN44GP44GR44GT?=

本当はデコードしちゃダメ

"」で括られている

"=?UTF-8?B?44GC44GE44GG44GI44GK?="

添付ファイル名とかでよく見る
本当はデコードしちゃダメ

ISO-2022-JP と書かれてるのに
ISO-2022-JP に無い文字が含まれている

「ア」「①」「Ⅲ」「㍻」「髙」など

本当はダメなんだけど普通に使われてる

ISO-2022-JP じゃなくて CP50221 として扱う

つらい 😇