DMARC Labs
All articles
TutorialXMLDMARC

How to Read a DMARC XML Report: A Field Guide for Email Admins

DMARC aggregate XML reports are dense and technical. This guide walks through every field — from report_metadata to auth_results — with real examples and plain-English explanations.

July 5, 202512 min read

DMARC aggregate reports look intimidating the first time you open one. Nested XML elements, Unix timestamps, IP addresses, and cryptic result codes — it reads like a debug log. This guide walks through every element, explains what it means in plain English, and shows you what to look for when diagnosing email authentication problems.

The Top-Level Structure

Every DMARC aggregate report follows the RFC 7489 schema. The root element is always <feedback>, and it contains exactly three types of children:

  1. <report_metadata> — information about the report itself
  2. <policy_published> — your DMARC policy as seen by the reporter
  3. <record> — one entry per unique sending source (one or more)
<?xml version="1.0" encoding="UTF-8" ?>
<feedback>
  <report_metadata> ... </report_metadata>
  <policy_published> ... </policy_published>
  <record> ... </record>
  <record> ... </record>
  <!-- potentially thousands more records -->
</feedback>

report_metadata: Who Sent This Report

<report_metadata>
  <org_name>Google LLC</org_name>
  <email>noreply-dmarc-support@google.com</email>
  <extra_contact_info>https://support.google.com/a/answer/2466580</extra_contact_info>
  <report_id>12456789012345678</report_id>
  <date_range>
    <begin>1751241600</begin>
    <end>1751327999</end>
  </date_range>
</report_metadata>

org_name

The name of the organization that generated this report. For Google Workspace and Gmail, this is “Google LLC”. For Microsoft (Outlook.com / Office 365), it is “Microsoft Corporation”. Smaller providers may use their company name or their mail server hostname.

email

The email address of the reporting organization. This is for reference only — do not reply to it. DMARC reporting is one-way.

report_id

A unique identifier for this report, assigned by the sending organization. Useful if you need to correlate a specific report with a provider when troubleshooting.

date_range / begin / end

Unix timestamps (seconds since January 1, 1970 UTC) indicating the start and end of the reporting period. DMARC reports cover a 24-hour window, typically midnight-to-midnight UTC.

NoteTo convert a Unix timestamp to a human-readable date, run: new Date(1751241600 * 1000).toISOString() in your browser console, or use an online converter.

policy_published: Your DMARC Policy

<policy_published>
  <domain>example.com</domain>
  <adkim>r</adkim>
  <aspf>r</aspf>
  <p>reject</p>
  <sp>reject</sp>
  <pct>100</pct>
</policy_published>

domain

The domain this DMARC policy applies to. This is the organizational domain, not necessarily the exact sending domain.

adkim — DKIM alignment mode

r = relaxed (subdomain of the organizational domain qualifies)
s = strict (exact domain match required)

Most organizations use r (relaxed). Strict mode is used when you need to prevent subdomains from satisfying alignment for the parent domain.

aspf — SPF alignment mode

Same as adkim but for SPF. r is relaxed, s is strict.

p — policy

The main DMARC policy applied to the organizational domain:

  • none — deliver and report, no action taken on failures
  • quarantine — send failures to spam/junk folder
  • reject — reject failures at the SMTP layer

sp — subdomain policy

Policy applied to subdomains of your organizational domain. If absent, the main policy p applies to subdomains as well. Common to set sp=reject even while p=none to immediately protect subdomains from spoofing.

pct — percentage

The percentage of messages that the policy is applied to. Ranges from 1 to 100. Using pct=10 means the policy applies to a random 10% of failing messages — useful for gradual rollout. When not specified, defaults to 100.

record: The Core Data

Each <record> element represents a unique combination of source IP address and authentication outcomes. A report can contain one record or thousands.

