StrutsのEmailValidatorの挙動に注意

StrutsのEmailバリデータ(正確には、Apache Coomons Validator)を使っていたら、予想外の挙動にすこしびっくりしました。

前後に空白が入ってもいい

 test@example.com

これは、最初に空白が入っていますが、有効と判定されます。

コメントが入ってもいい

(COMMENT)test@example.com

この入力も、有効と判定されます。
メールアドレス中の括弧はコメントなので空白と扱われるためです(そして、「前後に空白が入ってもいい」なので、前後にコメントを入れるのは有効)。

これはRFC5322の3.2.2に沿った動きなんですが・・・これが有効なのはちょっと困ります。
なぜなら、この文字列全体が「メールアドレス」ではないから*1
そのため、入力された値がメールアドレスのみだと思って処理をしているとバグの原因になります。


もし、メールアドレス部分だけ取りだしたり、チェックしたりするのならば、JavaMail の InternetAddressを使うといいかもしれません。

String input = "(COMMENT) test@example.com";
InternetAddress ia = new InternetAddress(input);

// メールアドレスのみ取得
System.out.println(ia.getAddress());  // test@example.com

// メールアドレスのみ入力されているか判定
System.out.println(ia.getAddress().equals(input));  // false

ドメインのレベルを深くすると例外が発生

test@example.com.com.com.com.com.com.com.com.com.com

この入力によって、例外(ArrayIndexOutOfBoundsException)を出します。
プログラム内部で、ドメインを分割するときの配列が10固定になっているので、それ以上の入力があるとバグってしまいます。
ちなみに、このアドレス自体は(フォーマットとして)有効です((こんなにドメインを深くすることはあまりないと思いますが…))。


この影響で、本来ははじいているはずのアドレスが通ってしまうことがあります。

test@example.com.com.com.com.com.com.com.com.com.a-z

Emailバリデータは「TLDトップレベルドメイン)はアルファベットのみが有効」というチェックをしているため、本来は「無効」です。
ただ、例外がその手前で発生するので、無効ではない -> 処理続行となります。


バグ一覧で確認したら、もう登録されていました。
これによると、「新しいバージョンで直したから、そちらを試してみて」とのこと。
[VALIDATOR-220] EmailValidator fails with ArrayIndexOutOfBoundsException on domain names longer than 10 segments - ASF JIRA

でも、その新しいバージョンであるv1.4は、Snapshot版しかないです*2
仕事に使うには不安が・・・。
しょうがないので、自分でEmailValidatorを呼ぶようにして、例外をキャッチしたらバリデートエラーになるようにしました。

*1:メールアドレスは、test@example.com の部分のみ

*2:その前のv1.3.1が出たのが4年前なので、休止状態?