How to Read Your DMARC Reports

DMARC aggregate reports tell you exactly who is sending mail as your domain and whether it authenticates. This guide takes you from the raw attachment to a clear verdict β€” get the report, unzip it, load it into the analyzer, and interpret every column.


Once you publish a DMARC record with a rua= tag, mailbox providers start emailing you daily aggregate reports β€” compressed XML files that list every source sending mail as your domain and whether it passed SPF and DKIM. They are the feedback loop that makes DMARC safe to enforce, but raw XML is unreadable. This guide walks the whole path: get the report, unzip it, load it into an analyzer, and interpret sources, alignment, dispositions, and the tell-tale signs of spoofing.

Prerequisites

You only receive reports if your DMARC record includes a rua= address β€” e.g. v=DMARC1; p=none; rua=mailto:dmarc@example.com. If you have not published one yet, start with the How to Configure DMARC guide, then come back once the first reports arrive (usually within 24 hours).

What a DMARC Aggregate Report Actually Is

An aggregate (rua) report is not a copy of any individual email. It is a daily statistical summary from one receiver (Google, Microsoft, Yahoo, etc.) that groups every message claiming to be from your domain by sending IP, and records how each group authenticated. Do not confuse it with a forensic (ruf) report, which contains per-message failure detail and is rarely sent today for privacy reasons.

Report typeTagContains
AggregateruaDaily XML summary grouped by IP β€” pass/fail counts, alignment, disposition.
Forensic / failurerufRedacted per-message samples of failures. Rarely sent by major providers.

Step 1: Get the Report

Reports arrive as email attachments at your rua address, one per receiver per day. Because volume adds up fast, send them to a dedicated mailbox (e.g. dmarc@example.com) rather than a personal inbox. Each attachment is named with the convention receiver!yourdomain!start!end.xml.gz, for example:

text
google.com!example.com!1721433600!1721520000.xml.gz enterprise.protection.outlook.com!example.com!1721433600!1721520000.xml.gz

The two long numbers are the Unix start/end timestamps for the 24-hour window the report covers.

Step 2: Unzip the Attachment

Attachments are compressed as .gz (gzip) or .zip. Decompress to get the raw .xml file:

bash
# gzip (.xml.gz) β€” Linux / macOS gunzip "google.com!example.com!1721433600!1721520000.xml.gz" # zip (.xml.zip) unzip "yahoo.com!example.com!1721433600!1721520000.xml.zip" # Windows PowerShell (gzip) # Right-click ‑> Extract, or use 7-Zip for .gz files
You can skip manual unzipping

The ShowDNS DMARC Report Analyzer accepts the compressed .gz and .zip file directly, as well as raw .xml. If you just want the answer, drag the attachment straight in β€” the steps below explain what it shows you.

Step 3: Understand the XML Structure

Before loading it into a tool, it helps to recognise the three parts of the file. Every report has the same shape:

xml
<feedback> <!-- WHO sent the report and for what window --> <report_metadata> <org_name>google.com</org_name> <email>noreply-dmarc-support@google.com</email> <report_id>1234567890</report_id> <date_range><begin>1721433600</begin><end>1721520000</end></date_range> </report_metadata> <!-- The policy the receiver saw published in your DNS --> <policy_published> <domain>example.com</domain> <adkim>r</adkim><aspf>r</aspf> <p>reject</p><sp>reject</sp><pct>100</pct> </policy_published> <!-- One <record> per sending IP --> <record> <row> <source_ip>203.0.113.9</source_ip> <count>42</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></dkim> <spf><domain>example.com</domain><result>pass</result></spf> </auth_results> </record> </feedback>

The important part is the repeated <record> block β€” one per source IP. Everything you act on lives there: the source, the message count, the policy_evaluated(alignment + disposition), and the raw auth_results.

Step 4: Load It Into the Analyzer

Reading dozens of these XML files by hand does not scale. Paste or drop the file (compressed or raw) into the analyzer to get a per-source breakdown with the pass/fail and alignment already computed:

Turn the raw XML into a readable tableDrop the .gz, .zip, or .xml in and see every source, its volume, alignment, and disposition.
Open the DMARC Report Analyzer

Step 5: Interpret the Sending Sources

Each row is one IP address that sent mail as your domain, with a message count. Your first job is to label every source as one of three things:

  • Known & authorized β€” your mail server, Google Workspace, Microsoft 365, or an ESP you deliberately use (SendGrid, Mailchimp, Amazon SES). These should pass and align.
  • Known but misconfigured β€” a legitimate service you forgot to authorize. It shows a familiar provider name but fails SPF/DKIM. This is what you fix before enforcing.
  • Unknown β€” an IP you do not recognise sending in your name. If it is failing, this is a spoofing signal (Step 8).

