DMARC Reports: How to Read Aggregate (rua) and Failure (ruf) Reports
DMARC aggregate reports are daily XML summaries of every IP sending as your domain and whether it passed. Here's how to read them and what to do with them.
On this page
DMARC aggregate reports (the rua reports) are XML files that receiving mail servers send you, usually once a day, summarizing every IP address that sent mail using your domain in the From line, how many messages it sent, and whether SPF, DKIM and DMARC passed. Failure reports (ruf) are per-message reports of individual failures, and most large providers don't send them. Read the aggregate reports by grouping rows by source, identifying each source, and checking whether its passes were aligned with your domain.
If you haven't published a DMARC record with a rua address yet, nothing gets sent. Start with What is DMARC? and the DMARC record generator.
Turning reports on
Reports go wherever your DMARC record's rua tag points:
v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com
A few things to get right:
- Use a dedicated mailbox or a reporting service. A domain with real volume gets reports from many receivers every day. Don't point
ruaat someone's personal inbox. - Sending reports to another domain needs permission. If
ruapoints outside your organizational domain (say,rua=mailto:reports@dmarc-vendor.example), receivers first look for a TXT record atexample.com._report._dmarc.dmarc-vendor.examplethat starts withv=DMARC1. If the vendor hasn't published it, receivers won't send. Reporting services handle this for their customers, but it's the first thing to check if reports never arrive. - Give it a few days. Reports usually cover one UTC day and arrive the day after.
Not every receiver reports. Google sends aggregate reports daily. Microsoft 365 sends them for mail its own MX receives, and documents that it doesn't send them when a domain's mail is routed through another service first.
What an aggregate report looks like
Reports arrive as compressed XML attachments with a subject line like:
Report Domain: example.com Submitter: google.com Report-ID: 1234567890
Here's a trimmed example with one passing source and one failing source:
<feedback>
<report_metadata>
<org_name>google.com</org_name>
<report_id>1234567890</report_id>
<date_range>
<begin>1791158400</begin>
<end>1791244799</end>
</date_range>
</report_metadata>
<policy_published>
<domain>example.com</domain>
<adkim>r</adkim>
<aspf>r</aspf>
<p>none</p>
<sp>none</sp>
</policy_published>
<record>
<row>
<source_ip>203.0.113.7</source_ip>
<count>4210</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>
<selector>s1</selector>
<result>pass</result>
</dkim>
<spf>
<domain>bounce.example.com</domain>
<result>pass</result>
</spf>
</auth_results>
</record>
<record>
<row>
<source_ip>198.51.100.24</source_ip>
<count>312</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>crm-example.net</domain>
<selector>k1</selector>
<result>pass</result>
</dkim>
<spf>
<domain>mail.crm-example.net</domain>
<result>pass</result>
</spf>
</auth_results>
</record>
</feedback>
The parts that matter
report_metadata says who sent the report (org_name) and the period it covers. The begin and end values are Unix timestamps in seconds.
policy_published is your DMARC record as the receiver saw it. If this doesn't match what you think you published, you have a DNS problem.
Each record is one row of traffic: a source IP and a message count, plus results.
policy_evaluated is the DMARC verdict. Its dkim and spf values are only pass or fail, and they mean aligned pass. disposition is what the receiver actually did: none, quarantine or reject. (Newer reports can also say pass, meaning "passed DMARC under an enforcing policy.") If the receiver overrode your policy, a reason element says why, with values like local_policy, mailing_list or trusted_forwarder.
auth_results shows the raw SPF and DKIM results and, crucially, which domain each one was for. This is where you see why something failed alignment.
Read the second record in the example again. In auth_results, DKIM passed and SPF passed. In policy_evaluated, both failed. That's not a contradiction: they passed for crm-example.net, not for example.com. That's the most common pattern you'll find, and it means a CRM is sending as you without custom DKIM. DMARC fail: why it fails and how to fix it covers the fix.
Reports produced under the new standard (RFC 9990) add an XML namespace and a few fields: np and testing in policy_published, discovery_method, and optional envelope_from and human_result elements. The structure above is otherwise the same.
How to work through your reports
Raw XML from dozens of receivers is not something to read by hand for long. Feed reports into a parser or reporting service that totals them by source. Then work through it like this:
- Sort sources by volume. Your top few sources account for most of your mail. Make sure they're clean first.
- Identify each source. Look up the reverse DNS of the IP, or which organization owns it. An IP that resolves to
o1.mail.esp-example.netis your email provider. Group IPs by owner, since one service sends from many. - Sort every source into one of four buckets:
| Bucket | What it looks like | What to do |
|---|---|---|
| Yours, aligned | policy_evaluated passes on DKIM (and ideally SPF) | Nothing. Keep it that way |
| Yours, not aligned | auth_results passes, but for the vendor's domain | Set up custom DKIM and a custom Return-Path for that service |
| Forwarded | Known forwarders or university/alumni IPs; SPF fails, DKIM often still passes | Usually nothing; aligned DKIM covers you |
| Not yours | Unrecognized IPs, failing everything, often low volume from many places | That's spoofing. It's what your policy is for |
- Fix the "yours, not aligned" sources one at a time. If a DKIM result shows
failfor your own domain, the signature is breaking in transit; see DKIM fail: body hash did not verify. If SPF showspermerror, check your SPF lookup count. - Watch for new sources. A source that wasn't there last month is either a new tool someone signed up for or a new spoofing campaign. Either way you want to know.
Don't add unrecognized IPs to your SPF record to make failures go away. If you don't know what a source is, find out first. Authorizing a spoofer is worse than leaving it failing.
Once every legitimate source lands in the first bucket, you're ready to tighten your policy. See DMARC policy: none vs quarantine vs reject.
Failure (ruf) reports
Failure reports, sometimes called forensic reports, describe individual messages that failed. They're requested with the ruf tag:
v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-failures@example.com; fo=1
The fo tag controls when they're generated:
| Value | Generates a report when |
|---|---|
0 (default) | All mechanisms fail to produce an aligned pass |
1 | Any mechanism fails to produce an aligned pass |
d | A DKIM signature fails, regardless of alignment |
s | SPF fails, regardless of alignment |
Don't count on them. Google says Gmail doesn't support ruf, and Microsoft says Microsoft 365 doesn't send failure reports even when a valid ruf address is published. The receivers that do send them often redact parts of the message, because the reports can contain personal data: the failure reporting spec (RFC 9991) spends a good deal of space on privacy and recommends redacting message bodies and addresses.
When you do get them, they're useful for one thing aggregate reports can't show: the actual headers of a failing message, including the Subject and the full DKIM signature. That can identify a mystery source in minutes. Just be aware you're receiving other people's data and handle the mailbox accordingly.
When to get help
If your reports show significant volume from sources you can't identify, or you've fixed what you can and pass rates still won't move, it's worth having someone go through the reports with you.
FAQ
How often do DMARC reports arrive?
Usually once a day per receiver, each covering one UTC day. A domain with a lot of mail can get hundreds of reports a day from different receivers.
Why am I not getting any DMARC reports?
Check that your DMARC record parses and has a rua address, using the SPF, DKIM and DMARC checker. If rua points to another domain, that domain has to publish the _report._dmarc authorization record. And give it a couple of days.
Why does the report show DKIM pass in one place and fail in another?
auth_results shows whether DKIM passed for whichever domain signed. policy_evaluated shows whether it passed for a domain aligned with your From address. A pass for your provider's domain shows up as pass in the first and fail in the second.
Should I turn on ruf reports?
You can, but few large providers send them, and the ones that arrive may contain personal data. Aggregate reports are what you'll actually work from.
Sources
Related guides
- DKIM Fail: Body Hash Did Not Verify, Signature Failed and Other CausesDKIM fails when the message changed after signing (body hash did not verify), the signed headers changed, or the receiver can't find a matching public key.
- DMARC Fail: Why DMARC Fails and How to Fix ItDMARC fails when neither SPF nor DKIM passes for a domain aligned with your From address. Usually a sender lacks custom DKIM. Here's how to find and fix it.
- DMARC Policy: p=none vs quarantine vs reject (and Getting to Enforcement)p=none only monitors, p=quarantine asks receivers to junk failing mail, p=reject asks them to refuse it. Start at none, fix your senders, then tighten.
- DMARC Record Syntax and Tags ExplainedA DMARC record is a TXT record at _dmarc.yourdomain with tags for policy, reporting and alignment. Here's what each tag does and what's changed under DMARCbis.
- SPF 10 DNS Lookup Limit, Void Lookups and SPF FlatteningSPF allows 10 DNS lookups per check. Go over and receivers return permerror, so SPF fails. Here's what counts, how void lookups work, and how to fix it.
- SPF, DKIM and DMARC Explained: How They Work TogetherSPF checks the sending server, DKIM checks a signature, and DMARC checks that one of them passed for your From domain and says what to do if not.
Still stuck?
Some deliverability problems take an experienced eye to untangle. Tell me what you're seeing and I'll tell you what I'd check first. The first 30-minute call is free.