Hibernate validator: @Email accepts ask@stackoverflow as valid?

You can also use constraint composition as a work-around. In the example below, I rely on the @Email validator to do the main validation, and add a @Pattern validator to make sure the address is in the form of [email protected] (I don't recommend using just the @Pattern below for regular Email validation)

@Email(message="Please provide a valid email address")
@Pattern(regexp=".+@.+\\..+", message="Please provide a valid email address")
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface ExtendedEmailValidator {
    String message() default "Please provide a valid email address";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Actually, @Email from Hibernate Validator uses regexp internally. You can easily define your own constraint based on that regexp, modified as you need (note the + at the end of DOMAIN):

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@Pattern(regexp = Constants.PATTERN, flags = Pattern.Flag.CASE_INSENSITIVE)
public @interface EmailWithTld {
    String message() default "Wrong email";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default { };
}

interface Constants {
    static final String ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~-]";
    static final String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)+";
    static final String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]";

    static final String PATTERN =
            "^" + ATOM + "+(\\." + ATOM + "+)*@"
                    + DOMAIN
                    + "|"
                    + IP_DOMAIN
                    + ")$";
}

Actually validating e-mail addresses is really complex. It is not possible to validate that an e-mail address is both syntactically correct and addresses the intended recipient in an annotation. The @Email annotation is a useful minimal check that doesn't suffer from the problem of false negatives.

The next step in validation should be sending an e-mail with a challenge that the user has to complete to establish that the user has access to the e-mail address.

It is better to be accept a few false positives in step 1 and allow some invalid e-mail addresses to pass through than to reject valid users. If you want to apply additional rules you can add more checks, but be really careful about what you assume to be a requirement of a valid e-mail address. For instance there is nothing in the RFCs that dictates that i@nl would be invalid, because nl is a registered country top-level domain.