Encabezados de correo: Leer “Received” correctamente — rastrea dónde falla la entrega

¿Te fue útil?

Tienes un trabajo: explicar por qué un correo no llegó. No “probablemente fue filtrado como spam.” No “Microsoft/Gmail tiene problemas.” Necesitas señalar el salto donde el mensaje dejó de comportarse como mensaje y empezó a comportarse como un rumor.

La forma más rápida es la cadena de cabeceras Received. Es lo más parecido que tiene el correo a una caja negra: desordenada, inconsistente y ocasionalmente manipulada. Pero si la lees como un SRE lee un trazo distribuido, normalmente puedes determinar el dominio de la falla en minutos.

El modelo mental: qué es realmente una cabecera Received

El correo funciona salto a salto. Cada servidor SMTP que acepta un mensaje y lo pasa adelante debería sellar una nueva cabecera Received en la parte superior. Así obtienes una pila: el salto más reciente arriba, el más antiguo abajo.

Puedes pensar en cada salto como un pequeño contrato: “Yo, servidor X, recibí este mensaje de Y a la hora T usando el protocolo P y lo entrego al siguiente paso.” El contrato lo escribe X, no Y. Esa es la clave. El salto que escribe la línea es el que puedes interrogar con logs y métricas.

Si estás habituado al trazado en sistemas distribuidos, esto es la versión de correo de una lista de spans sin IDs. No hay ID de traza global. No hay un esquema canónico. Mucha puntuación creativa. Aun así, si la lees con el escepticismo adecuado, es suficiente.

Dos reglas que te salvarán de ir a reuniones con las manos vacías:

  1. Las líneas Received son evidencia sólo dentro de fronteras de confianza. Cualquier cosa por debajo de tu primer ingreso confiable puede ser falsificada.
  2. La mayoría de los casos de “correo perdido” son en realidad casos de “correo retrasado”. Tu trabajo es decidir dónde se introdujo el retraso y si es esperado (reintento) o patológico (colapso de colas, bloqueo por políticas, enrutamiento erróneo).

Datos interesantes y contexto histórico (breve, concreto)

  • SMTP es anterior a la mayoría de las autenticaciones modernas. El protocolo central se estandarizó a principios de los años 80; los añadidos de autenticación llegaron décadas después.
  • Las cabeceras Received son anteriores al spam. Se diseñaron para trazar y depurar el enrutamiento de correo, no para entornos adversarios.
  • El formato de las cabeceras es “algo estructurado”, no estricto. Se anima a los servidores a añadir detalles, así que verás cláusulas específicas de proveedores y espacios en blanco creativos.
  • Las zonas horarias son una fuente recurrente de problemas. Los saltos pueden mostrar tiempos “yendo hacia atrás” cuando un servidor tiene el reloj mal o usa offsets raros.
  • Message-ID no garantiza unicidad. La mayoría de los MTA generan IDs sensatos, pero clientes defectuosos y algunos appliances los reutilizan o los dañan.
  • El greylisting se volvió popular como táctica anti-spam de bajo esfuerzo. Intencionalmente retrasa los primeros intentos de entrega; las cabeceras Received a menudo muestran huecos por reintentos.
  • SPF verifica el remitente del sobre, no el From visible. La gente aún confunde esto, incluidas personas con “Director” en su título.
  • DKIM firma cabeceras y cuerpo, pero no toda la “verdad”. No valida la cadena Received; valida la integridad desde quien firma.
  • Los proveedores grandes ejecutan múltiples capas de manejo de correo. Puedes ver saltos internos que no se mapean 1:1 con lo que crees que es “el servidor de correo”.

Anatomía de una línea Received: campos que importan, campos que mienten

Una cabecera Received típica puede verse así (no te encariñes; tu realidad será peor):

cr0x@server:~$ sed -n '1,8p' message.headers
Received: from mail-out.example.net (mail-out.example.net [203.0.113.10])
        by mx.google.com with ESMTPS id x12-20020a17090a000000b003e000000000si1234567pja.12.2026.01.04.10.11.12
        for <user@example.com>
        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
        Sun, 04 Jan 2026 10:11:12 -0800 (PST)
Received: from app01.corp.example (app01.corp.example [10.20.30.40])
        by mail-out.example.net (Postfix) with ESMTPA id 4A1B2C3D4E
        for <user@example.com>; Sun, 04 Jan 2026 18:11:10 +0000 (UTC)

Lo que importa:

  • “by”: el servidor que añadió esta línea. Este es tu ancla en los logs. Si no puedes acceder a logs en “by”, tus opciones de troubleshooting disminuyen.
  • “from”: quién se conectó a “by”. Puede ser un hostname + IP. El hostname suele ser reverse DNS o lo que el par afirmó. La IP es más difícil de falsificar a nivel TCP (pero NAT y proxies lo complican).
  • Cláusula de protocolo (with ESMTP, with ESMTPS, with LMTP): te indica si se usó TLS y si hubo autenticación (ESMTPA suele indicar envío autenticado).
  • Marca de tiempo: crítica para analizar retrasos. Trátala como cualquier timestamp en sistemas distribuidos: confíala solo si los relojes son sensatos.
  • IDs de cola: Postfix, Exchange y otros suelen poner un ID interno. Son oro porque se mapean directamente a los logs.

