How to read DMARC aggregate reports
What’s inside a DMARC aggregate (RUA) report, what each XML field means, how to spot legitimate senders vs spoofing, and what to do with forensic (RUF) reports.
Updated September 30, 2026
A DMARC aggregate (RUA) report is an XML file that a mailbox provider such as Gmail, Outlook.com or Yahoo emails to the address in your record’s rua= tag, usually once a day. It lists every IP address that sent mail with your domain in the From header, how many messages each sent, and whether each passed SPF and DKIM with alignment. Reading them is how you find your legitimate senders before enforcing DMARC and how you spot spoofing afterwards.
Who sends DMARC reports, and how often
Any receiver that checks DMARC can send aggregate reports; the large ones do, including Google, Microsoft (Outlook.com), Yahoo and many other providers and corporate gateways. Each report covers one reporting period, normally one day (often midnight to midnight UTC), for one policy domain. A domain with steady mail gets several reports a day, one from each receiver that saw its mail. Low-volume domains may get none on quiet days, because receivers only report when they received something.
To start receiving them, add a rua tag to your record, for example v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com. Reports arrive as email attachments. Some receivers send .zip files, others gzip (.gz), and a few plain .xml. The updated reporting standard, RFC 9990 (May 2026), says reports should be gzip-compressed, with file names like receiver.example!example.com!1790553600!1790639999.xml.gz: the reporter, your domain, and the start and end of the period as Unix timestamps.
An annotated example report
Here is a trimmed report for one day at example.com, showing the three kinds of source you’ll see most: your own platform, a third-party service, and a stranger. The comments aren’t part of a real report.
<?xml version="1.0" encoding="UTF-8"?>
<feedback>
<report_metadata>
<org_name>receiver.example</org_name>
<email>noreply-dmarc@receiver.example</email>
<report_id>8472615093746152093</report_id>
<date_range>
<begin>1790553600</begin> <!-- 2026-09-28 00:00:00 UTC -->
<end>1790639999</end> <!-- 2026-09-28 23:59:59 UTC -->
</date_range>
</report_metadata>
<policy_published>
<domain>example.com</domain>
<adkim>r</adkim>
<aspf>r</aspf>
<p>none</p>
<sp>none</sp>
<pct>100</pct>
</policy_published>
<!-- 1. Your own mail platform: SPF and DKIM both pass and align -->
<record>
<row>
<source_ip>192.0.2.10</source_ip>
<count>1240</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>google</selector>
<result>pass</result>
</dkim>
<spf>
<domain>example.com</domain>
<result>pass</result>
</spf>
</auth_results>
</record>
<!-- 2. An email service: DKIM aligned, SPF passes for the vendor's bounce domain -->
<record>
<row>
<source_ip>198.51.100.25</source_ip>
<count>310</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>pass</dkim>
<spf>fail</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>bounces.esp.example.net</domain>
<result>pass</result>
</spf>
</auth_results>
</record>
<!-- 3. Someone else using your domain: nothing passes -->
<record>
<row>
<source_ip>203.0.113.77</source_ip>
<count>18</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>
<spf>
<domain>example.com</domain>
<result>fail</result>
</spf>
</auth_results>
</record>
</feedback>report_metadata: who sent the report and when
org_name and email identify the receiver that wrote the report. report_id is unique per report, which lets you drop duplicates. date_range gives the start and end as Unix timestamps (seconds since 1970, UTC). RFC 9990 reports may also include a generator element naming the software.
policy_published: your record as the receiver saw it
This echoes the DMARC record the receiver found: the domain, p, sp, alignment modes adkim and aspf, and (in older-format reports) pct. It’s a quick check that receivers see the record you think you published. Reports in the RFC 9990 format add np (policy for non-existent subdomains), testing (the new t= flag) and discovery_method, and wrap everything in the namespace urn:ietf:params:xml:ns:dmarc-2.0. Expect both formats for a while.
record and row: one source, one line
Each record groups messages that share a source IP and the same results. row holds the summary:
source_ip: the IP that connected to the receiver. Look up its reverse DNS and owner to identify the sender.count: how many messages matched this row during the period.disposition: what the receiver did,none,quarantineorreject. It can differ from your policy when a receiver applies a local override, which some reports explain in areasonelement (forwarded, mailing list, local policy).
policy_evaluated vs auth_results: the part people misread
The same message has two sets of SPF and DKIM results, and they answer different questions.
| Element | Question it answers | Row 2 in the example |
|---|---|---|
policy_evaluated | Did SPF or DKIM pass and align with the From domain? (the DMARC verdict) | DKIM pass, SPF fail |
auth_results | Did the raw check pass, and for which domain? | DKIM pass for example.com, SPF pass for bounces.esp.example.net |
In row 2, SPF passed, but for the vendor’s bounce domain, so it doesn’t count for DMARC. DKIM passed for example.com and aligns, so the message passes DMARC. A message passes DMARC when either dkim or spf under policy_evaluated is pass. When auth_results shows a pass that policy_evaluated shows as a fail, you have an alignment problem; see DMARC alignment and why DMARC fails.
identifiers: which domains were involved
header_from is the domain in the From header, the one DMARC protects. Many reports also include envelope_from (the Return-Path domain SPF checked) and sometimes envelope_to. Under auth_results, each dkim entry gives the signing domain (the d= tag), the selector and the result; RFC 9990 makes the selector mandatory. Each spf entry gives the domain checked and a result such as pass, fail, softfail, neutral, none, temperror or permerror.
How to tell legitimate senders from spoofing
| Signal | Probably yours | Probably spoofing or spam |
|---|---|---|
| Reverse DNS / owner | Your mail platform or a service you use (google.com, outlook.com, a known email service) | Residential ISPs, hosting providers you don’t use, no reverse DNS |
| Volume | Steady, day after day, matching your sending patterns | Bursts, or a handful of messages from many IPs |
| Auth results | DKIM passes, perhaps for the vendor’s domain; SPF passes for some domain | Both fail, or DKIM missing entirely |
| Forwarding pattern | SPF fails but aligned DKIM passes, from another mail provider | n/a |
Row 3 in the example is typical spoofing: an IP you don’t use, a small count, SPF failing for your domain and no DKIM signature at all. At p=reject, that mail is refused. A failing source that looks like a real service (steady volume, a vendor’s reverse DNS, DKIM passing for the vendor’s domain) is almost always a tool someone in your organization uses that still needs setting up. Once every legitimate source passes, follow the plan from p=none to p=reject.
Sending reports to another domain (external authorization)
If your rua address is on a different domain from the one publishing the record (for example a reporting service), receivers first check that the destination agreed to receive them. Otherwise anyone could point floods of reports at a victim. The check is a TXT lookup at <your domain>._report._dmarc.<report domain>, and any record there starting with v=DMARC1 authorizes it. For example.com sending reports to reports.example.net, the reporting domain publishes:
| Host | Type | Value |
|---|---|---|
example.com._report._dmarc.reports.example.net | TXT | v=DMARC1A wildcard (*._report._dmarc.reports.example.net) authorizes every domain at once. |
You don’t publish this yourself; the reporting service does. If reports to a third-party address never arrive, a missing authorization record is the first thing to check. With DMARC Dojo each domain gets a private report inbox at rua.dmarcdojo.ai, already authorized, and the reports are parsed automatically into daily pass and fail statistics and a per-source breakdown with reverse DNS and provider names.
Forensic (RUF) failure reports
The ruf= tag requests failure reports: one message per failing email, often including headers and sometimes the content. They’re defined in RFC 9991 (previously part of RFC 7489) using the format from RFC 6591. They sound useful but are rarely worth relying on:
- Few receivers send them. Gmail doesn’t support
ruf, and Microsoft says it has no plans to send RUF for Outlook.com. Those two receive a large share of consumer mail. - Privacy. Failure reports can contain recipients’ addresses, subject lines and message content: personal data from people who aren’t your customers. RFC 9991 has a whole section on privacy considerations, and many receivers redact heavily or don’t send them for that reason.
- Volume. One report per failed message can mean thousands of emails during a spoofing campaign.
Aggregate reports give you what you need to reach enforcement. DMARC Dojo processes aggregate reports only, not forensic reports.
Frequently asked questions
Why am I not getting any DMARC reports?
Check that the record has a valid rua=mailto: address, that the mailbox accepts attachments, and, if the address is on another domain, that the _report._dmarc authorization record exists. Low-volume domains may also get few or no reports on quiet days.
Why do reports show IP addresses I don’t recognize?
Usually forwarding (a recipient’s mail being relayed onward), a service a colleague signed up for, or spoofing. Reverse DNS, volume and whether DKIM passes tell them apart.
Can I send DMARC reports to more than one address?
Yes. Separate addresses with commas in the rua tag, for example rua=mailto:a@example.com,mailto:b@example.net. Each external address needs its own authorization record.
Do aggregate reports contain message content?
No. They contain counts, IP addresses, domains and authentication results, with no subjects, recipients or bodies. That’s why every major receiver sends them.
Should I add a ruf address?
It rarely helps: Gmail and Outlook.com don’t send failure reports, and those that arrive may contain personal data you then have to handle carefully. Aggregate reports are enough to reach p=reject.