JavaMailの文字化け解決法
今回は以前JavaでWebアプリケーションを開発した際に遭遇したJavaMailに関しての対応策とその原因の調査結果を書きます。 対策は簡単だったのですが、原因は調査するにつれ込み入った話であることが分かりました。
Javaの関連記事:
- OutOfMemoryError回避のためのJavaコーディング – 前編
- OutOfMemoryErrorの原因と対応(3)
- 自力でNoClassDefFoundErrorを解決!(前半)
- ArrayListをスレッドセーフ化するには?
- SimpleDateFormatのマルチスレッド問題
メールの本文の最後に「?」や「w)w)」が入ってしまった
遭遇した問題というのは、JavaMailでメールを送信したところ、本文の最後に「?」や「w)w)」が入ってしまうというものでした。メーラーによって「?」か「w)w)」が入ってしまうのです。 環境はJ2SDK1.4.2_16でJavaMailのバージョン1.4を使用しました。
私が確認した限りでは、本文が日本語である場合、Thunderbirdでは「?」、Microsoft Outlookでは「w)w)」が文末に入ってしまうようでした。また、半角英字のみの場合この現象は起きませんでした。自分の普段使っているBeckyというメーラーではこの問題は発生しなかったのですが、ThunderbirdとMicrosoft Outlookで問題が起きているので対策を取るべく調査をしました。
下の画像は件名を「テストメール」、本文を「テストメールです」としてWebアプリケーションから送信したメールをThunderbirdで受信した際のスクリーンショットです。赤く囲った部分に入力していない「?」が入ってしまっています。
対処法
対処法はいたって単純です。本文の最後に改行コード(CRLF)、半角英数字、半角スペースのいずれかを入れることでこの現象を防ぐことが出来ます。
原因追求
原因を色々調べてみたところ、いくつか同様の件に関する報告を見つけることが出来ました。どうやら、原因として以下の3点が考えられるようです。
- 送信しようとしたメールの本文の形式がRFCの規約に違反している。
- JavaMailのバージョンの問題である。
- JavaのISO-2022-JPのエンコーダーに問題がある。
1つ目の「送信しようとしたメールの本文の形式がRFCの規約に違反している」という場合ですが、形式といえばRFC、ということでRFCの2821(Simple Mail Transfer Protocol)や2822(Internet Message Format)を読んでみました。
本文に関する規約として、メッセージ中の各行がCRLFを除いて998文字でなければいけないとか、CRとLFはCRLFとして使用されなければならないといった記述は見つけられました。しかし、本文であるメッセージボディの最後が改行コードでなければならないとか、最後は半角文字でなければならないといった記述は特に見当たりませんでした。また、JavaMailのAPIにも目を通してみたのですが、同様に本文に関しての規定は見当たりませんでした。
2つ目に「JavaMailのバージョンの問題である」という場合ですが、1.2.0から現状最新である1.4.1までの8つのバージョンのmail.jarでメールを送信してみたところ、全て同じ現象が起きました。どうやらmail.jarのバージョンの問題ではないようです。
3つ目の「JavaのISO-2022-JPのエンコーダーに問題がある」という場合ですが、2004年にSun MicrosystemsのBug DatabaseにJavaのISO-2022-JPのエンコーダーの問題が登録されていました。これによると末尾にエスケープシーケンスが挿入されないとのことです。JDK1.3から1.4に移行するとJavaMailで問題が起きるという報告もあることからJavaのISO-2022-JPのエンコーダーのバグであるという可能性は高そうです。
結局、先輩にもらったクラスを利用することで私はこの問題に対処しました。Windows-31Jを経由してISO-2022-JPに変換するクラスです。直接変換するのではなく、別の文字コードを経由することで問題が起きなくなるケースはよくあるとのことでした。
今回は満足の行く対処をすることが出来ました。調査の過程でも、RFCを読んだり、Bug Databaseを見たりと色々と勉強になり、良い経験だったのではではないかと思います。文字化けは多くのプログラマーを悩ませる問題ですが、遭遇した際は一度別の文字コードを経由するというアプローチを試してみるのも良さそうです。
参考サイト:
RFC 2821 Simple Mail Transfer Protocol
RFC 2822 Internet Message Format
Sun Microsystems Bug Database
@IT – j2sdkのバージョンアップに伴うjavamaiでの問題
Javaの関連記事: