Reading DMARC reports without losing your mind — the XML, the patterns, the action items
If you publish a DMARC record with a rua tag, receiving mail providers send you XML reports daily. Most people look at one, decide it's incomprehensible, and never read another. This article translates the XML into something you can act on.
What's in a report
Every report is an XML file containing summaries of mail sent during a 24-hour window claiming to be from your domain. Per source IP, the report tells you:
- How many messages were seen.
- Whether SPF aligned (the sending IP was in your SPF record).
- Whether DKIM aligned (the message had a valid signature from your domain).
- Whether the receiver applied your DMARC policy.
The minimal XML structure
<feedback>
<report_metadata>
<org_name>google.com</org_name>
<date_range>
<begin>...</begin>
<end>...</end>
</date_range>
</report_metadata>
<policy_published>
<domain>example.com</domain>
<p>none</p>
</policy_published>
<record>
<row>
<source_ip>192.0.2.10</source_ip>
<count>42</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>pass</dkim>
<spf>pass</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>example.com</domain>
<result>pass</result>
</dkim>
<spf>
<domain>example.com</domain>
<result>pass</result>
</spf>
</auth_results>
</record>
</feedback>
Each <record> block is one source IP's activity. Multiple records per report.
The patterns to look for
Pattern 1: Your own mail server is passing
- Source IP = your mail server.
- DKIM and SPF both pass and align.
- Disposition: none (you have p=none) or whatever your policy is.
This is healthy traffic. Nothing to do.
Pattern 2: A legitimate third-party sender is failing
- Source IP = your CRM, marketing service, ticket system, etc.
- DKIM and/or SPF fail.
- Count is > 0.
Action: add the third-party sender's IPs or include-mechanism to your SPF record, and/or enable DKIM signing on their platform with a CNAME-delegated key in your DNS.
Pattern 3: Spoofed traffic from unknown IPs
- Source IP = random, often residential or compromised servers.
- DKIM and SPF both fail.
- header_from = your domain.
- Counts can be small (a few) or huge (thousands).
Action: this is spoofers using your domain. Once your DMARC policy is at p=reject, receivers reject this traffic. Action is to verify DMARC is enforcing.
Pattern 4: One source IP, very low volume, DKIM-only pass
- Forwarded mail that lost the SPF alignment but kept the DKIM signature.
- Normal for mailing-list traffic.
Action: nothing. DMARC counts DKIM-only pass as aligned; forwarding is handled.
Tools to make this scannable
Reading the XML directly works for a few reports but becomes unmanageable at scale. Options:
- dmarcian, Postmark DMARC, Valimail — hosted DMARC analytics. You point your DMARC
ruaat their service, they parse and show you a dashboard. Free tiers exist. - parsedmarc (open-source) — parses XML and feeds Elasticsearch or just CSVs. Self-host if you don't want to send DMARC data to a third party.
- Mailcow's built-in DMARC dashboard — if you're using Mailcow, it shows you DMARC results for your domains.
For one domain, parsedmarc + a daily summary email is plenty. For more domains or compliance-driven monitoring, a hosted service is worth the cost.
Moving from p=none to p=quarantine to p=reject
The DMARC enforcement progression:
- p=none: monitor only. Receivers report but don't act on your DMARC policy. Stay here until reports show your legitimate sources passing consistently — typically 2-4 weeks.
- p=quarantine: receivers spam-folder failing messages. Watch reports for legitimate-but- failing sources to fix. Stay here a couple of weeks.
- p=reject: receivers reject failing messages outright. Spoofers can no longer impersonate your domain.
Don't skip steps. Going straight to p=reject before you've verified all legitimate sources align means rejecting your own real mail.
Sub-domain policy
Add a sp= tag for sub-domain policy:
v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc@example.com
This prevents spoofers from sending as random.example.com. Always set this — leaving sub-domain wide open while the apex is protected is a common oversight.
Common findings worth chasing
- HR/payroll system not signing DKIM. Common. Get them to enable DKIM and CNAME-delegate the key.
- Old marketing service still sending. Reports surface traffic from a service you stopped using years ago — they're still sending. Either reactivate or remove credentials.
- One employee's personal mail flowing through a gateway. Sometimes legitimate (an exec's home mail relayed through corp servers), sometimes shadow IT. Decide which.
- Genuine spoofing campaigns. You'll see large spikes when someone runs a phishing campaign impersonating your domain. p=reject stops them cold.
Also Read
Powered by WHMCompleteSolution