To read a DMARC report, skip most of the XML and answer three questions with it: who is sending as your domain, what share of that mail authenticates, which sources are failing. A DMARC aggregate report is a daily file from a mailbox provider listing every IP address that sent mail claiming to be you, how many messages each one sent, plus what the provider decided about them. Everything else in the file is packaging.
Almost nobody does this. The record gets published on day one with a rua= address, reports start arriving, the folder fills with gzipped XML from Google and Microsoft and a handful of providers you have never heard of, then the whole thing becomes an email filter rule. Which is how domains end up sitting on p=none for two years, watching themselves get spoofed without blocking any of it, unable to tighten because nobody can say what would break.
What actually arrives at your rua address
The rua= tag in your DMARC record is a request for feedback. Providers that honour it send you one report per domain per day, as an XML file attached to an email, usually gzipped and occasionally zipped. Filenames follow a convention that is worth recognising:
google.com!yourdomain.com!1754870400!1754956799.xml.gz
That is the reporting organisation, your domain, then the start and end of the window as seconds since the Unix epoch. So you can sort a folder by filename and get a clean timeline before you open anything.
Two limits to set expectations. These reports are aggregate, meaning they count messages by sending source rather than describing individual emails, so there is no recipient address or subject line in them. And they lag: a report covering Monday typically arrives Tuesday or Wednesday. DMARC also defines a failure report type behind a ruf= tag, but most large providers stopped sending those for privacy reasons, so aggregate reports are the feedback loop you actually get.
Every field in a DMARC report, annotated
The schema is flat and machine generated, which is why it is readable once you know what to ignore. Three blocks matter.
| Field | Block | What it tells you |
|---|---|---|
<org_name> | report_metadata | Who sent the report, such as google.com or Enterprise Outlook |
<report_id> | report_metadata | Unique identifier for this report. Use it to dedupe when a provider resends |
<begin> / <end> | report_metadata > date_range | The window covered, in seconds since the Unix epoch. Convert before comparing anything |
<domain> | policy_published | The domain the policy was found on. Confirms which record the provider read |
<p> | policy_published | The policy that provider saw: none, quarantine or reject. Check it against what you believe you published |
<sp> | policy_published | The separate policy for subdomains, if you set one |
<source_ip> | record > row | The IP that sent the mail. This is the anchor of the entire report |
<count> | record > row | Messages that IP sent in the window. Rows are aggregated, so one row can mean one message or forty thousand |
<disposition> | record > row > policy_evaluated | What the provider did: none, quarantine, reject |
<dkim> | record > row > policy_evaluated | The DKIM result after alignment. A pass here is a pass DMARC accepted |
<spf> | record > row > policy_evaluated | The SPF result after alignment |
<header_from> | record > identifiers | The From domain the recipient saw. Matters once subdomains start sending |
<spf> / <dkim> | record > auth_results | The raw authentication result before alignment. Looks almost identical, means something different |
One trap in that table. Under p=none, disposition reads none on every row, including the ones that failed badly, because you told receivers to take no action. Disposition describes the consequence, not the health. Read the SPF and DKIM verdicts for health.
The distinction that makes reports readable: passing is not aligning
This is the part that trips up everyone reading their first report. It is also the reason a domain can look healthy in one field while DMARC is junking its mail.
SPF and DKIM each authenticate a domain, but not necessarily your domain.
- SPF checks the envelope sender, the
Return-Pathaddress the receiving server sees during the SMTP conversation. On most sending platforms that is the platform's own bounce domain, not yours. SPF passes cleanly for a domain your recipient never sees. - DKIM checks the signature's
d=value. If your provider signs with a shared domain of their own rather than a key published on yours, DKIM also passes for someone else's domain.
DMARC ignores both of those unless the authenticated domain matches the From address the recipient reads. That match is alignment, the only thing DMARC actually scores. An unaligned pass is a DMARC failure. If your reports show this pattern, the fix is a DKIM key published on your own domain, which the SPF, DKIM and DMARC setup guide walks through per sending domain.
Two rules follow from that, both worth writing down before you summarise anything:
- Read
policy_evaluated, notauth_results. Theauth_resultsblock is the raw outcome. Summarising that block and calling it your DMARC health is the classic way to report a domain as fine while receivers are rejecting its mail. - A message passes DMARC on either aligned SPF or aligned DKIM. Not both. Requiring both is the opposite mistake, the one that makes a perfectly healthy domain look broken. Plenty of legitimate cold email passes on aligned DKIM alone with SPF unaligned forever, which is fine.
How to read a DMARC report in three questions
Everything above is orientation. This is the actual reading, in the same three passes whether you have one report or ninety.
Question 1: who is sending as me
Pull the distinct source_ip values across every report, then put a name to each one. Reverse DNS gets you most of the way, whois covers the rest.
On a well-behaved cold email domain the list is short: your sending platform's IPs, plus Google or Microsoft if the mailboxes live on Workspace or 365. On a company's main domain it is never short, because payroll software, the CRM, the helpdesk and a booking tool are all quietly sending as the domain. That difference is a real argument for keeping outreach on separate sending domains: a short source list is a domain you can actually reason about.
Question 2: what share of it authenticates
Sum count across every row for your total messages seen. Sum count again across rows where either evaluated SPF or evaluated DKIM passed. Divide the second by the first.
The thresholds we use for that ratio:
| Pass rate | Read it as |
|---|---|
| 99 percent or more | Clean. The failures are noise, usually forwarding |
| 95 to 99 percent | Watch. Something small is broken or something small is spoofing you |
| Below 95 percent | Act. Tightening the policy today would start junking real mail |
Two caveats keep this honest. The rate covers mail the reporting providers saw, so it is a sample weighted toward Gmail and Outlook rather than a full audit of your sending. And zero volume is not a clean bill of health, it is an absence of evidence. A brand new domain with no rows in its reports has proved nothing.
Question 3: which failing sources are mine
Take every row where both evaluated results failed, group by source_ip, sort by count descending. That list is the whole point of the exercise. Each entry on it is one of four things:
- A legitimate sender of yours that is not aligned. The most common answer by a distance, usually the DKIM problem above. Fixable in DNS.
- A forwarder. A recipient auto-forwards to another address, SPF breaks in transit because the forwarding server is not in your record, DKIM often survives. Shows up as many IPs each with small counts.
- Something connected without telling you. A newsletter tool, an invoicing app, a contractor's sequencer. Common on shared domains, rare on dedicated sending domains.
- Someone spoofing you. Which is what enforcement exists to stop.
The XML cannot tell you which of the four you are looking at. Only recognising the IP can. That is the actual work, which is also the step people skip before deciding their reports look fine.
The decision rule for tightening
Here is the rule the whole exercise builds toward: tighten only when you can name every failing source, not when the pass rate looks good.
The reason is that p=quarantine does not distinguish spoofers from you. It applies to all mail that fails alignment, including your own. Tighten while a legitimate sender of yours is unaligned and you have personally arranged for your campaigns to land in spam, on the domain where you did everything else right. The none versus quarantine decision covers the staged rollout, including the percentage flag that lets you tighten a slice at a time.
In practice that means two to four weeks of reports, every source identified, then p=quarantine. Since the 2024 Google and Yahoo sender requirements made DMARC mandatory for bulk senders, most people already have the record. The reports have been arriving the entire time. Reading a month of them is the cheapest protection available on the domain.
Reading a folder of them without handing them to anyone
Free online DMARC analyzers work by receiving your reports, which means pointing your rua= at their address or forwarding them on. Think about what that hands over. These reports name every IP address that sends on your behalf, dated and counted. For an agency that is a map of your infrastructure and your clients' infrastructure, in one file, refreshed daily.
The format does not justify the trade. It is flat XML with no attributes worth parsing, which is why ColdOps reads these with a small local script rather than a service: point it at a folder of .xml and .gz attachments and it prints the domain, the published policy, messages seen, the authenticated share, then the failing sources worst first with a verdict on whether it is safe to tighten. No account, no upload, nothing leaves the machine. If you would rather not run anything, opening a single report in any text editor and reading the rows by hand is genuinely fine for one domain.
Worth separating two checks that sound the same. The free DMARC checker reads the record you published and tells you what it instructs receivers to do. The aggregate reports tell you what the world actually did with mail claiming to be you. You need both, because a perfect record proves nothing about whether your mail aligns in the wild.
The ongoing problem is that neither check stays true. A regenerated DKIM key, a platform migration, a DNS edit made in a hurry, any of these break alignment on a domain that passed last month. Under an enforced policy the damage is your own campaigns going to spam quietly. ColdOps re-verifies DMARC, SPF, MX and blacklist status across every client sending domain on a schedule, so a record that breaks on Tuesday surfaces as an alert on Tuesday instead of a reply-rate mystery three weeks later.
If your reports have been arriving for a year and you have never opened one, start with the most recent week. Name the sources, work out the pass rate, then decide whether p=none is still doing anything for you.
Frequently asked
How do I read a DMARC report?
What does a DMARC aggregate report contain?
Why does my DMARC report show SPF pass but DMARC fail?
What is a good DMARC pass rate?
Do I need a DMARC report analyzer?
Keep reading
APRF: Aggregate Performance Reporting, Explained
Comcast sends APRF reports today and Google co-wrote the spec. What Aggregate Performance Reporting returns and why cold email cannot use it yet.
ReadDeliverabilitySURBL blacklist check: why clean domains still get filtered
A SURBL blacklist check reads the domains inside your email, not the one you send from. Why a clean sending domain still gets filtered, plus what to check.
ReadDeliverabilityEmail Deliverability Monitoring Tools: What to Watch
What email deliverability monitoring tools track, the signals that matter, when manual checking breaks down and how to choose a tool that fits your sending setup.
Read