Lo que suele mentir o confundir:

  • Nombres proporcionados por el cliente. Algunos MTA incluyen lo que el cliente dijo en HELO/EHLO. Eso no es identidad; es una cadena.
  • Saltos inferiores no confiables. Todo lo añadido por un servidor fuera de tu perímetro de confianza puede ser fabricado por un spammer o un relay defectuoso.
  • Exceso de confianza en el formateo. Algunos servidores envuelven líneas raro; algunos omiten campos; otros meten todo en una línea como si les pagaran por carácter.

Broma #1: Las cabeceras de correo son como las líneas de tiempo de un incidente: todos añaden una línea, y de algún modo sigue sin responder “¿quién tocó prod por última vez?”

Reglas de orden: de abajo hacia arriba, con aristas afiladas

El salto más antiguo está abajo. El salto más nuevo está arriba. Eso significa que lees las cabeceras Received de abajo hacia arriba para seguir el viaje del mensaje hacia adelante en el tiempo.

Aristas afiladas:

  • Desincronización de relojes puede hacer que el tiempo parezca viajar hacia atrás. Si un servidor está cinco minutos fuera, verás tiempos de tránsito negativos. No te asustes; verifica NTP.
  • La entrega local puede no añadir una línea Received. A veces la entrega final es a un almacén de buzón o una etapa de filtrado sin una nueva cabecera.
  • Los gateways pueden colapsar saltos. Un gateway de seguridad puede aceptar correo entrante y luego reinyectarlo internamente, añadiendo líneas que parecen “from gateway by internal-mx”, pero no verás la complejidad upstream.
  • Listas de correo y reenviadores pueden crear mensajes “nuevos” con Message-IDs distintos y cabeceras cambiadas, aunque el contenido visible para el usuario parezca el mismo.

Fronteras de confianza: qué líneas Received puedes creer

Las únicas cabeceras Received que deberías tratar como fiables son las añadidas por sistemas que controlas: tu MX, tu gateway de entrada, tus relays internos, tu servicio de submission.

Todo lo anterior del primer salto confiable es “evidencia aportada por el usuario”. Útil, pero no admisible. Esto no es paranoia; es martes.

Enfoque práctico:

  1. Identifica el primer salto que controlas. Normalmente es tu MX, gateway de entrada o el ingreso del proveedor hospedado.
  2. Marca todo lo que esté por debajo como cadena no confiable.
  3. Correlaciona el salto confiable con logs usando ID de cola, Message-ID y timestamp.

Si operas un sistema que recibe correo directamente desde Internet, exige prácticas sensatas que hagan que tus propias líneas Received sean valiosas: incluye IP conectante, incluye info TLS cuando esté presente, incluye ID de cola y mantiene los relojes precisos.

Retardos: cómo detectar colas, reintentos, greylisting y presión atrás

Las “rupturas” de entrega suelen ser simplemente “esperas” de entrega. Tu trabajo es clasificar la espera:

1) Retraso en cola en el lado del remitente

Síntoma: gran hueco temporal entre la línea Received más inferior “cliente → MTA remitente” y el siguiente salto “MTA remitente → MX destinatario”.

Interpretación: el remitente aceptó el mensaje pero no lo entregó de inmediato. Las causas incluyen congestión de cola saliente, problemas DNS, límites de velocidad, bloqueos por políticas o que el remitente esté siendo sometido a throttling por los destinatarios.

2) Greylisting / devoluciones temporales

Síntoma: intentos repetidos reflejados en logs (no normalmente en cabeceras), con huecos de minutos hasta la aceptación. En las cabeceras puede aparecer solo el intento final, con una marca de tiempo mucho después del envío original que afirma el usuario.

Interpretación: el destinatario rechazó los primeros intentos con un 4xx. El remitente reintentó. Esto es más o menos normal en algunos ecosistemas, pero es una decisión de negocio disfrazada de SMTP.

3) Colas entrantes en tu gateway o MX

Síntoma: el mensaje es aceptado por tu perímetro pero llega tarde al buzón. Las cabeceras muestran tránsito rápido hasta tu gateway, luego saltos internos “by” con timestamps que avanzan lentamente.

Interpretación: filtrado interno, escaneo de contenido, presión en el almacén de buzones o problemas de enrutamiento interno. Aquí es donde tus dashboards importan.

4) Retenciones por políticas y cuarentena

Síntoma: las cabeceras muestran aceptación, pero el usuario nunca ve el mensaje. Los logs muestran que fue desviado a cuarentena, moderación o retenido para revisión manual.

Interpretación: no es una “ruptura de entrega”. Es una decisión de política. Trátalo como tal: encuentra la regla, justifícala, ajústala si hace falta.

5) Eliminación silenciosa (raro, pero real)

Las eliminaciones verdaderamente silenciosas son menos comunes de lo que la gente piensa porque SMTP es transaccional. Pero ocurren dentro de ecosistemas: filtros pueden descartar, buzones pueden rechazar, y algunos sistemas mal configurados aceptan y luego pierden el mensaje. Buscas dónde ocurre el último recibo fiable y luego qué hizo el sistema después.

Señales de seguridad en Received: SPF, DKIM, DMARC, ARC y por qué importan en las rupturas de entrega

Las cabeceras Received te dicen la ruta. Los resultados de autenticación te indican si la historia de identidad del mensaje coincide con la realidad — al menos lo suficiente para que los proveedores lo acepten.

Authentication-Results es tu amigo

Muchos sistemas añaden una cabecera Authentication-Results. Puede incluir evaluaciones de SPF, DKIM y DMARC. La escribe un receptor, así que dentro de las fronteras de confianza es valiosa.

