DMARC Aggregate (RUA) Reports Explained

The daily XML feed that turns DMARC from a guess into a measurement — what receivers actually send you, what they deliberately leave out, and how to read it.


A DMARC aggregate report — the rua report — is an XML document that a receiving mail provider sends you once a day, summarising every message it saw claiming to be from your domain. It lists the sending IPs, how many messages came from each, whether SPF and DKIM passed, whether they aligned, and what the provider did with the mail. Aggregate reports are the only reason DMARC enforcement is safe to deploy: without them you would move from p=none to p=reject blind, hoping you had not forgotten a sender.

What a Report Actually Is

Every DMARC record with a rua= tag is an invitation. When a participating receiver — Google, Microsoft, Yahoo, Comcast, Mail.ru and hundreds of smaller operators — processes mail with your domain in the From: header, it records the outcome. At the end of its reporting window it rolls those outcomes up into a single XML file, compresses it, and emails it to the address you published.

Three properties define what you get:

  • Aggregated, not per-message. Identical results are collapsed into one record with a <count>. Ten thousand messages from one IP with the same authentication outcome arrive as a single record saying 10000.
  • Metadata only. No subject lines, no message bodies, no recipient addresses, no attachments. A report is safe to hand to a vendor and does not create a meaningful privacy obligation.
  • Per-receiver. Each provider reports only on the mail it received. Your picture of the world is a union of many separate reports, and it will never be complete — plenty of small receivers send nothing at all.
Reports arrive whatever your policy isAggregate reporting is independent of enforcement. p=none with a valid rua= collects full visibility while changing nothing about delivery, which is exactly why every DMARC rollout starts there.

The Anatomy of the XML

Every report has the same shape: one <report_metadata> block, one <policy_published> block, then one <record> per distinct combination of source IP and authentication result.

xml
<?xml version="1.0" encoding="UTF-8" ?> <feedback> <report_metadata> <org_name>google.com</org_name> <email>noreply-dmarc-support@google.com</email> <report_id>4829174726351928374</report_id> <date_range> <begin>1753574400</begin> <end>1753660799</end> </date_range> </report_metadata> <policy_published> <domain>example.com</domain> <adkim>r</adkim> <aspf>r</aspf> <p>quarantine</p> <sp>quarantine</sp> <pct>100</pct> </policy_published> <record> <row> <source_ip>198.51.100.24</source_ip> <count>1482</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>mail.sendingplatform.com</domain> <result>pass</result> </spf> </auth_results> </record> </feedback>

report_metadata

Who sent the report and for which window. The date_range values are Unix timestamps, almost always spanning 24 hours. org_name is the receiver, not you — a common early misreading.

policy_published

The DMARC record as the receiver resolved it at evaluation time. This block is quietly useful: it confirms your published policy propagated as intended, and a stale value here is the fastest way to catch a DNS change that never took effect.

row / policy_evaluated

The verdict. disposition is what the receiver did — none, quarantine or reject. The dkim and spf elements here are the DMARC-aligned results, not the raw ones.

auth_results

The raw mechanism results, with the domain each one authenticated. This is the block that explains why the verdict came out the way it did.

policy_evaluated and auth_results disagree on purposeIn the record above, auth_results/spf/result is pass but policy_evaluated/spf is fail. Both are correct: SPF genuinely passed — for mail.sendingplatform.com, which does not align with header_from of example.com. Comparing these two blocks is how you diagnose alignment from a report. See DMARC Alignment Explained.

What the Numbers Mean

A few semantics catch people out on their first reports:

  • count is messages, not recipients. One message to fifty recipients at the same provider may be counted once or fifty times depending on how it was delivered. Treat the figure as relative volume, not billing-grade accounting.
  • disposition: none does not mean the message passed. It means the receiver applied no punitive action — which is the correct behaviour under p=none even for total authentication failures. Read policy_evaluated/dkim and spf for the real answer.
  • Volumes are lumpy. A source that appears once with a count of 3 is usually noise; a source appearing daily with thousands is infrastructure you have forgotten about.
  • Absence proves nothing. A sender missing from reports may simply not have sent to any reporting receiver that day.

Configuring rua Correctly

The rua= tag takes a comma-separated list of mailto: URIs, optionally with a maximum report size:

text
# Single destination v=DMARC1; p=none; rua=mailto:dmarc@example.com # Two destinations — your own mailbox plus an analytics vendor v=DMARC1; p=none; rua=mailto:dmarc@example.com,mailto:rua@analytics.example.net # Cap report size at 10 megabytes v=DMARC1; p=none; rua=mailto:dmarc@example.com!10m # Request reports every 6 hours instead of daily (advisory only) v=DMARC1; p=none; rua=mailto:dmarc@example.com; ri=21600

Related tags worth knowing: ri= sets the requested reporting interval in seconds (default 86400, and receivers are free to ignore anything but daily), while fo= and ruf= govern forensic reports rather than aggregate ones.

