Validar direcciones de correo electrónico con expresiones regulares en JavaScript

En esta guía, veremos cómo validar una dirección de correo electrónico en JavaScript, usando expresiones regulares (RegEx), a través de ejemplos prácticos, cubriendo todos los casos extremos.

Introducción

Para los desarrolladores web, la validación de las entradas de los usuarios en varios tipos de formularios es de vital importancia. Dado que ese es el punto de partida de los datos que se envían entre el cliente y el servidor, debe asegurarse de que todo comience con el pie derecho, para que no termine con una validación sólida en el extremo del servidor, que a menudo es un mayor molestia que hacerlo en el front-end.

{.icon aria-hidden=“true”}

Además, la entrada puede ser maliciosa, en cuyo caso, también debe tener en cuenta la seguridad. Es mejor evitarlo por completo validando la entrada en el front-end.

En este artículo, veremos cómo validar direcciones de correo electrónico en JavaScript usando expresiones regulares.

Expresiones regulares en JavaScript

Para cualquiera que no esté familiarizado con las expresiones regulares, o para cualquiera que sienta que necesita un recordatorio rápido, ¡aquí está!

Las expresiones regulares son secuencias de metacaracteres que denotan un patrón. Estos patrones pueden ser de varios tipos: una mezcla de letras con dígitos, caracteres especiales e incluso caracteres de diferentes idiomas. Una abreviatura de expresión regular es RegEx o RegExp.

A través de metacaracteres, cuantificadores, grupos y caracteres de escape, puede expresar prácticamente cualquier patrón. Por ejemplo, esta expresión denota una secuencia de caracteres que contiene cualquier letra válida entre A-Z (tanto en minúsculas como en mayúsculas) o dígitos, en cualquier combinación:

1
^([A-Za-z]|[0-9])+$

{.icon aria-hidden=“true”}

Esto también se conoce como comprobar si una secuencia es alfanumérica.

Para el resto de la guía, asumiremos que está algo familiarizado con las expresiones regulares.

If you aren't familiar with Regular Expressions and would like to learn more - read our Guía de expresiones regulares y cadenas coincidentes en JavaScript!

Coincidencia de formatos de correo electrónico en JavaScript con expresiones regulares

En primer lugar, una expresión regular que coincida con todas las posibles direcciones de correo electrónico válidas no existe. Sin embargo, el que coincide 99.9%, sí lo hace. Al validar correos electrónicos, o realmente cualquier entrada, una buena práctica, que puede garantizar más o menos que el usuario coincidirá con RegEx, es limitar la entrada del usuario por adelantado.

Por ejemplo, el uso obligatorio de gmail.com o yahoo.com y el rechazo directo de los proveedores no admitidos (aunque, se encuentra con el problema de la escalabilidad y la actualización con este enfoque).

Se plantea otra pregunta:

¿Cuál es el formato de un correo electrónico?

Sorprendentemente, es una definición vaga, como veremos en breve, y puede ser simple o sólida en esto. Cubriremos las expresiones regulares más generales para validar el correo electrónico, así como aquellas que son más específicas en la guía.

Antes de entrar en el código, veamos una vista previa de los formatos de correo electrónico que analizaremos:

  • Formato general - (algo)@(algún_dominio).(algún_dominio_nivel_superior)
  • Hosts o dominios específicos: se refiere a un tipo específico de dominio o dominio de nivel superior
  • RFC 5322 - Formato de mensajes de Internet, que cubre el 99,9 % de las direcciones de correo electrónico

Expresión regular de formato de correo electrónico general

Después de muchos intentos de validación con expresiones regulares robustas, muchos ingenieros recurren al viejo formato "general" que funciona la mayor parte del tiempo. Si esto es algo bueno o no es discutible.

¿Qué implica una dirección de correo electrónico? Tiene que tener un símbolo @, así como alguna cadena que lo preceda y alguna cadena que lo preceda. Además, la segunda cadena debe contener un punto, que tiene 2 o 3 caracteres adicionales después de eso.

En conclusión, este es un boceto aproximado:

1
(randomString)@(randomString2).(2-3 characters)

Esto sigue la intuición general de que estos correos electrónicos son válidos:

1
2
3
[correo electrónico protegido]
[correo electrónico protegido]
[correo electrónico protegido]

Con eso en mente, para validar generalmente una dirección de correo electrónico en JavaScript a través de expresiones regulares, traducimos el bosquejo aproximado en un RegExp:

1
2
3
4
5
6
7
let regex = new RegExp('[a-z0-9][correo electrónico protegido][a-z]+\.[a-z]{2,3}');

let testEmails = ["notanemail.com", "[correo electrónico protegido]", "[correo electrónico protegido]", "[correo electrónico protegido]"];

testEmails.forEach((address) => {
    console.log(regex.test(address))
});

La primera cadena puede contener cualquier carácter alfanumérico en minúscula: john.doe.1, workingemail, etc.

Esto resulta en:

1
2
3
4
false
true
true
false

¿Esto siempre funcionará? No. Habrá algunos correos electrónicos mal formados que se transferirán. Tampoco puede realizar la detección de correo no deseado utilizando esta expresión regular, por lo que una dirección de correo electrónico que intuitivamente parece un correo no deseado pasa esta expresión sin problemas:

1
console.log(regex.test("[correo electrónico protegido]")); // true

Sin embargo, incluso las expresiones de validación de direcciones de correo electrónico más robustas y complejas fallan en esto: están ahí para validar el formulario, no si el correo electrónico existe.

