How to read DMARC reports and find every sender using your domain
DMARC reports show you who sends emails in your name – and whether those emails pass SPF and DKIM. Without them, a safe switch to p=quarantine or p=reject is hardly possible. Here's how to set them up, how to read them and what to watch out for.
What DMARC reports are
Large mailbox providers such as Gmail, Yahoo and Outlook.com send the owner of a domain an aggregate report once a day. It contains no emails and no recipients, just statistics: from which server IP did how many emails with your sender address come, and did they pass SPF, DKIM and DMARC?
That's valuable for two reasons:
- You find forgotten senders – invoicing software, shop, ticket system, contact form – before you lock them out with a strict DMARC policy.
- You see whether someone is spoofing your domain. Unknown IP addresses that fail are usually spam or phishing attempts in your name.
There are also failure reports (ruf=) on individual emails. For privacy reasons, though, the large providers hardly send them anymore – in practice, the aggregate reports are what counts.
Requesting reports
You request reports with the rua= part of your DMARC record:
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com"
Ideally, set up a separate mailbox for this. Depending on your email volume, several reports arrive every day, and in your normal inbox they just get in the way.
Important for external domains: if the reports are to go to an address on a different domain, such as an analysis service, that domain must authorize it. Otherwise the providers discard the reports. The authorization is a TXT record on the receiving domain, e.g. example.com._report._dmarc.analysis.example with the content v=DMARC1. Reputable services create it for you.
How a report is structured
A report is an XML file, usually attached as .zip or .gz. Shortened, it looks like this:
<report_metadata>
<org_name>google.com</org_name>
<date_range><begin>1760140800</begin><end>1760227199</end></date_range>
</report_metadata>
<policy_published><domain>example.com</domain><p>none</p></policy_published>
<record>
<row>
<source_ip>203.0.113.10</source_ip>
<count>412</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>example.com</domain><result>pass</result></spf>
</auth_results>
</record>
| Field | Meaning |
|---|---|
org_name | Who sends the report, e.g. google.com |
date_range | Period as Unix timestamps, usually one day |
source_ip | Server that delivered the emails |
count | Number of emails from this IP |
policy_evaluated | Result for DMARC, i.e. including alignment, and what happened to the emails (disposition) |
auth_results | Raw SPF and DKIM result, with the domain that was actually checked |
Interpreting the rows correctly
The most common misconception: auth_results says “pass”, so everything is fine. Not quite – what matters is policy_evaluated. It only says “pass” if the checked domain also matches your sender address (alignment).
| What the report shows | Meaning | What to do |
|---|---|---|
Your own server IP, DKIM and SPF pass | Everything correct | Nothing |
IP of a known service, raw SPF pass with the service's domain, DMARC fail | The service sends for you, but without your own domain | Authenticate your own domain in the service (add DKIM records) |
| IP of a service you don't know, with many emails | Forgotten sender or forgery | Check reverse DNS and owner of the IP, ask your team |
Many different unknown IPs, few emails per IP, all fail | Forgery attempts (spam, phishing) | Exactly what p=reject is for |
DKIM pass, SPF fail, IP of a mail provider | Forwarding: the forwarder isn't in your SPF | Normal – DKIM survives forwarding, DMARC still passes |
From report to p=reject
- Collect: receive reports with
p=nonefor two to four weeks. Otherwise monthly services like invoice sending won't show up. - Identify senders: assign every IP with significant volume to a service. Make sure every legitimate service signs with DKIM for your domain.
- Check: once all legitimate senders pass in
policy_evaluated, switch top=quarantine. - Complete: observe for further weeks, then
p=reject. Keep the reports active – that way a new service is noticed immediately.
Common pitfalls
- No reports despite
rua=: the address is on an external domain without an authorization record, or the mailbox rejects large attachments. - Reports from only a few providers: not every provider sends reports. Gmail, Yahoo and Outlook.com cover the majority, though.
- Numbers don't match: each provider only counts the emails that arrived at it. The sum is never your total volume.
- Reading XML by hand: confusing with more than a few senders. An analysis tool summarizes the reports by sender.
Whether SPF, DKIM and DMARC are right for a single email is shown immediately by the test on the home page – including alignment.