A good analyzer resolves each source_ip to a reverse-DNS hostname or provider so you can recognise it quickly. Cross-check anything unfamiliar against your published SPF record.

Step 6: Read Alignment β€” the Part That Trips People Up

A source can pass SPF or DKIM and still fail DMARC, because DMARC also requires alignment: the authenticated domain must match the visible From: domain. The report exposes this by showing two things per record β€” the raw auth_results and the aligned policy_evaluated. Compare them:

What you seeMeaningDMARC result
SPF pass + envelope domain = From domainSPF passes and alignsPass
SPF pass but envelope domain β‰  From domainPass without alignmentFails on SPF
DKIM pass + d= domain = From domainDKIM passes and alignsPass
DKIM pass but d= β‰  From domainPass without alignmentFails on DKIM

DMARC passes if either SPF or DKIM passes and aligns. So a source where SPF passes for a bulk sender's bounce domain but DKIM is not aligned will show up as a DMARC failure β€” the classic cause of the "Message rejected due to DMARC policy" bounce. If your record uses adkim=s or aspf=s, the domains must match exactly, not just at the organizational level.

Step 7: Read the Disposition

The <disposition> inside policy_evaluated is what the receiver actually did with the failing mail β€” which depends on the policy you published at the time:

DispositionYour policyWhat happened
nonep=noneDelivered normally. You are monitoring β€” nothing is blocked yet.
quarantinep=quarantineDelivered to spam/junk.
rejectp=rejectRefused outright β€” the message bounced.
Disposition none does not mean it passed

In p=none mode the disposition is always none, even for mail that failed authentication. Judge success by the dkim/spf results under policy_evaluated, not by the disposition. The disposition only tells you what the receiver did given your current policy.

Step 8: Spot the Spoofing Signals

DMARC reports are also your early-warning system for domain abuse. Watch for:

  • Unknown IPs with high fail counts β€” a source you do not recognise, failing both SPF and DKIM, sending in bursts. That is very likely spoofing or a phishing campaign using your domain.
  • Geographically odd sources β€” bulk mail from countries or hosting providers you never use.
  • Failures that never align β€” a source that passes SPF for its own domain but never for yours is forging your From address.

The safe response to spoofing is not to chase individual IPs β€” it is to reach full p=reject so those forged messages are refused. Legitimate-but-broken sources, by contrast, you fix by authorizing them in SPF/DKIM before you enforce.

Step 9: Act on What You Found

Turn the read-through into a short action list:

  • Legitimate source failing SPF β†’ add its include: to your SPF record.
  • Legitimate source failing DKIM β†’ enable DKIM signing with your domain and publish the selector.
  • Everything legitimate now passing and aligned β†’ step the policy up (none β†’ quarantine β†’ reject).
  • Only unknown/forged sources still failing β†’ you are safe to enforce p=reject.

After changes, confirm the record is live with the DMARC Lookup, then keep reading the next few days of reports to confirm the previously failing source now passes.

Frequently Asked Questions

How often do DMARC reports arrive?

Aggregate reports are sent once per day per receiver, covering a 24-hour window. A domain with mail landing at Google, Microsoft, and Yahoo will typically get three or more reports daily. Low-volume domains may get fewer, since a receiver only reports on days it saw mail from you.

Why does a source pass SPF but still fail DMARC?

Because SPF passing is not the same as SPF aligning. Bulk senders authenticate their own Return-Path (envelope) domain, which differs from your From domain, so DMARC sees no alignment. The fix is aligned DKIM signing with your domain, or a custom Return-Path on your own organizational domain.

What is the difference between rua and ruf reports?

rua gives daily aggregate statistics grouped by source β€” this is what you read to manage DMARC. ruf gives per-message forensic samples of individual failures, but most large providers no longer send them because of privacy concerns, so do not rely on ruf.

Do I need a paid service to read DMARC reports?

No. For occasional checks you can drop individual reports into the free ShowDNS DMARC Report Analyzer. Paid platforms (dmarcian, Postmark DMARC, Valimail) add value at scale by aggregating months of reports across many receivers into trend dashboards, but they are not required to interpret a report.

The report shows disposition "none" even though mail failed β€” is that bad?

Not by itself. In p=none mode every message is delivered and the disposition is always none, regardless of authentication. It means you are still in monitoring mode. Look at the SPF/DKIM results to see what would be blocked once you raise the policy.

Related Articles