Guía

Cómo funciona la verificación de email, etapa por etapa

Qué comprueba un verificador de email, etapa por etapa: sintaxis, DNS y MX, la sonda SMTP y la puntuación, y qué campo de la API rellena cada una.

Ilustración de un hombre que presenta una verificación de email con una lupa y una lista de control

Respuesta corta

La verificación de email comprueba una dirección en cuatro etapas sin enviar ningún mensaje: valida y normaliza la sintaxis, consulta los registros MX del dominio, pregunta por SMTP al servidor de destino si aceptaría el buzón y después puntúa las pruebas. En BounceIntel cada etapa rellena una parte de la respuesta, desde syntax y mx hasta smtp, is_reachable y score.reason_codes.

Una lista llena de direcciones muertas cuesta más que los envíos que desperdicia. Cada rebote duro le dice a Gmail, Outlook y Yahoo que no sabes a quién escribes, y lo tienen en cuenta contra tu dominio y tu IP de envío. Si se acumula, la siguiente campaña acaba en spam, también para las direcciones buenas.

La verificación de email sirve para encontrar esas direcciones antes de que lo haga un proveedor de correo. Esta guía sigue una dirección a través de las cuatro etapas que ejecuta un verificador, en orden, y muestra qué parte de una respuesta de la API de BounceIntel rellena cada etapa. Al terminar deberías poder leer un resultado por tu cuenta en lugar de fiarte de una etiqueta de una sola palabra.

Qué es la verificación (y qué no es)

La verificación de email es una prueba automática que determina si una dirección puede recibir correo en este momento. Se apoya en dos fuentes: los registros DNS públicos y una breve conversación con el servidor de correo que recibiría el mensaje. No se envía ningún email. La conversación termina antes de que se transmita contenido alguno, así que la persona detrás de la dirección no ve nada.

Conviene ser igual de claro sobre lo que la verificación no puede decirte:

  • Si una persona lee el buzón. Un buzón puede existir y estar abandonado. Eso lo responden los datos de interacción, no la verificación.
  • Si la dirección seguirá funcionando el mes que viene. La gente cambia de trabajo y los buzones se eliminan. Un resultado describe el momento de la comprobación, y por eso cada resultado de BounceIntel incluye score.freshness, de fresh a expired.
  • Si una dirección es una trampa de spam. Los dominios conocidos por operar trampas se marcan, pero una trampa bien hecha está diseñada para parecer una dirección real que funciona.
  • Si tienes permiso para escribir a alguien. Es una cuestión de consentimiento, y ninguna prueba técnica puede responderla.

Etapa 1: sintaxis y normalización

La primera etapa nunca sale del verificador. Divide la dirección por la @ en una parte local y un dominio, y comprueba que ambas estén bien formadas. Una dirección que falla aquí se queda aquí: sin consulta DNS, sin conexión al servidor de nadie y con un resultado is_reachable: "invalid", el código de motivo invalid_syntax y una puntuación de 0.

Dos detalles deciden si una dirección poco habitual pasa:

  • Los dominios internacionalizados como münchen.de se convierten a su forma ASCII (xn--mnchen-3ya.de), y todas las etapas siguientes usan esa forma.
  • Las partes locales no ASCII como josé@example.com se consideran no válidas. Entregarles correo requiere una extensión SMTP que la mayoría de servidores de destino no ofrece, así que en la práctica rebotan.

La misma etapa prepara dos cosas que puedes usar de inmediato. syntax.normalized_email da la forma canónica del buzón: en Gmail, los puntos y todo lo que va después de un + no cambian el destino, así que [email protected] se normaliza como [email protected], lo que facilita detectar duplicados en una lista. Y cuando el dominio está a una o dos letras de un proveedor conocido, syntax.suggestion propone la corrección probable (gmial.com pasa a gmail.com) y se añade el código de motivo possible_typo.

CampoQué te indica
syntax.is_valid_syntaxSi la dirección está bien formada
syntax.username, syntax.domainLas dos mitades, tal como se verificaron
syntax.normalized_emailEl buzón canónico, para eliminar duplicados
syntax.suggestionUna corrección probable de errata, o null

Etapa 2: registros DNS y MX

Un dominio anuncia adónde debe ir su correo mediante registros MX. El verificador los consulta y la respuesta aparece en mx.records (los servidores de correo del dominio) y mx.accepts_mail. Un dominio sin registros MX no tiene adónde entregar, y el resultado lleva el código de motivo no_mx. Solo con eso se descarta una cantidad sorprendente de direcciones malas: dominios de empresa caducados, erratas que resultan estar registradas y dominios inventados escritos en formularios de registro.

