ROUTE 3390

備忘録的な用途で書いていますが、どなたかの役に立つ事があれば嬉しいです。

メール送信でタイトルが化ける原因

漢字や中国語のようなマルチバイトを含むメールを送信するときにハマったので記録。

文字コードはとーぜんutf8だしょ。 という事でヘッダに「text/plain; charset=utf-8」を指定。
メール本文もutf8で記述したものをセットした。
タイトルも同じくutf8で記述したものをセットした。

でも化けた。
タイトルだけ化けた。

なぜか?
タイトル(Subject)はヘッダなのだ。


ヘッダで「このメールはutf8だぜ」って指定している。
そのため本文は化けない。
しかし、同じくヘッダであるSubjectはutf8とは言われていない。

更にいうとメールのヘッダに8ビット文字は使用出来ない。
使えるのは7ビット文字だ。


どうすればいいか?
Subjectにも「これはutf8だぜ」って指定すればいい。
メールの規則によればこうなる。

=?utf-8?タイトル?=

これをSubjectに入れてあげると「タイトル」って文字はutf8だぜ って認識してくれる。


でもこれだけではダメ。ちらっと書いたけれど
使えるのは7ビット文字だ。
という事はBASE64エンコードする必要がある。
「タイトル」はBASE64エンコードすると「44K/44Kk44OI44Or」になる。
で、こうやって書いてSubjectにセットする。

=?utf-8?B?44K/44Kk44OI44Or?=

B?って書いてあげると「この文字列はBASE64エンコードされてるんだぜ」って意味になる。

ヘッダにこう書かれていると、メールを受け取ったメーラーは
こうやって解釈する。
「44K/44Kk44OI44Or って文字列はBASE64デコードしてくれよな。
 あと、こいつはutf8で書かれているからよっ よろしくな」


この仕組みを分かっていなかった僕はハマった。


PerlだとEncode.pmがとても便利。

use utf8;
use Encode;

my $subject = encode('MIME-Header', 'タイトル');

これで$subjectには「=?utf8?B?44K/44Kk44OI44Or?=」が格納されている。

ちなみに、このヘッダへの文字コード指定やBASE64指定はSubjectに限った事ではなく、FromやToなど他のヘッダにも使用出来る。

よくアドレスに日本語の名前が付いていたりするのは、こういうヘッダにしているからだった。

utf8ではなくjisコードを指定したい場合は=?iso-2022-jp?B? という感じになるみたい。(試してないです)