DMARC monitoring

How to read a DMARC report, and what to do with what it says.

DMARC is the only part of email authentication that reports back. Publish one DNS record and every large mailbox provider starts sending you a daily list of everyone sending mail as your domain. This page opens one of those reports, names every field, and walks the route from p=none to p=reject without breaking your own mail on the way.

The checkup asks for a free account before it shows the report. No card, and it reads only public DNS.

The three records

SPF, DKIM and DMARC do three different jobs.

SPF

A TXT record on your domain listing which servers may send mail for it.

The question it answers

Did this message arrive from a server the domain owner authorized?

The part that catches people

SPF is checked against the envelope sender, the address in the SMTP MAIL FROM command, not the From: line the recipient sees. Those are usually different, and that difference is the whole reason DMARC exists. SPF also has a hard limit of 10 DNS lookups (RFC 7208); go over it and the result is permerror, which fails, silently, for every message.

DKIM

A cryptographic signature added by your mail server, verified against a public key published in DNS at a selector.

The question it answers

Did this message leave the signing domain unaltered?

The part that catches people

DKIM survives forwarding where SPF does not, which makes it the more durable of the two. It breaks when a mailing list rewrites the subject or appends a footer, and when a key is rotated on the provider side and the DNS record is not updated to match.

DMARC

A TXT record at _dmarc.yourdomain.com carrying a policy and a reporting address.

The question it answers

Given the SPF and DKIM results, what should a receiver do with mail claiming to be from me — and where do I want the report?

The part that catches people

DMARC is the only one of the three that produces reporting. Publishing p=none with a rua= address changes nothing about delivery and starts a daily feed of who is sending as you. That is the entire first step.

An aggregate report, opened

One record block, with every field named.

This is the shape defined by RFC 7489, trimmed to a single record. A real report has one of these blocks per sending IP address. The IP below is from a range reserved for documentation.

<feedback>
  <report_metadata>
    <org_name>google.com</org_name>
    <email>noreply-dmarc-support@google.com</email>
    <report_id>4512339918283746501</report_id>
    <date_range>
      <begin>1756684800</begin>
      <end>1756771199</end>
    </date_range>
  </report_metadata>
  <policy_published>
    <domain>yourcompany.com</domain>
    <adkim>r</adkim>
    <aspf>r</aspf>
    <p>none</p>
    <sp>none</sp>
    <pct>100</pct>
  </policy_published>
  <record>
    <row>
      <source_ip>203.0.113.44</source_ip>
      <count>37</count>
      <policy_evaluated>
        <disposition>none</disposition>
        <dkim>fail</dkim>
        <spf>fail</spf>
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from>yourcompany.com</header_from>
    </identifiers>
    <auth_results>
      <spf>
        <domain>mail.example.net</domain>
        <result>pass</result>
      </spf>
    </auth_results>
  </record>
</feedback>
org_name
Who sent you the report. It is a receiving mailbox provider, not a sender — Google, Microsoft, Yahoo, Mail.ru and others each send their own.
date_range
Unix timestamps. Reports are usually a 24-hour window, which is what the ri= tag defaults to, so a busy domain gets one report per provider per day.
policy_published
The DMARC record as that provider read it, which is worth checking against what you think you published. adkim and aspf are the alignment modes: r is relaxed (a subdomain match counts), s is strict (an exact match is required).
source_ip and count
One IP address that sent mail claiming to be from your domain, and how many messages it sent in the window. This is the part you actually read: a list of everyone sending as you.
policy_evaluated
The DMARC verdict. disposition is what the receiver did — none, quarantine or reject. The dkim and spf values here are the aligned results, which is not the same as whether SPF or DKIM passed at all.
identifiers / header_from
The domain in the From: line the recipient saw. DMARC only cares about this one, because it is the only address a human ever looks at.
auth_results
The raw results, before alignment. SPF passed here for mail.example.net — but the From: line said yourcompany.com, those two do not align, and so policy_evaluated records spf as fail.

The field everyone misreads

Alignment, and why a pass can still be a fail.

A pass in auth_results and a fail in policy_evaluated is not a bug

It is the single most confusing thing in DMARC and it is working correctly. auth_results says SPF or DKIM verified something. policy_evaluated says whether the thing it verified was your domain. A vendor sending on your behalf with their own return-path gets an SPF pass for their domain and a DMARC fail for yours, every time, until you authenticate them properly.

This is why forwarded mail fails

A forwarder relays your message from its own server. SPF now checks the forwarder's IP against your record and fails. DKIM usually survives, because the signature travels with the message — which is why a domain relying on SPF alone gets a wall of failures from mailing lists and forwarding rules, and one relying on DKIM does not.

Relaxed alignment is almost always what you want

Under relaxed alignment (adkim=r, aspf=r, the default), mail from news.yourcompany.com aligns with yourcompany.com. Under strict it does not. Publishing strict alignment early is a common way to break your own newsletter.

