Pregunta

Estoy usando la anotación @Email para validar una dirección de correo electrónico. El problema que estoy teniendo es que está aceptando las cosas como ask@stackoverflow como una dirección válida de correo electrónico. Supongo que esto se debe a que quieren direcciones de apoyo de la intranet, pero me parece que no puede encontrar una bandera por lo que hace cheque por una extensión.

¿Es realmente necesario para cambiar a @Pattern (y cualquier recomendación para un patrón de correo electrónico que sea flexible) o me estoy perdiendo algo?

¿Fue útil?

Solución

En realidad, @Email de Hibernate Validator uses expresión regular internamente . Se puede definir fácilmente su propio restricción basada en esa expresión regular, modificado como sea necesario (véase la categoría + al final de 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
                    + ")$";
}

Otros consejos

También puede utilizar restricción composición como un trabajo en torno. En el siguiente ejemplo, que se basan en el validador @Email hacer la validación principal, y añadir un validador @Pattern para asegurarse de que la dirección está en la forma de x@y.z (No recomiendo usar sólo el @Pattern a continuación para la validación de correo electrónico regular)

@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 {};
}

En realidad validación de direcciones de correo electrónico es realmente compleja. No es posible validar que una dirección de correo electrónico es tanto sintácticamente correcta y direcciones del destinatario en una anotación. La anotación @Email es un cheque mínimo útil que no sufre el problema de los falsos negativos.

El siguiente paso en la validación debe enviar un e-mail con un reto que el usuario tiene que completar para establecer que el usuario tiene acceso a la dirección de correo electrónico.

Es mejor estar aceptar un par de falsos positivos en el paso 1 y permitir que algunas direcciones de correo electrónico no válidos para pasar a través de rechazar los usuarios válidos. Si desea aplicar reglas adicionales que puede añadir más controles, pero tenga mucho cuidado con lo que suponemos que es un requisito de una dirección válida de correo electrónico. Por ejemplo no hay nada en los RFC que dicta que i@nl no sería válida, porque nl es un dominio de nivel superior país de registro.

Aquí hay un validador de correo electrónico javax.validation usando Apache Commons Validador

public class CommonsEmailValidator implements ConstraintValidator<Email, String> {

    private static final boolean ALLOW_LOCAL = false;
    private EmailValidator realValidator = EmailValidator.getInstance(ALLOW_LOCAL);

    @Override
    public void initialize(Email email) {

    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if( s == null ) return true;
        return realValidator.isValid(s);
    }
}

Y la anotación:

@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();
    }
}

Obviamente estoy tarde a la fiesta, todavía estoy respondiendo a esta pregunta,

¿Por qué no puede usamos la anotación @Pattern con expresiones regulares en nuestra clase de validación como este

public Class Sigunup {

    @NotNull
    @NotEmpty
    @Pattern((regexp="[A-Za-z0-9._%-+]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}")
    private String email;

}

Es más fácil.

La solución de composición de restricción no funciona. Cuando el correo electrónico se utiliza en conjunción con el modelo, la expresión regular Email se mantiene en su mayor precedencia. Creo que esto es debido a que el correo electrónico de anotación anula algunos atributos del patrón, es decir, banderas y expresión regular (la clave aquí) Si quito @Email, sólo entonces se aplicará la expresión regular @Pattern en validaciones.

/**
 * @return an additional regular expression the annotated string must match. The default is any string ('.*')
 */
@OverridesAttribute(constraint = Pattern.class, name = "regexp") String regexp() default ".*";

/**
 * @return used in combination with {@link #regexp()} in order to specify a regular expression option
 */
@OverridesAttribute(constraint = Pattern.class, name = "flags") Pattern.Flag[] flags() default { };

Se puede utilizar el correo electrónico expresión regular, también debe asegurarse de que la validación no falla cuando el correo electrónico está vacía.

@Email(regexp = ".+@.+\\..+|")
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface ExtendedEmail {

  @OverridesAttribute(constraint = Email.class, name = "message")
  String message() default "{javax.validation.constraints.Email.message}";

  @OverridesAttribute(constraint = Email.class, name = "groups")
  Class<?>[] groups() default {};

  @OverridesAttribute(constraint = Email.class, name = "payload")
  Class<? extends Payload>[] payload() default {};
}
Añadir

Si va a probar la solución anterior https://stackoverflow.com/a/12515543/258544 la @ReportAsSingleViolation en el defination anotación, de esta manera se evita tanto mensaje de validación (uno de @Email y uno de @Pattern) ya que es una anotación compuesta:

    @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
    @ReportAsSingleViolation

De javax.validation @interface ReportAsSingleViolation: validación-api: 1.1.0.Final) definición anotación: " ... La evaluación de las limitaciones compuestos se detiene en la primera validación error en caso de que la restricción de la composición se anota con ReportAsSingleViolation "

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top