Rails3 のメール受信で文字化けしちゃう件
実は Rails3 はあんまり関係なくて、 Rails3 で受信したメールを解析する際にデフォルトで利用できる、 mail-ruby ライブラリの話。 あ、環境は、
- Ruby 1.8.7
- mail-ruby 2.2.17
ね。
現在の TODO に、
- Improve MIME support for character sets in headers, currently works, mostly, needs refinement.
ってあるからそのうち改善されるのかもしれないけど、 とりあえず現状、 Ruby 1.8.7 で mail-ruby ライブラリを使って受信したメールを解析する際に文字化けのリスクがある。
というのも受信したメールの文字コードの情報が mail-ruby を利用してメールを解析してる間にロストしてしまうため、 UTF-8 の文字コードでメールのタイトルを表示したい!と思っても 解析対象のメールの文字コードがわからないのでUTF-8に変換しようがない。
例えば、文字コードが iso-2022-jp でエンコードされたタイトルを表示したくても、
mail = Mail.read_from_string(<<-EOM)
Sender: Yuanying <xxxx@example.com>
Subject: =?iso-2022-jp?B?GyRCJUYlOSVIGyhC?=
Date: Wed, 15 Dec 2010 15:18:41 +0900
To: "O. Yuanying" <xxxx@example.com>
aaaaaaa
EOM
puts mail.header['Subject'].charset # -> UTF-8
puts mail.subject # -> B%F%9%H
とかなってしまう。どう考えても UTF-8 じゃないのに charset が UTF-8 とか。 ソースを読んでみるとヘッダに入ってる 'iso-2022-jp' はどっかに捨ててるんですよね。
これが Ruby 1.9 系だった場合、文字列に文字コードの情報が含まれてるので、 解析対象のメールがどんな文字コードでエンコードされてようが、 UTF-8 で出力したい場合は、
puts mail.subject.encode('UTF-8')
でおk。
んで、Ruby 1.8 系でどうにか解析したメールを UTF-8 で表示したい場合は二つ方法があって、
- kconv を使う
- mail-ruby にモンキーパッチを当てる
という二つの方法がある。
kconv を使う
この場合は簡単で、表示したい時に、
require 'kconv'
puts mail.subject.toutf8
ってやればおk。 けど文字コードの判定に失敗した場合文字化けする。
mail-ruby にモンキーパッチを当てる
パッチはこんなの。
このファイルを mail ライブラリを利用した際に読み込んでやれば良い。
出力する際の文字コードを変更したい場合は Ruby18.force_encode_to_default
を変更してやればおk。
まあ、どっちも気持ち悪いけどね。