¿Cuál es el mejor método de validación de direcciones de correo electrónico de Java?

¿Cuáles son las buenas bibliotecas de validación de direcciones de correo electrónico para Java? ¿Hay alguna alternativa al validador de los comunes ?

Apache Commons es generalmente conocido como un proyecto sólido. Sin embargo, tenga en cuenta que deberá enviar un correo electrónico de verificación a la dirección si desea asegurarse de que se trate de un correo electrónico real y de que el propietario desea que se use en su sitio.

EDITAR : Hubo un error en el que era demasiado restrictivo en el dominio, lo que provocaba que no aceptara correos electrónicos válidos de nuevos TLD.

Este error se resolvió el 03 / Jan / 15 02:48 en la versión 1.4.1 del validador común

Usar el paquete oficial de correo electrónico de Java es el más fácil:

 public static boolean isValidEmailAddress(String email) { boolean result = true; try { InternetAddress emailAddr = new InternetAddress(email); emailAddr.validate(); } catch (AddressException ex) { result = false; } return result; } 

El validador de Apache Commons se puede usar como se menciona en las otras respuestas.

pom.xml:

  commons-validator commons-validator 1.4.1  

build.gradle:

 compile 'commons-validator:commons-validator:1.4.1' 

La importación:

 import org.apache.commons.validator.routines.EmailValidator; 

El código:

 String email = "myName@example.com"; boolean valid = EmailValidator.getInstance().isValid(email); 

y para permitir direcciones locales

 boolean allowLocal = true; boolean valid = EmailValidator.getInstance(allowLocal).isValid(email); 

