7
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

Hibernate Validator の @Email を使ってはいけない?

有名な話だったらゴメンよ!

Hibernate Validator 先生はめっちゃ便利なわけですが、ある日こんなことが。

「おい! hoge@+gmail.com とか入力されてメール送信系が例外吐いてんぞ! 誰だバリデーションしてねえ馬鹿は!?」

まずそんな馬鹿な作りにしたやつは誰だ。
この時、Hibernate Validator のバージョンは 5.2.2 Final でした。なんで最新じゃないのかって? 知るもんかい。

なお何ら問題なくバリデーションされていた模様

どこを見ても @Validated は付いています。あれ? と思って hoge@!@#$%^&()_+ とかやると……引っかかる。動いてるよなー。
ってことはこいつドメイン部の+通しちまうんじゃねえか!!

なお最新版

5.2.2 で存在した EmailValidator は 最新版 (2018/01/17) では @Deprecated 。では現行はどうなんでしょう?
https://github.com/hibernate/hibernate-validator/blob/7c0afb18cc83aab5e73827a6659af23970dd26f5/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/EmailValidator.java
ありゃ、見当たらない。Abstract の方でしょうか。

DomainNameUtil.isValidEmailDomainAddress( domainPart );

ほうほう、DomainNameUtil 。

private static final String DOMAIN_CHARS_WITHOUT_DASH = "[a-z\u0080-\uFFFF0-9!#$%&'*+/=?^_`{|}~]";
private static final String DOMAIN_LABEL = "(" + DOMAIN_CHARS_WITHOUT_DASH + "-*)*" + DOMAIN_CHARS_WITHOUT_DASH + "+";
private static final String DOMAIN = DOMAIN_LABEL + "+(\\." + DOMAIN_LABEL + "+)*";

デデドン!!(絶望)
……これは参ったなあ。ドメインは RFC1035 ベースで見たほうがいいんじゃないの?って Issue を書くべきかしら。

じゃあ何使えばいいのよ?

Apache commons-validator が割といいらしいっすよ1
……もっとも、日本語アドレス (Gmailとかは対応してるらしい) みたいなキワモノまで使えるかは試してませんが。

commons-validator ってアノテーションでついてたっけ?

ついてません。さくっとこんな感じで書きませう。


@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE,  ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {CommonsEmailValidator.class})
@Documented
@ReportAsSingleViolation
public @interface Email {

    String message() default "{org.hibernate.validator.constraints.Email.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        Email[] value();
    }
}

public class CommonsEmailValidator implements ConstraintValidator<Email, String> {

    @Override
    public void initialize(Email email) {
        // nothing to do
    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if( s == null || s.isEmpty() ) return true;
        return EmailValidator.getInstance(false).isValid(s);
    }
}

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
7
Help us understand the problem. What are the problem?