Qué hacer con ella:

  • Si SPF falla, revisa el registro SPF del dominio del remitente del sobre y la alineación con la IP remitente.
  • Si DKIM falla, revisa el dominio firmante, el selector, problemas de canonicalización y si un intermedio modificó el cuerpo/cabeceras.
  • Si DMARC falla, revisa la alineación entre el dominio From y los dominios SPF/DKIM; también revisa la política (reject/quarantine/none).

ARC puede explicar “el reenvío rompió mi DMARC”

Los reenviadores y listas de correo suelen romper DKIM (al modificar el mensaje) y SPF (porque reenvían desde su propia IP). ARC (Authenticated Received Chain) permite a intermediarios preservar resultados de autenticación upstream. Al diagnosticar fallos de entrega por reenvío, la presencia y validación de ARC puede marcar la diferencia entre “misterioso” y “obvio”.

Usa señales de autenticación para decidir si la ruptura fue por transporte o por política. Si el transporte parece bien pero DMARC falla con política estricta, no estás depurando redes. Estás depurando identidad y alineación.

Guion de diagnóstico rápido

¿Quieres velocidad? Deja de leer la novela de cabeceras. Haz esto:

Primero: identifica el último salto “by” confiable

  1. Localiza la línea Received más alta escrita por el sistema destinatario que confías (tu MX / gateway / ingreso del proveedor).
  2. Extrae: marca de tiempo, ID de cola (si existe), IP conectante y “for <recipient>”.
  3. Decisión: si no tienes un salto confiable, no tienes evidencia. Pide al remitente las cabeceras completas desde su elemento enviado, o solicita logs a su admin.

Segundo: clasifica el dominio de la falla

  • No aceptado por tu perímetro: no hay línea Received confiable → lado del remitente o transporte Internet (DNS, enrutamiento, bloqueos por reputación).
  • Aceptado por perímetro pero no entregado: existe Received confiable → tu pipeline interno (filtrado, buzón, enrutamiento, cuarentena).
  • Entregado pero “desaparecido”: las cabeceras muestran entrega final pero el usuario no lo encuentra → reglas cliente, búsqueda en buzón, carpetas o archivado descendente.

Tercero: mide retrasos salto a salto

  1. Lee las cabeceras Received de abajo a arriba dentro del segmento confiable.
  2. Calcula deltas de tiempo entre saltos adyacentes.
  3. Decisión: el salto con el mayor delta es donde buscar colas, throttling o retenciones.

Cuarto: correlaciona con logs usando IDs

IDs de cola, Message-ID y la dirección del destinatario son tus claves de unión. Escoge dos; usa tres si puedes.

Quinto: decide qué vas a decir a las personas

No digas “el correo está retrasado.” Di “aceptado por nuestro gateway a las 10:11:12 PST, retenido en el escaneo de contenido durante 34 minutos por cola del sandbox de adjuntos, luego entregado.” La gente odia la incertidumbre más que las malas noticias.

Tareas prácticas (con comandos, significado de salida y decisiones)

Abajo hay tareas reales que puedes ejecutar en MTA basados en Linux y toolboxes comunes. Cada tarea incluye: comando, salida de muestra, qué significa y la decisión que tomas.

Tarea 1: Extraer y ver sólo la cadena Received (sanidad rápida)

cr0x@server:~$ awk 'BEGIN{RS="";FS="\n"} {for(i=1;i<=NF;i++) if($i ~ /^Received:/) print $i}' message.eml
Received: from app01.corp.example (app01.corp.example [10.20.30.40]) by mail-out.example.net (Postfix) with ESMTPA id 4A1B2C3D4E for <user@example.com>; Sun, 04 Jan 2026 18:11:10 +0000 (UTC)
Received: from mail-out.example.net (mail-out.example.net [203.0.113.10]) by mx.google.com with ESMTPS id x12-... for <user@example.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 04 Jan 2026 10:11:12 -0800 (PST)

Qué significa: Tienes una cadena corta; probablemente sólo dos saltos en la muestra. En correo real verás más.

Decisión: Si la cadena es inesperadamente corta, sospecha que el mensaje se generó dentro de un proveedor, o que un gateway o cliente eliminó cabeceras. Pide la “cabecera original completa” desde la UI del buzón, no una copia reenviada.

Tarea 2: Identificar el primer salto confiable (patrón para tu MX/gateway)

cr0x@server:~$ grep -n '^Received:' -n message.eml | head
12:Received: from mail-out.example.net (mail-out.example.net [203.0.113.10]) by mx-inbound.corp.example with ESMTPS id 9F3A2B1C for <user@corp.example>; Sun, 04 Jan 2026 18:11:12 +0000 (UTC)
18:Received: from unknown (HELO sender.example) (198.51.100.23) by mail-out.example.net with SMTP; Sun, 04 Jan 2026 18:11:10 +0000 (UTC)

Qué significa: La línea “by mx-inbound.corp.example” es tu ingreso confiable. Todo lo por debajo podría ser real o ficción.

Decisión: Comienza la correlación desde ese ID de cola (9F3A2B1C) y la marca de tiempo. Ignora el “unknown (HELO …)” upstream para decisiones de culpabilidad a menos que coincida con otra evidencia.

Tarea 3: Parsear timestamps y calcular retrasos por salto (trazo distribuido barato)

cr0x@server:~$ grep '^Received:' -n message.eml
12:Received: ...; Sun, 04 Jan 2026 18:11:12 +0000 (UTC)
18:Received: ...; Sun, 04 Jan 2026 18:11:10 +0000 (UTC)

Qué significa: Dos segundos desde el relay remitente hasta tu MX. Eso es normal.

