GAE/Jでメーリングリスト・メールマガジン実装

 文芸の記事だけになりそうなので、少しはプログラミングのトピックも書こうと思う。
 前にも少し書いたけれど、いまGAE/Jの環境を使ったサイトをいくつか管理している。
 サークルぐらいの規模の集団が相手で、携帯電話(いわゆるガラケー)での利用者がかなり多い。
 そんなガラパゴス諸島で、GAE/Jのメールを使った暮らしについて書こうと思う。

携帯のメールアドレスはRFCに準拠していない場合がある

 サイトでメールマガジン機能を公開して初めて明らかになった問題。
 ピリオドが2つ連続していたり、アットマークの直前にピリオドがあったりするメールアドレスは、実はRFCに準拠していない不正なアドレスだ。不正なアドレスなので、JavaのInternetAddressオブジェクトに変換しようとすると、AddressExceptionが発生する。
 これは、メール送受信のどちらでも問題となる。
 GAE/JではJavaMailのMimeMessageを使ってメールを解析できるが、そこでgetFromを何となく使うと、いきなり落ちて慌てたりする。
 解決策としては、MimeMessageのgetHeaderの方で"From"を指定して文字列として取り出せば、Addressオブジェクトに変換しないので落ちたりしない。
 また、DatastoreのEmailクラスではわざわざRFC準拠のチェックなどしていないようなので、不正なアドレスの文字列をそのままEmailに変換してDatastoreに入れても問題なかった。
 GAE/Jではメール受信がHTTPリクエストの形に変換され、リクエストボディに丸ごとメール内容(きっとMIME形式)が入っているので、MimeMessageを介さずに自力解読するという手もあるだろう。ガラケーの事を考えると、案外それが現実的な解なのかもしれない(涙)。
 で、DatastoreのEmailに変換してDatastoreに格納して安心した矢先、今度は送信時にもAddressExceptionが発生して衝撃を受ける
 MimeMessageのsetRecipients(String引数バージョン)を使ってもダメだし、Transportの方で送信先を指定しても引数Addressだし、InternetAddressが悪いんじゃーと独自にAddress派生クラスを作ってみてもTransport内部で例外発生してダメだった。
 かなり困ったが、GoogleのEmailではエラーが起きなかった事を思い出し、LowLevel-API(com.google.appengine.api.mail)を直接使ってみたらうまくいった。
 困ったときはLowLevel。ヘンな抽象レイヤーのある環境(某窓会社とか)では共通の合言葉だと思う。
 あと、試していないけれど、ローカルパート(アドレスのユーザー名部分)をダブルクオートで囲めばJavaMailでも大丈夫かもしれない。
 この問題、そもそも携帯のアドレスにRFC準拠でないものを設定できてしまっていたのが原因だ。
 携帯キャリアも問題に気づいているらしく、今は制限を掛けているらしい。しかし、メールアドレスなんて変えないで済むならみんな変えないわけで、ずっと同じ変なアドレスを使っている人はけっこうな数が存在するだろう。

課金なしでは、一度の送信で最大8人まで

 これもサークル向けサイトで公開して初めてわかった。課金を有効にすると、一度に何千人だか同時送信できるようだ。
 課金しても無料分のリソースを使い切らない限りタダのままなので、9人以上同時に送る場合は課金しても良いと思う。
 TaskQueueとかで超頑張ればなんとかなるとは思うけど……。