Hablando técnicamente, podría existir [correo electrónico protegido], entonces, ¿quiénes somos nosotros para decir que no se basa solo en una expresión regular?

Direcciones de correo electrónico específicas

Reducir la cantidad de incertidumbre ayuda. Cuanta menos incertidumbre haya, menos restricciones usted necesita imponer usando una expresión. Esto hace que la validación de direcciones de correo electrónico específicas sea más precisa utilizando los mismos formatos generales que acabamos de ver: no tiene que cubrir tantos casos extremos.

Echemos un vistazo a algunos casos generales que se refieren al dominio y al dominio de nivel superior.

Validación de un dominio de dirección de correo electrónico con JavaScript

Digamos que trabajas en una empresa llamada Stack Abuse. Todo el personal tiene un correo electrónico que termina en @wikihtp.com y la cadena de usuario es la que cambia. El boceto aproximado se vería así:

1
(randomString)@wikihtp.com

Esto facilita mucho nuestra tarea, ya que algunas de las variables, como el nombre de dominio y el tipo de organización, ahora están fijas. Estas dos son las típicas variables que causan problemas, ya que los nombres de dominio pueden variar enormemente.

Validar una dirección de correo electrónico perteneciente a un dominio específico se convierte en una tarea fácil, utilizando la clase RegExp:

1
2
3
4
5
6
7
let regex = new RegExp('[a-z0-9][correo electrónico protegido]');

let testEmails = ["notanemail.com", "[correo electrónico protegido]", "[correo electrónico protegido]"];

testEmails.forEach((address) => {
    console.log(regex.test(address))
});

Esto resulta en:

1
2
3
false
true
false

Con este enfoque, puede cambiar cualquier cadena literal para que coincida con sus necesidades. Como siempre, la primera parte de la expresión regular se puede cambiar para que coincida con mayúsculas, incluir caracteres especiales como + o _, etc.

Validación de dominios de nivel superior de dirección de correo electrónico en JavaScript

Este caso es bastante similar al anterior, excepto que estaremos limitando los últimos dos o tres caracteres del correo electrónico.
Estos pueden ser literalmente cualquiera de: .com, .org, .edu, .eu, .us, etc. Hagamos coincidir solo los correos electrónicos que contengan .edu ya que nunca es únicamente este dominio de nivel superior, pero en cambio, algo así como [correo electrónico protegido].

1
2
3
4
5
6
7
let regex = new RegExp('[a-z0-9][correo electrónico protegido][a-z]+\.edu\.[a-z]{2,3}');

let testEmails = ["notanemail.com", "[correo electrónico protegido]", "[correo electrónico protegido]"];

testEmails.forEach((address) => {
    console.log(regex.test(address))
});

Un correo electrónico no válido, así como uno válido fallan, porque no contienen un edu en su dominio de nivel superior, sin embargo, la dirección inventada de Yale funciona:

1
2
3
false
false
true

Formato RFC 5322 {# formato rfc5322}

El Formato RFC 5322 es un formato de mensaje de Internet (formato clásico de un mensaje de correo electrónico). El RFC 5322 solo dicta lo que debe permitirse, no es una expresión en sí misma.

Hay múltiples expresiones que implementan las reglas establecidas, y pueden volverse bastante complejas.

Si se implementa correctamente, la expresión regular compatible con RFC 5322 debería validar el 99,99 % de las direcciones de correo electrónico válidas.

Una versión abreviada es:

1
let regex = new RegExp("([!#-'*+/-9=?A-Z^-~-]+(\.[!#-'*+/-9=?A-Z^-~-]+)*|\"\(\[\]!#-[^-~ \t]|(\\[\t -~]))+\")@([!#-'*+/-9=?A-Z^-~-]+(\.[!#-'*+/-9=?A-Z^-~-]+)*|\[[\t -Z^-~]*])");

Mientras que una versión extendida que cubre casos extremos adicionales es:

1
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Estas expresiones no son particularmente fáciles de comprender a menos que las divida en grupos y pase algún tiempo leyéndolas. Sin embargo, una forma más fácil es visualizarlo:

*[La imagen y la declaración de precisión son cortesía de Correo electrónicoRegex.com]{.small}.

Dicho esto, usemos esta expresión para validar un par de direcciones:

1
2
3
4
5
6
7
let regex = new RegExp("([!#-'*+/-9=?A-Z^-~-]+(\.[!#-'*+/-9=?A-Z^-~-]+)*|\"\(\[\]!#-[^-~ \t]|(\\[\t -~]))+\")@([!#-'*+/-9=?A-Z^-~-]+(\.[!#-'*+/-9=?A-Z^-~-]+)*|\[[\t -Z^-~]*])");

let testEmails = ["notanemail.com", "[correo electrónico protegido]", "[correo electrónico protegido]"];

testEmails.forEach((address) => {
    console.log(regex.test(address))
});

Esto resulta en:

1
2
3
false
true
true

Puede continuar y probar esta expresión de forma interactiva a través de una hermosa interfaz en [regex101]{rel=“nofollow noopener noreferrer” target="_blank"}.

Conclusión

En conclusión, realmente no existe una sola forma "adecuada" de validar las direcciones de correo electrónico mediante expresiones regulares. Sin embargo, hay una forma incorrecta: si no cubre los casos, no debería ser correcto.

Para aquellos que quieren asegurarse de que literalmente, casi todo esté cubierto, utilice el formato RFC 5322.