Blog/Deliverability

How to Read DMARC Aggregate (RUA) Reports

MR
Marcus Rodriguez
Jul 1, 2026

Your DMARC aggregate feed is the only place that shows you every server sending mail as your domain. Here's how to decode the XML, catch the alignment trap, and find the spoofers and shadow-IT senders hiding in the data.

Hero image for: How to Read DMARC Aggregate (RUA) Reports

Updated Jul 1, 2026

TL;DR: A DMARC aggregate (RUA) report is a daily XML file from each mailbox provider listing every IP that sent mail using your domain, the message count, and whether SPF and DKIM aligned. Read it by matching each source_ip to a sender you recognize, then checking policy_evaluated for DMARC pass or fail. Unknown IPs that fail are spoofers or unauthorized senders; known IPs that fail are usually alignment gaps you can fix.

You turned on DMARC, dropped a rua= tag into your DNS, and now a .gz file lands in a mailbox every morning. Open one and it's a wall of XML. No subject lines, no message bodies, no names. Just IP addresses, counts, and a stack of pass/fail flags.

That wall of XML is the most useful deliverability signal most cold senders never read. It's the only report that shows you every single server sending mail under your domain, the ones you set up and the ones you didn't. For a team running outreach across several domains and a dozen mailboxes, that's the difference between knowing your authentication is solid and hoping it is.

This guide is about reading the data, not setting up the records. If you still need to publish SPF, DKIM, and a DMARC record, start with our SPF, DKIM, DMARC authentication guide and come back here once reports are flowing. We'll decode the XML field by field, walk through a real record, and show you how to turn a daily feed of IPs into a short list of senders to fix or shut down.

Key Takeaways

  • An aggregate report is metadata only: sending IP, message count, and aligned SPF/DKIM results per provider, per day. It never contains message content.
  • The single most important field is policy_evaluated, which shows the DMARC verdict after alignment, not the raw SPF/DKIM result you might expect.
  • A message can show spf=pass in auth_results but spf=fail in policy_evaluated. That gap is an alignment failure, and it's the most common thing operators misread.
  • Unknown IPs that fail DMARC are either spoofers or forgotten "shadow IT" senders. Both show up in the same place: the records with a failing disposition.
  • Raw XML stops scaling around the third report. A parser or analyzer turns the feed into a sender table you can actually act on.

What a DMARC aggregate report actually is

A DMARC aggregate report is a daily summary that a receiving provider (Gmail, Yahoo, Microsoft, and many others) sends back to you, listing how mail claiming to be from your domain was authenticated on their end. The current standard, RFC 9990, defines it as an XML document, usually GZIP-compressed, delivered by email to whatever address you named in your DMARC rua tag. RFC 9990 is the 2026 replacement for the original DMARC spec, RFC 7489, which split into three documents: core policy, aggregate reporting, and failure reporting.

Here's what matters about the format before you open one:

  • It's aggregated, not per-message. Each row groups together every message that shared the same source IP and the same authentication outcome over the reporting window. A row with count=128 means 128 messages, not one.
  • It contains zero content. No subjects, no bodies, no recipient addresses. That's by design, and it's why aggregate reports are safe to collect at scale. The message-level detail lives in failure reports (RUF), a separate and far less common feed.
  • It arrives roughly once a day, per provider. The reporting interval is requested by the ri tag in your DMARC record, which RFC 7489 sets to a default of 86,400 seconds, or 24 hours. Providers treat that as a request, not an order, and almost all of them send one report per day regardless.

So if you send from three sending domains and your mail reaches Gmail, Yahoo, and Outlook users, expect roughly three reports per domain per day, nine files, each covering a 24-hour window. That volume is exactly why you should never point rua at a mailbox you read by hand.

One quick boundary: this report tells you who is sending as your domain and whether it authenticates. It does not tell you your Gmail spam-complaint rate or your inbox-versus-spam placement. Those live in provider reputation dashboards, which our domain health monitoring guide covers. Aggregate reports answer a narrower, sharper question: is every server using my domain supposed to be?

Getting the reports flowing (the rua tag)

You only get aggregate reports if your DMARC record asks for them. The request is the rua tag, and it points at one or more mailboxes:

1v=DMARC1; p=none; rua=mailto:dmarc@yourbrand.com; pct=100

