Cómo depurar “Enviado pero no recibido” desde la perspectiva del equipo de producto
A todos nos ha pasado: en el panel aparece como sent, el log dice “OK”, el proveedor devolvió un “accepted”… y aun así el usuario insiste: “no me llegó nada”. Desde producto, esto se vuelve un tema delicado porque impacta activación, verificación, pagos, recuperación de contraseña y, en general, confianza.
La clave es entender una verdad incómoda pero útil: “enviado” casi nunca significa “entregado a la bandeja de entrada”. “Enviado” suele significar que tu sistema lo pasó al proveedor de email, y de ahí empieza otra historia: filtros, reputación, DNS, bloqueos, rate limits, bandejas, carpetas, y reglas internas del usuario.
1) Alinea definiciones: “Enviado”, “Aceptado”, “Entregado”, “Leído”
Antes de hacer hipótesis, define el idioma común para todo el equipo (producto, soporte, ingeniería). Si no, el incidente se convierte en “yo digo que sí / tú dices que no”.
- Enviado (app): tu sistema ejecutó la acción y disparó la llamada al proveedor o MTA.
- Aceptado (provider): el proveedor aceptó el mensaje para procesarlo, no garantiza entrega.
- Entregado (delivered): el proveedor afirma que lo entregó al servidor del destinatario (aun puede caer a spam).
- Rebotado (bounce): fallo de entrega (hard/soft), normalmente con razón y código.
- Diferido (deferred): el mensaje se reintenta; común por rate limit o reputación temporal.
- Abierto/clic: señales posteriores (y a veces no confiables si el cliente bloquea tracking).
Desde producto, lo más efectivo es diseñar el flujo interno para que puedas responder: “¿hasta qué punto del pipeline llegó?” con evidencia.
2) Empieza por el triage: ¿es un caso aislado o un incidente?
Lo primero es clasificar. Un caso aislado se atiende con soporte y diagnósticos puntuales. Un incidente requiere priorización y comunicación.
Señales de caso aislado
- Le pasa a un solo usuario o a un dominio específico (por ejemplo, un proveedor local).
- El resto de eventos (registro/OTP) se ven normales.
- El usuario puede recibir otros correos (no es problema de su cuenta).
Señales de incidente
- Sube el porcentaje de “sent” sin “delivered” o aumentan bounces/deferred.
- Se concentra en un tipo de email (OTP, reset, confirmación) o un template nuevo.
- Coincide con un cambio: dominio, proveedor, IP, contenido, o deploy.
Como equipo de producto, tu objetivo no es adivinar: es reducir incertidumbre rápido y evitar que el problema bloquee conversiones.
3) Recolecta evidencia correcta (sin marear al usuario)
Para depurar “sent but not received” necesitas datos consistentes. Un error típico es pedirle al usuario “¿revisaste spam?” y ya. Eso ayuda, pero rara vez cierra el caso.
Checklist mínimo para soporte (lo que sí sirve)
- Correo destino exacto (con dominio) y si es alias (por ejemplo, con +tag).
- Hora aproximada y zona horaria del intento.
- Tipo de email: OTP, reset, confirmación, factura, notificación.
- Captura del inbox: bandeja principal, spam, promociones (si aplica), y búsqueda por asunto.
- Si el usuario tiene reglas/filtros activos o redirecciones.
Si tu producto permite, agrega un botón tipo “reenviar email” con cooldown, y una opción de cambiar correo cuando el email no llega. Eso reduce tickets y mejora activación.
4) Depura por capas: del producto al proveedor y al dominio
Piensa el flujo como una cadena. En cada eslabón hay fallas típicas y señales específicas. La ventaja de este enfoque es que ordena el caos.
Capa A: aplicación (tu backend)
- ¿Se generó el evento? (ej. “send_verification_email”)
- ¿Se creó un mensaje? con ID interno, user_id, template_id, timestamp.
- ¿Hubo excepción? timeouts, reintentos, colas atoradas.
- ¿Se envió al proveedor? request_id, response_code, provider_message_id.
Acción de producto: pide a ingeniería que el panel o logs expongan un “delivery trace” por mensaje: message_id interno → provider_message_id → estado. Esto es oro para soporte y reduce “idas y vueltas”.
Capa B: proveedor de email (ESP/MTA)
Aquí se decide gran parte del destino del mensaje. “Accepted” es apenas el inicio. Lo ideal es revisar eventos del proveedor: delivered, bounced, deferred, spam complaint.
- Bounce hard: dirección inválida, dominio inexistente, bloqueos permanentes.
- Bounce soft: buzón lleno, throttling, problemas temporales del receptor.
- Deferred: reintentos por reputación, rate limit, greylisting.
- Delivered: llegó al servidor destino, pero puede caer a spam/promociones.
Acción de producto: define un “SLA interno” por tipo de email (OTP vs newsletter). Si es OTP, la experiencia debe tener fallback (SMS, push, TOTP, o cambiar correo) porque el email no siempre es instantáneo.
Capa C: configuración del dominio (DNS y autenticación)
Muchos problemas aparecen por DNS mal configurado o incompleto. Aunque producto no edite DNS, sí puede exigir un checklist de go-live y un monitor.
- SPF: autoriza qué servidores pueden enviar por tu dominio.
- DKIM: firma criptográfica para validar integridad y origen.
- DMARC: política de cómo tratar correos que fallen SPF/DKIM y reportes.
- Reverse DNS / PTR (si aplica): relevante si envías desde IPs propias.
Señal típica: el proveedor marca “delivered” o “accepted”, pero ciertos dominios receptores filtran agresivamente, especialmente cuando DKIM/SPF/DMARC no están bien o la alineación falla.
Capa D: reputación y contenido
Si de repente los correos dejan de llegar, muchas veces no es “un bug”, sino un tema de reputación (dominio/IP) o de contenido que activa filtros.
- Cambios recientes de asunto, texto, links o tracking.
- Palabras que suenan a phishing (“verify now”, “urgent”, “click here”).
- Enlaces acortados o dominios raros.
- HTML pesado, imágenes sin texto, o mala estructura.
Acción de producto: trata los cambios de plantilla como cambios de “infra de crecimiento”. Haz rollout gradual y monitorea tasa de entrega por dominio y por template.
Capa E: cliente del usuario (bandeja, filtros, carpetas)
Incluso con “delivered”, el mensaje puede aterrizar en spam, promociones, social o ser ocultado por reglas. En empresas, hay gateways (seguridad) que filtran antes de que el usuario lo vea.
- Reglas del usuario (filters) que archivan o redirigen.
- Bloqueos corporativos y firewalls de correo.
- Listas de remitentes bloqueados.
- Alias mal escritos o dominios con errores (typos).
5) Diseña un flujo de depuración “producto-friendly”
Un equipo de producto no tiene por qué meterse a 20 dashboards distintos para entender un caso. Lo ideal es definir un flujo estándar y repetirlo.
Paso 1: Identifica el mensaje
A partir del usuario y timestamp, encuentra el message_id interno. Debe existir una entidad “Message” con: destino, tipo, template, estado, intentos, y provider_message_id.
Paso 2: Clasifica el estado real
- Si no existe message_id: falla en app (evento no disparó o se perdió).
- Si existe pero no hay provider_message_id: falla al enviar o cola.
- Si hay provider_message_id pero no hay “delivered”: revisar bounces/deferred.
- Si hay “delivered”: enfocarse en spam/promociones/filtros del receptor.
Paso 3: Toma una acción inmediata (para salvar conversión)
Para OTP o confirmaciones, la prioridad es que el usuario complete el paso. Opciones típicas: reenviar con cooldown, ofrecer cambio de correo, permitir WhatsApp/SMS, o un método alterno temporal.
6) Pruebas controladas que sí ayudan
Para salir del “a mí me pasa / a mí no”, arma pruebas repetibles. En producto, lo valioso es convertir el caos en un experimento.
- Matrix de dominios: prueba con varios dominios (corporativos, gratuitos, regionales).
- Comparación por template: OTP vs reset vs bienvenida.
- Comparación por contenido: mismo envío con asunto alterno y sin links sospechosos.
- Timing: prueba en distintos horarios (rate limits o throttling pueden variar).
- Sin tracking: envío sin pixel/track para ver si cambia el filtrado.
Si ves que el problema se concentra en un dominio receptor, casi siempre es reputación o política del receptor. Si se concentra en un template nuevo, suele ser contenido o un bug de rendering.
7) Métricas que producto debería monitorear siempre
No puedes mejorar lo que no ves. Un dashboard mínimo para salud de deliverability debe existir, aunque el equipo sea pequeño.
- Acceptance rate: porcentaje de mensajes aceptados por el proveedor.
- Delivery rate: delivered / accepted, por tipo de email y por dominio receptor.
- Bounce rate: hard y soft separados.
- Deferred rate: indicador temprano de reputación o throttling.
- Complaint rate: reportes de spam (si aplica).
- Time-to-deliver: p50/p95 de entrega (clave para OTP).
Consejo práctico: separa métricas de correos transaccionales (OTP, reset) vs marketing. Si mezclas todo, no vas a entender qué está fallando.
8) Errores comunes (y cómo evitarlos)
“Si dice sent, ya estuvo”
No. “Sent” es una métrica interna. Necesitas eventos del proveedor para saber si se entregó o rebotó. Producto debe insistir en instrumentación correcta.
“Reenviemos 10 veces”
Reenviar sin control puede empeorar reputación y hacer que el usuario reciba una avalancha tarde. Implementa cooldown, y si es OTP, invalida códigos previos con claridad.
“Es culpa del usuario”
A veces el usuario tiene filtros, sí, pero el enfoque correcto es: dar herramientas para resolver. Un botón “no me llegó” con pasos guiados reduce fricción y tickets.
“Cambiar el contenido no afecta”
Cambia muchísimo. Un link mal visto o un asunto agresivo puede disparar filtros. Haz cambios de plantilla con el mismo cuidado que un cambio de pricing.
9) Playbook rápido para soporte (copy/paste interno)
Este mini playbook ayuda a que soporte y producto hablen el mismo idioma.
- Confirmar email destino y hora del intento.
- Buscar message_id interno y provider_message_id.
- Revisar estado del proveedor: delivered / bounced / deferred.
- Si delivered: pedir revisión de spam/promociones y filtros; sugerir búsqueda por remitente.
- Si deferred: reenviar con cooldown y sugerir esperar unos minutos; ofrecer método alterno si es OTP.
- Si bounce hard: pedir corrección del correo; sugerir otro dominio.
- Registrar patrón por dominio y template para detectar incidentes.
10) Cierre: lo importante para producto
“Enviado pero no recibido” es un problema clásico porque vive entre equipos: app, proveedor, DNS, reputación y usuario final. Desde producto, la meta no es volverte experto en deliverability de la noche a la mañana, sino construir un sistema que haga el diagnóstico rápido, repetible y accionable.
Si hoy solo puedes hacer una mejora, que sea esta: agrega trazabilidad por mensaje (IDs y estados) y un flujo dentro del producto para que el usuario pueda resolver sin abrir un ticket. Eso protege conversión, reduce soporte y mejora la percepción de confiabilidad.