Skip to content
email By Peter Mastras 7 May 2026 10 min read

Reading DMARC aggregate reports: what the XML actually tells you

DMARC aggregate reports arrive as compressed XML almost nobody reads. Here's what each field means, the failure patterns to watch for, and how to act on them.

You’ve configured rua=mailto: in your DMARC record and the reports are arriving. Most people either ignore them or send them to a third-party dashboard without reading the underlying data. That’s a problem, because the XML tells you exactly what’s happening with your authentication — and the dashboards don’t always surface the right detail.

This is what the structure means and how to read it.

What’s in the file

DMARC aggregate reports (rua) arrive as gzip-compressed XML attachments, typically once every 24 hours from each large receiving provider — Google, Microsoft, Yahoo, and others. The XML has a consistent structure defined by RFC 7489.

Each report covers a specific time window (usually one calendar day) and a specific sending organisation. A busy domain might receive 5–10 reports per day. A quiet domain might receive 1–2.

The top-level structure looks like:

<feedback>
  <report_metadata>...</report_metadata>
  <policy_published>...</policy_published>
  <record>...</record>
  <record>...</record>
</feedback>

Each <record> represents a group of messages with the same source IP and authentication result.

report_metadata

<report_metadata>
  <org_name>Google Inc.</org_name>
  <email>noreply-dmarc-support@google.com</email>
  <report_id>12345678</report_id>
  <date_range>
    <begin>1714867200</begin>
    <end>1714953600</end>
  </date_range>
</report_metadata>

This tells you who sent the report and what time window it covers. The timestamps are Unix epoch — convert them to confirm the report is from the expected day. If you’re missing an expected sender (for example, you never get Microsoft reports despite sending to Outlook addresses), that’s worth investigating — it may mean your rua address isn’t receiving all reports.

policy_published

<policy_published>
  <domain>example.com</domain>
  <adkim>r</adkim>
  <aspf>r</aspf>
  <p>quarantine</p>
  <sp>none</sp>
  <pct>100</pct>
</policy_published>

This reflects what DMARC policy Google saw when they looked up your domain. Check p (the policy applied to the main domain) and sp (for subdomains).

adkim and aspf are the alignment modes — r is relaxed, s is strict. Relaxed SPF alignment means the organisational domain just needs to match (so mail.example.com passes for example.com). Strict requires an exact match. Most deployments use relaxed for both.

pct should be 100 in production unless you’re deliberately rolling out a policy incrementally.

What to look for: If p says none here and you think you’ve moved beyond that, recheck your live DMARC record with a DNS query or the email auth checker.

The record structure

<record>
  <row>
    <source_ip>209.85.220.41</source_ip>
    <count>47</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>
      <result>pass</result>
      <selector>selector1</selector>
    </dkim>
    <spf>
      <domain>example.com</domain>
      <result>pass</result>
    </spf>
  </auth_results>
</record>

This is the most important section. Work through it in order:

source_ip — The server that sent the message. Look up unfamiliar IPs before assuming they’re legitimate. Common legitimate sources include Microsoft 365 (40.92.*, 40.107.*, 52.100.*), Google Workspace (209.85.*, 74.125.*), Mailchimp, Salesforce, and your own infrastructure. Unexpected IPs are worth investigating — they may be:

  • A service you forgot was sending on your behalf
  • A misconfigured application
  • Someone attempting to spoof your domain

count — How many messages came from this source IP during the reporting window. An unfamiliar IP with a count of 50,000 is a spoofing attempt. An unfamiliar IP with a count of 3 is probably a forgotten service.

policy_evaluated — What DMARC actually did with these messages. disposition: none means no action (either your policy is p=none, or the messages passed). disposition: quarantine or disposition: reject means DMARC failed and your policy was enforced.

dkim and spf in policy_evaluated — These reflect DMARC alignment, not just raw pass/fail. A message can have a technically valid SPF record but still fail DMARC alignment if the return-path domain doesn’t match the From address domain. This is the most common source of confusion.

auth_results — The raw authentication results before alignment is applied. A message might show spf: pass here but spf: fail in policy_evaluated — that means SPF passed on the envelope domain, but DMARC alignment failed because the envelope domain doesn’t match the From address.

Patterns to look for

Lots of failing records from a single IP you don’t recognise — Check whether it’s spoofing. Look at header_from — if it’s your domain but you don’t control that IP, someone is sending email claiming to be you.

Your own mail servers failing alignment — Usually caused by SPF being configured on the envelope domain (the return-path) rather than the From domain, or DKIM not being configured on that sending path. Common with CRM and marketing platforms that send on your behalf using their own return-path.

Microsoft 365 or Google Workspace failing — Typically means DKIM isn’t enabled for your domain in the M365 Admin Centre, or the CNAME records weren’t published correctly. DMARC can still pass via SPF alignment in M365, but that breaks in forwarding scenarios.