En esta etapa también se compara la dirección con lo que se sabe de su dominio y de su parte local:

  • misc.is_disposable marca los servicios de buzones desechables (código de motivo disposable).
  • misc.is_role_account marca direcciones compartidas como info@ o support@ (role_account).
  • misc.is_spam_trap_domain marca dominios conocidos por operar trampas de spam (spam_trap).
  • Los proveedores gratuitos de consumo como Gmail se anotan con free_provider.

El host MX también identifica el proveedor de correo que hay detrás del dominio, como Google Workspace o Microsoft 365. Eso importa para la siguiente etapa, porque cada gran proveedor responde a la verificación a su manera.

Filas de racks de servidores en un centro de datos luminoso

Etapa 3: la sonda SMTP

Esta es la etapa que separa una verificación real de una simple comprobación de formato. El verificador se conecta a uno de los hosts MX del dominio en el puerto 25 y empieza la misma conversación que cualquier servidor de envío:

  1. Se presenta con EHLO.
  2. Indica un remitente con MAIL FROM.
  3. Indica la dirección que comprueba con RCPT TO.
  4. Lee la respuesta del servidor para ese destinatario y cierra la conexión.

El mensaje en sí, el paso DATA, nunca ocurre. Lo que importa es cómo respondió el servidor en el paso 3:

  • Aceptada (respuesta 250): smtp.is_deliverable es true.
  • Rechazada por usuario desconocido: smtp.is_deliverable es false, con el código de motivo smtp_undeliverable.
  • Rechazada porque la cuenta está desactivada: smtp.is_disabled es true (disabled_mailbox).
  • Rechazada porque el buzón está lleno: smtp.has_full_inbox es true (full_inbox).

En la misma conexión, BounceIntel pregunta después por un segundo destinatario: una dirección aleatoria de 15 caracteres en el mismo dominio que no puede existir. Si el servidor también la acepta, smtp.is_catch_all es true. Más abajo verás por qué importa.

"smtp": {
  "can_connect_smtp": true,
  "is_deliverable": true,
  "is_disabled": false,
  "has_full_inbox": false,
  "is_catch_all": false
}

No todos los servidores responden con claridad. Algunos retrasan a propósito a los remitentes desconocidos con un rechazo temporal (greylisting), otros limitan la frecuencia, otros rechazan conexiones de redes que no reconocen y otros simplemente no responden a tiempo. Nada de eso es un veredicto sobre la dirección, y BounceIntel no finge que lo sea. El resultado pasa a unknown, y un código de motivo nombra lo que ocurrió: transient_smtp, smtp_policy_block, smtp_timeout, smtp_network, smtp_ambiguous o smtp_unreachable.

Etapa 4: puntuación y códigos de motivo

La última etapa convierte todas las señales de las tres primeras en algo accionable. score.score va de 0 a 100 y corresponde a una categoría: 80–100 es valid, 50–79 es risky, 1–49 es unknown y 0 es invalid. score.confidence y score.confidence_level (high, medium, low o very_low) indican cuántas pruebas respaldan ese número, y score.safe_to_send da la respuesta de sí o no.

La parte sobre la que construir es score.reason_codes. Enumera cada señal que influyó en el resultado como cadenas estables sobre las que tu código puede decidir, y score.sub_reason nombra la que fue determinante. Junto a ella, bounce_risk.action recomienda qué hacer (send, send_with_caution, verify_manually o do_not_send) y bounce_risk.risk_factors explica esa recomendación, cada factor con su peso.

Este es un resultado real para una dirección de soporte compartida en un dominio que acepta todo el correo, reducido a los campos de puntuación:

{
  "input": "[email protected]",
  "is_reachable": "risky",
  "score": {
    "score": 55,
    "category": "risky",
    "confidence_level": "low",
    "reason_codes": ["catch_all", "role_account", "catch_all_high_risk"],
    "sub_reason": "catch_all",
    "safe_to_send": false
  },
  "bounce_risk": {
    "action": "verify_manually",
    "risk_factors": [
      { "signal": "smtp_is_catch_all", "contribution": 20, "description": "Corporate catch-all mailbox" },
      { "signal": "is_role_account", "contribution": 10, "description": "Role-based mailbox" }
    ]
  }
}

En tu código, decide según la recomendación y guarda los códigos de motivo para quien revise la dirección más adelante:

