Skip to content
Spamjadoo

DMARC Explained: The Complete Guide

DMARC is a DNS record that tells receiving mail servers what to do when a message claiming to be from your domain fails both SPF and DKIM alignment, and asks them to send you reports about it. Published at _dmarc.yourdomain, it is the only standard that lets a domain owner say: refuse mail that pretends to be me.

Published 10 September 2026 · Spamjadoo engineering

What DMARC actually does

SPF and DKIM both authenticate a message, but neither one checks the address the recipient sees. SPF checks the envelope sender, the MAIL FROM address the receiving server sees during the SMTP session. DKIM checks whatever domain is in the d= tag of the signature. A spammer can pass both while displaying your domain in the From: header, because nothing ties the authenticated domain to the displayed one.

DMARC closes that gap with one rule: at least one of SPF or DKIM must pass, and the domain it authenticated must match the From: header domain. That match is called alignment. If neither aligns, the message fails DMARC, and the domain owner’s published policy tells the receiver what to do.

The second half of DMARC is reporting. Receivers that support it send the domain owner a daily summary of every message they saw claiming that domain, with pass and fail counts per sending IP. This is the only standardised way to find out who is sending as your domain, legitimately or not.

The record

DMARC lives in a TXT record at _dmarc. plus your domain:

_dmarc.example.com.  IN TXT  "v=DMARC1; p=reject; sp=reject; pct=100; rua=mailto:dmarc-agg@example.com; ruf=mailto:dmarc-fail@example.com; adkim=r; aspf=r; fo=1"
TagRequiredMeaning
v=DMARC1YesVersion. Must be first.
p=YesPolicy for the domain: none, quarantine or reject.
sp=NoPolicy for subdomains. Defaults to the value of p.
pct=NoPercentage of failing mail the policy applies to. Default 100.
rua=No, but you want itWhere aggregate reports go. Comma-separated mailto: URIs.
ruf=NoWhere per-message failure reports go. Few receivers send them.
adkim=NoDKIM alignment mode: r relaxed (default) or s strict.
aspf=NoSPF alignment mode: r relaxed (default) or s strict.
fo=NoWhen to send failure reports. 0 both fail (default), 1 either fails, d DKIM fails, s SPF fails.
rf=, ri=NoFailure report format and report interval. Leave at defaults.

Two rules receivers enforce that catch people out. There must be exactly one DMARC record; two is treated as none. And the p= tag must be present; a record without it is invalid, and receivers treat the domain as having no policy.

Paste any domain into the DMARC checker to see its record read back as a sentence.

Alignment in detail

Relaxed alignment means the authenticated domain and the From: domain share an organisational domain. Mail from news.example.com signed with d=example.com aligns under relaxed mode. Strict alignment requires an exact match.

For SPF, the domain being aligned is the envelope sender. Many bulk-mail providers put their own domain in the envelope sender so that bounces come back to them. That mail cannot align on SPF; it has to align on DKIM, which means the provider must sign with your domain, not theirs. Every “add these CNAMEs for DKIM” instruction from an email provider exists to make that possible.

For DKIM, the aligned domain is the d= value in the signature. A message can carry several signatures; if any one of them passes and aligns, DMARC passes on DKIM.

The practical consequence: set up DKIM signing on your own domain for every sending service, and treat SPF as a bonus. Forwarding breaks SPF, mailing lists break SPF, and any provider using its own bounce domain breaks SPF alignment. DKIM survives all three as long as the signed content is not altered.

Reading aggregate reports

Aggregate reports are XML files, one per receiver per day, sent to the rua address. Each contains a list of records like this one, simplified:

<record>
  <row>
    <source_ip>203.0.113.25</source_ip>
    <count>1420</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><result>pass</result></dkim>
    <spf><domain>bounce.provider.example</domain><result>pass</result></spf>
  </auth_results>
</record>

This record says: 1,420 messages from 203.0.113.25 claimed example.com. SPF passed for the provider’s bounce domain but did not align, so <spf> under policy evaluation shows fail. DKIM passed and aligned, so DMARC passed. Disposition none means nothing was done, which is correct for a passing message.

