DMARC reports: how to read the aggregate XML without losing your mind
Learn how to read a DMARC aggregate report by breaking down each XML section, understanding alignment vs. raw results, and spotting failures before they hurt deliverability.

What DMARC aggregate reports are
When you publish a DMARC record with a rua= tag, you are asking every receiving mail server to send you a summary of how messages from your domain performed against SPF and DKIM checks. These summaries are DMARC aggregate reports. They arrive as gzipped XML files, usually once per day, from every major provider that processes your mail: Google, Microsoft, Yahoo, and dozens of others.
The reports are defined in RFC 7489, Section 7.2. They are not human-friendly. A single day's report from Gmail for a moderately active domain can run to hundreds of lines of raw XML. Multiply that by every provider sending you reports, and the volume gets unmanageable fast.
But the data inside is critical. Aggregate reports are the only reliable way to see which IP addresses are sending mail as your domain, whether authentication passes or fails, and whether your DMARC policy is being applied correctly.
Why the XML feels overwhelming
A DMARC aggregate report is not complex in structure. The problem is presentation. The XML contains nested elements with terse tag names like <auth_results>, <policy_evaluated>, and <source_ip>. There are no labels, no summaries, no color coding. Opening a raw report in a text editor gives you a wall of angle brackets with no obvious entry point.
The good news: once you understand the three major sections, every aggregate report follows the same pattern. You can read any of them.
The three sections of every report
Every DMARC aggregate report XML file contains three main blocks.
1. Report metadata
This section identifies who sent the report and what period it covers.
<report_metadata>
<org_name>google.com</org_name>
<email>noreply-dmarc-support@google.com</email>
<report_id>17284937461234567890</report_id>
<date_range>
<begin>1717459200</begin>
<end>1717545600</end>
</date_range>
</report_metadata>
The <org_name> tells you which provider generated the report. The <date_range> uses Unix timestamps. In this example, the report covers a 24-hour window. You will get one of these from each provider that received mail claiming to be from your domain during that period.
2. Published policy
This section mirrors the DMARC policy the reporting server found in your DNS at the time of evaluation.
<policy_published>
<domain>yourdomain.com</domain>
<adkim>r</adkim>
<aspf>r</aspf>
<p>reject</p>
<sp>reject</sp>
<pct>100</pct>
</policy_published>
The <p> tag is your domain policy: none, quarantine, or reject. The <adkim> and <aspf> tags show alignment mode: r for relaxed (subdomains can match), s for strict (exact domain match required). If what you see here does not match what you intended, your DNS record needs attention.
3. Record rows
This is where the real data lives. Each <record> block represents a group of messages from a single source IP that shared the same authentication outcome.
<record>
<row>
<source_ip>209.85.220.41</source_ip>
<count>1523</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>pass</dkim>
<spf>pass</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>yourdomain.com</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>yourdomain.com</domain>
<result>pass</result>
<selector>google</selector>
</dkim>
<spf>
<domain>yourdomain.com</domain>
<result>pass</result>
</spf>
</auth_results>
</record>
Here is what each field means:
<source_ip>: The IP address that sent the messages. Reverse-DNS this to identify the sending service.<count>: How many messages from this IP had this exact result combination. A count of 1,523 means over fifteen hundred messages matched.<disposition>: What the receiver actually did:none(delivered normally),quarantine(sent to spam), orreject(blocked).<dkim>and<spf>inside<policy_evaluated>: Whether each check passed DMARC alignment, not just whether the raw check passed.<auth_results>: The raw SPF and DKIM results before alignment evaluation. You can pass raw SPF but fail DMARC alignment if the domains do not match.
The distinction that matters most
The difference between <policy_evaluated> and <auth_results> is the single most important thing to understand when you read a DMARC aggregate report. They answer different questions.
<auth_results> tells you: did the raw SPF or DKIM check pass? <policy_evaluated> tells you: did the passing result also align with the domain in the From header?
A raw SPF pass with a DMARC SPF failure means the envelope domain (Return-Path) does not align with the From header domain. This is extremely common when third-party services send on your behalf. Your marketing platform might use bounce.mailprovider.com as the Return-Path. Your SPF record authorizes that server, so raw SPF passes. But because the Return-Path domain is not yours, DMARC alignment fails.
This is fine, as long as DKIM passes and aligns through the d= tag matching your From domain. If both alignment checks fail, those messages are exposed to DMARC policy enforcement. Depending on your <p> setting, that means quarantine or rejection.
Patterns to watch for
Once you can parse the structure, focus on these scenarios:
Unknown source IPs with high volume. If you see an IP sending thousands of messages as your domain and you do not recognize it, someone may be spoofing your domain. Check whether your DMARC policy is set to reject. If it is still at none, those spoofed messages are being delivered.
Known services failing alignment. Your CRM or marketing tool might pass raw SPF but fail DMARC alignment. This is expected behavior for many third-party senders, but only acceptable if DKIM is passing and aligned. Verify by checking the <auth_results> DKIM section for your domain in the d= field.
Inconsistent DKIM results from a single provider. If an IP shows dkim=pass on some records and dkim=fail on others during the same reporting period, check for a stale or missing DKIM DNS record. Key rotation without updating DNS is a frequent cause.
Low counts with disposition: reject. Small numbers of rejected messages from unrecognized IPs are usually spoofing attempts being blocked by your policy. This is DMARC working as intended. No action needed.
When to stop reading XML manually
Parsing raw XML works for one-off debugging. It does not scale. If your domain sends through multiple providers, you will receive dozens of aggregate reports per day. Each one needs to be decompressed, parsed, and cross-referenced against your known sending sources.
The AcuityScan DMARC Analyzer parses aggregate XML files and presents the data as structured output: source IPs mapped to sending services, pass/fail rates, and alignment status at a glance. If you need to build or update the underlying DMARC record, the DMARC Record Generator produces a valid TXT record with each tag explained.
For a full view of your domain's email authentication setup, run a scan at acuityscan.com. The email module validates SPF syntax, checks DMARC enforcement, probes 16 common DKIM selectors, and scans against 77 verified active email blacklists.
TL;DR
- DMARC aggregate reports are XML files sent by receiving mail servers summarizing how your domain's messages performed against SPF, DKIM, and DMARC alignment.
- Every report has three sections: metadata (who sent it), published policy (your DMARC record as seen by the receiver), and record rows (per-IP authentication results).
- The critical distinction is between raw auth results and policy-evaluated alignment results. A raw SPF pass can still be a DMARC alignment failure.
- Watch for unknown source IPs, known services failing alignment, and inconsistent DKIM results across reporting periods.
- Manual XML review works for debugging single reports. For ongoing monitoring, use a parser that maps IPs to services and flags failures automatically.
Scan your own site
See what 350+ checks find on your domain.
Free, no signup, 60 seconds. Email auth · DNS · SSL · Performance · SEO · Accessibility · Privacy · Mobile.
