← Volver al blog

Cómo leer un reporte DMARC agregado: el XML, campo por campo

Cómo leer un reporte DMARC agregado: el XML, campo por campo

Publicaste un registro DMARC con una dirección en rua y desde entonces cada mañana llega algo a ese buzón: un archivo comprimido con un nombre que parece un comando de terminal y adentro una página de XML. La mayoría lo abre, ve una pared de etiquetas y lo cierra. Ese archivo es la única vista gratuita y continua que tienes de quién está poniendo tu dominio en el From de un correo, así que vale la pena dedicarle veinte minutos.

El formato tiene especificación propia desde mayo de 2026. El RFC 9990 cubre los reportes agregados, el RFC 9991 los reportes de fallo y el RFC 9989 el protocolo. Juntos reemplazan al RFC 7489, que era la referencia desde 2015. Casi todas las guías que vas a encontrar en línea siguen describiendo el documento viejo. El XML conservó su forma pero ganó campos nuevos, y saber cuáles son te dice qué receptores están al día.

De dónde salen los reportes

Cada receptor que soporta reportes DMARC lee tu registro, ve la dirección de reporte y empieza a contar. Agrupa el correo que vio con tu dominio por IP de origen y por resultado de autenticación, y te manda los totales del período. No te manda los mensajes.

_dmarc.ejemplo.com.  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@ejemplo.com"

Los reportes llegan como XML adjunto, comprimido en gzip o zip, y el RFC 9990 fija el nombre del archivo para que puedas ordenar el buzón a mano:

receptor!dominio-de-la-politica!inicio!fin[!id-unico].extension

google.com!ejemplo.com!1788566400!1788652800.zip

El primer campo es quién te está avisando, el segundo es el dominio del que te avisa y los dos números son la ventana en segundos Unix. Pon la dirección de reporte en un grupo y no en el buzón de una persona, porque un dominio con volumen real junta una docena de estos al día de proveedores que jamás habías oído nombrar, y esa dirección tiene que sobrevivir a quien la configuró.

Los reportes agregados llevan conteos y veredictos, nunca contenido: sin asuntos, sin destinatarios, sin cuerpos. El detalle por mensaje vive en los reportes de fallo, la etiqueta ruf especificada ahora en el RFC 9991, y la mayoría de los receptores grandes no los envía por privacidad. Planifica el trabajo con los datos agregados, porque en la práctica es todo lo que vas a tener.

Las tres partes del archivo

Todo reporte tiene el mismo esqueleto: quién lo envía y de qué período, cómo leyó tu política, y luego un bloque por cada combinación distinta de IP de origen y resultado de autenticación. Este es un reporte completo con un solo registro que pasa:

<feedback>
  <report_metadata>
    <org_name>google.com</org_name>
    <email>noreply-dmarc-support@google.com</email>
    <report_id>3921764408171295000</report_id>
    <date_range>
      <begin>1788566400</begin>
      <end>1788652800</end>
    </date_range>
  </report_metadata>
  <policy_published>
    <domain>ejemplo.com</domain>
    <adkim>r</adkim>
    <aspf>r</aspf>
    <p>none</p>
    <sp>none</sp>
    <np>reject</np>
    <testing>n</testing>
    <discovery_method>treewalk</discovery_method>
  </policy_published>
  <record>
    <row>
      <source_ip>209.85.220.41</source_ip>
      <count>128</count>
      <policy_evaluated>
        <disposition>none</disposition>
        <dkim>pass</dkim>
        <spf>pass</spf>
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from>ejemplo.com</header_from>
    </identifiers>
    <auth_results>
      <dkim>
        <domain>ejemplo.com</domain>
        <selector>google</selector>
        <result>pass</result>
      </dkim>
      <spf>
        <domain>ejemplo.com</domain>
        <scope>mfrom</scope>
        <result>pass</result>
      </spf>
    </auth_results>
  </record>
</feedback>

Así se ve lo sano: tu propio correo, tu propio selector, ambas verificaciones alineadas, nada que hacer. Los reportes reales traen veinte bloques como este y dos son interesantes. Si prefieres no contar etiquetas a las tres de la tarde, pega un reporte y obtén el mismo desglose en tabla:

report_metadata: quién te avisa y de cuándo

org_name y email identifican al receptor, no a ti. report_id es único para ese reportante, lo cual importa cuando quitas duplicados de un año de reportes, porque un reporte retransmitido reutiliza su nombre de archivo y su identificador originales.

Los dos números de date_range son segundos desde el inicio de 1970. Conviértelos en cualquier terminal de Linux o macOS:

date -u -d @1788566400     # 2026-09-05 00:00:00 UTC
date -u -r 1788566400      # la variante de macOS

