54 lines
1.6 KiB
Python
54 lines
1.6 KiB
Python
import re
|
|
from typing import Any, Optional, Tuple
|
|
|
|
# Regex práctico (no RFC completo) para validar emails
|
|
_EMAIL_RE = re.compile(
|
|
r"""^(?=.{3,254}$) # longitud total razonable
|
|
(?=.{1,64}@) # parte local máx. 64
|
|
[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+
|
|
(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)* # puntos en la parte local
|
|
@
|
|
(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+ # labels dominio
|
|
[A-Za-z]{2,63}$ # TLD
|
|
""",
|
|
re.X,
|
|
)
|
|
|
|
def corregir_y_validar_email(texto: Any) -> Tuple[bool, Optional[str]]:
|
|
"""
|
|
Normaliza y valida un email.
|
|
Correcciones aplicadas:
|
|
- Reemplaza comas por puntos.
|
|
- Elimina espacios alrededor y dentro (p. ej. 'a @ b . com' -> 'a@b.com').
|
|
- Convierte el dominio a minúsculas.
|
|
- Colapsa puntos consecutivos en el dominio ('..' -> '.').
|
|
Devuelve (es_valido, email_corregido | None).
|
|
"""
|
|
if texto is None:
|
|
return False, None
|
|
|
|
s = str(texto).strip()
|
|
|
|
# 1) comas -> puntos
|
|
s = s.replace(",", ".")
|
|
|
|
# 2) quita espacios
|
|
s = re.sub(r"\s+", "", s)
|
|
|
|
# 3) separar local y dominio (si es posible)
|
|
if s.count("@") != 1:
|
|
# no intentamos correcciones más agresivas si hay 0 o >1 '@'
|
|
return False, s or None
|
|
|
|
local, domain = s.split("@", 1)
|
|
|
|
# 4) normalizaciones de dominio
|
|
domain = domain.lower()
|
|
domain = re.sub(r"\.{2,}", ".", domain) # colapsar puntos dobles
|
|
|
|
candidato = f"{local}@{domain}"
|
|
|
|
# 5) validar
|
|
es_valido = _EMAIL_RE.match(candidato) is not None
|
|
return es_valido, (candidato if candidato else None)
|