Decisión: Si ves minutos u horas entre saltos confiables adyacentes, ese es tu cuello de botella. Ve al MTA/gateway responsable del salto tardío y revisa colas y devoluciones.

Tarea 4: En Postfix, buscar logs por ID de cola

cr0x@mailgw01:~$ sudo grep '9F3A2B1C' /var/log/mail.log | tail -n 5
Jan  4 18:11:12 mailgw01 postfix/smtpd[22110]: 9F3A2B1C: client=mail-out.example.net[203.0.113.10], sasl_method=PLAIN, sasl_username=
Jan  4 18:11:13 mailgw01 postfix/cleanup[22122]: 9F3A2B1C: message-id=<CAO9z9kGx12345@mail-out.example.net>
Jan  4 18:11:14 mailgw01 postfix/qmgr[1211]: 9F3A2B1C: from=<noreply@example.net>, size=48212, nrcpt=1 (queue active)
Jan  4 18:47:02 mailgw01 postfix/smtp[23110]: 9F3A2B1C: to=<user@corp.example>, relay=mbx01.corp.example[10.0.10.25]:25, delay=2149, delays=0.2/0.1/2130/18, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as 7C8D9E0F)
Jan  4 18:47:02 mailgw01 postfix/qmgr[1211]: 9F3A2B1C: removed

Qué significa: El mensaje estuvo mayormente en cola antes de entregarlo a mbx01. El desglose delays=0.2/0.1/2130/18 indica tiempo en diferentes fases; el enorme tercer número es la pista clara.

Decisión: Deja de culpar al remitente. Investiga por qué tu gateway retuvo el mensaje ~35 minutos: integración con filtro de contenido, límites de velocidad, respuestas lentas del buzón downstream o retención por política.

Tarea 5: Comprobar la cola de Postfix por acumulación

cr0x@mailgw01:~$ mailq | head -n 20
-Queue ID-  --Size-- ----Arrival Time---- -Sender/Recipient-------
9F3A2B1C       48212 Sun Jan  4 18:11:12  noreply@example.net
                                         user@corp.example
A1B2C3D4        1200 Sun Jan  4 18:12:01  alerts@vendor.example
                                         oncall@corp.example

Qué significa: Hay una cola activa. La presencia de múltiples mensajes alrededor del mismo tiempo sugiere un retraso sistémico, no un caso aislado.

Decisión: Si la cola crece y la antigüedad aumenta, trátalo como incidente: revisa disponibilidad downstream, latencia de filtros de contenido, resolución DNS y límites de velocidad.

Tarea 6: Distribución de edad de la cola en Postfix (¿es “correo viejo”?)

cr0x@mailgw01:~$ sudo postqueue -p | awk 'BEGIN{count=0} /^[A-F0-9]/ {id=$1} /[0-9][0-9]:[0-9][0-9]:[0-9][0-9]/ {count++} END{print "queue_entries="count}'
queue_entries=42

Qué significa: Conteo rápido y sencillo de entradas en cola. No perfecto, pero es un detector.

Decisión: Si las entradas suben respecto a la línea base, revisa por qué el correo no se drena: timeouts de relay= downstream, fallos en handshake TLS o un servicio de filtrado lento.

Tarea 7: Verificar DNS para MX del destinatario y reverse DNS del remitente (básicos de reputación)

cr0x@server:~$ dig +short MX corp.example
10 mx-inbound.corp.example.
cr0x@server:~$ dig +short A mx-inbound.corp.example
192.0.2.55
cr0x@server:~$ dig +short -x 203.0.113.10
mail-out.example.net.

Qué significa: MX resolvible; el remitente tiene PTR. La falta de PTR o nombres desajustados pueden desencadenar receptores más estrictos y provocar fallos temporales o colocación en spam.

Decisión: Si la resolución MX es inestable o falta PTR, arregla DNS. Si no puedes arreglar el PTR del remitente, espera variabilidad en la entrega y usa vías de envío autenticadas.

Tarea 8: Comprobar alineación SPF del dominio del remitente del sobre

cr0x@server:~$ dig +short TXT example.net | sed -n '1,3p'
"v=spf1 ip4:203.0.113.0/24 include:_spf.provider.example -all"

Qué significa: El dominio declara qué IPs pueden enviar. Si tu Received muestra una IP remitente distinta, SPF fallará en receptores que aplican la política.

Decisión: Si SPF no incluye las IPs reales de salida, actualiza SPF. Si el remitente usa un tercero, asegúrate de incluirlos y no exceder límites de búsquedas DNS.

Tarea 9: Inspeccionar Authentication-Results desde el lado del destinatario

cr0x@server:~$ grep -i '^Authentication-Results:' -n message.eml | head -n 2
25:Authentication-Results: mx-inbound.corp.example; spf=pass smtp.mailfrom=noreply@example.net; dkim=pass header.d=example.net; dmarc=pass header.from=example.net

Qué significa: El transporte puede fallar aún, pero las comprobaciones de identidad pasaron. Eso desplaza el foco lejos del rechazo por DMARC y hacia enrutamiento, colas o filtrado de contenido.

Decisión: Si DMARC falla y la política es estricta, no pierdas horas en trazados de red. Corrige la alineación o ajusta la política para remitentes legítimos.

Tarea 10: En Exchange (o logs estilo Exchange), buscar en tracking de mensajes (ejemplo colector Linux)