The report contains no message content

Aggregate reports are counts, IP addresses and verdicts. No subject lines, no bodies, no recipient addresses. Forensic reports (the ruf= tag) can carry more, and most large providers do not send them at all, largely on privacy grounds.

The rollout

Five steps from reporting to enforcement.

The order matters more than the speed. Every step past the first can break legitimate mail if the one before it was not finished, which is why almost every domain that goes wrong went straight to p=reject on a Friday. M3AAWG, the anti-abuse working group that most large mailbox providers belong to, publishes sender best-practice documents worth reading alongside this.

  1. 1. Publish p=none with a reporting address

    A TXT record at _dmarc.yourdomain.com reading v=DMARC1; p=none; rua=mailto:your-report-address. It changes nothing about delivery and starts the feed.

    Reports begin arriving within a day or two from the larger providers.

  2. 2. Read two weeks of reports and build the sender list

    Every source_ip with your domain in header_from is something sending as you. Expect surprises: the accounting package, the CRM, the appointment reminder tool, the fundraising platform somebody signed up for in 2019.

    Two weeks, minimum. A monthly invoice run or a quarterly newsletter will not appear in a three-day sample.

  3. 3. Authenticate every legitimate sender, one at a time

    For each one, follow the vendor's instructions to add their DKIM keys to your DNS and, where relevant, their SPF include. Watch the pass rate for that source climb in the next report before moving to the next sender.

    As long as it takes. This is the actual work, and the reason most domains never finish it.

  4. 4. Move to p=quarantine

    Once mail you recognize is passing aligned, tighten to quarantine. Failing mail lands in spam rather than the inbox, which is recoverable if you got something wrong.

    Sit here long enough to see a full business cycle, then read the reports again.

  5. 5. Move to p=reject

    Failing mail is refused at the door. This is the setting that actually stops someone spoofing your exact domain, and it is the only one that does.

    Keep reading the reports. A new vendor added next year will fail on the day it is switched on.

The domains you forgot

A domain that sends no mail should say so.

Old brand names, redirect domains, the .net you bought defensively. None of them send mail, all of them can be spoofed, and none of them are on anyone's list. Three records close that off completely, and unlike a live sending domain there is no rollout period because there is no legitimate mail to break.

; A domain that never sends mail should say so, explicitly:
yourparkeddomain.com.        IN TXT  "v=spf1 -all"
_dmarc.yourparkeddomain.com. IN TXT  "v=DMARC1; p=reject; rua=mailto:your-report-address"
yourparkeddomain.com.        IN MX   0 .

How DomainGuard helps

The records for free, the report parsing on a plan.

Free

The checkup reads SPF, DKIM, DMARC, MX, MTA-STS and TLS reporting, checks the SPF lookup count against the limit, and tells you how strong the policy you published actually is. Unlimited domains, whenever you press scan.

Starter and up

Point your rua= address at the one we give you and the aggregate XML is parsed into a sender list with pass rates over time, so step 2 above becomes reading a table rather than unzipping attachments.

What we will not do

Change your DNS, send mail on your behalf, or advance your policy for you. The dashboard shows the record it recommends and the day your reports say it is safe to publish it. You paste it at your DNS provider.

Questions people actually ask

What is actually in a DMARC aggregate report?

An XML file, usually gzipped, sent daily by each receiving mailbox provider. It contains who sent the report, the reporting window, the DMARC record as that provider read it, and then one block per sending IP address: the IP, how many messages it sent, the DMARC verdict, the domain in the From: line, and the raw SPF and DKIM results. No message content, no subject lines, no recipient addresses.

Why does my report show SPF passing and DMARC failing?

Alignment. SPF is checked against the envelope sender, but DMARC only counts a pass if the domain SPF verified matches the domain in the From: line the recipient sees. A vendor sending on your behalf with its own return-path gets an SPF pass for its own domain, which does not align with yours, so DMARC records a fail. Fix it by adding that vendor's DKIM keys to your DNS.

How long should I stay on p=none?

Long enough to see a full business cycle and to authenticate every legitimate sender you find — two weeks is the minimum useful sample and longer is common. The mistake is not moving too fast, it is never moving at all: p=none stops nothing, and a domain that sits there for years has reporting and no protection.

What about domains that do not send mail?

Publish the fact. An SPF record of v=spf1 -all, a DMARC record of p=reject, and a null MX record (a single MX with priority 0 pointing at a dot, per RFC 7505) tell every receiver that no mail should ever claim to come from that name. Parked and redirect domains are a favorite for spoofing precisely because nobody bothers.

How does DomainGuard fit in?

The free checkup reads your SPF, DKIM, DMARC, MX and MTA-STS records and tells you what is missing or malformed, including the SPF lookup count. DMARC aggregate report processing, which means pointing your rua= address at us so the XML is parsed into a sender list, is a Starter feature, $6.99 a month through Apple in-app purchase. We never change your DNS; you publish the record when you are ready.