Última respuesta, pero creo que es simple y digna:

  public boolean isValidEmailAddress(String email) { String ePattern = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"; java.util.regex.Pattern p = java.util.regex.Pattern.compile(ePattern); java.util.regex.Matcher m = p.matcher(email); return m.matches(); } 

Casos de prueba :

enter image description here

Para fines de producción, las validaciones de nombres de dominio deben realizarse en red.

Si está tratando de hacer una validación de formulario recibida del cliente, o simplemente una validación de beans, no lo dude. Es mejor hacer una validación de correo electrónico suelto en lugar de hacer una estricta y rechazar a algunas personas (por ejemplo, cuando intentan registrarse para su servicio web). Con casi todo lo permitido en la parte de nombre de usuario del correo electrónico y tantos nuevos dominios que se agregan literalmente todos los meses (por ejemplo, .company, .entreprise, .estate), es más seguro no ser restrictivo:

 Pattern pattern = Pattern.compile("^.+@.+\\..+$"); Matcher matcher = pattern.matcher(email); 

Tarde a la pregunta, aquí, pero: Mantengo una clase en esta dirección: http://lacinato.com/cm/software/emailrelated/emailaddress

Se basa en la clase de Les Hazlewood, pero tiene numerosas mejoras y corrige algunos errores. Licencia de Apache

Creo que es el analizador de correo electrónico más capaz en Java, y todavía tengo que ver uno más capaz en cualquier idioma, aunque puede haber uno por ahí. No es un analizador tipo lexer, sino que usa una expresión regular de java complicada, y por lo tanto no es tan eficiente como podría ser, pero mi compañía ha analizado más de 10 mil millones de direcciones del mundo real con él: sin duda se puede usar en un alto rendimiento situación. Tal vez una vez al año llegue a una dirección que cause un desbordamiento de la stack de expresiones regulares (apropiadamente), pero estas son direcciones de spam que tienen cientos o miles de caracteres de largo con muchas comillas y paréntesis, entre otros.

RFC 2822 y las especificaciones relacionadas son realmente bastante permisivas en términos de direcciones de correo electrónico, por lo que una clase como esta es exagerada para la mayoría de los usos. Por ejemplo, la siguiente es una dirección legítima, según especificación, espacios y todo:

 " (again) 

Ningún servidor de correo permitiría eso, pero esta clase puede analizarlo (y reescribirlo en una forma utilizable).

Descubrimos que las opciones existentes del analizador de correo electrónico de Java no eran suficientemente duraderas (es decir, todas ellas no podían analizar algunas direcciones válidas), por lo que creamos esta clase.

El código está bien documentado y tiene muchas opciones fáciles de cambiar para permitir o no permitir ciertos formularios de correo electrónico. También proporciona una gran cantidad de métodos para acceder a ciertas partes de la dirección (lado izquierdo, lado derecho, nombres personales, comentarios, etc.), para analizar / validar los encabezados de la lista de buzones, para analizar / validar la ruta de retorno (que es único entre los encabezados), y así sucesivamente.

El código tal como está escrito tiene una dependencia de javamail, pero es fácil de eliminar si no desea la funcionalidad menor que proporciona.

Me pregunto por qué a nadie se le ocurrió @Email por las restricciones adicionales de Hibernate Validator. El validador en sí es EmailValidator .

Les Hazlewood ha escrito una clase de validador de correo electrónico que cumple con RFC 2822 muy exhaustiva utilizando expresiones regulares de Java. Puede encontrarlo en http://www.leshazlewood.com/?p=23 . Sin embargo, su minuciosidad (o la implementación de Java RE) conduce a la ineficiencia: lea los comentarios sobre los tiempos de análisis para direcciones largas.

Transmití parte del código en Zend_Validator_Email:

 @FacesValidator("emailValidator") public class EmailAddressValidator implements Validator { private String localPart; private String hostName; private boolean domain = true; Locale locale; ResourceBundle bundle; private List messages = new ArrayList(); private HostnameValidator hostnameValidator; @Override public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { setOptions(component); String email = (String) value; boolean result = true; Pattern pattern = Pattern.compile("^(.+)@([^@]+[^.])$"); Matcher matcher = pattern.matcher(email); locale = context.getViewRoot().getLocale(); bundle = ResourceBundle.getBundle("com.myapp.resources.validationMessages", locale); boolean length = true; boolean local = true; if (matcher.find()) { localPart = matcher.group(1); hostName = matcher.group(2); if (localPart.length() > 64 || hostName.length() > 255) { length = false; addMessage("enterValidEmail", "email.AddressLengthExceeded"); } if (domain == true) { hostnameValidator = new HostnameValidator(); hostnameValidator.validate(context, component, hostName); } local = validateLocalPart(); if (local && length) { result = true; } else { result = false; } } else { result = false; addMessage("enterValidEmail", "invalidEmailAddress"); } if (result == false) { throw new ValidatorException(messages); } } private boolean validateLocalPart() { // First try to match the local part on the common dot-atom format boolean result = false; // Dot-atom characters are: 1*atext *("." 1*atext) // atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*", // "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~" String atext = "a-zA-Z0-9\\u0021\\u0023\\u0024\\u0025\\u0026\\u0027\\u002a" + "\\u002b\\u002d\\u002f\\u003d\\u003f\\u005e\\u005f\\u0060\\u007b" + "\\u007c\\u007d\\u007e"; Pattern regex = Pattern.compile("^["+atext+"]+(\\u002e+["+atext+"]+)*$"); Matcher matcher = regex.matcher(localPart); if (matcher.find()) { result = true; } else { // Try quoted string format // Quoted-string characters are: DQUOTE *([FWS] qtext/quoted-pair) [FWS] DQUOTE // qtext: Non white space controls, and the rest of the US-ASCII characters not // including "\" or the quote character String noWsCtl = "\\u0001-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f"; String qText = noWsCtl + "\\u0021\\u0023-\\u005b\\u005d-\\u007e"; String ws = "\\u0020\\u0009"; regex = Pattern.compile("^\\u0022(["+ws+qText+"])*["+ws+"]?\\u0022$"); matcher = regex.matcher(localPart); if (matcher.find()) { result = true; } else { addMessage("enterValidEmail", "email.AddressDotAtom"); addMessage("enterValidEmail", "email.AddressQuotedString"); addMessage("enterValidEmail", "email.AddressInvalidLocalPart"); } } return result; } private void addMessage(String detail, String summary) { String detailMsg = bundle.getString(detail); String summaryMsg = bundle.getString(summary); messages.add(new FacesMessage(FacesMessage.SEVERITY_ERROR, summaryMsg, detailMsg)); } private void setOptions(UIComponent component) { Boolean domainOption = Boolean.valueOf((String) component.getAttributes().get("domain")); //domain = (domainOption == null) ? true : domainOption.booleanValue(); } } 

Con un validador de nombre de host de la siguiente manera:

 @FacesValidator("hostNameValidator") public class HostnameValidator implements Validator { private Locale locale; private ResourceBundle bundle; private List messages; private boolean checkTld = true; private boolean allowLocal = false; private boolean allowDNS = true; private String tld; private String[] validTlds = {"ac", "ad", "ae", "aero", "af", "ag", "ai", "al", "am", "an", "ao", "aq", "ar", "arpa", "as", "asia", "at", "au", "aw", "ax", "az", "ba", "bb", "bd", "be", "bf", "bg", "bh", "bi", "biz", "bj", "bm", "bn", "bo", "br", "bs", "bt", "bv", "bw", "by", "bz", "ca", "cat", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn", "co", "com", "coop", "cr", "cu", "cv", "cx", "cy", "cz", "de", "dj", "dk", "dm", "do", "dz", "ec", "edu", "ee", "eg", "er", "es", "et", "eu", "fi", "fj", "fk", "fm", "fo", "fr", "ga", "gb", "gd", "ge", "gf", "gg", "gh", "gi", "gl", "gm", "gn", "gov", "gp", "gq", "gr", "gs", "gt", "gu", "gw", "gy", "hk", "hm", "hn", "hr", "ht", "hu", "id", "ie", "il", "im", "in", "info", "int", "io", "iq", "ir", "is", "it", "je", "jm", "jo", "jobs", "jp", "ke", "kg", "kh", "ki", "km", "kn", "kp", "kr", "kw", "ky", "kz", "la", "lb", "lc", "li", "lk", "lr", "ls", "lt", "lu", "lv", "ly", "ma", "mc", "md", "me", "mg", "mh", "mil", "mk", "ml", "mm", "mn", "mo", "mobi", "mp", "mq", "mr", "ms", "mt", "mu", "museum", "mv", "mw", "mx", "my", "mz", "na", "name", "nc", "ne", "net", "nf", "ng", "ni", "nl", "no", "np", "nr", "nu", "nz", "om", "org", "pa", "pe", "pf", "pg", "ph", "pk", "pl", "pm", "pn", "pr", "pro", "ps", "pt", "pw", "py", "qa", "re", "ro", "rs", "ru", "rw", "sa", "sb", "sc", "sd", "se", "sg", "sh", "si", "sj", "sk", "sl", "sm", "sn", "so", "sr", "st", "su", "sv", "sy", "sz", "tc", "td", "tel", "tf", "tg", "th", "tj", "tk", "tl", "tm", "tn", "to", "tp", "tr", "travel", "tt", "tv", "tw", "tz", "ua", "ug", "uk", "um", "us", "uy", "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu", "wf", "ws", "ye", "yt", "yu", "za", "zm", "zw"}; private Map> idnLength; private void init() { Map biz = new HashMap(); biz.put(5, 17); biz.put(11, 15); biz.put(12, 20); Map cn = new HashMap(); cn.put(1, 20); Map com = new HashMap(); com.put(3, 17); com.put(5, 20); Map hk = new HashMap(); hk.put(1, 15); Map info = new HashMap(); info.put(4, 17); Map kr = new HashMap(); kr.put(1, 17); Map net = new HashMap(); net.put(3, 17); net.put(5, 20); Map org = new HashMap(); org.put(6, 17); Map tw = new HashMap(); tw.put(1, 20); Map idn1 = new HashMap(); idn1.put(1, 20); Map idn2 = new HashMap(); idn2.put(1, 20); Map idn3 = new HashMap(); idn3.put(1, 20); Map idn4 = new HashMap(); idn4.put(1, 20); idnLength = new HashMap>(); idnLength.put("BIZ", biz); idnLength.put("CN", cn); idnLength.put("COM", com); idnLength.put("HK", hk); idnLength.put("INFO", info); idnLength.put("KR", kr); idnLength.put("NET", net); idnLength.put("ORG", org); idnLength.put("TW", tw); idnLength.put("ایران", idn1); idnLength.put("中国", idn2); idnLength.put("公司", idn3); idnLength.put("网络", idn4); messages = new ArrayList(); } public HostnameValidator() { init(); } @Override public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { String hostName = (String) value; locale = context.getViewRoot().getLocale(); bundle = ResourceBundle.getBundle("com.myapp.resources.validationMessages", locale); Pattern ipPattern = Pattern.compile("^[0-9a-f:\\.]*$", Pattern.CASE_INSENSITIVE); Matcher ipMatcher = ipPattern.matcher(hostName); if (ipMatcher.find()) { addMessage("hostname.IpAddressNotAllowed"); throw new ValidatorException(messages); } boolean result = false; // removes last dot (.) from hostname hostName = hostName.replaceAll("(\\.)+$", ""); String[] domainParts = hostName.split("\\."); boolean status = false; // Check input against DNS hostname schema if ((domainParts.length > 1) && (hostName.length() > 4) && (hostName.length() < 255)) { status = false; dowhile: do { // First check TLD int lastIndex = domainParts.length - 1; String domainEnding = domainParts[lastIndex]; Pattern tldRegex = Pattern.compile("([^.]{2,10})", Pattern.CASE_INSENSITIVE); Matcher tldMatcher = tldRegex.matcher(domainEnding); if (tldMatcher.find() || domainEnding.equals("ایران") || domainEnding.equals("中国") || domainEnding.equals("公司") || domainEnding.equals("网络")) { // Hostname characters are: *(label dot)(label dot label); max 254 chars // label: id-prefix [*ldh{61} id-prefix]; max 63 chars // id-prefix: alpha / digit // ldh: alpha / digit / dash // Match TLD against known list tld = (String) tldMatcher.group(1).toLowerCase().trim(); if (checkTld == true) { boolean foundTld = false; for (int i = 0; i < validTlds.length; i++) { if (tld.equals(validTlds[i])) { foundTld = true; } } if (foundTld == false) { status = false; addMessage("hostname.UnknownTld"); break dowhile; } } /** * Match against IDN hostnames * Note: Keep label regex short to avoid issues with long patterns when matching IDN hostnames */ List regexChars = getIdnRegexChars(); // Check each hostname part int check = 0; for (String domainPart : domainParts) { // Decode Punycode domainnames to IDN if (domainPart.indexOf("xn--") == 0) { domainPart = decodePunycode(domainPart.substring(4)); } // Check dash (-) does not start, end or appear in 3rd and 4th positions if (domainPart.indexOf("-") == 0 || (domainPart.length() > 2 && domainPart.indexOf("-", 2) == 2 && domainPart.indexOf("-", 3) == 3) || (domainPart.indexOf("-") == (domainPart.length() - 1))) { status = false; addMessage("hostname.DashCharacter"); break dowhile; } // Check each domain part boolean checked = false; for (int key = 0; key < regexChars.size(); key++) { String regexChar = regexChars.get(key); Pattern regex = Pattern.compile(regexChar); Matcher regexMatcher = regex.matcher(domainPart); status = regexMatcher.find(); if (status) { int length = 63; if (idnLength.containsKey(tld.toUpperCase()) && idnLength.get(tld.toUpperCase()).containsKey(key)) { length = idnLength.get(tld.toUpperCase()).get(key); } int utf8Length; try { utf8Length = domainPart.getBytes("UTF8").length; if (utf8Length > length) { addMessage("hostname.InvalidHostname"); } else { checked = true; break; } } catch (UnsupportedEncodingException ex) { Logger.getLogger(HostnameValidator.class.getName()).log(Level.SEVERE, null, ex); } } } if (checked) { ++check; } } // If one of the labels doesn't match, the hostname is invalid if (check != domainParts.length) { status = false; addMessage("hostname.InvalidHostnameSchema"); } } else { // Hostname not long enough status = false; addMessage("hostname.UndecipherableTld"); } } while (false); if (status == true && allowDNS) { result = true; } } else if (allowDNS == true) { addMessage("hostname.InvalidHostname"); throw new ValidatorException(messages); } // Check input against local network name schema; Pattern regexLocal = Pattern.compile("^(([a-zA-Z0-9\\x2d]{1,63}\\x2e)*[a-zA-Z0-9\\x2d]{1,63}){1,254}$", Pattern.CASE_INSENSITIVE); boolean checkLocal = regexLocal.matcher(hostName).find(); if (allowLocal && !status) { if (checkLocal) { result = true; } else { // If the input does not pass as a local network name, add a message result = false; addMessage("hostname.InvalidLocalName"); } } // If local network names are not allowed, add a message if (checkLocal && !allowLocal && !status) { result = false; addMessage("hostname.LocalNameNotAllowed"); } if (result == false) { throw new ValidatorException(messages); } } private void addMessage(String msg) { String bundlMsg = bundle.getString(msg); messages.add(new FacesMessage(FacesMessage.SEVERITY_ERROR, bundlMsg, bundlMsg)); } /** * Returns a list of regex patterns for the matched TLD * @param tld * @return */ private List getIdnRegexChars() { List regexChars = new ArrayList(); regexChars.add("^[a-z0-9\\x2d]{1,63}$"); Document doc = null; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); try { InputStream validIdns = getClass().getClassLoader().getResourceAsStream("com/myapp/resources/validIDNs_1.xml"); DocumentBuilder builder = factory.newDocumentBuilder(); doc = builder.parse(validIdns); doc.getDocumentElement().normalize(); } catch (SAXException ex) { Logger.getLogger(HostnameValidator.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(HostnameValidator.class.getName()).log(Level.SEVERE, null, ex); } catch (ParserConfigurationException ex) { Logger.getLogger(HostnameValidator.class.getName()).log(Level.SEVERE, null, ex); } // prepare XPath XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes = null; String xpathRoute = "//idn[tld=\'" + tld.toUpperCase() + "\']/pattern/text()"; try { XPathExpression expr; expr = xpath.compile(xpathRoute); Object res = expr.evaluate(doc, XPathConstants.NODESET); nodes = (NodeList) res; } catch (XPathExpressionException ex) { Logger.getLogger(HostnameValidator.class.getName()).log(Level.SEVERE, null, ex); } for (int i = 0; i < nodes.getLength(); i++) { regexChars.add(nodes.item(i).getNodeValue()); } return regexChars; } /** * Decode Punycode string * @param encoded * @return */ private String decodePunycode(String encoded) { Pattern regex = Pattern.compile("([^a-z0-9\\x2d]{1,10})", Pattern.CASE_INSENSITIVE); Matcher matcher = regex.matcher(encoded); boolean found = matcher.find(); if (encoded.isEmpty() || found) { // no punycode encoded string, return as is addMessage("hostname.CannotDecodePunycode"); throw new ValidatorException(messages); } int separator = encoded.lastIndexOf("-"); List decoded = new ArrayList(); if (separator > 0) { for (int x = 0; x < separator; ++x) { decoded.add((int) encoded.charAt(x)); } } else { addMessage("hostname.CannotDecodePunycode"); throw new ValidatorException(messages); } int lengthd = decoded.size(); int lengthe = encoded.length(); // decoding boolean init = true; int base = 72; int index = 0; int ch = 0x80; int indexeStart = (separator == 1) ? (separator + 1) : 0; for (int indexe = indexeStart; indexe < lengthe; ++lengthd) { int oldIndex = index; int pos = 1; for (int key = 36; true; key += 36) { int hex = (int) encoded.charAt(indexe++); int digit = (hex - 48 < 10) ? hex - 22 : ((hex - 65 < 26) ? hex - 65 : ((hex - 97 < 26) ? hex - 97 : 36)); index += digit * pos; int tag = (key <= base) ? 1 : ((key >= base + 26) ? 26 : (key - base)); if (digit < tag) { break; } pos = (int) (pos * (36 - tag)); } int delta = (int) (init ? ((index - oldIndex) / 700) : ((index - oldIndex) / 2)); delta += (int) (delta / (lengthd + 1)); int key; for (key = 0; delta > 910; key += 36) { delta = (int) (delta / 35); } base = (int) (key + 36 * delta / (delta + 38)); init = false; ch += (int) (index / (lengthd + 1)); index %= (lengthd + 1); if (lengthd > 0) { for (int i = lengthd; i > index; i--) { decoded.set(i, decoded.get(i - 1)); } } decoded.set(index++, ch); } // convert decoded ucs4 to utf8 string StringBuilder sb = new StringBuilder(); for (int i = 0; i < decoded.size(); i++) { int value = decoded.get(i); if (value < 128) { sb.append((char) value); } else if (value < (1 << 11)) { sb.append((char) (192 + (value >> 6))); sb.append((char) (128 + (value & 63))); } else if (value < (1 << 16)) { sb.append((char) (224 + (value >> 12))); sb.append((char) (128 + ((value >> 6) & 63))); sb.append((char) (128 + (value & 63))); } else if (value < (1 << 21)) { sb.append((char) (240 + (value >> 18))); sb.append((char) (128 + ((value >> 12) & 63))); sb.append((char) (128 + ((value >> 6) & 63))); sb.append((char) (128 + (value & 63))); } else { addMessage("hostname.CannotDecodePunycode"); throw new ValidatorException(messages); } } return sb.toString(); } /** * Eliminates empty values from input array * @param data * @return */ private String[] verifyArray(String[] data) { List result = new ArrayList(); for (String s : data) { if (!s.equals("")) { result.add(s); } } return result.toArray(new String[result.size()]); } } 

Y un validIDNs.xml con patrones regex para los diferentes tlds (demasiado grande para incluir 🙂

   AC ^[\u002d0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$   AR ^[\u002d0-9a-zà-ãç-êìíñ-õü]{1,63}$   AS /^[\u002d0-9a-zà-öø-ÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľłńņňŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźż]{1,63}$   AT /^[\u002d0-9a-zà-öø-ÿœšž]{1,63}$   BIZ ^[\u002d0-9a-zäåæéöøü]{1,63}$ ^[\u002d0-9a-záéíñóúü]{1,63}$ ^[\u002d0-9a-záéíóöúüőű]{1,63}$   
 public class Validations { private Pattern regexPattern; private Matcher regMatcher; public String validateEmailAddress(String emailAddress) { regexPattern = Pattern.compile("^[(a-zA-Z-0-9-\\_\\+\\.)]+@[(azAz)]+\\.[(a-zA-z)]{2,3}$"); regMatcher = regexPattern.matcher(emailAddress); if(regMatcher.matches()) { return "Valid Email Address"; } else { return "Invalid Email Address"; } } public String validateMobileNumber(String mobileNumber) { regexPattern = Pattern.compile("^\\+[0-9]{2,3}+-[0-9]{10}$"); regMatcher = regexPattern.matcher(mobileNumber); if(regMatcher.matches()) { return "Valid Mobile Number"; } else { return "Invalid Mobile Number"; } } public static void main(String[] args) { String emailAddress = "suryaprakash.pisay@gmail.com"; String mobileNumber = "+91-9986571622"; Validations validations = new Validations(); System.out.println(validations.validateEmailAddress(emailAddress)); System.out.println(validations.validateMobileNumber(mobileNumber)); } } 

Si está buscando verificar si una dirección de correo electrónico es válida, entonces VRFY lo ayudará a conseguirlo. Descubrí que es útil para validar direcciones de intranet (es decir, direcciones de correo electrónico para sitios internos). Sin embargo, es menos útil para los servidores de correo de Internet (consulte las advertencias en la parte superior de esta página)

Aunque hay muchas alternativas a los recursos comunes de Apache, sus implementaciones son, en el mejor de los casos, rudimentarias (como la implementación de Apache commons ) e incluso incorrectas en otros casos.

También me mantendría alejado de la llamada expresión regular simple “no restrictiva”; No hay tal cosa. Por ejemplo, @ se permite varias veces dependiendo del contexto, ¿cómo se sabe que el requerido está allí? Simple regex no lo entenderá, aunque el correo electrónico sea válido. Cualquier cosa más compleja se vuelve propensa a errores o incluso contiene asesinos de rendimiento ocultos . ¿Cómo vas a mantener algo como esto ?

El único validador completo basado en expresiones RFC que conozco es el email-rfc2822-validator con su expresión regular “refinada” apropiadamente llamada Dragons.java . Sin embargo, solo admite la especificación RFC-2822 anterior , aunque es lo suficientemente adecuada para las necesidades modernas (RFC-5322 la actualiza en áreas que ya están fuera del scope de los casos de uso diario).

Pero realmente lo que quieres es un lector que analice correctamente una cadena y la descomponga en la estructura del componente de acuerdo con la gramática RFC. EmailValidator4J parece prometedor en ese sentido, pero todavía es joven y limitado.

Otra opción que tiene es usar un servicio web como el servicio web de validación probado por batalla de Mailgun o la API de Mailboxlayer (solo tomó los primeros resultados de Google). No es estrictamente compatible con RFC, pero funciona lo suficientemente bien para las necesidades modernas.

¿Qué quieres validar? ¿La direccion de correo electronico?

La dirección de correo electrónico solo se puede verificar en cuanto a su conformidad con el formato. Ver el estándar: RFC2822 . La mejor forma de hacerlo es una expresión regular. Nunca sabrá si realmente existe sin enviar un correo electrónico.

Revisé el validador de bienes comunes. Contiene una clase org.apache.commons.validator.EmailValidator. Parece ser un buen punto de partida.

La versión actual del validador de Apache Commons es 1.3.1 .

La clase que valida es org.apache.commons.validator.EmailValidator. Tiene una importación para org.apache.oro.text.perl.Perl5Util que proviene de un proyecto ORO de Yakarta retirado.

Por cierto, encontré que hay una versión 1.4, aquí están los documentos API . En el sitio dice: “Última publicación: 05 de marzo de 2008 | Versión: 1.4-SNAPSHOT”, pero eso no es definitivo. La única forma de crear usted mismo (pero esta es una instantánea, no LIBERA) y usar, o descargar desde aquí . Esto significa que 1.4 no se ha hecho definitivo durante tres años (2008-2011). Esto no está en el estilo de Apache. Estoy buscando una mejor opción, pero no encontré una que sea muy adoptada. Quiero usar algo que esté bien probado, no quiero golpear ningún error.

También es posible que desee verificar la longitud: los correos electrónicos tienen un máximo de 254 caracteres de largo. I use the apache commons validator and it doesn’t check for this.

There don’t seem to be any perfect libraries or ways to do this yourself, unless you have to time to send an email to the email address and wait for a response (this might not be an option though). I ended up using a suggestion from here http://blog.logichigh.com/2010/09/02/validating-an-e-mail-address/ and adjusting the code so it would work in Java.

 public static boolean isValidEmailAddress(String email) { boolean stricterFilter = true; String stricterFilterString = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"; String laxString = ".+@.+\\.[A-Za-z]{2}[A-Za-z]*"; String emailRegex = stricterFilter ? stricterFilterString : laxString; java.util.regex.Pattern p = java.util.regex.Pattern.compile(emailRegex); java.util.regex.Matcher m = p.matcher(email); return m.matches(); } 

This is the best method:

 public static boolean isValidEmail(String enteredEmail){ String EMAIL_REGIX = "^[\\\\w!#$%&'*+/=?`{|}~^-]+(?:\\\\.[\\\\w!#$%&'*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\\\.)+[a-zA-Z]{2,6}$"; Pattern pattern = Pattern.compile(EMAIL_REGIX); Matcher matcher = pattern.matcher(enteredEmail); return ((!enteredEmail.isEmpty()) && (enteredEmail!=null) && (matcher.matches())); } 

Sources:- http://howtodoinjava.com/2014/11/11/java-regex-validate-email-address/

http://www.rfc-editor.org/rfc/rfc5322.txt

Another option is use the Hibernate email validator , using the annotation @Email or using the validator class progtwigtically, like:

 import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator; class Validator { // code private boolean isValidEmail(String email) { EmailValidator emailValidator = new EmailValidator(); return emailValidator.isValid(email, null); } } 

Heres my pragmatic approach, where I just want reasonable distinct blah@domain addresses using the allowable characters from the RFC. Addresses must be converted to lowercase beforehand.

 public class EmailAddressValidator { private static final String domainChars = "a-z0-9\\-"; private static final String atomChars = "a-z0-9\\Q!#$%&'*+-/=?^_`{|}~\\E"; private static final String emailRegex = "^" + dot(atomChars) + "@" + dot(domainChars) + "$"; private static final Pattern emailPattern = Pattern.compile(emailRegex); private static String dot(String chars) { return "[" + chars + "]+(?:\\.[" + chars + "]+)*"; } public static boolean isValidEmailAddress(String address) { return address != null && emailPattern.matcher(address).matches(); } }