cr0x@loghost:~$ grep -R "CAO9z9kGx12345@mail-out.example.net" /var/log/exchange-message-tracking.log | tail -n 3
2026-01-04T18:11:12Z,RECEIVE,SMTP,MBX01,user@corp.example,CAO9z9kGx12345@mail-out.example.net,192.0.2.55
2026-01-04T18:45:50Z,AGENTINFO,TRANSPORT,MBX01,user@corp.example,CAO9z9kGx12345@mail-out.example.net,ContentFilter=SandboxWait
2026-01-04T18:47:02Z,DELIVER,STOREDRIVER,MBX01,user@corp.example,CAO9z9kGx12345@mail-out.example.net,Inbox

Qué significa: El mensaje se recibió rápidamente, luego estuvo esperando sandboxing. Es un retraso de procesamiento interno.

Decisión: Escala o ajusta el sandbox/AV, o exime flujos de bajo riesgo si el negocio lo tolera. No le pidas al remitente que “reenvíe” como estrategia.

Tarea 11: Confirmar fallos de negociación TLS cuando un salto muestra ESMTPS pero la entrega se estanca

cr0x@mailgw01:~$ sudo grep -E "TLS|handshake|SSL" /var/log/mail.log | tail -n 5
Jan  4 18:20:11 mailgw01 postfix/smtp[24001]: warning: TLS library problem: error:0A000126:SSL routines::unexpected eof while reading
Jan  4 18:20:11 mailgw01 postfix/smtp[24001]: warning: TLS policy lookup failed
Jan  4 18:20:11 mailgw01 postfix/smtp[24001]: warning: TLS handshake failed for mbx01.corp.example[10.0.10.25]:25: unexpected EOF
Jan  4 18:20:12 mailgw01 postfix/smtp[24001]: 9F3A2B1C: to=<user@corp.example>, relay=mbx01.corp.example[10.0.10.25]:25, delay=540, delays=0.2/0.1/520/20, dsn=4.4.2, status=deferred (lost connection with mbx01.corp.example[10.0.10.25] while sending end of data -- message may be sent more than once)
Jan  4 18:20:12 mailgw01 postfix/qmgr[1211]: 9F3A2B1C: deferred: lost connection with mbx01.corp.example[10.0.10.25] while sending end of data

Qué significa: Tu gateway no puede completar TLS o la conexión con downstream. Eso causará devoluciones y largas colas, que los usuarios interpretarán como “correo desaparecido”.

Decisión: Arregla el desajuste de políticas TLS, problemas de certificado o resets del balanceador. Si hace falta, relaja temporalmente la exigencia TLS internamente mientras remiendas (con cuidado y controles compensatorios).

Tarea 12: Validar hora del sistema local y NTP (para dejar de depurar viajes en el tiempo)

cr0x@mailgw01:~$ timedatectl
               Local time: Sun 2026-01-04 18:52:10 UTC
           Universal time: Sun 2026-01-04 18:52:10 UTC
                 RTC time: Sun 2026-01-04 18:52:10
                Time zone: UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

Qué significa: El reloj está sano. Si no lo estuviera, las marcas de tiempo Received se vuelven poco fiables y perseguirás el salto equivocado.

Decisión: Si el reloj no está sincronizado, arregla NTP primero. Luego reevalúa la línea temporal de cabeceras.

Tarea 13: Confirmar si un mensaje está en cuarentena (ejemplo: BD/log de cuarentena de gateway)

cr0x@mailgw01:~$ sudo grep -R "CAO9z9kGx12345@mail-out.example.net" /var/log/mailgw/quarantine.log | tail -n 2
2026-01-04T18:12:02Z action=quarantine reason="AttachmentSandboxPending" queue_id=9F3A2B1C msgid=CAO9z9kGx12345@mail-out.example.net
2026-01-04T18:46:55Z action=release reason="SandboxVerdictClean" queue_id=9F3A2B1C msgid=CAO9z9kGx12345@mail-out.example.net

Qué significa: El mensaje no “falló”. Fue retenido. Ahora tienes una explicación clara y un control de ajuste.

Decisión: Si la cuarentena es demasiado lenta para necesidades del negocio, escala el sandbox o ajusta la política para remitentes y tipos de archivo conocidos como seguros.

Tarea 14: Rastrear un mensaje usando Message-ID a través de múltiples hosts (grep + ssh)

cr0x@ops:~$ for h in mailgw01 mailgw02 mbx01; do echo "== $h =="; ssh $h "sudo grep -R \"CAO9z9kGx12345@mail-out.example.net\" /var/log/mail.log | tail -n 2"; done
== mailgw01 ==
Jan  4 18:11:13 mailgw01 postfix/cleanup[22122]: 9F3A2B1C: message-id=<CAO9z9kGx12345@mail-out.example.net>
Jan  4 18:47:02 mailgw01 postfix/smtp[23110]: 9F3A2B1C: to=<user@corp.example>, relay=mbx01.corp.example[10.0.10.25]:25, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as 7C8D9E0F)
== mailgw02 ==
== mbx01 ==
Jan  4 18:47:02 mbx01 postfix/smtpd[18001]: 7C8D9E0F: client=mailgw01.corp.example[10.0.10.5]
Jan  4 18:47:03 mbx01 postfix/local[18012]: 7C8D9E0F: to=<user>, orig_to=<user@corp.example>, relay=local, status=sent (delivered to mailbox)

Qué significa: Traza de extremo a extremo en tu estate. La ausencia en mailgw02 sugiere que el enrutamiento no lo involucró.

Decisión: Si el Message-ID aparece en ingreso pero no en el buzón, enfoca en la etapa de relay. Si aparece en el buzón y el usuario no lo encuentra, cambia a reglas del cliente, foldering e indexación de búsqueda.