Three things to get right:

  1. Every address needs the mailto: prefix, and you separate multiple addresses with commas. Google's own DMARC setup guidance shows the exact syntax and warns that this "can potentially result in a high volume of report emails," so use a dedicated mailbox, a group, or an analyzer service, never a personal inbox.
  2. You need at least p=none. A policy of none is monitor-only: it changes nothing about how your mail is treated but still triggers the full reporting feed. Google explicitly recommends starting at none and tightening later as you learn how your mail authenticates.
  3. If you collect reports for a domain you don't own the reporting destination for, the receiving domain may need an authorization record. When [email protected] lives on the same domain you're reporting on, this doesn't apply. It only comes up with third-party analyzer addresses on a different domain.

That's the entire setup for reading. We're deliberately not covering how to move your policy from none to quarantine to reject, because that's a staged decision with its own playbook. Once your reports are clean, our DMARC p=reject migration guide walks the enforcement ladder step by step. For now, stay at p=none and read.

The DMARC XML report explained, field by field

Open a report and you'll find a single <feedback> root wrapping three logical sections: who sent the report, what policy you published, and a list of records describing the actual mail. Here's a trimmed real-world example with two records:

1<?xml version="1.0" encoding="UTF-8"?>
2<feedback>
3 <report_metadata>
4 <org_name>google.com</org_name>
5 <email>noreply-dmarc-support@google.com</email>
6 <report_id>14159265358979</report_id>
7 <date_range>
8 <begin>1717200000</begin>
9 <end>1717286400</end>
10 </date_range>
11 </report_metadata>
12 <policy_published>
13 <domain>outreach.yourbrand.com</domain>
14 <adkim>r</adkim>
15 <aspf>r</aspf>
16 <p>none</p>
17 <sp>none</sp>
18 <pct>100</pct>
19 </policy_published>
20 <record>
21 <row>
22 <source_ip>209.85.220.41</source_ip>
23 <count>128</count>
24 <policy_evaluated>
25 <disposition>none</disposition>
26 <dkim>pass</dkim>
27 <spf>pass</spf>
28 </policy_evaluated>
29 </row>
30 <identifiers>
31 <header_from>outreach.yourbrand.com</header_from>
32 </identifiers>
33 <auth_results>
34 <dkim>
35 <domain>outreach.yourbrand.com</domain>
36 <selector>google</selector>
37 <result>pass</result>
38 </dkim>
39 <spf>
40 <domain>outreach.yourbrand.com</domain>
41 <result>pass</result>
42 </spf>
43 </auth_results>
44 </record>
45 <record>
46 <row>
47 <source_ip>198.51.100.24</source_ip>
48 <count>43</count>
49 <policy_evaluated>
50 <disposition>none</disposition>
51 <dkim>fail</dkim>
52 <spf>fail</spf>
53 </policy_evaluated>
54 </row>
55 <identifiers>
56 <header_from>outreach.yourbrand.com</header_from>
57 </identifiers>
58 <auth_results>
59 <spf>
60 <domain>mailer.some-crm.com</domain>
61 <result>pass</result>
62 </spf>
63 </auth_results>
64 </record>
65</feedback>

Let me map every element to plain English. The structure below matches the schema defined in RFC 7489.

Element

What it means

report_metadata > org_name

The provider that sent the report (here, Google).

report_metadata > date_range

Start and end of the window, in Unix epoch seconds. 1717200000 to 1717286400 is exactly one day.

policy_published > domain

The domain the report covers.

policy_published > p / sp

The DMARC policy you published for the domain (p) and its subdomains (sp): none, quarantine, or reject.

policy_published > adkim / aspf

Alignment mode. r is relaxed (an organizational-domain match is enough), s is strict (an exact domain match is required).

policy_published > pct

The percentage of mail the published policy applied to.

record > row > source_ip

The IP that connected and sent the mail. This is your primary clue to who's sending.

record > row > count

How many messages this IP sent with this exact outcome in the window.

policy_evaluated > disposition

What the receiver actually did: none, quarantine, or reject.

policy_evaluated > dkim / spf

The DMARC-aligned result. This is the verdict that decides pass or fail, and it's the field people misread.

identifiers > header_from

The domain in the visible From header, the one DMARC checks alignment against.

auth_results > spf / dkim

The raw authentication results: which domain authenticated, and (for DKIM) the selector used.

The two halves to keep separate are policy_evaluated and auth_results. The first is the DMARC view: did authentication pass and align with the From domain? The second is the raw SPF/DKIM machinery underneath. Most of the confusion in DMARC reporting comes from reading one when you mean the other.

How to read a DMARC aggregate report record

