: O. Yuanying

Rails3 のメール受信で文字化けしちゃう件

Wikipedia での「文字化け」の項

実は 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 で表示したい場合は二つ方法があって、

  1. kconv を使う
  2. mail-ruby にモンキーパッチを当てる

という二つの方法がある。

kconv を使う

この場合は簡単で、表示したい時に、

require 'kconv'
puts mail.subject.toutf8

ってやればおk。 けど文字コードの判定に失敗した場合文字化けする。

mail-ruby にモンキーパッチを当てる

パッチはこんなの。

このファイルを mail ライブラリを利用した際に読み込んでやれば良い。

出力する際の文字コードを変更したい場合は Ruby18.force_encode_to_default を変更してやればおk。

まあ、どっちも気持ち悪いけどね。