Tarea 15: Inspeccionar latencia del filtro de contenido (ejemplo: logs de estadísticas de amavis/milter)

cr0x@mailgw01:~$ sudo grep -E "milter|amavis|scan time" /var/log/mail.log | tail -n 5
Jan  4 18:12:05 mailgw01 amavis[3101]: (03101-02) Passed CLEAN, [203.0.113.10] [203.0.113.10] <noreply@example.net> -> <user@corp.example>, Queue-ID: 9F3A2B1C, Message-ID: <CAO9z9kGx12345@mail-out.example.net>, Hits: -, size: 48212, queued_as: 9F3A2B1C, 92 ms
Jan  4 18:45:49 mailgw01 milter-sandbox[4021]: queue_id=9F3A2B1C verdict=pending wait=2010s
Jan  4 18:46:55 mailgw01 milter-sandbox[4021]: queue_id=9F3A2B1C verdict=clean wait=2066s

Qué significa: El escaneo AV es rápido; el sandbox es el cuello de botella y lo deja explícito.

Decisión: Ajusta concurrencia del sandbox, cambia qué se sandboxea o implementa patrones de entrega asíncrona si tu gateway lo permite (entregar y luego remediar, si la política lo autoriza).

Tarea 16: Verificar que las reglas del buzón del usuario no “se comieron” el correo (ejemplo auditoría reglas server-side)

cr0x@mbx01:~$ sudo grep -R "user@corp.example" /var/log/mailbox-rules.log | tail -n 5
2026-01-04T18:47:05Z user=user@corp.example rule="Move vendor mail" match="From contains example.net" action="move" folder="Vendors"
2026-01-04T18:47:05Z user=user@corp.example msgid=CAO9z9kGx12345@mail-out.example.net result="moved" folder="Vendors"

Qué significa: La entrega tuvo éxito; falló la visibilidad. El mensaje está en otra carpeta.

Decisión: Deja de tratarlo como un incidente del MTA. Ayuda al usuario a arreglar reglas o ajusta los valores por defecto corporativos.

Tres mini-historias corporativas desde el frente

Mini-historia 1: El incidente causado por una suposición equivocada

El ticket decía: “El correo de nuestro procesador de pagos no llega. Debe ser su caída.” Venía de finanzas, lo que implica urgencia, ambigüedad y un adjunto con invitación de calendario.

El administrador junior hizo lo que hacen los juniors cuando la sala está ruidosa: miró la línea Received más alta en el mensaje que el procesador reenviaba como prueba. Mostraba el hostname del procesador, y luego nada que pareciera nuestro entorno. Concluyeron: “No lo recibimos. Problema del procesador.” Tenían medio razón y completamente equivocados donde importaba.

Pedimos las cabeceras de un mensaje que sí llegó más temprano ese día y comparamos las cadenas. El correo que faltaba no estaba perdido; golpeaba nuestro gateway perimetral y era puesto en cuarentena silenciosamente por un nuevo tipo de adjunto. Nuestro gateway tenía una retención de política que no generaba notificaciones visibles para remitentes externos, porque alguien se quejó una vez de “demasiados correos de cuarentena”. Esa persona ya estaba en otra organización, por supuesto.

La suposición errónea fue “si no está en la bandeja, no lo recibimos.” La cadena Received desde nuestro gateway confiable demostró que sí lo habíamos recibido. Los logs mostraron el ID de cola, la acción de cuarentena y que la liberación nunca ocurrió porque el servicio de sandbox estaba caído. Esa última parte fue la verdadera caída — y era nuestra.

Restauramos el sandbox, liberamos los mensajes en cuarentena y tomamos una decisión importante: la cuarentena sin notificación es deuda operativa. A veces es necesaria, pero entonces te debes dashboards y alertas, porque los usuarios vendrán con horcas y te las habrás ganado.

Mini-historia 2: La optimización que salió mal

Una empresa relativamente grande quiso “optimizar la latencia de seguridad de correo.” El plan parecía razonable: pasar de sandboxing de adjuntos síncrono (retener correo hasta veredicto) a un pipeline más rápido aumentando paralelismo y endureciendo políticas TLS. Más rápido y más seguro. ¿Qué podría salir mal?

El cambio cayó un viernes, claro. El paralelismo aumentó, lo que incrementó la carga CPU en el gateway. Las políticas TLS se endurecieron, aumentando fallos de handshake con un relay de buzón interno que tenía una configuración de suite de cifrado antigua. El gateway empezó a diferir entregas, pero aún aceptaba correo entrante, apilándolo en la cola como platos en un buffet.

Las cabeceras Received lo contaban: timestamps de aceptación entrante normales, pero el traspaso interno a los servidores de buzón se retrasaba 20–60 minutos. Usuarios culparon a remitentes externos, remitentes culparon nuestra reputación y la dirección culpó “al correo” como concepto. Mientras, la cola creció y el disco del gateway se llenó, porque las colas son almacenamiento aunque no quieras admitirlo.

Revertimos la severidad TLS para relays internos, reducimos el paralelismo del sandbox para ajustarlo a la realidad CPU y añadimos umbrales de monitorización de tamaño de cola que generan paginación. La lección dolorosa: afinar rendimiento en sistemas de correo es como afinar una base de datos. Puedes mover el cuello de botella, pero también puedes crear un modo de fallo completamente nuevo con mejor marketing.

Mini-historia 3: La práctica aburrida pero correcta que salvó el día

