¿Qué es la verificación de email? Guía para desarrolladores
Cuando alguien escribe una dirección de email en tu formulario de registro, ¿qué sabes realmente de ella? Si solo compruebas la sintaxis —¿tiene forma de email?— no sabes casi nada. La verificación de email es el proceso de determinar si una dirección es real, alcanzable y merece la pena.
Esta guía explica qué comprueba de verdad la verificación, cómo funciona cada capa y en qué punto de tu stack encaja.
Lo que la verificación de email no es
La validación de sintaxis no es verificación de email. Comprobar que una dirección encaja con /^[^\s@]+@[^\s@]+\.[^\s@]+$/ solo te dice que la cadena tiene una arroba y un punto. No detecta:
test@mailinator.com— dirección desechable, borrada en 10 minutosnoreply@example.com— dirección de rol que no lee nadieuser@nonexistent-domain.com— dominio sin servidor de correoghost@real-company.com— dirección cuyo buzón se eliminó
Una cadena de verificación completa tiene cinco capas distintas. Cada una elimina una clase diferente de direcciones malas.
Capa 1: validación de sintaxis
La primera comprobación normaliza y valida el formato de la dirección según el RFC 5321 y el RFC 5322. Más allá de la expresión regular básica, detecta casos límite como:
- Puntos dobles (
user..name@domain.com) - Puntos al principio o al final de la parte local
- Caracteres inválidos en la parte local
- Direcciones demasiado largas (límite del RFC: 254 caracteres en total, 64 en la parte local)
La mayoría de las direcciones que fallan aquí lo hacen por una errata del usuario, y este paso se completa en microsegundos.
Capa 2: consulta del dominio y de los registros MX
Una sintaxis válida no significa que el dominio exista ni que acepte correo. La segunda capa hace consultas de DNS:
- Consulta de registros MX — ¿tiene el dominio registros de intercambio de correo apuntando a un servidor SMTP?
- Respaldo con el registro A — si no hay registro MX, ¿resuelve el dominio siquiera?
- Existencia del dominio — ¿está registrado y sin caducar?
Un dominio como emai.com (errata habitual de email.com) pasa la validación de sintaxis pero no tiene registro MX, y nunca lo tendrá. Esta comprobación elimina categorías enteras de erratas y de dominios caducados hace poco.
# Comprobación manual: consultar los registros MX de un dominio
dig MX gmail.com
# ;; ANSWER SECTION:
# gmail.com. 3600 IN MX 5 gmail-smtp-in.l.google.com.Capa 3: verificación SMTP
La comprobación más valiosa es un diálogo SMTP con el servidor de correo. El verificador se conecta al servidor MX, empieza una conversación y pregunta si el buzón existe, sin llegar a enviar ningún correo.
El intercambio es así:
→ EHLO verifier.mailbeam.dev
← 250-smtp.gmail.com Hello
→ MAIL FROM:<probe@mailbeam.dev>
← 250 2.1.0 OK
→ RCPT TO:<user@gmail.com>
← 250 2.1.5 OK ← el buzón existe
Si el servidor responde con un 550 o un 551 al comando RCPT TO, el buzón no existe. El verificador emite entonces un RSET para abortar antes de enviar nada.
Esto detecta direcciones que pasan la sintaxis y los registros MX pero que no tienen buzón real: algo habitual tras la rotación de empleados, el cierre de cuentas o la creación masiva de cuentas falsas.
Límites de SMTP
Algunos servidores de correo no colaboran. Responden 250 OK a cualquier dirección (comportamiento catch-all) para no revelar qué buzones existen. Otros limitan la tasa de sondeos de verificación SMTP. Ahí es donde importa la cuarta capa.
Capa 4: puntuar los casos ambiguos
Cuando SMTP da un resultado ambiguo —normalmente un dominio catch-all— necesitas algo distinto de un sí o un no. Algunos servicios aplican un modelo de machine learning entrenado con datos históricos de envío. Mailbeam usa en su lugar una puntuación aditiva: un conjunto fijo de señales con pesos y topes publicados, en el que una dirección catch-all nunca puede pasar de 70 porque ningún sondeo puede confirmarla.
El compromiso es deliberado. Una rúbrica no va a superar a un buen modelo en direcciones genuinamente ambiguas, pero cada punto es trazable hasta una comprobación, así que cuando el número sorprende se puede averiguar por qué. La salida es de 0 a 100 en lugar de un resultado binario, lo que permite aplicar umbrales distintos según el caso de uso:
const result = await verifyEmail(email);
if (result.catchAll) {
// Email corporativo: acepta con confianza alta, marca la media, rechaza la baja
if (result.score >= 70) return "accept";
if (result.score >= 40) return "flag_for_review";
return "reject";
}Capa 5: comprobaciones de metadatos
Más allá de la entregabilidad, las API de verificación exponen metadatos útiles:
disposable— ¿es un dominio de email temporal conocido (Mailinator, 10MinuteMail, etc.)?role— ¿es una dirección de rol comoinfo@,noreply@oadmin@?suggestion— ¿el usuario quería escribirgmail.comen lugar degmai.com?free— ¿es un proveedor gratuito (Gmail, Outlook)?
Estas señales te permiten aplicar reglas distintas a tipos de dirección distintos: por ejemplo, aceptar direcciones de rol para contactos de facturación y rechazarlas en listas de marketing.
Cuándo usar la verificación de email
En el registro (en tiempo real)
El punto de integración de más valor. Verifica la dirección antes de crear la cuenta, mientras la persona sigue en el formulario.
// Server Action de Next.js
async function createAccount(formData: FormData) {
const email = formData.get("email") as string;
const result = await verifyEmail(email);
if (!result.valid) {
return { error: result.suggestion
? `¿Querías decir ${result.suggestion}?`
: "Esa dirección de email no parece válida." };
}
if (result.disposable) {
return { error: "No se permiten direcciones de email temporales." };
}
// continúa con la creación de la cuenta
}La verificación en tiempo real necesita una API por debajo de 100 ms: cualquier cosa más lenta bloquea el envío del formulario de forma perceptible.
Antes de un envío masivo
Antes de importar un CSV o de enviar a una lista fría, lanza un trabajo de verificación por lotes. Así proteges tu reputación como remitente antes de que haya daño.
const auth = { Authorization: `Bearer ${process.env.MAILBEAM_KEY}` };
// Envía la lista; la respuesta es un id de trabajo, no los resultados.
const job = await fetch("https://api.mailbeam.dev/v1/verify/batch", {
method: "POST",
headers: { ...auth, "Content-Type": "application/json" },
body: JSON.stringify({ emails }),
}).then((r) => r.json());
// Espera al webhook batch.completed, o consulta /v1/jobs/:id hasta que termine.
const { results } = await fetch(
`https://api.mailbeam.dev/v1/jobs/${job.job_id}/results?format=json`,
{ headers: auth }
).then((r) => r.json());
const deliverable = results
.filter((r) => r.status === "deliverable" && r.score >= 60)
.map((r) => r.email);Limpieza periódica de listas
Las direcciones de email se degradan a un ritmo de entre el 20 % y el 30 % al año. Direcciones que eran válidas hace 18 meses pueden rebotar hoy. Limpiar la lista cada 6 meses mantiene la tasa de rebote a raya sin tocar el frontend.
Qué hacer con el resultado
Un error habitual es tratar la verificación como una puerta binaria. El patrón mejor es un tratamiento por niveles:
| Resultado | Acción |
|---|---|
valid: true, score >= 70 | Aceptar de inmediato |
valid: true, score 40–69 | Aceptar, pero vigilar la interacción |
valid: true, score < 40, catchAll: true | Aceptar en flujos de alta intención; rechazar en captación en frío |
valid: false, suggestion | Mostrar la sugerencia al usuario |
disposable: true | Bloquear con un mensaje |
valid: false, sin sugerencia | Mostrar un error de validación genérico |
Resumen
La verificación de email es una cadena, no una comprobación única:
- Sintaxis — ¿es válido el formato?
- DNS/MX — ¿acepta correo el dominio?
- SMTP — ¿existe ese buzón concreto?
- Puntuación — en dominios catch-all, ¿cuánta confianza queda?
- Metadatos — ¿es desechable, de rol o una errata?
Ejecutar las cinco capas —con una API o construyendo tu propia cadena— es lo que separa una dirección real de una que lo parece.