Take the two records above and read them the way an operator should: IP first, then verdict, then the why.

Record one, IP 209.85.220.41, count 128. That's a Google IP, the selector is google, and both the DKIM and SPF domains are outreach.yourbrand.com, matching the header_from. The policy_evaluated shows dkim=pass and spf=pass, disposition none. This is your own mail, sent through Google Workspace, fully aligned and passing DMARC. Nothing to do. This is what every legitimate sending source should look like.

Record two, IP 198.51.100.24, count 43. Here's the lesson. Look at auth_results: SPF actually passed for mailer.some-crm.com. But policy_evaluated > spf says fail. How can SPF pass and DMARC-SPF fail at the same time?

Alignment. SPF authenticated the envelope domain mailer.some-crm.com, but the visible header_from is outreach.yourbrand.com. Those two domains don't share an organizational root, so under DMARC the SPF result doesn't align, and an unaligned pass counts as a fail. There's no DKIM signature on this mail at all, so DKIM can't rescue it. Net result: this mail fails DMARC even though SPF technically passed.

That's the alignment trap, and it's the most valuable thing a report teaches you. The fix tells you the category:

  • If mailer.some-crm.com is a service you use (a CRM, a helpdesk, a newsletter platform sending as your outreach domain), this is a legitimate sender that isn't aligned yet. You fix it by setting up domain-aligned DKIM with that vendor or adding their domain to an SPF path that aligns.
  • If you have no idea what mailer.some-crm.com is, you've just found either shadow IT or a spoofer riding your domain.

Either way, the report did its job: it surfaced a sending source you'd otherwise never have seen. Run this read on every record. Match source_ip to a sender you recognize, confirm policy_evaluated shows pass, and flag anything that fails or that you can't identify.

How to find unauthorized senders in DMARC reports

This is where aggregate reports earn their keep. Every server sending as your domain shows up here, which means the ones you didn't authorize do too. After a few days of data, sort your records into three buckets.

Bucket 1: legitimate, aligned, passing. Your Workspace or Microsoft 365 mailboxes, your warmup traffic, your sending platform. These pass DMARC cleanly and need no action. Build a short allowlist of these IPs and IP ranges so you can spot anything new fast.

Bucket 2: legitimate but failing. Real services you use that aren't aligned, the second-record case above. Maybe it's a transactional vendor, an analytics tool that sends digest emails, or a CRM blasting from a shared pool. These are safe in the sense that you authorized them, but they're dragging your authentication percentage down and they'll get blocked the moment you reach an enforcing policy. Fix alignment for each one before you tighten the policy.

Bucket 3: unknown and failing. Unfamiliar IPs, often from networks you've never used, with header_from set to your domain and a failing disposition. This is the bucket that matters for security. It's some mix of:

  • Spoofers trying to send phishing or spam as your brand. They can forge the From header but can't pass your DKIM or align your SPF, so they fail, and once you move to p=reject they get blocked outright.
  • Forwarders. Mail forwarded through a third party often breaks SPF alignment and sometimes DKIM. These are mostly benign. When a receiver can tell, it may add a policy override reason of forwarded or mailing_list to the record.
  • Forgotten shadow IT. A contractor's tool, an old form handler, a one-off script someone set up two years ago and never told you about. Functionally identical to a spoofer in the report until you trace the IP and recognize it.

The override reason element, when present, tells you why a receiver didn't apply your published policy to a record. The values defined in RFC 7489 include forwarded, sampled_out (the message fell outside your pct setting), trusted_forwarder, mailing_list, local_policy, and other. A reason is a hint about context, not a verdict, but it helps you tell a broken forwarder apart from a genuine spoofer.

To work bucket 3, take each unknown source_ip and do a reverse DNS lookup and a WHOIS check. If it resolves to a service you can place (your own infrastructure, a vendor you forgot about), it moves to bucket 1 or 2. If it resolves to a random hosting provider in a country you don't operate in, sending dozens of messages a day that all fail, you're looking at abuse, and the answer is to finish your enforcement migration so those messages get rejected.

DMARC report analyzer setup

You can read one XML file by hand. You cannot read thirty a week across four domains, and you definitely can't eyeball trends in IP behavior over a month. This is the point where raw XML stops scaling and you set up a parser.

You have two honest paths:

Open source. parsedmarc is a widely used open-source tool that ingests aggregate reports straight from an IMAP mailbox, parses the XML, enriches IPs with reverse DNS, and ships the results to a dashboard like Elasticsearch and Kibana. It's free, it's self-hosted, and it's the right call if you have the engineering time and want full control of the data.