En otro lugar, otra vibra: tenían un runbook de “traza de correo” que nadie presumía. Era una página de pasos: extraer cadena Received, localizar primer salto confiable, correlacionar ID de cola, comprobar cuarentena, confirmar entrega en buzón. No era emocionante. Era correcto.

Una tarde, un VIP se quejó de que una enmienda de contrato “nunca llegó” y amenazó con escalar. El on-call siguió el runbook. En cinco minutos tenía el ID de cola del gateway, la marca exacta de aceptación y el ID del relay interno mostrando entrega final al almacén de buzón.

Luego revisaron las reglas del buzón: el mensaje fue movido a la carpeta “Legal” y marcado como leído por un cliente móvil. No era un problema del MTA. Era un flujo de trabajo del usuario. El on-call dio una explicación clara: “Entregado a las 14:03 UTC, movido por la regla X a la carpeta Y.” La escalada se desvaneció.

La práctica que salvó el día no fue una herramienta elegante. Fue logging consistente, relojes que no mentían y el hábito de correlacionar IDs en lugar de adivinar. La fiabilidad suele ser la ausencia de drama lograda con buena higiene.

Errores comunes: síntomas → causa raíz → solución

  • Síntoma: “Las cabeceras Received muestran que fue entregado, pero el usuario dice que nunca llegó.”
    Causa raíz: Problema de colocación visible al usuario (reglas, bandeja enfocada, carpeta de spam, movimiento server-side, archivo).
    Solución: Correlaciona el salto final confiable + logs de entrega al buzón; revisa acciones de reglas; confirma ruta de carpetas y comportamiento del cliente; desactiva reglas problemáticas.
  • Síntoma: Timestamps van hacia atrás entre saltos.
    Causa raíz: Desincronización de reloj o configuración de zona horaria en un servidor; ocasionalmente, plegado de cabeceras mal interpretado por herramientas.
    Solución: Verifica NTP (timedatectl); corrige zona horaria; revisa con cabeceras en crudo.
  • Síntoma: No hay línea Received confiable desde tu perímetro.
    Causa raíz: Nunca aceptaste el mensaje; el remitente no te alcanzó; MX DNS equivocado; bloqueo por política upstream; remitente envió al dominio incorrecto.
    Solución: Verifica registros MX; confirma la dirección del destinatario; pide logs/bounce al remitente; revisa tus logs perimetrales por intentos de conexión.
  • Síntoma: Gran retraso entre aceptación en tu MX y entrega al buzón.
    Causa raíz: Backlog en pipeline entrante: filtro de contenido, sandbox, AV, DLP, lentitud del almacén de buzones, fallos TLS en relays internos.
    Solución: Identifica qué salto interno introdujo el retraso; revisa profundidad de cola; escala el cuello de botella; arregla TLS/cipher mismatch; añade alertas en edad de cola.
  • Síntoma: El remitente afirma “recibimos 250 OK” pero no encuentras el mensaje.
    Causa raíz: El 250 fue de un relay intermedio (no tú), o lo aceptaste y luego lo cuarentenaste/reescribiste, o los logs se perdieron por rotación.
    Solución: Empareja el servidor que emitió 250 con el hop “by” en Received; solicita sus logs; asegúrate de conservar logs de correo suficiente tiempo para necesidades de negocio.
  • Síntoma: Ciertos dominios externos fallan o retrasan consistentemente, otros funcionan bien.
    Causa raíz: Problemas de reputación/throttling, desajuste de políticas TLS, aplicación de DMARC, o falsos positivos del filtro de contenido específicos del patrón del remitente.
    Solución: Inspecciona Authentication-Results; revisa logs TLS; coordina allowlisting cuidadosamente (preferir basado en DKIM); ajusta reglas de contenido con evidencia.
  • Síntoma: El correo reenviado desde una cuenta personal no llega, pero el envío directo sí.
    Causa raíz: SPF falla y DKIM se rompe al reenviar; la política DMARC de rechazo/cuarentena se aplica en el receptor.
    Solución: Fomenta el envío directo; implementa manejo ARC-aware; para reenvíos internos, usa SRS y preserva DKIM cuando sea posible.
  • Síntoma: Múltiples copias duplicadas llegan horas después.
    Causa raíz: Reintentos del remitente tras entrega incierta (conexión perdida después de DATA), o un gateway reinyectó por timeout.
    Solución: Revisa logs por “message may be sent more than once”; arregla estabilidad de conexión downstream; asegura filtrado idempotente cuando sea factible.

Listas de verificación / plan paso a paso

Paso a paso: traza un único mensaje perdido

  1. Obtén el artefacto correcto: las cabeceras originales completas desde la UI del buzón del destinatario (no un mensaje reenviado). Si es posible, consigue la fuente cruda.
  2. Extrae las líneas Received y léelas de abajo hacia arriba.
  3. Identifica el primer “by” confiable (tu MX/gateway/proveedor ingress). Todo lo de abajo es contexto no confiable.
  4. Registra las claves de unión: ID(s) de cola, Message-ID, dirección del destinatario, marcas de tiempo.
  5. Revisa logs perimetrales por aceptación, rechazos o devoluciones alrededor de la marca de tiempo.
  6. Revisa estado de colas (profundidad + antigüedad). Determina si es sistémico.
  7. Revisa pipeline de contenido (AV/sandbox/DLP) por retenciones y latencia.
  8. Revisa traspaso de relays internos por fallos TLS, timeouts o presión atrás.
  9. Revisa logs de entrega al buzón y colocación final (carpetas/reglas/cuarentena).
  10. Escribe la explicación para humanos: “Aceptado en X, retrasado en Y por Z, entregado en T.” Incluye tiempos y sistemas.