Sending reports to another domain needs its permissionIf the rua address is not on the same organizational domain as the DMARC record, the receiving domain must publish an authorisation record — otherwise conforming receivers silently discard the reports. This is the single most common reason a vendor dashboard stays empty after "correct" setup.
bash
# example.com wants reports delivered to analytics.example.net. # The record is published in DNS by the OPERATOR OF analytics.example.net: example.com._report._dmarc.analytics.example.net. IN TXT "v=DMARC1" # Verify it exists before blaming the sender: dig +short TXT example.com._report._dmarc.analytics.example.net

Receiving Them Without a Vendor

Reports land as ordinary email with a compressed attachment — .zip or .gz — and a machine-readable subject line of the form Report Domain: example.com Submitter: google.com Report-ID: ….

Point rua at a dedicated mailbox rather than a person's inbox. Even a modest domain collects dozens of reports a day, and mixing them into human mail guarantees they get ignored.

bash
# Decompress whatever a receiver sent you unzip -o 'google.com!example.com!1753574400!1753660799.zip' gunzip -k 'enterprise.protection.outlook.com!example.com!...xml.gz' # Quick look at sources and volumes without any tooling xmllint --xpath '//record/row/source_ip/text()' report.xml grep -oP '(?<=<count>)[0-9]+' report.xml | paste -sd+ | bc

Raw XML is fine for a spot check and painful as a habit — one day of mail can be several hundred records across a dozen files. The DMARC Report Analyzer takes the ZIP or XML directly and renders sources, counts, alignment and disposition as a sortable table, which is enough for most domains without paying for a monitoring platform.

Aggregate vs Forensic Reports

Aggregate (rua)Forensic (ruf)
ContentsStatistical summary, metadata onlyIndividual failed message, headers and sometimes body
FrequencyTypically once per dayPer failure, in near real time
FormatXML, compressedAFRF / RFC 6591 message
Privacy exposureMinimalHigh — contains real recipient data
Support in practiceBroadRare; most large receivers never send them

For nearly every domain, aggregate reports are the whole story. Forensic reports are worth configuring only if you have a specific investigative need and have thought about the privacy implications of receiving other people's message content.

What Reports Cannot Tell You

Knowing the limits saves a lot of misdirected effort:

  • No message content. You cannot tell what a suspicious sender was actually sending, only that they sent.
  • No recipients. There is no way to find out who received a spoofed message.
  • Delayed by design. Reports describe yesterday. They are not an alerting mechanism, and a live incident will not show up for hours.
  • IP, not identity. Records give a source IP; mapping it to "the CRM team's new tool" is manual work — reverse DNS and WHOIS get you most of the way.
  • Forwarding looks like an attack. A legitimate message relayed through a mailing list appears as an unknown IP failing SPF. Volume and consistency are what distinguish it from real abuse.

Using Reports to Reach Enforcement

The reports exist to answer one question: is it safe to turn the policy up yet? The working loop is:

  1. Publish p=none with rua= and collect two to four weeks of data.
  2. Inventory every source with meaningful volume, and label each one legitimate or not.
  3. For each legitimate source, fix SPF and DKIM until at least one shows an aligned pass.
  4. Move to p=quarantine, optionally with pct=, and watch for new failures.
  5. When the aligned-pass rate holds steady near 100%, move to p=reject.
  6. Keep reading the reports afterwards — new SaaS tools get adopted without anyone telling you.

For the mechanics of working through a single report file, see How to Read Your DMARC Reports.

Frequently Asked Questions

How often do aggregate reports arrive?

Once every 24 hours from most receivers. The ri= tag lets you request a shorter interval, but it is advisory — the large providers send daily regardless. Expect the first reports within 24 to 72 hours of publishing a rua address.

I published rua but no reports are arriving. Why?

In order of likelihood: fewer than 24 hours have passed; the DMARC record has a syntax error so it is not being parsed at all; the reports are being filtered as spam at your mailbox; or the rua address is on a different domain and the _report._dmarc authorisation record is missing. Confirm the record parses with a DMARC Lookup first.

Do aggregate reports contain personal data?

Not in any meaningful sense. They carry source IPs, counts and authentication results — no recipients, subjects or content. Forensic (ruf) reports are an entirely different matter and can contain real message data.

Why do different providers report different results for the same mail?

Each receiver evaluates independently, and they differ in how they handle forwarding, how they interpret edge cases, and which mail they happen to receive. Disagreement between Google and Microsoft on the same sender is normal; a source failing at every receiver is the signal worth acting on.

Do I need a paid DMARC monitoring service?

Not to get started. A dedicated mailbox and an analyzer will carry a small or medium domain through a full rollout. Paid platforms earn their keep at scale — many domains, long retention, trend alerting and automated source identification — rather than by revealing anything the XML does not already contain.

Should I keep collecting reports after reaching p=reject?

Yes. Enforcement is not a finished state. New tools get adopted, vendors rotate infrastructure, and DKIM keys get rolled — each of which can start silently rejecting legitimate mail. Reports are how you find out before your users do.

Related