<record>
  <row>
    <source_ip>209.85.128.0</source_ip>
    <count>4821</count>
    <policy_evaluated>
      <disposition>none</disposition>
      <dkim>pass</dkim>
      <spf>pass</spf>
    </policy_evaluated>
  </row>
  <identifiers>
    <envelope_to>example.com</envelope_to>
    <envelope_from>bounce.example.com</envelope_from>
    <header_from>example.com</header_from>
  </identifiers>
  <auth_results>
    <dkim>
      <domain>example.com</domain>
      <selector>google</selector>
      <result>pass</result>
    </dkim>
    <spf>
      <domain>bounce.example.com</domain>
      <result>pass</result>
    </spf>
  </auth_results>
</record>

row / source_ip

The IP address of the server that connected to the receiving mail server (the MTA that did the actual SMTP delivery). This is typically the IP of your ESP, your own mail server, or a legitimate/illegitimate third party.

row / count

How many messages were sent from this source IP with this exact combination of authentication outcomes during the reporting period. A count of 4821 means 4,821 messages from that IP, all with the same policy_evaluated result.

policy_evaluated / disposition

What the receiving server actually did with these messages based on your policy:

  • none — delivered normally
  • quarantine — placed in spam/junk
  • reject — rejected at SMTP layer (not delivered)

When your policy is p=none, the disposition will always be none regardless of authentication results — the provider is reporting without taking action.

policy_evaluated / dkim and spf

These are the critical fields. They indicate whether DKIM/SPF passed AND aligned. This is different from the raw authentication result in auth_results:

auth_results resultAlignmentpolicy_evaluated result
passDomain aligns with From:pass
passDomain does NOT align with From:fail
failN/Afail

A message passes DMARC if at least one of policy_evaluated/dkim or policy_evaluated/spf is “pass”.

identifiers / header_from

The domain in the visible From: header of the email — the domain your recipients see in their mail client. This is the domain that DMARC alignment is checked against.

auth_results / dkim

The raw DKIM check result, before alignment is applied:

  • pass — signature verified successfully
  • fail — signature verification failed (key mismatch, body modified)
  • temperror — temporary DNS lookup failure, try again later
  • permerror — permanent error (malformed key record, invalid signature)
  • neutral — no result (domain not in DNS)

The selector field identifies which DKIM key was used (e.g.,google, s1, default). If you see a selector you don't recognize, a third-party platform may be signing your messages with its own key.

auth_results / spf

The raw SPF check result for the envelope sender domain (Return-Path):

  • pass — sending IP is listed in the SPF record
  • fail — sending IP is explicitly unauthorized (-all)
  • softfail — sending IP is weakly unauthorized (~all)
  • neutral — policy does not make an assertion (?all)
  • none — no SPF record found
  • temperror / permerror — DNS errors

Common Record Patterns and What They Mean

Pattern: Both pass — healthy

<policy_evaluated>
  <disposition>none</disposition>
  <dkim>pass</dkim>
  <spf>pass</spf>
</policy_evaluated>

This is what you want. The source IP is a known, authenticated sender with correct alignment. All is well.

Pattern: SPF pass, DKIM fail — common for third-party senders

<policy_evaluated>
  <disposition>none</disposition>
  <dkim>fail</dkim>
  <spf>pass</spf>
</policy_evaluated>

The sender is in your SPF record and SPF aligns. But DKIM is absent or not aligned. This is passing DMARC via SPF but is fragile — if the message is forwarded, SPF will break. Configure DKIM signing on this platform.

Pattern: Both fail — unauthenticated sender

<policy_evaluated>
  <disposition>reject</disposition>
  <dkim>fail</dkim>
  <spf>fail</spf>
</policy_evaluated>

This is either an unauthorized sender being actively blocked (if you are at p=reject) or a gap in your authentication coverage that you need to address before enforcing. Check the source IP via WHOIS to determine if this is a legitimate sender with missing configuration or spoofing traffic.


Understanding the difference between auth_results (raw crypto result) and policy_evaluated (alignment-aware result) is the single most important concept in reading DMARC reports. Most confusion in DMARC troubleshooting comes from not knowing which section is relevant to DMARC compliance.

Ready to analyze your DMARC reports?

DMARC Labs processes large XML files entirely in your browser — no upload, no signup, no data retention. Supports files up to 100MB+.

Analyze for Free