¿Cuál es la forma más correcta de validar una dirección de correo electrónico?

El mejor recurso que pude encontrar para esto fue este sitio web:
http://www.dominicsayers.com/ise…

Algunos puntos destacados:

  • El estándar actual es RFC3696 (no RFC2822)
  • No existe (aparentemente) una expresión regular conocida que valide correctamente una dirección de correo electrónico en todos los casos. Los dos validadores que podría encontrar que parecen ser 100% correctos están escritos en PHP (lenguaje de programación) y son 300-400 de líneas de código:

Código de Dominic Sayers:
http://code.google.com/p/isemail…

Código de Cal Henderson:
http://code.iamcal.com/php/rfc822/

La mayoría de las personas está de acuerdo en que es más fácil ser menos que perfecto en su validación ya que eso puede ser mucho más simple (hay un montón de expresiones regulares simples que funcionan razonablemente bien).

Además de los estándares, me resulta muy útil escribir controladores personalizados para Hotmail, Yahoo, Gmail, AOL. Al final del día, esos dominios cubrirán la mayor parte de su base de usuarios. Todas sus reglas de sintaxis son bastante simples y públicas. También es una buena práctica tener una lista de “errores comunes” con la que se verifica. Algunos dominios pueden tener registros MX válidos, pero probablemente sean solo un error tipográfico, es decir, hotmial.com.

Al validar las direcciones de correo electrónico, hay algunas cosas a tener en cuenta:

Sintaxis Arcana:

  • De acuerdo con RFC 5321, la parte local (a la izquierda de la ‘@’) puede contener cualquier carácter ASCII imprimible (0x20 a 0x7E). Es solo que algunos caracteres / cadenas deben ser citados y / o escapados. Por ejemplo, la identificación de usuario ‘@foo “bar” user!’ podría incluirse en una dirección de correo electrónico como “@foo \” bar \ “user!” @ example.com. ¿Desea aceptar direcciones tan poco comunes (probablemente: sí)? ¿Desea corregir al usuario si no obtiene la cita correcta (probablemente: no, suponiendo que debe saber lo que está haciendo si usa direcciones extrañas).
  • ¿Qué pasa con los puntos (‘.’) Al final de la parte local? En las partes locales sin comillas, el ‘.’ solo es válido entre palabras, no al final. Por ejemplo, una dirección con el ID de usuario ‘abc’ debería escribirse como “abc” @ example.com. ¿Desea corregir al usuario en este caso especial (probablemente: sí, pero ya no está validando más)?
  • En RFC 821, las primeras versiones del estándar, incluso los caracteres ASCII no imprimibles, excepto CR y LF (0x00 a 0x09, 0x0B, 0x0C, 0x0E a 0x1F y 0x7F) eran legales como parte de la parte local. ¿Desea aceptar direcciones que hacen uso de esto (probablemente: no, tales direcciones nunca funcionaron de manera confiable de todos modos).
  • En los encabezados de correo electrónico, como se define en RFC 5322, puede agregar nuevas líneas y comentarios adicionales. Por ejemplo, [correo electrónico protegido] es equivalente a foo (comentario) .bar (aquí (“oops”)) @ (esto no es un) ejemplo.com en encabezados de correo. ¿Desea aceptar esta sintaxis extendida (probablemente: no, a menos que esté escribiendo un analizador para encabezados de correo electrónico)?
  • Sin embargo, ¿desea aceptar (y recortar) espacios al principio o al final (probablemente: sí para la entrada del usuario)?

Direcciones incompletas:

  • ¿Desea aceptar partes locales desnudas sin un dominio (por ejemplo, “usuario” en lugar de ” [correo electrónico protegido] “) (probablemente: no, excepto en un entorno corporativo donde se puede implicar un dominio estándar como “ejemplo.com” )?
  • La parte del dominio puede incluir un nombre de host (por ejemplo, ” [correo electrónico protegido] ” en lugar de ” [correo electrónico protegido] “). ¿Desea aceptar tales direcciones (probablemente: no, incluso en un entorno corporativo)?

Internacionalización:

  • RFC 5890 y siguientes. extender los nombres de dominio para incluir caracteres Unicode. ¿Desea aceptar dichos nombres de dominio internacionalizados (probablemente: sí)? En caso afirmativo, ¿hasta dónde está dispuesto a llegar para asegurarse de que el dominio sea válido como nombre de dominio internacionalizado? Las reglas son muy complejas y si un personaje es válido puede incluso depender del contexto. Además, ¿desea que la dirección validada esté en el formato solo ASCII?
  • RFC 5336 extiende la parte local para incluir caracteres Unicode. ¿Desea aceptar tales direcciones de correo electrónico internacionalizadas (probablemente: todavía no)?
  • La ‘@’ también puede escribirse como U + FE6B (SMALL COMMERCIAL AT) o U + FF20 (FULLWIDTH COMMERCIAL AT). ¿Desea corregir esto al ASCII ‘@’ (probablemente: sí, si acepta partes y / o dominios locales internacionalizados, de lo contrario no?)

Otros asuntos:

  • ¿Desea exigir longitudes máximas para la parte local (64 caracteres), el dominio (255 caracteres) o la dirección de correo electrónico (254 caracteres) (probablemente: no, ya que RFC 5321 fomenta explícitamente el soporte de direcciones más largas)?
  • ¿Quieres comprobar si el dominio existe realmente?
  • Ya no hay una lista definitiva de dominios válidos de nivel superior. Ya no puede suponer que el dominio de nivel superior siempre es com, net, org, edu, gov, int, mil o un código de país de dos letras. Ni siquiera puede suponer que el dominio de nivel superior será más corto que n caracteres.
  • Como alternativa a un nombre de dominio, el lado derecho también puede incluir una dirección literal incluida entre corchetes (por ejemplo, [correo electrónico protegido] [192.66.123.45] o [correo electrónico protegido] [2001: DB8 :: 1234]). ¿Quieres aceptar estos (probablemente: no). Si lo hace, ¿desea limitarlo a IPv4 / IPv6 o desea aceptar futuros formatos de dirección?

Entonces, ¿todavía quieres una expresión regular simple?

Sin internacionalización, iría con este:
^([-!#$%&'*+/=?^_`{|}~A-Za-z0-9]+(\.[-!#$%&'*+/=?^_`{|}~A-Za-z0-9]+)*|"([\x20\x21\x23-\x5B\x5D-\x7E]|\\[\x20-\x7E])*")@(([A-Za-z0-9]([-A-Za-z0-9]*[A-Za-z0-9])?)(\.[A-Za-z0-9]([-A-Za-z0-9]*[A-Za-z0-9])?)+)$

Esto supone:

  • No desea aceptar y corregir ninguna sintaxis incorrecta. Ni siquiera espacios al principio o al final.
  • No desea aceptar literales de dirección.
  • No quieres aceptar direcciones parciales.

Con la internacionalización, debe comenzar con la normalización a Unicode NFC y con la asignación de caracteres de ancho completo a caracteres estrechos. Luego, extienda la expresión regular anterior reemplazando ‘A-Za-z0-9’ después de la ‘@’ con lo que su motor de expresión regular proporcione para que coincida con los caracteres PVALID lo más cerca posible.

Cal’s también es bastante exhaustivo http://code.iamcal.com/php/rfc822/