const { bounce_risk, score } = await res.json();

if (bounce_risk.action === "do_not_send") {
  suppress(email, score.reason_codes);
} else if (bounce_risk.action === "verify_manually") {
  queueForReview(email, score.reason_codes);
} else {
  accept(email);
}

La puntuación también tiene en cuenta el historial de tu propia cuenta con esa dirección en los últimos 180 días, y por eso una segunda comprobación puede volver con más confianza que la primera.

El punto ciego del catch-all

La etapa 3 tiene un límite que ningún verificador puede sortear. Algunos dominios están configurados para aceptar correo de cualquier dirección, exista o no. Pregunta a su servidor por jane.doe@ y dirá que sí; pregunta por una cadena de caracteres aleatorios y volverá a decir que sí. La conversación SMTP demuestra que el dominio recibe correo. No puede demostrar que exista el buzón que te interesa.

Para eso sirve la sonda con una dirección aleatoria. Cuando se acepta, BounceIntel marca el resultado como risky en lugar de safe, añade el código de motivo catch_all y gradúa el riesgo con un código de gravedad (catch_all_low_confidence, catch_all_medium_confidence o catch_all_high_risk) basado en pruebas como la configuración del dominio y los patrones de nombre ya verificados en esa empresa. Un verificador que llama «válidas» a estas direcciones está describiendo la cortesía del servidor, no el buzón.

Qué significan «safe / risky / invalid / unknown»

is_reachable es el resumen en una palabra de todo lo anterior. El verificador gratuito de este sitio muestra los mismos cuatro valores, con etiquetas traducidas.

is_reachableQué pasóQué hacer
safeEl servidor aceptó el buzón y no apareció ninguna señal de riesgoEnviar
riskyEl buzón parece existir, pero el dominio es catch-all, la dirección es desechable o genérica, el buzón está lleno o el dominio opera trampas de spamLeer los códigos de motivo y decidir
invalidSintaxis incorrecta, o el servidor rechazó o desactivó el buzónEliminarla
unknownEl servidor no dio una respuesta útil: tiempo agotado, greylisting o bloqueoConservarla y volver a comprobarla más tarde

Aquí es fácil equivocarse en dos cosas. unknown describe un servidor en un momento dado, no la dirección, así que borrar esas direcciones es tirar contactos buenos. Y risky agrupa situaciones muy distintas: un buzón lleno suele ser temporal, mientras que una dirección desechable nunca será de un cliente. La etiqueta es un resumen. La decisión corresponde a bounce_risk.action y score.reason_codes.

Cuándo usar tiempo real y cuándo masivo

Las cuatro etapas son las mismas en ambos casos. Lo que cambia es el momento.

La verificación en tiempo real, una dirección cada vez con POST /v1/check_email, va donde una dirección entra en tus sistemas: formularios de registro, pago, formularios de contacto comercial o un comercial escribiendo en el CRM. La persona sigue ahí, así que una errata detectada por syntax.suggestion se puede corregir en el momento en lugar de convertirse en un rebote la semana siguiente. Llama a la API desde tu servidor, nunca desde código del navegador con tu clave, y trata unknown como «aceptar y volver a comprobar más tarde» para que un servidor lento nunca bloquee un registro real.

La verificación masiva, con POST /v1/bulk o subiendo un CSV en el panel, va antes de un envío: una newsletter a una lista que llevaba tiempo sin usarse, una importación de una feria o de un nuevo CRM, o una revisión periódica de una base antigua. Cada fila vuelve con los mismos campos. Las listas se degradan a medida que la gente cambia de empresa, así que verifica todo lo que no se haya comprobado en unos meses antes de enviarle correo.

Tiempo realMasiva
EndpointPOST /v1/check_emailPOST /v1/bulk y después consultar el trabajo
Mejor momentoCuando se recoge la direcciónAntes de una campaña o tras una importación
Beneficio principalErratas corregidas con la persona todavía presenteDirecciones muertas eliminadas antes de rebotar
Qué hacer con unknownAceptarla y volver a comprobarApartarla de este envío y volver a comprobar

Comprueba una dirección y lee el resultado

Todo lo que muestra el verificador sale de la misma API a la que llamaría tu código. La documentación de la API describe cada campo de la respuesta, la verificación masiva cubre listas completas y los precios muestran cuánto cuesta un plan con acceso a la API.

Protege tu reputación como remitente antes del próximo envío.

Verifica una lista, conecta la API a tu formulario de registro y mantén las direcciones malas lejos de tus campañas.