FortWatch

DMARC Explained: The Complete Guide to Stopping Email Spoofing

FortWatch

FortWatch Team

DMARC Explained: The Complete Guide to Stopping Email Spoofing

The Email That Wasn't From Us

In 2016, the campaign chairman of a U.S. presidential candidate received an email from "google.com" warning him to reset his password. He clicked. He entered his credentials. The email wasn't from Google. The credentials went to a Russian intelligence operation. The fallout reshaped a presidential election.

That phishing email worked because Google's email authentication had a gap. So did the recipient's. So does almost every domain on the internet. If you don't have DMARC configured correctly, anyone with five minutes and a free SMTP relay can send email that looks exactly like it came from your domain. Customers, employees, partners — they have no easy way to tell the difference.

This guide covers DMARC end-to-end: what it actually does, how to read a DMARC record, how to roll one out without breaking legitimate email, how to interpret the reports it generates, and how to monitor it once it's in place. By the end, you'll be able to look at any domain's DMARC record and tell whether spoofers can fake email from that domain.

You can check any domain's DMARC, SPF, and DKIM right now with our free in-browser checker — no signup required. Use it as you read along.

The Three Records: A 60-Second Refresh

DMARC doesn't work alone. It's the policy layer that sits on top of two underlying email authentication standards. Here's the quick version of all three.

SPF (Sender Policy Framework) is a DNS TXT record on your root domain that lists which IP addresses and hostnames are allowed to send email for you. A receiving mail server checks the connecting IP against your SPF record. If it doesn't match, SPF fails.

example.com.   IN   TXT   "v=spf1 include:_spf.google.com include:mailgun.org -all"

DKIM (DomainKeys Identified Mail) attaches a cryptographic signature to every outgoing email. The receiving mail server fetches your public key from DNS and verifies the signature. If the signature doesn't validate, the message has been tampered with — or didn't come from you in the first place.

selector1._domainkey.example.com.   IN   TXT   "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3..."

DMARC (Domain-based Message Authentication, Reporting & Conformance) is the policy layer. It tells receivers two things: (1) what to do when SPF or DKIM fails, and (2) where to send aggregate reports about authentication results. Without DMARC, SPF and DKIM are advisory — receivers can ignore them. With DMARC, they become enforceable.

_dmarc.example.com.   IN   TXT   "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; pct=100;"

You need all three. SPF without DMARC can be bypassed. DKIM without DMARC isn't enforced. DMARC without SPF and DKIM has nothing to enforce. Together they form a complete email authentication stack.

Reading a DMARC Record Line by Line

A DMARC record is a single TXT record at _dmarc.yourdomain.com made of semicolon-separated tags. Each tag controls one piece of behavior. Here's a typical strict policy parsed tag by tag:

v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc@example.com; ruf=mailto:forensic@example.com; pct=100; adkim=s; aspf=s; fo=1
TagWhat it controlsCommon values
vVersion. Always DMARC1.DMARC1
pPolicy for the root domain when authentication fails.none · quarantine · reject
spPolicy for subdomains. Defaults to p if absent.none · quarantine · reject
ruaWhere to send daily aggregate reports.mailto:dmarc@example.com
rufWhere to send per-message forensic reports.mailto:forensic@example.com
pctPercentage of failing mail to apply the policy to. Default 100.0100
adkimDKIM alignment mode. s = strict (exact match), r = relaxed.s · r
aspfSPF alignment mode. Same as adkim but for SPF.s · r
foFailure-reporting options. 1 = report on any failure.0 · 1 · d · s

The minimum useful DMARC record has just v, p, and rua. Everything else is optional but worth understanding because misconfigurations of these advanced tags are where most DMARC failures hide.

The Three Policy Levels: What Each One Actually Does

The p tag is the heart of DMARC. It tells receivers exactly what to do with mail that fails authentication. There are three values, and they behave very differently in practice.

p=none — Monitoring only. Receivers report on failures but deliver the mail anyway. This is the starting point for every new DMARC deployment because it lets you see who's sending mail under your domain without blocking anything. The downside: spoofers know p=none means "no enforcement," and you get zero protection while you're in this state. Many domains that started with p=none never moved past it. That's the most common DMARC mistake there is.

p=quarantine — Send to spam. Mail that fails authentication gets routed to the recipient's spam folder. The user can still see it if they look, but it doesn't land in the inbox. This is a meaningful improvement over p=none because spoofed mail loses its primary value: looking real to a busy inbox-scanning user. Most organizations use p=quarantine as a transition step toward reject.

