検索してもまったく情報出てこなかったので、需要があると信じて。
なにが起きたか
JavaMail 1.6.2以上で、特殊なメールアドレス(2連続のドット「..」が使用されていたり、@マークの直前でドット「.@」を設定しているメールアドレス)に対するバリデーションが追加されており、この条件のメールアドレスにメール送信しようとすると必ずAddressExceptionが発生する。
(1.6.4からはJakarta Mailと名前が変わってますが、この記事では古い名称のJavaMailで呼ぶことにします。)
わたしはSpring Bootの2.1系でspring-boot-starter-mailを使った際に、JavaMail 1.6.4が使われていて、この例外に遭遇しました。
参考
問題になるメールアドレスの説明はこちら。
- ドコモさんの特殊な形式のアドレス(RFC違反アドレス)のご利用について
- メールアドレスの例は、
hoge.@docomo.ne.jp
など。
回避策
ワークアラウンドとして、考えられる案は次の通り。
- JavaMail 1.6.1以下を使う
- ほかのライブラリをさがす(ただ、わたしは候補見つけられていません)
- JavaのアプリでSMTPでメール送信を行わず、メール送信処理をAPI経由で実現する
- クラウドサービスで使えるところはないか探す、あるいは自前で作る。自前の場合はAPI経由ではなく、Shared Databaseで連携してもよい。
他に考えられる対応
- そもそも新規サービスなら、登録時にRFC違反のメールアドレスをバリデーションエラーにする。
- その際はどのルールに引っかかっているか説明し、メールアドレスの変更までお願いできるととてもよい。
- 昔からあるサービスで、すでに特殊なメールアドレスでの登録がある場合は、メールアドレスのお願いをしてみる(ただし、効果はないかもしれない)
JavaMailのコードの説明
2018年に加えられた変更で、JavaMailのInternetAddressクラスのバリデーションが厳しくなった。
このクラスはJavaMailでメールアドレスを表現するバリューオブジェクトらしい。
JavaMail 1.6.2 のコードを見てみると、本事象に関係するのはバリデーションをかけてる箇所のうち、特にこのあたりやここ 。
本件が関係していると、例外のメッセージとしては、"Local address contains dot-dot"や
"Local address ends with dot"あたりが出てくると思われる。
このバリデーションは、checkAddressメソッドのvalidate引数(なお、バージョン1.6.3以降では、strict引数)に関係なくバリデーションがかかる。そのため、無効化したり、回避する方法がないように見える。つまり、メソッドレベルで無理なので、設定でも回避できなさそうに思われる。
そのため、とりあえず回避するなら、このバリデーションが実装されてないバージョンである1.6.1に下げるか、JavaMailを使わないという選択肢になると考えられる。
余談ですが、JavaMailは1.6.3より Eclipse EE4J Projectに移管されており、1.6.4より名称もJakarta Mail と変わっています