Python: validar la dirección de correo electrónico con expresiones regulares (RegEx)

En esta guía, veremos cómo validar direcciones de correo electrónico en Python con expresiones regulares, con una expresión simple de propósito general, así como una expresión regular robusta compatible con RFC5322.

Introducción

Expresiones regulares, o RegEx para abreviar, son expresiones de patrones que se pueden usar para acciones de búsqueda y reemplazo de texto, validaciones, división de cadenas y mucho más. Estos patrones consisten en caracteres, dígitos y caracteres especiales, de tal forma que el patrón coincide con ciertos segmentos de texto que estamos buscando.

Las expresiones regulares se usan ampliamente para la coincidencia de patrones, y varios lenguajes de programación tienen interfaces para representarlas, así como para interactuar con los resultados de las coincidencias.

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

If you would like to learn more about Python's interface with Regular Expressions, read our Guía de expresiones regulares en Python!

Expresión regular de correo electrónico de propósito general {#expresiónregular de correo electrónico de propósito general}

Vale la pena señalar que no existe tal expresión regular que coincida con todas las posibles direcciones de correo electrónico válidas. Aunque hay expresiones que pueden coincidir con la mayoría de las direcciones de correo electrónico válidas.

Necesitamos definir qué tipo de dirección de correo electrónico formato estamos buscando. El formato de correo electrónico más común es:

1
(username)@(domainname).(top-leveldomain)

Por lo tanto, podemos reducirlo a un patrón del símbolo @ que divide el prefijo del segmento de dominio.

El prefijo es el nombre del destinatario: una cadena que puede contener letras mayúsculas y minúsculas, números y algunos caracteres especiales como . (punto), - (guion) y _ ( guion bajo).

El dominio consta de su nombre y un dominio de nivel superior dividido por un símbolo . (punto). El nombre de dominio puede tener letras mayúsculas y minúsculas, números y símbolos - (guiones). Además, el nombre de dominio de nivel superior debe tener al menos 2 caracteres (ya sea en mayúsculas o minúsculas), pero puede ser más largo.

{.icon aria-hidden=“true”}

Nota: Hay reglas mucho más detalladas con respecto a los correos electrónicos válidos, como el recuento de caracteres, caracteres más específicos que se pueden usar, etc. Echaremos un vistazo a una expresión regular extendida y altamente a prueba de fallas. según lo definido por RFC5322 después del enfoque de propósito general.

En términos simples, nuestra expresión regular de correo electrónico podría verse así:

1
(string1)@(string2).(2+characters)

Esto coincidiría correctamente con direcciones de correo electrónico como:

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

Nuevamente, usando la misma expresión, estas direcciones de correo electrónico fallarían:

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

Vale la pena señalar que las cadenas no deben contener ciertos caracteres especiales, para que no vuelvan a romper el formulario. Además, el dominio de nivel superior no puede ser ... Teniendo en cuenta esos casos también, podemos poner estas reglas en una expresión concreta que tenga en cuenta algunos casos más que la primera representación:

1
([A-Za-z0-9]+[.-_])*[A-Za-z0-9][correo electrónico protegido][A-Za-z0-9-]+(\.[A-Z|a-z]{2,})+

Un carácter especial en el prefijo no puede estar justo antes del símbolo @, ni el prefijo puede comenzar con él, por lo que nos aseguramos de que haya al menos un carácter alfanumérico antes y después de cada carácter especial.

En cuanto al dominio, un correo electrónico puede contener algunos dominios de nivel superior divididos con un punto.

Obviamente, esta expresión regular es más complicada que la primera, pero cubre todas las reglas que hemos definido para el formato de correo electrónico. Una vez más, es probable que no valide correctamente algún caso extremo en el que no hayamos pensado.

Validar dirección de correo electrónico con Python

El módulo re contiene clases y métodos para representar y trabajar con expresiones regulares en Python, por lo que lo importaremos a nuestro script. El método que usaremos es re.fullmatch(pattern, string, flags). Este método devuelve un objeto de coincidencia solo si la cadena completa coincide con el patrón; en cualquier otro caso, devuelve Ninguno.

{.icon aria-hidden=“true”}

Nota: re.fullmatch() se introdujo en Python 3.4, antes de eso, se usó re.match() en su lugar. En las versiones más nuevas, se prefiere fullmatch().

Vamos a compilar() la expresión regular anterior y definir una función simple que acepte una dirección de correo electrónico y use la expresión para validarla:

1
2
3
4
5
6
7
8
9
import re

regex = re.compile(r'([A-Za-z0-9]+[.-_])*[A-Za-z0-9][correo electrónico protegido][A-Za-z0-9-]+(\.[A-Z|a-z]{2,})+')

def isValid(email):
    if re.fullmatch(regex, email):
      print("Valid email")
    else:
      print("Invalid email")

El método re.compile() compila un patrón de expresión regular en un objeto de expresión regular. Se usa principalmente por razones de eficiencia, cuando planeamos hacer coincidir el patrón más de una vez.

Ahora, probemos el código en algunos de los ejemplos que vimos anteriormente:

1
2
3
4
isValid("[correo electrónico protegido]")
isValid("[correo electrónico protegido]")
isValid("[correo electrónico protegido]")
isValid("[correo electrónico protegido]")

Esto resulta en:

1
2
3
4
Valid email
Valid email
Invalid email
Invalid email

Impresionante, ¡tenemos un sistema en funcionamiento!

Expresión regular robusta de correo electrónico

La expresión que hemos usado arriba funciona bien para la mayoría de los casos y funcionará bien para cualquier aplicación razonable. Sin embargo, si la seguridad es una preocupación mayor, o si le gusta escribir expresiones regulares, puede optar por reducir el alcance de las posibilidades y al mismo tiempo permitir el paso de direcciones de correo electrónico válidas.

Las expresiones largas tienden a volverse un poco complicadas y difíciles de leer, y esta expresión no es una excepción:

1
2
3
4
5
6
7
8
9
(?:[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])?
|\[(?:(?:(2(5[0-5]|[0-4][0-9])
|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])
|1[0-9][0-9]|[1-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])+)\])

Esta es la expresión regular compatible con RFC5322 que cubre el 99,99 % de las direcciones de correo electrónico ingresadas. Esto ayuda mucho:

*[Imagen y reclamo son cortesía de Correo electrónicoRegex.com]{.small}.

En realidad, esta no es la única expresión que cumple con RFC5322. Muchos de ellos lo hacen, con diversos grados de éxito. Una versión más corta que todavía cumple con la especificación se puede importar fácilmente al método re.compile() de Python para representar una expresión:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import re

regex = re.compile(r"([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\"([]!#-[^-~ \t]|(\\[\t -~]))+\")@([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])")

def isValid(email):
    if re.fullmatch(regex, email):
        print("Valid email")
    else:
        print("Invalid email")

isValid("[correo electrónico protegido]")
isValid("[correo electrónico protegido]")
isValid("[correo electrónico protegido]")
isValid("[correo electrónico protegido]")

Esto también resulta en:

1
2
3
4
Valid email
Valid email
Invalid email
Invalid email

Conclusión

Para concluir esta guía, revisemos lo que hemos aprendido. Hay muchas formas de validar correos electrónicos usando expresiones regulares, principalmente dependiendo del formato que estemos buscando. En relación con eso, no existe un patrón único que funcione para todos los formatos de correo electrónico, simplemente necesitamos definir las reglas que queremos que siga el formato y construir un patrón en consecuencia.

Cada nueva regla reduce el grado de libertad en las direcciones aceptadas.