GNU-JavaMailでメールを送ると件名が文字化けする
メール送信機能をJavaで実装したところ、なぜか件名が文字化けするという問題にぶち当たりました。
しかも、不思議なことにWindowsからだと大丈夫なのに、Linuxからだと化ける・・・。
最初は文字コード指定を間違えたと思っていろいろ確認したんですが、特に問題なし。
message.setSubject("メール送信テスト","ISO-2022-JP");
いろいろ調べてわかったこと。
原因は、RedHat LinuxにインストールされているJavaMailでした。
てっきり JavaMail って Sun がリリースしている奴が使われていると思っていたんですが、RedHat に標準で入っているのは GNU ライセンスによる互換実装のもの(classpathx-javamail)でした。
Sun の JavaMail -> Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle
GNU の JavaMail -> GNU JavaMail - GNU Project - Free Software Foundation (FSF)
そして、このGNU版のソースを確認したところ、こんな処理が入ってました。
private static String encodeWord(String text, String charset, String encoding, boolean word) throws UnsupportedEncodingException{ if (asciiStatus(text.getBytes()) == ALL_ASCII){ return text; }
(この処理は、javax/mail/internet/MimeUtility.javaの391〜398行目)
すべての文字が ASCII ならば、エンコードせずにそのままの値を返しています。
しかし、Linux 上のデフォルトエンコードは「ISO-8859-1(ラテンアルファベット)」なので、このように引数なしで getBytes をすると、日本語が解釈不明で「?」に化けてしまい、常にエンコードされません。
つまり、完全に GNU-JavaMail のバグが原因でした。
しかも、このメソッドは private なので回避不能・・・。
どうしよう・・・
/var/lib/Tomcat5/common/lib/[javamail].jar を入れ替えれば問題は解決しますが・・・。
運用の方から、「いじってもいいけど rpm パッケージ単位で」と言われてしまいました。
作戦1:Sun 公式の JavaMail に置き換える
というわけで、さっそく rpm を入れ替えようとしましたが、すでに入っている GNU-JavaMail は Tomcat などに依存関係があるため消せない。
しかも、JavaMail の rpm はあるけど*1、一緒に必要な JavaBeans Activation Framework(JAF) が見つからない*2。
作戦2:WARファイルの /WEB-INF/lib に Sun 公式の mail.jar を入れる
消すのをあきらめて、優先順位の高いクラスパスに直接 jar を入れてみる*3。
ところが、これだと NoClassDefFoundError。
どうやら、JavaMail の jar が tomcat5/common/lib と /WEB-INF/lib の両方にあると、両方とも認識しないらしい。
結局・・・
1週間粘って解決のめど立たず(−−;)
なにかいい方法をご存知の方、ぜひ教えてください・・・
*2:Java6には標準で入っているから? でも、Red HatにはGNUのJAFが入ってしまっているので、Sun-JavaMailを使うならSun-JAFがないと、組み合わせがまずそう…
*3:Servlet の仕様で、Webアプリケーションごとのライブラリ(/WEB-INF/lib 配下)が優先されるようになっている。ただし、今回の JavaMail のように javax.* のパッケージの場合は common が優先されるから、意味ない・・・。 参考:http://www.jajakarta.org/tomcat/tomcat5.0/ja/docs/tomcat-docs/class-loader-howto.html