How to read a DMARC aggregate report (rua) and what to do with it
A DMARC aggregate report is a daily summary that large mailbox providers send to the address in the rua tag of your DMARC record. It lists every IP address that sent mail using your domain in the From line, how many messages each one sent, and whether SPF and DKIM passed and aligned with your domain. It does not contain message content, subjects or recipients' addresses.
Reading these reports is how you find out who is really sending as you: your own mail servers, the CRM, the invoicing tool, the newsletter platform, and anyone else who simply puts your domain in the From line. That list is what you need before you move your policy from p=none to enforcement.
Since May 2026 the format is defined in RFC 9990, which together with RFC 9989 (the DMARC mechanism itself) replaced the older RFC 7489. If you need a refresher on the 3 records, start with SPF, DKIM and DMARC explained.
How reports reach you
You ask for reports with the rua tag in your DMARC record:
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com"
Each participating provider then emails you an XML file, usually compressed. RFC 9990 says the XML SHOULD be GZIP compressed, with the extension .xml.gz, and the file name follows a fixed pattern:
mail.receiver.example!example.com!1013662812!1013749130.xml.gz
That is the reporting organization, your domain, and the start and end of the period as Unix timestamps. The reporting period typically covers a single UTC day.
If reports should go to a mailbox on a different domain (for example a reporting service at reports.example.net), that domain has to confirm it accepts them. Receivers look up a TXT record such as example.com._report._dmarc.reports.example.net containing v=DMARC1, and if it is missing, they ignore the rua address. A missing confirmation record is a common reason why reports never arrive.
The structure of one report
Every report has the same 3 parts. Here is a shortened example based on the sample in RFC 9990:
<feedback xmlns="urn:ietf:params:xml:ns:dmarc-2.0">
<report_metadata>
<org_name>Sample Reporter</org_name>
<date_range><begin>302832000</begin><end>302918399</end></date_range>
</report_metadata>
<policy_published>
<domain>example.com</domain>
<p>quarantine</p>
<testing>n</testing>
</policy_published>
<record>
<row>
<source_ip>192.0.2.123</source_ip>
<count>123</count>
<policy_evaluated>
<disposition>pass</disposition>
<dkim>pass</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<envelope_from>example.com</envelope_from>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim><domain>example.com</domain><result>pass</result><selector>abc123</selector></dkim>
<spf><domain>example.com</domain><result>fail</result></spf>
</auth_results>
</record>
</feedback>
- report_metadata: who sent the report and which period it covers.
- policy_published: the DMARC record the receiver saw. Compare it with what you think you published.
- record: one block per combination of sending IP and results. A busy domain gets many of these.
Reading a record, field by field
source_ip and count. The server that connected to the receiver and how many messages it delivered in that period. This is where you identify senders: a reverse DNS lookup (dig -x 192.0.2.123 +short) or the IP owner often tells you whether it belongs to your mail provider, your CRM or someone unknown.
policy_evaluated. The DMARC verdict. Here dkim and spf are not the raw results but the alignment results: did the check pass for a domain matching your From domain. DMARC passes if at least one of them is pass. disposition shows what the receiver did: none, pass, quarantine or reject. If it differs from your policy, a reason element explains why, for example a forwarding or mailing list override.
identifiers. header_from is the domain your recipients saw. envelope_from is the domain the SPF check used, which is often a subdomain of your sending service rather than yours.
auth_results. The raw SPF and DKIM results with the domains they were checked for. RFC 9990 now requires the DKIM selector, which helps you tell which service signed the message.
In the example above, DKIM passed and aligned, SPF failed, and the message passed DMARC anyway. That is a typical picture for a service that signs with your domain but sends from its own envelope domain.
Sorting senders into 3 groups
After a few weeks of reports, every source IP fits into one of these groups:
- Known and passing. Your mail provider and properly configured services. Nothing to do.
- Known but failing. A legitimate tool (help desk, invoicing, newsletter) that sends without aligned DKIM, or is missing from SPF. Enable DKIM with your domain in that tool, or add it to SPF while watching the 10 lookup limit.
- Unknown and failing. Servers you cannot attribute to anything you use. Some are forwarders and mailing lists; others are someone putting your domain in the From line. These are exactly the messages a
p=quarantineorp=rejectpolicy would stop, the same kind of mail used in fake invoice scams.
Group 2 is the one that matters before enforcement. If you switch to p=quarantine while a legitimate tool is still failing, its mail goes to spam.
Practical tips
- Use a dedicated mailbox or a report processing tool. Raw XML from several providers every day is hard to read by hand.
- Watch the
testingvalue. RFC 9989 replaced the oldpcttag with attest mode tag;t=yasks receivers to apply a milder action than your policy. - Look at volume, not only failures. A sudden new source with a high
countdeserves attention even if it passes. - Keep reports for a few months so you can compare before and after a change.
- Remember that mailbox providers increasingly expect DMARC from bulk senders, as covered in Gmail and Yahoo sender requirements.
A short checklist
- DMARC record with a
ruaaddress someone actually reads. - External report destinations confirmed with a
_report._dmarcrecord. - Every source IP attributed to a service you know.
- Aligned DKIM enabled for every legitimate sender.
- Unknown failing sources reviewed, then the policy moved to
p=quarantineand laterp=reject.
Where Guarding fits
DMARC reports show what receivers saw. We watch the other side from the outside every day: your SPF, DKIM and DMARC records, lookalike domains and the rest of your external exposure. When a record is weakened or a selector disappears, a person reviews it and you get the exact change to make, as described in what happens when we find something. You can see how it looks in the example dashboard.
More articles
Pinned
We now proudly guard InvestTimes.com
Invest Times, an English language financial daily about startups and investing, has chosen Guarding. From today we watch InvestTimes.com from the outside, around the clock.
PHP2Shell: which PHP versions are fixed and how to check yours
The PHP project fixed 2 critical flaws on October 21, 2026. Here is which versions contain the fix, how to see what your server reports and what to ask your host.
SPF, DKIM and DMARC explained for business owners
3 DNS records decide whether anyone can send email that looks like it came from your domain. Here is what each one does and how to check yours in minutes.