Esa ventana es del reportante, no de tu jornada. Normalmente va de medianoche a medianoche UTC, seis horas adelante de San Salvador, así que el pico que viste el martes por la tarde puede caer en lo que el reporte llama miércoles. Convierte antes de cruzar nada con tus propios registros.

policy_published: tu registro leído por alguien más

Este bloque es el receptor leyéndote tu DNS de vuelta, y es la forma más rápida de encontrar el error de dedo que llevas un mes mirando sin ver. Si p dice none y tú jurabas haber pasado a quarantine la semana pasada, o el cambio nunca propagó o editaste la zona equivocada.

Tres de los campos del ejemplo anterior no existían en la especificación anterior y conviene reconocerlos:

  • np lleva tu política para subdominios inexistentes, la etiqueta que te deja rechazar correo de subdominios que ni siquiera están en DNS sin tocar la política de los que sí lo están.
  • testing lleva el valor de la nueva etiqueta t, que reemplazó al despliegue por porcentaje. La vieja etiqueta pct quedó obsoleta en el RFC 9989, junto con rf y ri. Un registro que todavía las trae no está roto, porque los receptores ignoran lo que no reconocen, pero quedó escrito contra un documento superado.
  • discovery_method dice cómo dedujo el receptor tu dominio organizacional: psl con la vieja Public Suffix List, o treewalk con el método basado en DNS que define el RFC 9989. Es el indicador más claro de qué tan actualizado está cada receptor.

adkim y aspf son los modos de alineación, r para relajado y s para estricto. El relajado acepta coincidencia a nivel de dominio organizacional, así que el correo firmado por mail.ejemplo.com alinea con un From en ejemplo.com. El estricto exige el nombre exacto. Empieza en relajado. El estricto es un endurecimiento posterior y rompe a los remitentes en subdominios sin avisar.

El bloque record, leído en el orden correcto

Cada record es un grupo de mensajes, no un mensaje. Léelo en este orden y deja de ser confuso.

source_ip y count. La IP que se conectó y cuántos mensajes salieron de ahí en la ventana. Ordena cada reporte por count de mayor a menor. Las tres primeras filas son tus flujos de correo reales, y cualquier fila que falle dentro de las diez primeras es un sistema tuyo que olvidaste, no un delincuente.

header_from. El dominio de la línea From que ve el lector. Esa es la identidad que DMARC protege. envelope_from, cuando aparece, es la dirección de rebote, y es la que SPF verifica de verdad.

policy_evaluated. El veredicto después de la alineación, más la disposition que aplicó el receptor: none, quarantine o reject. En p=none la disposition siempre es none, así que ese campo no te dice nada hasta que endurezcas. Los que importan son sus hijos dkim y spf.

auth_results. El resultado crudo de cada verificación, con el dominio que se verificó. En DKIM además tienes el selector, que es como distingues la firma de tu Workspace de la de tu plataforma de facturación.

El par de campos que todo el mundo lee mal

Esta es la fila que genera casi toda la confusión, y vale la pena leerla dos veces:

  <policy_evaluated>
    <disposition>none</disposition>
    <dkim>fail</dkim>
    <spf>fail</spf>
  </policy_evaluated>
  ...
  <identifiers>
    <header_from>ejemplo.com</header_from>
  </identifiers>
  <auth_results>
    <spf>
      <domain>mailer.proveedor.net</domain>
      <scope>mfrom</scope>
      <result>pass</result>
    </spf>
  </auth_results>

SPF pasó y DMARC falló en el mismo mensaje, y SPF no tiene nada roto. La verificación pasó para mailer.proveedor.net, el dominio de rebote del proveedor, mientras el lector ve ejemplo.com. Dos dominios distintos, sin alineación, sin DMARC. Los resultados dentro de auth_results son las verificaciones crudas; los de policy_evaluated son esas mismas verificaciones después de preguntar si hablaban del dominio del From.

A DMARC le basta con que una de las dos pase y alinee. Por eso el arreglo duradero para una plataforma de marketing o de facturación casi siempre es autenticar el dominio con una llave DKIM propia, en lugar de colgar otro include de un SPF que ya está cerca del límite de diez consultas.

Reenvíos y las filas que parecen ataque pero no lo son

Una fila con tu header_from, un SPF que falla y una firma DKIM que pasa y alinea suele ser un reenvío. Alguien dejó un auto forward en su dirección vieja, o una lista de correo retransmitió tu mensaje. El reenvío reescribe la conexión, así que la IP que envía ya no es tuya y SPF no tiene nada que decir. La firma DKIM viaja con el mensaje y sobrevive, que es justo para lo que existe.