High failure count at p=none — If your policy is p=none and you’re seeing significant authentication failures, you have a deliverability problem that isn’t being corrected — it’s just not being enforced yet. The path to p=quarantine or p=reject requires getting failures to zero first.

Everything passing but your policy is still none — This is the right state before moving to enforcement. Once a full week of reports shows near-zero failures from your legitimate sending infrastructure, you can move to p=quarantine with confidence.

Acting on the data

The typical workflow after reading reports:

  1. Identify all sending IPs in the records and confirm you know what each one is
  2. For any failing alignment records from your legitimate senders, identify whether the fix is SPF (add the service to your SPF include chain) or DKIM (configure DKIM signing on that platform)
  3. For spoofing attempts (unknown IPs with your From domain), accelerate your path to p=reject — that’s what stops them
  4. Track your failure rate over time — the goal is to reduce it to near zero before enforcing policy

If you’re seeing failures but can’t identify the cause, the email auth checker will show your current SPF, DKIM and DMARC configuration. For IP-level blacklist status on your sending infrastructure, the blacklist checker covers 14+ major RBLs.

DMARC reports contain exactly the information you need to fix authentication problems. The XML is verbose but the structure is predictable — once you’ve read a few, they take five minutes to interpret.

rua vs ruf: aggregate vs forensic reports

DMARC defines two report types, set by two separate tags in your record:

  • rua=aggregate reports. The daily XML statistics described above. Pass/fail counts grouped by source IP, no message content. This is what you actually work from.
  • ruf=forensic (failure) reports. Near-real-time, per-message copies of individual emails that failed DMARC, with headers and partial content redacted.

In practice, ruf is mostly dead. Privacy regulation and the risk of leaking recipient data led almost every major provider — Google, Microsoft, Yahoo — to stop sending forensic reports years ago. If you set ruf= you’ll receive little or nothing. Don’t rely on it; the aggregate rua data is the source of truth for diagnosing authentication, and it’s enough to get to enforcement.

A minimal, correct record requesting aggregate reports looks like:

v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com

How to open the reports without a dashboard

The attachment arrives gzip- or zip-compressed (filenames like google.com!yourdomain.com!1714867200!1714953600.xml.gz). You don’t need a paid platform to read one:

# gzip (.gz) — most common
gunzip 'google.com!yourdomain.com!....xml.gz'

# zip (.zip) — some senders, e.g. Microsoft
unzip 'enterprise.protection.outlook.com!....zip'

Then open the .xml in any editor, or pretty-print it:

xmllint --format report.xml | less

For ongoing monitoring rather than spot checks, a parser or a free dashboard tier (dmarcian, Postmark’s DMARC tool, Valimail Monitor) aggregates many reports into one view and trends your pass rate over time. That’s convenient at volume — but every figure they show comes straight from the same XML fields above, so reading the raw file is always enough to settle a specific question the dashboard glosses over.

If you want the configuration side checked rather than the reports, the email auth checker validates your live SPF, DKIM and DMARC records in seconds, and the Microsoft 365 DKIM setup guide covers the most common alignment fix — getting DKIM signing on your own domain.

Sources

Frequently asked questions

What is a DMARC aggregate report?
A DMARC aggregate report (the 'rua' report) is an XML summary that receiving mail providers send back to the address in your DMARC record's rua= tag. It lists, per sending source IP, how many messages claimed to be from your domain and whether they passed SPF, DKIM and DMARC alignment. It contains no message content — just authentication statistics.
What is the difference between rua and ruf reports?
rua reports are aggregate: daily XML statistics of pass/fail counts per source, and they are what almost everyone uses. ruf reports are forensic: near-real-time copies of individual failing messages (redacted), sent per failure. Most providers no longer send ruf for privacy reasons, so rua aggregate reports are the practical data source.
How often are DMARC aggregate reports sent?
Typically once every 24 hours from each large receiving provider (Google, Microsoft, Yahoo and others), each covering one calendar day. A busy domain may get 5-10 reports a day; a quiet one, 1-2. The interval is requested by the ri= tag in your DMARC record (default 86400 seconds), but most providers only honour daily.
How do I open a DMARC aggregate report?
The attachment is gzip- or zip-compressed XML. Decompress it (gunzip file.xml.gz, or unzip), then open the .xml in any text editor or feed it to an XML viewer. For volume, a parser script or a free dashboard (dmarcian, Postmark, Valimail) renders the records into a table — but the raw XML holds the same data.
What does the disposition field mean in a DMARC report?
disposition is what DMARC actually did with the messages: none (delivered, no action), quarantine (sent to spam), or reject (refused). It reflects the policy that was applied, so disposition: none can mean either your policy is p=none or the messages passed authentication.
Why does SPF pass in auth_results but fail in policy_evaluated?
auth_results shows the raw SPF check on the envelope (return-path) domain; policy_evaluated shows DMARC alignment. SPF can pass on the envelope domain yet fail DMARC because that domain doesn't match the visible From address domain. Aligning SPF (or DKIM) to the From domain is the fix.

Need help with your email infrastructure?

Talk to an engineer