p=reject — Block at the SMTP layer. Mail that fails authentication is bounced before delivery. The recipient never sees it. This is full enforcement and what every domain should aim for eventually. The risk: if you have legitimate senders that fail SPF or DKIM (a forgotten Mailchimp account, a SaaS app sending notifications "from" your domain), they'll be blocked too. That's why you don't go straight to reject — you migrate carefully.

The Migration Playbook: From Zero to p=reject

Going from no DMARC to p=reject in one step will break legitimate email. Going there gradually, watching reports as you go, is how you ship enforcement without losing mail. Here's the playbook.

Week 1: Set up SPF and DKIM properly. Before DMARC enforces anything, your underlying authentication has to work. Make sure SPF lists every IP and provider that sends mail for you (Google Workspace, Mailchimp, SendGrid, your own SMTP, transactional providers). Make sure DKIM is signing on every legitimate sender. Use the DMARC checker tool to verify both records are present and parsing correctly.

Week 2: Publish DMARC with p=none. The simplest possible record is enough to start collecting reports:

_dmarc.example.com.   IN   TXT   "v=DMARC1; p=none; rua=mailto:dmarc@example.com;"

Weeks 3–4: Read the reports. Aggregate reports arrive daily as XML attachments. They tell you which IPs sent mail under your domain, what authentication results they got, and how many messages each. You're looking for two things: (1) legitimate senders that are failing authentication (fix them), and (2) unauthorized senders (this is the spoofing you're about to block).

Reading raw DMARC XML is unpleasant. Free tools like Postmark's DMARC analyzer, dmarcian's free tier, or Valimail's free monitoring will parse them into readable dashboards. Pick one and let it run for two to four weeks until you've fixed every legitimate sender failing authentication.

Week 5: Move to p=quarantine with low pct. Don't enforce on 100% of mail right away. Start at 10% and watch what happens:

"v=DMARC1; p=quarantine; pct=10; rua=mailto:dmarc@example.com;"

If reports look clean for a week, raise to 25%, then 50%, then 100%. If you see a spike in legitimate mail being quarantined, drop back, fix the underlying issue, and try again.

Week 8 onward: Move to p=reject. Same gradual approach. Start at pct=10, watch reports, ramp to 100%. Once you're at p=reject; pct=100;, you're done. Spoofed mail under your domain can no longer reach inboxes.

Don't forget subdomains. The sp tag controls subdomain policy. If you only set p=reject without sp=reject, attackers can spoof mail from support.example.com, billing.example.com, or any subdomain you've never used. Always set sp=reject explicitly:

"v=DMARC1; p=reject; sp=reject; pct=100; rua=mailto:dmarc@example.com;"

The Five Most Common DMARC Mistakes

Once you start checking domains in the wild, you see the same misconfigurations repeatedly. Here are the five worst.

1. Stuck on p=none forever. Most domains that publish DMARC stop at p=none and never move. The result is a record that does nothing — receivers see "no enforcement" and treat failures the same as if there were no DMARC at all. p=none is a starting line, not a destination.

2. No rua tag. Without rua, you get no aggregate reports. You can't see who's sending mail under your domain, can't fix legitimate senders that are failing, and can't progress safely to quarantine or reject. Always include rua from day one.

3. Missing sp tag. If you set p=reject on the root domain but don't set sp, the policy still defaults to your root domain's p value — but only because of an RFC default. Many implementations get this wrong, and explicitly setting sp=reject removes ambiguity. Always be explicit.

4. pct below 100 in production. If your DMARC record has pct=50, half of failing mail still gets delivered. pct is a migration tool — it should be at 100 once you're past the rollout phase. Audit periodically; pct<100 records are usually leftovers from migrations that never finished.

5. Multiple DMARC records on the same domain. Some teams accidentally publish two TXT records at _dmarc.domain.com. The DMARC spec says receivers should ignore the entire record set if there's more than one — meaning you get zero enforcement. Always check that there's exactly one DMARC record per domain.

Reading DMARC Aggregate Reports

The reports that arrive at your rua address are XML files, usually compressed as .zip or .gz. Each report covers one day of authentication results from one mail receiver (Google, Microsoft, Yahoo, etc.). Here's what a single record inside one looks like:

