How to Read DMARC Aggregate Reports Without a Paid Tool
You published a DMARC record weeks ago, and now a mailbox is filling with zipped XML attachments from Google, Microsoft and Yahoo that nobody on the team opens.

You published a DMARC record weeks ago, and now a mailbox is filling with zipped XML attachments from Google, Microsoft and Yahoo that nobody on the team opens. Those files are DMARC aggregate reports, and they are the only way to know whether moving your policy to quarantine or reject will quietly break invoices, password resets or your newsletter.
Plenty of vendors will parse them for a monthly fee. For a small domain sending a few thousand messages a day, you can read them yourself in about fifteen minutes a week. This guide walks through the structure of a report, what each field tells you, and a workflow for tightening your policy without losing mail.
What DMARC aggregate reports actually contain
When a receiving mail provider sees messages claiming to come from your domain, it records the results of SPF and DKIM checks, groups them by sending IP address, and once a day sends a summary to the address in the rua tag of your DMARC record. Each report covers a 24 hour window from one provider.
The file is gzip or zip compressed XML, usually 1 to 50 KB. Inside are three main parts:
- report_metadata: who sent the report, a report ID and the date range as Unix timestamps.
- policy_published: the DMARC policy the receiver saw for your domain, including p, sp, pct and the adkim and aspf alignment modes.
- record: one entry per sending source, repeated as many times as needed. This is where all the useful information lives.
Aggregate reports never include message content, subject lines or recipient addresses. They are counts and authentication results, nothing more. That makes them safe to store and share inside your team.
Reading a single record line by line
Each record has a row section and an auth_results section. Read them in this order.
- source_ip and count. The IP that sent mail as your domain, and how many messages it sent that day. Start with the biggest counts.
- policy_evaluated. Shows the final DMARC verdict for dkim and spf (pass or fail) and the disposition the receiver applied: none, quarantine or reject.
- identifiers. The header_from domain, which should be yours, plus envelope_from if the receiver includes it.
- auth_results. The raw DKIM and SPF results with the domain each check was performed against, plus the DKIM selector.
The key concept is alignment. DMARC passes only if SPF or DKIM passes and the domain that passed matches your From domain. A newsletter platform can pass SPF for its own bounce domain while failing DMARC for yours, because the domains do not align. If the difference between authentication and alignment is still fuzzy, our explainer on why email authentication records confuse website owners covers it in plain terms.
Sorting sources into three buckets
After a week of reports, list every source IP with its total count and DMARC result. Look up who owns each IP using a reverse DNS lookup or a WHOIS query from your terminal. Then sort them:
| Bucket | What it looks like | Action |
|---|---|---|
| Legitimate and aligned | Your mail server or ESP, DKIM pass with your domain | Nothing, this is the goal |
| Legitimate but failing | A CRM, helpdesk or billing tool sending as you, DKIM signed with the vendor's domain | Set up custom DKIM for your domain in that service |
| Unknown or spoofing | Residential IPs, unfamiliar hosting providers, small counts from many countries | Leave it failing, a stricter policy will block it |
The middle bucket is the one that matters. In my experience, a typical small business has two to five forgotten senders: an invoicing tool, a form plugin on the website, a scheduling app, maybe an old marketing platform someone still uses. Every one needs aligned DKIM before you move past p=none.
A free workflow for parsing the files
You do not need a paid dashboard. A workable setup takes under an hour to build.
- Dedicated mailbox. Point rua at a separate address so reports do not clutter a human inbox. A filter rule can collect them in one folder.
- Batch download. Export the attachments once a week into a folder. Most mail clients let you select all and save attachments in one action.
- Decompress and parse. A short Python script using the standard library's gzip, zipfile and xml.etree modules can turn a folder of reports into a CSV with columns for date, reporter, source IP, count, DKIM result, SPF result and disposition. It is about 40 lines.
- Self hosted option. If you prefer a ready made tool, open source parsedmarc can read the mailbox over IMAP and push results into Elasticsearch or a simple JSON output. It runs happily in a small container.
Open the CSV in a spreadsheet, sort by count descending, and filter on DMARC fail. That view answers most questions in a few minutes.
Why I would not jump straight to p=reject
A lot of guides say to publish p=reject on day one because spoofing is dangerous and anything softer is half a measure. For a brand new domain with a single sending service, fine. For an established domain, that advice causes real outages.
The problem is that forgotten senders only show up when they send. A quarterly billing run or an annual renewal reminder might not appear in your reports for weeks. Reject too early and those messages disappear silently, and you hear about it from a customer who never received an invoice.
A safer path for an existing domain looks like this:
- p=none for at least four weeks, ideally covering one full billing cycle. Fix every legitimate source that fails.
- p=quarantine with pct=25 for two weeks, then raise pct to 100 if nothing breaks.
- p=reject with pct=25, watching reports closely, then 100.
That is roughly two to three months end to end. Slower, but you will not be the person explaining why password reset emails stopped. It also pairs well with fixing the reasons mail ends up in junk, covered in how email deliverability works and why messages land in spam.
Odd things you will see in reports
- Forwarded mail failing SPF. When a recipient forwards your message, the forwarding server's IP is not in your SPF record. DKIM usually survives, so DMARC still passes. If you see SPF fail with DKIM pass, this is normally the cause.
- Mailing lists breaking DKIM. Lists that add footers or change subject lines invalidate the signature. Some receivers apply local overrides, shown as a reason field such as mailing_list or forwarded.
- Duplicate reports. Some providers send two reports for overlapping windows. Deduplicate by report ID before you add counts together.
When a single message looks suspicious, aggregate data will not tell you more. At that point, pull the full headers from a test message and follow the steps in reading email headers to trace a delivery problem.
Frequently asked questions
How often are DMARC aggregate reports sent?
Most large providers send one report per day per domain, covering the previous 24 hours. Smaller receivers may send less often or not at all. Expect the first reports to arrive within one to two days of publishing a rua address.
What does DMARC fail mean in an aggregate report?
It means neither SPF nor DKIM passed with a domain aligned to your From address for those messages. The cause is usually a legitimate service that is not set up with custom DKIM, or someone spoofing your domain. Check the source IP to tell which.
Do DMARC reports show the content of emails?
No. Aggregate reports only include counts, sending IPs and authentication results. Forensic reports, set with the ruf tag, can include message samples, but most major providers no longer send them for privacy reasons.
More in Email Infrastructure
Email Infrastructure
Dedicated IP for Email Sending and When a Shared Pool Wins
A client of mine was sending 9,000 receipts and newsletters a month when their email provider offered a dedicated IP for an...
Email Infrastructure
How to Read Email Headers and Trace a Delivery Problem
A customer swears they never got your invoice. Your sending dashboard says "delivered".
Email Infrastructure
Why Your Newsletter Lands in the Promotions Tab
You send a newsletter, it arrives, nobody opens it, and eventually you find it quietly sitting in the promotions tab.