Paso a paso: decidir si es lado remitente o receptor

  1. Si no tienes una línea Received confiable desde tu infraestructura: trátalo como lado remitente o enrutamiento Internet. Pide códigos de bounce o logs de su MTA.
  2. Si tienes una aceptación confiable pero no entrega al buzón: trátalo como pipeline receptor. Modo manejo de incidentes.
  3. Si tienes entrega al buzón pero el usuario no lo encuentra: trátalo como problema de visibilidad/reglas. No llames al equipo MTA por un problema de UI.

Checklist operativo: hacer útiles las cabeceras Received en tu entorno

  • Mantén NTP sano en todo equipo que toque correo.
  • Asegura que tus MTAs logueen IDs de cola y Message-IDs y retengan logs lo suficiente para investigaciones de negocio.
  • Expón profundidad de cola y antigüedad del mensaje más antiguo como métricas con umbrales de paginación.
  • Instrumenta filtros de contenido con métricas de latencia y veredicto.
  • Documenta fronteras de confianza: qué saltos son tuyos, cuáles son proveedores y cuáles pertenecen a Internet público.

Broma #2: La forma más rápida de encontrar un cuello de botella en el correo es programar una reunión al respecto: el correo llegará durante la reunión, solo para fastidiarte.

Preguntas frecuentes

1) ¿Por qué las cabeceras Received parecen “al revés”?

Porque cada servidor antepone su línea Received en la parte superior. El recorrido del mensaje hacia adelante en el tiempo se lee de abajo hacia arriba.

2) ¿Se pueden falsificar las cabeceras Received?

Todo lo que esté fuera de tu frontera de confianza puede ser falsificado porque un remitente puede añadir cabeceras arbitrarias. La línea Received añadida por tu primer MX/gateway confiable es el ancla en la que confías.

3) ¿Cuál es la diferencia entre “from” y “by” en una cabecera Received?

by es el servidor que escribió la línea. from es el par que se conectó a él. Al depurar, “by” es donde buscas logs.

4) ¿Qué identificador es mejor para correlacionar logs: Message-ID o ID de cola?

El ID de cola es mejor dentro de un solo MTA porque es local y garantiza mapeo a logs. Message-ID es mejor entre sistemas, pero puede faltar o duplicarse. Usa ambos cuando sea posible.

5) Veo ESMTPA en una línea Received. ¿Qué me indica?

Frecuentemente indica envío autenticado (un cliente se autenticó). Eso suele significar que el correo entró al sistema del remitente a través de un servicio de submission, no por un relay abierto. También acota la búsqueda al host de submission.

6) El remitente afirma que recibió “250 OK.” ¿No prueba eso la entrega?

Prueba la aceptación por algún servidor SMTP, no necesariamente la entrega final al buzón del destinatario. Necesitas emparejar qué servidor emitió el 250 con un hop “by” en Received y luego trazar hacia adelante.

7) ¿Cómo sé si el retraso es por greylisting?

Las cabeceras solas a menudo no muestran reintentos; los logs sí. Busca 4xx en logs del destinatario o del remitente, seguido por una entrega exitosa posterior. La “hora de envío” del usuario puede ser mucho anterior a tu hora de aceptación.

8) ¿Por qué a veces hay muchos saltos internos en grandes proveedores?

Los proveedores grandes canalizan correo por múltiples servicios: MTAs de borde, filtrado antispam, motores de política y entrega a buzón. Cada capa puede añadir una línea Received y cada una es un posible punto de retraso.

9) ¿Y si no hay Received en absoluto?

Eso es inusual para correo de Internet. Puede que estés viendo un fragmento de mensaje, un copia/pega o un mensaje reenviado donde el cliente reemplazó cabeceras. Pide la fuente cruda otra vez, desde “ver original” del buzón.

10) ¿Cómo se relacionan SPF/DKIM/DMARC con “dónde falla la entrega”?

Si DMARC falla con política estricta, la ruptura es por aplicación de política en el receptor, no por transporte. Las cabeceras Received mostrarán la ruta, pero los resultados de autenticación explican por qué un hop rechazó, puso en cuarentena o colocó en spam.

Conclusión: pasos siguientes que puedes hacer esta semana

El diagnóstico de entrega de correo pierde mucho misterio cuando tratas las cabeceras Received como un trazo de saltos y los logs como la verdad de terreno. Ancla en el primer salto confiable, mide retrasos entre saltos y correlaciona usando ID de cola y Message-ID. Luego habla en tiempos y sistemas, no en impresiones.

Pasos prácticos:

  1. Escribe (o toma prestado) un runbook de una página que siga el Guion de diagnóstico rápido y el plan paso a paso arriba.
  2. Añade dos métricas a tu monitorización: profundidad de cola y edad del mensaje más antiguo en cada salto de manejo de correo que poseas.
  3. Audita tu comportamiento de cuarentena/retenciones: si retienes correo, necesitas visibilidad y notificaciones, o te estás preparando para futuros incidentes.
  4. Verifica sincronización horaria entre MTAs, gateways y servidores de buzón. La deriva de tiempo convierte el análisis de cabeceras en arte performático.

“La esperanza no es una estrategia.” — idea parafraseada común en círculos de operaciones y fiabilidad

← Anterior
IP/Dominio de correo en lista negra: cómo verificar y solicitar la eliminación correctamente
Siguiente →
Construcciones multi-etapa de Docker: reducir imágenes sin romper el tiempo de ejecución

Deja un comentario