Cómo funciona la detección de accept-all y cómo leer los resultados de Cold Leads
- Para quién
- Desarrolladores y equipos de operaciones que deciden qué hacer con los resultados risky
- El problema
- Algunos servidores de correo aceptan correo para cualquier dirección de su dominio, así que una comprobación de buzón no puede distinguir a una persona real de un nombre inventado. Otros servidores solo responden de forma temporal, o no se puede conectar con ellos en absoluto, y una simple etiqueta valid puede ocultar que el buzón nunca se comprobó.
- La solución
- Entienda el diálogo SMTP que ejecuta un verificador y qué significa cada respuesta; después lea el estado, la puntuación y los códigos de motivo que devuelve Cold Leads, incluidos los casos en que la comprobación del buzón no se ejecutó.
- Qué obtiene
- Una tabla de decisión que asigna una acción a cada código de motivo de Cold Leads, y un script que la aplica a una dirección.
Las direcciones, los identificadores y los resultados de los ejemplos son ilustrativos. example.com está reservado para documentación, así que una comprobación real de estas direcciones devuelve invalid.
Los ejemplos de código son iguales en todos los idiomas; sus comentarios están en inglés.
El diálogo SMTP detrás de una comprobación de buzón
Un verificador consulta los hosts MX del dominio y abre una conexión SMTP con uno de ellos en el puerto 25. Saluda al servidor, indica un remitente y un destinatario, lee la respuesta al destinatario y se despide antes de que se envíe ningún mensaje. La segunda sesión pregunta al mismo servidor por una dirección que no puede existir.
# Session 1: is the address accepted?
S: 220 mx1.example.com ESMTP
C: EHLO verifier.example.net
S: 250-mx1.example.com
S: 250 SIZE 52428800
C: MAIL FROM:<check@verifier.example.net>
S: 250 2.1.0 Sender OK
C: RCPT TO:<anna@example.com>
S: 250 2.1.5 Recipient OK <- accepted (a 550 here would mean: rejected)
C: QUIT <- no DATA command: nothing is delivered
S: 221 2.0.0 Bye
# Session 2: would the same server also accept an address that cannot exist?
S: 220 mx1.example.com ESMTP
C: EHLO verifier.example.net
S: 250 mx1.example.com
C: MAIL FROM:<check@verifier.example.net>
S: 250 2.1.0 Sender OK
C: RCPT TO:<zq7c41e09b2a6f5d@example.com>
S: 250 2.1.5 Recipient OK <- also accepted: the server accepts all addresses
C: QUIT
S: 221 2.0.0 ByeLos códigos de respuesta y lo que permiten concluir
Los códigos de respuesta se definen en el RFC 5321. El primer dígito lleva el significado: 2 es éxito, 4 un fallo temporal, 5 un fallo permanente.
| Respuesta | Significado en el RFC 5321 | Qué puede concluir un verificador |
|---|---|---|
| 220 | Servicio listo (el banner de saludo) | El servidor habla SMTP; la comprobación puede continuar. |
| 250, 251, 252 | Acción completada, se reenviará, o no se puede verificar pero se aceptará | El servidor aceptará ahora correo para este destinatario. En un servidor accept-all, eso no dice nada del buzón. |
| 421 | Servicio no disponible, cerrando el canal | Ninguna conclusión; el servidor está ocupado o rechaza al verificador. |
| 450, 451, 452 | Buzón no disponible, error local, almacenamiento insuficiente (temporal) | Ninguna conclusión. Los servidores con greylisting responden así a remitentes desconocidos y esperan un reintento minutos después. |
| 550 | Buzón no disponible, por ejemplo no encontrado, o rechazado por política | Normalmente el buzón no existe, pero un bloqueo por política al servidor que hace la comprobación tiene el mismo aspecto. |
| 551, 552, 553, 554 | Usuario no local, almacenamiento excedido, nombre de buzón no permitido, transacción fallida | Rechazo permanente de este destinatario en esta sesión. |
La prueba de accept-all, el greylisting y otros límites
- Accept-all: después de que se acepte la dirección real, el verificador pregunta al mismo servidor por una parte local aleatoria del mismo dominio. Si también se acepta, la primera aceptación no aporta información, y el resultado es risky con el motivo catch_all.
- Greylisting (RFC 6647): un servidor rechaza temporalmente las combinaciones desconocidas de remitente y destinatario con una respuesta 4xx y acepta un reintento más tarde. Una sola pasada solo ve el 4xx, y Cold Leads no espera ni reintenta dentro de una misma comprobación, así que el resultado es risky con smtp_unknown.
- Rebotes tardíos: algunos servidores aceptan a todos los destinatarios durante el diálogo y rechazan a los desconocidos solo después de haber aceptado un mensaje, con un rebote. Una comprobación no puede ver esto.
- Bloqueos por política: un servidor puede rechazar al propio host que hace la comprobación. Cold Leads trata los rechazos en el saludo, en EHLO o en MAIL FROM como smtp_unknown, y cualquier respuesta 500–559 en RCPT TO como mailbox_missing.
- Puerto 25: la comprobación necesita una conexión SMTP saliente. Muchas plataformas cloud y serverless bloquean el puerto 25 de salida, y entonces no hay ningún diálogo.
Qué devuelve Cold Leads y cuándo no se ejecutó la comprobación
Una comprobación ejecuta, en este orden: sintaxis (un fallo termina la comprobación), una lista integrada de 40 dominios de correo desechable, una lista de 25 nombres de rol (info, sales, support, admin y otros) y una consulta MX que, a falta de MX, recurre al registro A del dominio. La comprobación SMTP del buzón y de accept-all solo se ejecuta cuando Cold Leads puede abrir una conexión SMTP con uno de los dos primeros hosts MX. El array reasons siempre indica en qué caso está.
{
"email": "anna@example.com",
"status": "valid",
"score": 75,
"reasons": ["smtp_unreachable"],
"mx": "mx1.example.com",
"catch_all": false,
"disposable": false,
"role": false,
"checked_at": "2026-09-30T08:15:02.114Z",
"cached": false
}| Último motivo | status | score | Significado |
|---|---|---|---|
| ok | valid | 97 (80 para direcciones de rol) | El servidor aceptó la dirección y no aceptó la dirección aleatoria. |
| catch_all | risky | 60 | El servidor aceptó tanto la dirección como la dirección aleatoria. |
| mailbox_missing | invalid | 2 | El servidor rechazó al destinatario con una respuesta de 500 a 559. |
| smtp_unknown | risky | 50 | Sin respuesta concluyente: una respuesta temporal 4xx, un rechazo al verificador, un host MX en una red privada o una mezcla de hosts inaccesibles y dudosos. |
| smtp_unreachable | valid | 75 (65 para direcciones de rol) | Ningún host MX respondió en el puerto 25 desde el host que hace la comprobación. El dominio acepta correo, pero el buzón y accept-all no se probaron. |
| timeout | risky | 50, o 60 si la dirección se aceptó pero la prueba de accept-all no terminó | Se agotó el margen opcional de timeout_ms. El resultado no se guarda en caché. |
| no_mx | invalid | 0 | El dominio no tiene registro MX ni registro A. |
| syntax | invalid | 0 | La dirección no cumple las reglas de sintaxis; no se comprueba nada más. |
- disposable y role aparecen antes del último motivo cuando corresponden. Un dominio desechable deja el estado en risky con una puntuación de 40 (ok), 30 (smtp_unreachable) o 20 (smtp_unknown).
- catch_all solo es true cuando la prueba de accept-all se ejecutó y la dirección aleatoria se aceptó. Su valor false solo es informativo cuando el último motivo es ok o mailbox_missing; tras smtp_unreachable, smtp_unknown o timeout, accept-all no se probó. La herramienta MCP verify_email, alojada o local, devuelve catch_all como null en esos casos; la API REST devuelve false.
- cached es true cuando el resultado sale de la caché de 30 días; checked_at muestra entonces la hora de la comprobación original.
- Los resultados de las tareas masivas solo llevan el último código de motivo, como reason.
Una tabla de decisión y un script que la aplica
| Último motivo | Acción sugerida |
|---|---|
| ok | Enviar. |
| smtp_unreachable | Enviar con cuidado: lotes pequeños, y eliminar los rebotes duros de inmediato. El buzón no se confirmó. |
| catch_all | Revisar. Conservar solo si tiene otra señal de que la persona existe, como una respuesta o un patrón de dirección conocido en esa empresa. |
| smtp_unknown | Revisar. Una nueva comprobación dentro de 30 días devuelve el resultado en caché y cuesta igualmente un crédito. |
| timeout | Volver a comprobar con un timeout_ms mayor, de hasta 30 000; los timeouts no se guardan en caché. |
| mailbox_missing, no_mx, syntax | Descartar. |
| disposable presente | Descartar para prospección B2B. |
// node decide.mjs anna@example.com (Node 18+, COLDLEADS_API_KEY=sk_... in the environment)
const email = process.argv[2];
const res = await fetch("https://coldleads.app/api/v1/verify", {
method: "POST",
headers: { "x-api-key": process.env.COLDLEADS_API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ email, timeout_ms: 10000 }),
});
const r = await res.json();
if (!res.ok) throw new Error(`HTTP ${res.status}: ${r.error}`);
const final = r.reasons[r.reasons.length - 1];
// catch_all only carries information when a mail server answered the probe
const smtpAnswered = ["ok", "catch_all", "mailbox_missing"].includes(final);
const ACTION = {
ok: "send",
smtp_unreachable: "send carefully: domain accepts mail, mailbox not checked",
catch_all: "review: the server accepts every address",
smtp_unknown: "review: no definite answer from the server",
timeout: "check again with a larger timeout_ms",
mailbox_missing: "drop",
no_mx: "drop",
syntax: "drop",
};
console.log({
email: r.email,
status: r.status,
score: r.score,
reasons: r.reasons,
mailbox_checked: smtpAnswered,
catch_all: smtpAnswered ? r.catch_all : "not tested",
cached: r.cached,
action: r.disposable ? "drop: disposable domain" : ACTION[final] ?? "review",
});Límites y costes
- 1 crédito por verificación, incluidos los fallos de sintaxis y los resultados servidos desde la caché de 30 días.
- timeout_ms es opcional y acepta de 1 000 a 30 000 milisegundos; con cualquier otro valor la respuesta es 400 bad_timeout.
- La API forma parte del plan Business: $99 al mes con 10 000 créditos al mes; los paquetes extra de 1 000 créditos cuestan $5. 120 peticiones por minuto por clave.
Preguntas frecuentes
¿Por qué una dirección es valid si su buzón no se comprobó?
Porque no poder conectar con un servidor de correo desde el host que comprueba no es una prueba en contra de la dirección. El estado refleja las comprobaciones que se ejecutaron: la sintaxis es correcta y el dominio acepta correo. La puntuación más baja (75 en lugar de 97) y el motivo smtp_unreachable le indican que el propio buzón no se probó.
¿catch_all false significa que el dominio no es accept-all?
Solo si la prueba se ejecutó, lo que se ve en un último motivo ok o mailbox_missing. Tras smtp_unreachable, smtp_unknown o timeout, accept-all nunca se probó.
¿Cambia el resultado si vuelvo a comprobar una dirección risky?
En un plazo de 30 días, una nueva comprobación devuelve el resultado en caché (cached: true) y cuesta igualmente 1 crédito. Los resultados timeout no se guardan en caché, así que vale la pena volver a comprobarlos con un timeout_ms mayor.
¿Una verificación envía un correo a la persona?
No. El diálogo termina con QUIT justo después del paso del destinatario, antes del comando DATA, así que no se entrega ningún mensaje.