Hosted analyzers. A range of commercial DMARC platforms (Dmarcian, Valimail, EasyDMARC, PowerDMARC, URIports, and others) will take over your rua address, parse everything, group senders into named services, and flag new or failing sources for you. They cost money and they own your report pipeline, but they turn "decode this XML" into "here are your four sending services and one of them isn't aligned." For most outreach teams, the time saved is worth it.

Whichever you pick, the analyzer setup is the same shape: point your rua tag at the tool's ingestion address (or a mailbox it reads), let a few days of reports accumulate, and start reading the sender table instead of the XML. The goal isn't a prettier report. It's getting to a place where a new failing sender pages you within a day instead of hiding in a file you never opened.

Turning report findings into action

Reading reports isn't the endgame. Reaching a clean, enforced policy is. Here's the loop the data drives:

  1. Inventory every passing sender (bucket 1) and confirm they cover all the mail you actually send. For cold outreach, that's your Workspace or Microsoft 365 mailboxes plus your warmup traffic.
  2. Fix every legitimate-but-failing sender (bucket 2) by aligning SPF or, better, adding domain-aligned DKIM with that vendor. DKIM alignment survives forwarding, SPF often doesn't.
  3. Investigate every unknown sender (bucket 3), reclassify what you can, and accept that the rest are spoofers your enforcement policy will block.
  4. Watch the failing percentage drop. Once almost all of your legitimate volume passes and aligns, you're ready to tighten the policy. That migration from none to reject is its own staged process, covered in our DMARC p=reject guide.

This matters more than it used to. Google's sender guidelines require bulk senders (those sending 5,000 or more messages a day to Gmail) to publish a DMARC policy of at least none and to align SPF or DKIM with the From domain. Microsoft went further: since May 5, 2025, Outlook.com, Hotmail, and Live.com reject mail from high-volume domains that fail SPF, DKIM, and DMARC, rather than just routing it to junk. Aggregate reports are how you confirm you're compliant before those thresholds bite.

One related payoff: a fully aligned, enforced domain is the prerequisite for showing your brand logo in the inbox. If that's on your roadmap, see our BIMI setup guide, which sits on top of the clean p=quarantine or p=reject state your reports help you reach. And if you're deciding where to send cold mail from in the first place, isolating outreach on a sending subdomain keeps these reports focused on outreach traffic instead of mixing in your corporate mail.

Common questions

How long until DMARC reports start arriving?

Usually within 24 to 72 hours of publishing a record with a valid rua tag, assuming your domain is actually sending mail that reaches reporting providers. No mail to Gmail or Outlook users means no reports from them. If nothing shows up after a few days of real sending, recheck your rua syntax: every address needs mailto: and the record must include at least p=none.

Why do some reports show SPF passing but DMARC failing?

Because DMARC requires alignment, not just authentication. SPF can pass for the envelope domain while the visible From domain is something else entirely. When those two domains don't share an organizational root, the SPF pass doesn't align, and DMARC treats an unaligned pass as a fail. DKIM alignment works the same way. It's the single most common point of confusion in reading these reports.

Do aggregate reports show me who I emailed or what I sent?

No. Aggregate reports contain only metadata: sending IPs, message counts, and pass/fail authentication results. They never include recipients, subjects, or message bodies. The message-level detail you might be picturing lives in failure reports (RUF), a separate feed most major providers don't even send.

What's the difference between aggregate (RUA) and forensic (RUF) reports?

Aggregate reports (rua) are daily statistical summaries: counts of mail per IP and their authentication outcomes, with no content. Forensic or failure reports (ruf) are near-real-time, per-message samples of mail that failed, and can include header detail. Because of privacy concerns, most large providers send aggregate reports but not forensic ones, so the RUA feed is what you'll actually work with day to day.

Can I just read the XML by hand?

For one domain with two or three sending sources, yes, for a week. Beyond that the volume buries you, and trends across IPs over time are nearly impossible to spot in raw files. Set up a parser or analyzer early. The whole point of the feed is catching a new failing sender within a day, and you can't do that by opening files manually.

Sources

Share the article

10x your leads, meetings and deals.

MailBeast scales your outreach campaigns with unlimited email sending accounts & warmup, smart sequences and AI-powered inbox management.

MailBeastSign up for free
Send Smarter. Land in Inboxes.
Close More Deals.
2026 MailBeast. All rights reserved.