El patrón inverso, DKIM que falla mientras SPF pasa y alinea, suele significar que algo modificó el mensaje en tránsito: una lista agregó un pie de página, o una pasarela de seguridad reescribió los enlaces. Conteos pequeños y un origen que resuelve a una universidad, a un servidor de listas o a una pasarela corporativa: eso es comportamiento normal de internet y no es motivo para retrasar el endurecimiento.

Algunos reportantes también llenan un elemento reason dentro de policy_evaluated con valores como forwarded, mailing_list, trusted_forwarder o local_policy, que te dicen que el receptor hizo una excepción. Los reportes viejos pueden traer sampled_out, un resto de la etiqueta de porcentaje ya obsoleta. Tómalos como pistas, porque llenarlos es opcional y casi nadie lo hace.

Suplantación contra tu propio DNS desordenado

Después de quince días de reportes, los orígenes que fallan se separan solos en dos montones.

Tus propios sistemas se ven como infraestructura: la misma IP o el mismo rango pequeño todos los días, un conteo que sigue el ritmo del negocio, y un bloque auth_results sin ninguna entrada de DKIM porque nadie completó nunca la autenticación de dominio en ese proveedor. La IP resuelve a un nombre que reconoces: un CRM, un manejador de formularios, la planilla, el proveedor de facturación, la multifuncional del segundo piso.

La suplantación se ve como el clima: IPs dispersas en redes con las que no tienes ninguna relación, conteos que se disparan dos días y desaparecen, sin firma DKIM o con una firma de un dominio que no es tuyo, y sin ningún patrón que coincida con algo que tú operes. Llega y se va.

El orden de trabajo es el aburrido. Arregla todo el primer montón hasta que cada flujo legítimo autentique y alinee. El segundo montón es exactamente para lo que sirve una política de endurecimiento, y no puedes endurecer con seguridad hasta vaciar el primero. Si algunas de esas filas ya te están generando rebotes, la guía del rechazo de Gmail cubre los mensajes de error que vas a ver.

Qué hacer con lo que encontraste

Leer reportes no es la meta. La meta es una política que proteja el dominio, y los reportes son la forma de llegar ahí sin dejar a nadie sin correo. Cuando todo el primer montón autentique, sube la política: monitoreo, luego quarantine, luego reject, revisando los reportes en cada escalón. La guía de despliegue trae la secuencia y los tiempos.

Dos hábitos valen la pena después de endurecer. Revisa los reportes cada mes y no cada día, porque un origen nuevo que falla casi siempre significa que un área contrató una herramienta sin avisarle a nadie. Y nunca quites la dirección de rua. No cuesta nada, es el único aviso que vas a recibir, y Google exige un registro DMARC a los dominios que envían más de 5,000 mensajes al día a cuentas de Gmail.

Cómo ayuda Guanacos Tech

Leemos estos reportes cada semana, en inglés y en español, para empresas de Norteamérica y Latinoamérica. Un proyecto típico arranca con dos semanas de datos agregados, termina con todos los remitentes legítimos alineados y la política endurecida, y te deja una lista corta de qué IP es qué sistema, para que el siguiente reporte te tome cinco minutos y no una tarde. Si tienes reportes acumulándose en un buzón y ninguna idea de qué filas importan, agenda una llamada y revisamos uno real contigo.

Fuentes

Preguntas frecuentes

¿Cada cuánto llegan los reportes DMARC agregados?

La mayoría de los receptores grandes envía un reporte por dominio de política por día, con una ventana que suele ir de medianoche a medianoche UTC. El intervalo lo elige el receptor, no tú: la vieja etiqueta ri que pedía otra frecuencia quedó obsoleta en el RFC 9989, y en la práctica los receptores ya la ignoraban. Espera unos cuantos reportes diarios de los proveedores grandes y alguno ocasional de servidores pequeños.

¿Por qué un reporte muestra SPF en pass y DMARC en fail para el mismo mensaje?

Porque responden preguntas distintas. El resultado dentro de auth_results dice que la verificación SPF pasó para el dominio que iba en el sobre, muchas veces el dominio de rebote del proveedor. El resultado dentro de policy_evaluated dice si ese dominio alineaba con el dominio del From que ve el lector. Un pass sin alineación es un fallo de DMARC, y es el patrón más común en reportes de plataformas de marketing, CRM y facturación.

¿Los reportes agregados me muestran los correos?

No. Traen conteos, IPs de origen y resultados de autenticación, sin asuntos, destinatarios ni cuerpos. El detalle por mensaje corresponde a los reportes de fallo, la etiqueta ruf especificada en el RFC 9991, y la mayoría de los receptores grandes no los envía por privacidad. Cualquier trabajo de entregabilidad que planifiques debe asumir que los datos agregados son todo lo que vas a tener.