What to look for, in order:

  1. Rows where both aligned results are fail, with high counts. Either a legitimate service you have not set up, or spoofing. Look the IP up; a reverse DNS check usually identifies a real provider.
  2. Rows where SPF aligns but DKIM fails. A service sending as your domain without signing. It will break the moment the mail is forwarded. Set up DKIM.
  3. Rows where DKIM passes but not for your domain. A provider signing with its own domain. Ask for domain-aligned signing.
  4. Small counts from many unrelated IPs. Normal background spoofing. This is what the policy is for.

Raw XML does not scale past a handful of reports a day. Use a report processor; several are free at low volume. The report processor is not the point, though. The point is the list of senders it produces.

From none to reject, without losing mail

The order matters. Every step is reversible, and nothing changes for your mail until step 4.

Step 1: publish p=none with a rua address

v=DMARC1; p=none; rua=mailto:dmarc@example.com

This changes nothing for delivery. Reports start arriving within a day or two. Wait at least two weeks, four if your business has monthly billing runs or other periodic senders.

Step 2: fix every legitimate source

For each sender the reports show as failing:

  • If you control the server, add its IP to SPF and set up DKIM signing with your domain.
  • If it is a third-party service, follow their authentication setup. Almost every serious provider supports domain-aligned DKIM via CNAME records. Add their SPF include only if your lookup count has room.
  • If it is a service nobody recognises, find out who signed up for it before you cut it off. Marketing tools acquired on a credit card are the usual answer.

Check each fix with the DKIM checker and by sending a test message to a mailbox where you can read the Authentication-Results header.

Step 3: quarantine at a low percentage

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

Ten percent of failing mail goes to spam. If a legitimate sender was missed, one in ten of its messages is delayed rather than all of them, and the reports show the disposition. Raise pct over a few weeks: 10, 25, 50, 100.

Step 4: reject

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

Failing mail is refused. Keep rua forever; new services appear and the reports are how you find them before their mail is rejected.

Subdomains

sp= defaults to p=, so a parent at reject covers subdomains unless you say otherwise. Two situations need care. Subdomains that send mail through their own services need their own SPF and DKIM. And any subdomain that never sends mail should have its own DMARC record at reject, or be covered by sp=reject, so nobody can spoof hr.example.com even though example.com is enforced.

Common mistakes

  • Two DMARC records, usually after a migration. Receivers treat this as no record. The checker flags it.
  • p=none for years. The reports arrive and nobody reads them. p=none gives you no protection; it is a starting point, not a configuration.
  • pct= below 100 at reject. The unprotected percentage is delivered as if you had no policy.
  • rua pointing at another domain without authorisation. If reports go to dmarc@reports.example.net for example.com, the receiving domain must publish example.com._report._dmarc.reports.example.net TXT v=DMARC1 or receivers will not send.
  • Strict alignment before checking subdomain senders. adkim=s breaks any subdomain signing with the parent domain’s key.
  • Assuming DMARC stops all phishing. It stops exact-domain spoofing. Look-alike domains (examp1e.com) and display-name tricks are a different problem; see the spoofing and BEC guide when it publishes.

DMARC and the 2024 bulk-sender rules

Since February 2024, Google and Yahoo require senders of more than 5,000 messages a day to their users to publish a DMARC record (at least p=none), authenticate with both SPF and DKIM, align on at least one, support one-click unsubscribe for bulk mail, and stay under a 0.3% spam complaint rate. Microsoft applied similar rules to Outlook.com in 2025. These are delivery requirements, not recommendations: mail that misses them is rejected or junked at the receiver.

For a domain that only sends transactional mail from one or two systems, meeting the rules takes an afternoon. The steps above are the same steps.

Where DMARC is evaluated

Most gateways evaluate DMARC after the whole message has been received, because DKIM needs the body. Spamjadoo evaluates the SPF half at MAIL FROM, before content is transferred. For a domain at p=reject where the connecting server fails SPF and the policy does not need to wait for a DKIM rescue, the message is refused during the session and the sender’s server generates the bounce. The DKIM half runs on the traffic that reaches DATA. See how it works for the full sequence.

Quick reference

  • Record location: _dmarc.yourdomain TXT.
  • Minimum viable record: v=DMARC1; p=none; rua=mailto:you@yourdomain.
  • Target record: v=DMARC1; p=reject; sp=reject; rua=mailto:you@yourdomain.
  • Pass condition: SPF or DKIM passes and aligns with the From: domain.
  • Reports: daily XML to rua. Use a processor.
  • Tools: DMARC checker, SPF checker, DKIM checker.