まず、今回の目的なのだが、メール配信を行った際のバウンスメールのクリーニングを行いたいということだ。
パッと思いついた方法は、
@.返信されたfailure noticeメールの内容を解析。
A.送信前に指定アドレスが存在するか確認。
だった。で、そこから調査。
まず、@のfailure noticeの解析だけど非常に困難だ。人間が見る分には分かるのだが、プログラムで解析するためにはどうしても法則がないと難しい。フォーマットもMTAによって違うみたいだし諦めた。(Mailmanというものでどうにかなりそうな気もしたけどやめた。)
次にAの方法だけど、SMTPコマンドにVRFYというメールアドレスの確認ができるものがあったのだが、ほとんどのMTAで利用できないように設定されているのが現状らしい。
まあ、スパムが蔓延しているこの世の中では仕方がないのだろう。やだやだ。
で、両方が挫折して困ったときに見つけたのがVERPというものだ。
まず、VERPとは
自ホストがmy.co.jpだとして、
hogehoge@example.jp へメールを送信する際に、
bounce+hogehoge=example.jp@my.co.jp をEnvelope Fromに設定する。
そうすると、bounceに返ってきたメールアドレスをパースすれば良いからエラーになったアドレスの特定が簡単だよ。
という仕組み。
でも、ここで疑問を感じた。
それはメールアドレス長のこと。
軽く調査したところ、『RFC 2821 SMTP』というもので定義されており、
ユーザ名は64文字まで、ドメイン名は255文字まで、ユーザー名+ドメインなどを含めた全体は256文字までらしい。
もし、送信先のアドレスのが64文字以上だった場合は、Envelope Fromに設定するアドレスはオーバーするじゃん。
大丈夫なのか〜?
でもVERPは浸透している手法だと思うし、自分が思いつくようなことは当然分かってるよな〜。
と思いつつも、面倒なので調査も実験もしていない。いつかやってみよう。
で、今回採用した手法は、メッセージIDを利用する方法だ。だから、VERPもどきと呼んでいる。
ちなみにメッセージIDとは、
一つのメールに付加されるメッセージID は全世界で唯一のものであり、他のいかなるメールとも重複しないというもの。
自分の環境では、22885256.01222947793984.JavaMail.hogehoge.XXX-D-200という形式だった。
これならば、送信する環境のユーザー名やホスト名の調整にて64文字オーバーの心配はなくなると目論んでいる。
簡単な流れは、
@.送信する際のメッセージIDを取得、これをキーに送信先アドレスを記録。
A.Envelope Fromのユーザー部分には、メッセージIDを登録。
B.バウンスメールが帰って来た際は、ユーザー部をキーにエラーアドレスを特定。
ということ。
これで送信先のMTAがエラーを通知してくれれば、どのアドレスか特定が出来て、クリーニングが行える。
送信時に@、Aの処理を行う、Mailetと、
ローカルに配信されたメールがVERPもどきか判定するMatcherと、
パースを行うMailetという3つのクラスを作成した。
一応、目的は達成!!
でも、1つ気に入らないことがあって、VERP形式で送信するとどうしても1件ずつの配信にせざるを得ない。
例えばメーラーで複数に一斉配信しても、MTAでは実質1件ずつ送ってる。
仕方のないことなのかもしれないけど、これってどうなんだろ。。。
調査してみたけど、解決策は見つからなかった。今後の課題です。