Javaでメールを扱うライブラリとしてJavaMailが有名ですが、設計が古いため、使いにくかったり、いろいろと罠が潜んでいます。その中で自分が痛い目にあったこと、痛い目にあいそうなことを書いておきます(つД`)ノ
はじめに
- この記事を書いた時のJavaMailの最新版は1.5.4です。
- 必ずAPI documentationを読みましょう。動くからとメソッドの意味も分からずに使ってると後で泣きます。
Sessionを取得する方法
javax.mail.Session#getDefaultInstance()を使う例がよく載っていますが、これは避けたほうがいいです。
- javax.mail.Session#getDefaultInstance(Property props)
- javax.mail.Session#getDefaultInstance(Property props, Authenticator authenticator)
このprops引数には以下のように書かれています。つまり、同じメソッドを違うプロパティを引数として呼ぶと、2度目は無視され、意図しない挙動になります。
props - Properties object. Used only if a new Session object is created.
対処方法としては、getDefaultInstanceの代わりにgetInstanceを使いましょう。こちらは新しいオブジェクトを返すので安全です。
- javax.mail.Session#getInstance(Property props)
- javax.mail.Session#getInstance(Property props, Authenticator authenticator)
Returns:
a new Session object
デバッグ情報を出力する方法
デバッグ情報を出力する方法は以下の2種類です。mail.debugの設定はSession作成時のデフォルト、setDebugはSessionごとに設定するメソッドです。
- プロパティの"mail.debug"を"true"にする(javax.mailパッケージの説明より)
- javax.mail.Session#setDebug(boolean debug)
ネットを検索すると「"mail.smtp.debug"を"true"にする」という情報が見つかりますが、com.sun.mail.smtpパッケージの説明にはありません。以前はあったのか、そもそも間違いなのか分かりませんが、設定しても何も起きません(´・ω・`)
送信時のエラー取得
JavaMailでは多数の例外が定義されていますが、全てMessagingExceptionのサブクラスとして定義されています。そのため、以下のようにMessagingExceptionをcatchするだけで、通常は事足ります。
try {
Transport.send(msg);
} catch(MessagingException e) {
...
}
しかし、メールを送信する場合は別です。javax.mail.Transport#send(Message msg)などでメールを送信しますが、このメソッドはSendFailedExceptionという例外も発生します。
Throws:
SendFailedException - if the message could not be sent to some or any of the recipients.
MessagingException - for other failures
このSendFailedExceptionは、送信に成功したアドレス、失敗したアドレスの情報が取得できます。以下のように書くことで、複数人に同時に送ったときに、一部だけ失敗した場合の対処が可能です。ただし、nullを返す場合があるので注意してください。
try {
Transport.send(msg);
} catch(SendFailedException e) {
// 現在なら当然List<Address>を返すべき
Address[] sentAddresses = e.getValidSentAddresses();
Address[] invalidAddresses = e.getInvalidAddresses();
Address[] unsentAddresses = e.getValidUnsentAddresses();
...
// FIXME: nullチェックしないとダメ!
for(Address : unsentAddresses)
{
...
}
} catch(MessagingException e) {
...
}