<record>
  <row>
    <source_ip>185.225.45.12</source_ip>
    <count>47</count>
    <policy_evaluated>
      <disposition>quarantine</disposition>
      <dkim>fail</dkim>
      <spf>fail</spf>
    </policy_evaluated>
  </row>
  <identifiers>
    <header_from>example.com</header_from>
  </identifiers>
  <auth_results>
    <dkim><domain>example.com</domain><result>fail</result></dkim>
    <spf><domain>example.com</domain><result>fail</result></spf>
  </auth_results>
</record>

Translation: 47 messages claiming to be from example.com were sent from IP 185.225.45.12. They failed both DKIM and SPF, so the receiver applied your quarantine policy. That IP is either a legitimate sender you forgot about or a spoofer.

The hard part is making sense of dozens of these reports per day across multiple domains. Free aggregator tools (dmarcian, Postmark, Valimail's monitoring tier) parse the XML, group by sender, and show you trends. Don't try to read raw DMARC XML for more than a week — your sanity will not survive.

Beyond DMARC: BIMI, MTA-STS, and TLS-RPT

DMARC is the foundation, but modern email security has three more layers worth knowing about.

BIMI (Brand Indicators for Message Identification) lets your verified logo appear next to authenticated emails in supporting clients (Gmail, Yahoo, Apple Mail). BIMI requires p=quarantine or p=reject at minimum, plus a special TXT record pointing to your logo SVG. It's a marketing win — emails with brand logos get higher open rates — and a security win, because users learn to associate the logo with authentic mail.

MTA-STS (Mail Transfer Agent Strict Transport Security) forces TLS encryption on email delivery to your mail servers. Without it, attackers on the network path can downgrade SMTP connections to plaintext and intercept email in transit. MTA-STS publishes a policy file at https://mta-sts.yourdomain.com and a TXT record telling sending servers to enforce TLS.

TLS-RPT (TLS Reporting) works alongside MTA-STS and tells sending servers where to send daily reports about TLS connection failures. If a sender hits a certificate error or downgrade attempt while delivering to you, you'll know about it.

None of these replace DMARC. They extend it. Get DMARC to p=reject first, then add the others.

Continuous DMARC Monitoring: Why Set-and-Forget Doesn't Work

You finally got to p=reject; sp=reject; pct=100;. Email auth is solid. You're done — until someone on the marketing team adds a new email provider, or DevOps sets up a transactional sender, or your registrar account gets compromised and someone weakens your DMARC policy without you noticing.

DMARC drift is silent. There are no alerts, no error messages, no logs in your usual monitoring stack. Records can be edited at the registrar, by anyone with DNS access, at any time. The only way to catch this reliably is continuous monitoring: a system that re-checks your DMARC, SPF, and DKIM records on a schedule and alerts you the second anything changes.

That's exactly what FortWatch does. Hourly checks across every domain you own, automatic alerts when policies weaken (p=rejectp=none), and a unified dashboard for multi-domain organizations. It's also free to start — create an account and add your first domain in under two minutes.

If you just want a one-time check right now, the free DMARC & SPF Checker runs entirely in your browser, queries Cloudflare's public DNS, and shows you exactly what's configured. No signup, no data sent to our servers, no rate limits.

The Eight-Item DMARC Checklist

Run this against every domain you own. Anything that fails is something to fix this week.

  1. SPF record exists on the root domain and ends with -all (strict) or ~all (soft fail).
  2. SPF lookup count under 10 — count include, a, mx, ptr, exists, and redirect mechanisms. Over 10 fails validation per RFC 7208.
  3. DKIM key exists on at least one selector and the public key parses correctly.
  4. DMARC record exists at _dmarc.yourdomain.com and parses without errors.
  5. DMARC policy is quarantine or reject — not stuck on p=none.
  6. Subdomain policy explicitly set with sp=reject (not relying on default behavior).
  7. Aggregate reports going somewhere you readrua tag points to a monitored mailbox or aggregator service.
  8. Continuous monitoring in place so the next time someone weakens the policy, you find out within an hour, not three months later.

Check your domain right now with the free DMARC & SPF Checker. If anything fails, you have your weekend project.

Share this post
Get started

Ready to secure your infrastructure?

Try for free — scan your entire attack surface in under 5 minutes. No credit card required.

  • No credit card required

  • 14-Day free trial

Ready to secure your stack?

Secure your entire stack today

Start scanning in under 5 minutes. No credit card required. 14-day free trial included.