How to Read a DMARC Report: The Aggregate XML, Field by Field
Published July 1, 2026
A DMARC aggregate report is a compressed XML file that a mailbox provider emails you daily, summarizing every source that sent mail claiming to be your domain: each sending IP address, how many messages it sent, and whether they passed SPF and DKIM with alignment. Reading one means unzipping the attachment and walking the XML's three parts: report metadata, your published policy, and one record per sending source. It's entirely doable by hand for one report, and entirely impractical at scale.
What arrives in your inbox
Once your DMARC (Domain-based Message Authentication, Reporting and Conformance) record includes a rua address, providers that received mail claiming to be your domain send you a report, typically daily. It arrives as an email with a compressed attachment: a .zip or .gz file containing a single XML document. Gmail, Microsoft, Yahoo, and most other large providers all send them; expect several separate reports per day, one from each provider.
Every report has the same shape, defined by the DMARC specification: a root feedback element containing report_metadata (who sent the report and for what date range), policy_published (the DMARC record they saw for your domain), and one or more record elements: one per unique combination of sending IP and authentication results.
report_metadata and policy_published
report_metadata identifies the report itself: org_name (the provider reporting, such as google.com), a contact email, a unique report_id, and a date_range with begin and end timestamps in Unix time (seconds since 1970, a common machine format for dates). This tells you whose traffic you're looking at and for which 24-hour window.
policy_published echoes back the DMARC record the provider found in your DNS when it evaluated your mail: your domain, the p= policy, sp= subdomain policy, adkim and aspf alignment modes, and pct percentage. It's worth a glance: if it doesn't match the record you think you published, you've found a propagation problem or a typo before reading any further.
The record element: where the data lives
Each record describes one sending source. Its row element carries the headline facts, identifiers tells you which domain was displayed, and auth_results holds the raw check outcomes. Here's what each field means:
| Field | Where | What it tells you |
|---|---|---|
| source_ip | row | The IP address that delivered the mail (the sending server) |
| count | row | How many messages this row summarizes |
| policy_evaluated > disposition | row | What the receiver did: none, quarantine, or reject |
| policy_evaluated > dkim / spf | row | The DMARC verdict per mechanism: pass only if the check passed AND aligned |
| header_from | identifiers | The domain shown in the From line (what DMARC protects) |
| envelope_from | identifiers | The hidden bounce domain SPF actually checked |
| auth_results > dkim: domain, result | auth_results | Each DKIM signature found: the d= domain it signed with, and pass/fail |
| auth_results > spf: domain, result | auth_results | The domain SPF was checked against, and pass/fail |
The one distinction that unlocks everything
The row's policy_evaluated results and the auth_results section can disagree, and the difference is the single most useful thing in the report. auth_results shows raw outcomes: did SPF pass for whatever domain was in the envelope, did each DKIM signature verify. policy_evaluated shows the DMARC view: pass only if the raw pass was also aligned with the header_from domain.
So a record showing auth_results SPF pass (for bounce.someesp.com) and DKIM pass (for someesp.com), but policy_evaluated fail on both, is telling you: this sender works, but it's authenticating as itself, not as you. That's an alignment fix (usually completing the service's custom-domain setup), not a security incident.
Forwarding or spoofing? How to tell
Failing records fall into three patterns. Learn them and reports stop being scary.
- Misconfigured legitimate sender: recognizable volume, auth_results passing for the service's own domain, DMARC failing on alignment: fix the service's DKIM setup
- Forwarding: small counts, SPF fail but DKIM pass with your domain (which means DMARC still passes), source IPs at universities, ISPs, or personal-domain hosts (harmless, no action)
- Spoofing: SPF fail and DKIM fail or absent, header_from is your domain, IPs in ranges you've never used, often bursty volume. This is exactly what your policy exists to stop
Nobody does this by hand at scale, and you shouldn't
Walking one XML file like this is genuinely worth doing once: the format stops being mysterious and the concepts become concrete. But a real domain receives multiple reports daily from different providers, each covering different slices of traffic, and the questions that matter (is this IP Mailchimp or an attacker, has my pass rate held for two weeks, did a new sender appear) require joining data across weeks of files and mapping IPs to services.
That's parsing work, and machines should do it. If you have a report file in hand right now, drop it into our free DMARC report analyzer at /tools/dmarc-report-analyzer and it will decode everything above instantly, with each sending source identified. For the ongoing version (every report from every provider, collected and interpreted automatically, with alerts when something changes), that's what DMARCPath does all day.
Frequently asked questions
- Why don't DMARC reports show me the actual emails?
- Aggregate (rua) reports are deliberately privacy-safe: counts and authentication results per sending IP, never subject lines, recipients, or content. A separate mechanism, forensic (ruf) reports, can include message details, but most major providers no longer send them, precisely for privacy reasons.
- How often do reports arrive?
- Typically once per day per reporting provider, covering the previous 24 hours. A domain with normal traffic usually receives reports from Google, Microsoft, and Yahoo daily, plus occasional ones from smaller providers. No report from a provider simply means it saw no mail claiming to be your domain.
- A record shows disposition=none but my policy is quarantine. Why?
- Receivers may override your policy when they're confident mail is legitimate, commonly for recognized forwarders and mailing lists. Some reports include a reason element explaining the override. Scattered overrides are normal and not a sign your record is broken.
Keep reading
Reading about it is step one
DMARCPath does the watching for you: every sender identified, every failure explained, and a guided path to p=reject. One domain free, forever.
Start monitoring free →