What a DMARC report actually is
Publish a DMARC record with an rua= address and mailbox providers start sending
you aggregate reports: one XML file per provider per day, listing every IP that
sent mail claiming to be your domain, how many messages each one sent, and whether SPF and DKIM
passed and aligned.
Two things it is worth knowing before you open one:
- Aggregate reports contain no message content. No subjects, no recipients, no bodies. They are counts grouped by sending IP. That is why they are safe to collect and why they cannot tell you which message failed.
- They are not the same as forensic reports. A
ruf=address asks for per-message failure samples, which do contain headers and sometimes more. Most providers no longer send them at all, for privacy reasons, so in practice DMARC visibility means aggregate reports.
What they give you is the one thing you cannot get any other way: a list of everything in the world sending email as your domain, including the systems inside your own company that nobody remembers setting up. That inventory is the entire point, and it is what makes a safe move to enforcement possible.
Getting the reports in the first place
A minimal record that only collects data, changing nothing about delivery:
v=DMARC1; p=none; rua=mailto:dmarc@example.com
It goes at _dmarc.example.com as a TXT record. p=none means
“apply no policy, just tell me” — it is the correct starting point and it cannot hurt
your delivery. Check the record is actually live and readable with a
DNS lookup tool before waiting on
reports that will never arrive.
Two practical notes. Reports arrive daily and in bulk, so send them to a dedicated mailbox rather than your own. And if you want reports sent to an address at a different domain, that domain has to authorise it with its own DNS record — a missing authorisation record is the commonest reason reports silently never show up.
Reading the XML: three blocks
Every aggregate report has the same shape. Once you have seen it once it stops being intimidating.
Block 1: who sent the report
<report_metadata> names the reporting organisation, gives a report ID and a
date range. The date range is the thing to notice: reports are usually a 24-hour window, and they
arrive a day or two late, so the IP you are looking at did its sending in the past.
Block 2: the policy they saw
<policy_published> is your own DMARC record as that provider read it:
p (your policy), sp (subdomain policy), pct (the percentage
you asked to be enforced), and the alignment modes. This block is a useful sanity check — if it
does not match what you think you published, your record has a syntax problem or has not
propagated yet.
Block 3: the rows that matter
Then a series of <record> elements. Each one is a group of messages
from one IP with one outcome, not a single email. Each contains a <row> with
the source IP and a count, a <policy_evaluated> with the DMARC result and what
the provider actually did, and an <auth_results> with the underlying SPF and
DKIM results.
Reading one row in practice
Work through it in this order, and the row answers itself:
- Who is the IP? Look it up. A name like a known email platform means it is a service of yours; an unfamiliar network is the one to investigate.
- How many messages? Two messages is noise. Twenty thousand is a system.
- What does
<policy_evaluated><disposition>say?none,quarantineorreject— what the provider did about it. - Did SPF and DKIM pass, and did they align? That pair is the whole diagnosis, and it is the next section.
The four combinations, and what each means
DMARC passes if either SPF or DKIM passes and is aligned with the visible From: domain. That gives four cases:
- SPF pass + DKIM pass. Your properly configured sender. Nothing to do.
- SPF pass, DKIM fail. Usually a service sending from an authorised IP without signing. Get DKIM signing enabled — SPF alone is fragile, because it breaks the moment a message is forwarded.
- SPF fail, DKIM pass. Most often legitimate forwarded mail: the forwarder's IP is not in your SPF record, but the signature survived. DMARC passes on DKIM alone, which is exactly the design working.
- Both fail. Either a sender of yours that was never configured, or someone spoofing you. Telling those apart is the next section.
Watch for one trap in the XML: a result can read pass in
<auth_results> and still fail DMARC, because the authenticated domain was not
aligned with the From: domain. A platform signing with its own domain produces exactly
that. If that is confusing, why an SPF
pass is not a DMARC pass goes through alignment in detail.
Telling your own senders from spoofing
Almost everyone's first reports look alarming and almost none of it is an attack. Sort the failing IPs into three piles:
- Yours, misconfigured. A CRM, an invoicing system, a ticketing tool, a marketing platform, an application server. Clues: the IP resolves to a recognisable provider, the volume is steady day after day, and the messages are being delivered. Fix: authorise it properly, preferably with DKIM.
- Forwarders. Low volume, scattered IPs, universities and small mail hosts, SPF failing while DKIM passes. Not a problem, and not fixable from your side.
- Actual spoofing. Unfamiliar networks, often bursty, frequently foreign to your business, failing both checks. The reassuring part: with a policy in place this mail is already being rejected, which is the whole point.
The sequence matters. Identify everything in the first pile before you tighten the policy, because enforcement turns a misconfigured sender of yours into undelivered mail.
Why forwarders look like attackers
This confuses everyone once. A mailing list or an alias relays your message from its own server, so your SPF record is checked against an IP you never authorised and fails — correctly. The report shows an unknown IP failing SPF while sending as you, which reads exactly like abuse.
Two tells separate them. Forwarded mail usually still passes DKIM, because the signature travels with the message, so DMARC passes overall. And the volume is small and spread across many unrelated IPs rather than concentrated. Mailing lists are the exception that can break both: some rewrite the subject or append a footer, which invalidates the DKIM signature and leaves a genuine message failing everything.
Using the reports to get to enforcement
The reports exist to make this move safe. A workable sequence:
- Stay at
p=noneuntil the reports are boring — typically a few weeks. You are waiting until every legitimate sender you find has been authorised and nothing new appears. - Fix senders as you find them, preferring DKIM. A sender with DKIM survives forwarding; one with only SPF does not.
- Move to
p=quarantine, optionally withpct=to ramp. Failing mail goes to spam rather than disappearing, so a mistake is recoverable. - Then
p=reject, once quarantine has been quiet. This is the point at which spoofed mail using your domain is actually refused. - Keep reading the reports afterwards. A new vendor added six months from now will show up as a failing IP, and you want to see it before someone tells you their invoices are bouncing.
Do not set p=reject on day one. The only thing that makes enforcement safe is the
inventory the reports give you, and that takes weeks to become complete.
The guide to SPF, DKIM and DMARC
covers the records themselves.
Common mistakes
- Jumping to
p=rejectbefore reading reports. The forgotten system is usually the one that invoices your customers. - Reading each row as one message. A row is a group of messages from one IP with one outcome.
- Treating every failing IP as an attacker. Most early failures are your own services and ordinary forwarding.
- Assuming a
passinauth_resultsmeans DMARC passed. Without alignment to the From: domain it does not. - Sending reports to a monitored human mailbox. They arrive daily from dozens of providers. Use a dedicated address.
- Forgetting the subdomain policy. Without
sp=, subdomains inheritp, which may not be what you want during a rollout. - Fixing SPF only. SPF breaks on forwarding; DKIM is what carries DMARC through it.
- Turning reporting off once you reach reject. That is when it starts being an early warning system.
The short version
A DMARC aggregate report is a daily XML list of every IP sending as your domain, with counts
and SPF/DKIM results — no message content. Read each row in four steps: identify the IP, look at
the volume, read the disposition, then check whether SPF or DKIM passed and aligned.
Expect most early failures to be your own unconfigured services and ordinary forwarding rather
than spoofing, fix senders with DKIM wherever you can, and only move from p=none to
quarantine and then reject once the reports have gone quiet. Check your
_dmarc record is published and readable with the free
DNS lookup tool, and if an SPF result
in a report looks contradictory,
the SPF troubleshooting guide
explains why.
Related tools and guides:
- DNS Lookup - Query A, AAAA, MX, TXT, NS and more DNS records with values and TTL, plus reverse DNS.
- Why Your SPF Record Keeps Failing (and How to Fix It) - How to read your SPF record
Frequently Asked Questions
What is in a DMARC aggregate report?⌄
An XML file, usually covering 24 hours from one mailbox provider, listing every IP that sent mail claiming to be your domain, how many messages each sent, whether SPF and DKIM passed and aligned, and what the provider did about it. It contains no message content — no subjects, recipients or bodies.
How do I start receiving DMARC reports?⌄
Publish a TXT record at _dmarc.yourdomain.com reading v=DMARC1; p=none; rua=mailto:your address. p=none applies no policy, so it cannot affect delivery. Use a dedicated mailbox, since reports arrive daily from many providers, and note that sending reports to an address at another domain requires that domain to authorise it with its own DNS record.
Why do DMARC reports show IPs I do not recognise?⌄
Usually for two innocent reasons: a service of yours that was never authorised — a CRM, invoicing or ticketing system — or ordinary mail forwarding, where the forwarder relays from its own IP and fails SPF while DKIM still passes. Genuine spoofing tends to be bursty, from unrelated networks, and fails both checks.
When is it safe to move to p=reject?⌄
Once your reports have been quiet for a few weeks: every legitimate sender identified and authorised, preferably with DKIM, and nothing new appearing. Move through p=quarantine first, where failing mail goes to spam rather than being refused, so any mistake is recoverable.
Why does a row show SPF pass but DMARC fail?⌄
Because DMARC requires alignment as well as authentication: the domain that passed SPF must match the visible From: domain. A platform sending with its own return path passes SPF on its own domain, which does nothing for yours, so the alignment check fails and DMARC fails with it.
15+ years of hands-on experience in web development and security. Focused on practical web security: keeping websites secure, reliable and easy to troubleshoot. BuildToolForge exists to make these checks free, private and understandable. Tools run in your browser wherever possible, and nothing you enter into a tool is stored.
How we write our guides: Every guide is written from hands-on experience, checked against the official standards, and tested with our own tools on real domains. We update guides when standards or tools change. Found a mistake? Email contact@buildtoolforge.com.