DMARC quarantine vs reject: when to switch and how to roll it out safely

Was this helpful?

Your CEO just forwarded an email that “looks like it’s from Finance” and asks if the wire transfer is legit.
The headers say it’s not from you. Your users can’t tell. And your domain is about to become the attacker’s favorite costume.

DMARC is the grown-up fix. But flipping from p=none to p=reject isn’t a brave little checkbox—it’s a production change that can quietly break real mail.
This is how you ship it like an SRE: measurable, reversible, and boring in the best way.

DMARC in production: the mental model that avoids self-inflicted outages

DMARC is not “an authentication protocol.” It’s a policy and a reporting pipeline that sits on top of SPF and DKIM.
It tells receivers what to do when mail that claims to be from your domain fails authentication and, crucially, fails alignment.

Alignment is the part people half-remember and then regret.
DMARC doesn’t care that SPF passed for bounce.vendor-mail.example if the message claims to be from yourbrand.com.
It doesn’t care that DKIM passed for mailer.thirdparty.com if the visible From is yourbrand.com and they didn’t sign with your domain (or a properly aligned one).

Here’s the cleanest working model:

  • Identity in the From header is what users see and what DMARC protects.
  • SPF authenticates the SMTP envelope sender (Return-Path / MAIL FROM), not the From header.
  • DKIM authenticates a signing domain (d=), not the From header.
  • DMARC requires at least one of SPF or DKIM to pass and align with the From domain.
  • Policy: p=none observes, p=quarantine nudges, p=reject slams the door.

The operational truth: DMARC isn’t hard, it’s wide. Your domain likely sends email from places you don’t remember:
ticketing systems, HR tools, CRM, marketing platforms, status pages, contractor automation, printers, scanners, and that one app a team built in 2018 and still “temporarily” runs.

A well-run DMARC rollout is basically asset discovery for outbound email, with DNS changes at the end.

Interesting facts and quick history (the stuff that explains today’s weirdness)

  • SPF predates DMARC by almost a decade. SPF started in the early 2000s as a response to rampant spoofing, but it never authenticated what users see in From.
  • DKIM came from a merger of two competing approaches. DomainKeys (Yahoo) and Identified Internet Mail (Cisco) converged into DKIM, which is why some terminology still feels like it was written by committee.
  • DMARC emerged from “we’re tired of phishing our own users.” Major mailbox providers and large senders pushed it to stop direct-domain spoofing, not to fix every spam problem.
  • DMARC’s killer feature is reporting. Aggregate reports (RUA) turn receivers into telemetry sources. That’s rare in email land, which usually runs on vibes and blame.
  • Mail forwarding is older than most of your SaaS stack. The original email ecosystem assumed forwarding and remailing were normal. DMARC enforcement can collide with that history.
  • ARC exists because “forwarding breaks SPF/DKIM” wouldn’t die. Authenticated Received Chain is a band-aid to preserve authentication results across intermediaries.
  • Large receivers have gradually tightened behavior. DMARC compliance didn’t become mainstream overnight; providers phased enforcement and UI signals over years, which is why advice from 2016 often fails today.
  • DMARC is not just for reject. Many high-volume orgs live at p=quarantine with pct ramping, because some mail ecosystems never become perfectly deterministic.

Quarantine vs reject: what actually changes on the wire

In theory, DMARC policy is “receiver’s choice.” In practice, big mailbox providers treat your policy as a strong signal.
You are telling them, “I have control of my domain and I’m ready to have you enforce it.”

What quarantine usually means

Quarantine is a “treat as suspicious” instruction. Most commonly: spam folder, junk classification, or additional filtering.
Some receivers will still deliver to inbox depending on their own model.

Operationally, quarantine is a staging lane:

  • You start seeing user complaints (“my invoice emails are going to spam”) without the hard stop of outright rejection.
  • You can discover misaligned senders that were “working” only because receivers were lenient.
  • You can ramp enforcement with pct while you fix underlying alignment.

What reject usually means

Reject is the receiver refusing delivery during SMTP (ideal) or dropping later (less ideal).
If your legitimate mail fails DMARC under a reject policy, you often get:

  • Hard bounces for transactional mail.
  • Silent non-delivery depending on receiver behavior (rare, but it happens).
  • Fire drills: “emails are not arriving” is a business outage, not an IT ticket.

Reject is the goal for high-trust domains (executives, payroll, finance, legal) and for brands that are frequently spoofed.
It’s also a promise: you’re telling receivers your authentication posture is mature enough that failing messages are probably hostile.

One opinionated rule: do not go to reject until you can answer, with evidence, “What systems send mail as our domain, and do they align?”
If your answer is “mostly Microsoft 365,” you are not ready. “Mostly” is how outages happen.

Joke #1: DMARC is like putting a lock on your front door—great move—until you remember your roommate still uses the window.

Preflight: prerequisites before you touch the DMARC policy

The safest rollout starts with boring inventory and ends with policy. In between: alignment fixes.
Here’s what you should have in place before you raise enforcement.

1) You own and can change DNS reliably

DMARC lives in DNS. If your DNS workflow is “somebody in another department clicks around,” you need a change process:
version control, review, and predictable propagation windows. The failure mode is simple: wrong TXT record, broken auth, hours of uncertainty.

2) SPF is not perfect, but it’s sane

SPF needs to cover your legitimate senders and avoid exceeding the 10 DNS-lookup limit. Also: minimize ~all ambiguity over time.
SPF passing is not enough for DMARC, but SPF chaos makes DMARC analysis miserable.

3) DKIM signing exists for primary sending platforms

DKIM is your best friend when mail is forwarded or relayed.
If you can sign with d=yourbrand.com (or aligned subdomain), do it.

4) You have a reporting mailbox and someone reads it

DMARC aggregate reports are XML. They’re not “human-friendly,” but they’re operationally gold.
You need a mailbox to receive them, a parser/workflow (commercial or internal), and an on-call-ish expectation: someone checks when you change policy.

5) You understand your risk tolerance

A bank’s tolerance is not a creative agency’s tolerance. Decide:

  • Which domains must go to reject fast (executive-facing, payment-facing)?
  • Which domains can stay quarantine longer (marketing-heavy, lots of third parties)?
  • Do you need subdomain policies (sp=)?

Practical tasks (with commands, outputs, and decisions)

These are real tasks you can run from a shell. They won’t fix DMARC by themselves, but they will keep you from guessing.
Each task includes: command, sample output, what it means, and the decision you make.

Task 1: Inspect the current DMARC record

cr0x@server:~$ dig +short TXT _dmarc.yourbrand.com
"v=DMARC1; p=none; rua=mailto:dmarc-rua@yourbrand.com; ruf=mailto:dmarc-ruf@yourbrand.com; fo=1; adkim=r; aspf=r; pct=100"

Meaning: Current policy is monitoring only (p=none). Relaxed alignment for SPF and DKIM. Reporting is configured.

Decision: If rua is missing, stop and add it before enforcement. No telemetry, no rollout.

Task 2: Validate the DMARC record syntax from DNS

cr0x@server:~$ python3 - <<'PY'
import re, subprocess, shlex
domain="_dmarc.yourbrand.com"
out=subprocess.check_output(["dig","+short","TXT",domain],text=True).strip()
print(out)
if "v=DMARC1" not in out:
    raise SystemExit("Missing v=DMARC1")
if " p=" not in out and ";p=" not in out:
    raise SystemExit("Missing p=")
print("Looks like DMARC-ish TXT is present.")
PY
"v=DMARC1; p=none; rua=mailto:dmarc-rua@yourbrand.com; ruf=mailto:dmarc-ruf@yourbrand.com; fo=1; adkim=r; aspf=r; pct=100"
Looks like DMARC-ish TXT is present.

Meaning: You at least have a DMARC-ish record returned consistently.

Decision: If multiple TXT strings show up for DMARC (more than one record), fix DNS immediately; receivers can behave unpredictably.

Task 3: Inspect the current SPF record

cr0x@server:~$ dig +short TXT yourbrand.com | sed -n 's/^"//; s/"$//; /v=spf1/p'
v=spf1 include:spf.protection.outlook.com include:mailgun.org ip4:203.0.113.10 ~all

Meaning: SPF exists and lists a couple of providers plus an IP, ending in softfail.

Decision: If you see multiple SPF records, consolidate. If you see a long chain of includes, you must check DNS lookup count next.

Task 4: Count SPF DNS lookups (avoid the 10-lookup cliff)

cr0x@server:~$ python3 - <<'PY'
import dns.resolver, re
domain="yourbrand.com"
visited=set()
def get_spf(d):
    txt=[]
    for r in dns.resolver.resolve(d,"TXT"):
        s="".join([b.decode() for b in r.strings])
        if s.startswith("v=spf1"):
            txt.append(s)
    return txt[0] if txt else None

lookups=0
def walk(d):
    global lookups
    if d in visited: return
    visited.add(d)
    spf=get_spf(d)
    if not spf: return
    for token in spf.split():
        if token.startswith("include:"):
            lookups += 1
            walk(token.split(":",1)[1])
        if token.startswith("redirect="):
            lookups += 1
            walk(token.split("=",1)[1])

walk(domain)
print("Estimated include/redirect lookups:", lookups)
print("Visited domains:", len(visited))
PY
Estimated include/redirect lookups: 2
Visited domains: 3

Meaning: You are below the common 10-lookup SPF limit (this script only approximates; real evaluation includes other mechanisms).

Decision: If you’re near/over 10, simplify SPF before tightening DMARC. Otherwise you’ll “fix” spoofing by breaking mail.

Task 5: Check DKIM selector records for a known sender

cr0x@server:~$ dig +short TXT selector1._domainkey.yourbrand.com
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx...snip..."

Meaning: A DKIM public key exists for selector1. That’s necessary for receivers to validate DKIM signatures from that selector.

Decision: If you don’t know which selectors are in use, pull a recent outbound message header and find s= and d=.

Task 6: Verify DMARC alignment on a sample message (from headers)

cr0x@server:~$ awk 'BEGIN{RS="";FS="\n"} {for(i=1;i<=NF;i++) if($i ~ /Authentication-Results:/) print $i}' sample.eml
Authentication-Results: mx.google.com;
       dkim=pass header.i=@yourbrand.com header.s=selector1 header.b=abc123;
       spf=pass (google.com: domain of bounce@mg.yourbrand.com designates 203.0.113.10 as permitted sender) smtp.mailfrom=bounce@mg.yourbrand.com;
       dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=yourbrand.com

Meaning: DMARC passes because at least one of SPF or DKIM passes and aligns with header.from=yourbrand.com. DKIM alignment is perfect here.

Decision: If DMARC fails but SPF passes, you probably have SPF passing for a different domain (misalignment). Fix alignment, not “more SPF.”

Task 7: Locate top failing sources in RUA aggregate XML (quick and dirty)

cr0x@server:~$ ls -1 dmarc-rua/ | head
google.com!yourbrand.com!1735516800!1735603200.xml
outlook.com!yourbrand.com!1735516800!1735603200.xml

cr0x@server:~$ grep -RhoE '<source_ip>[^<]+' dmarc-rua/*.xml | sed 's/<source_ip>//' | sort | uniq -c | sort -nr | head
  482 203.0.113.10
  117 198.51.100.25
   41 192.0.2.77

Meaning: You have a few major source IPs generating DMARC-seen traffic.

Decision: Identify each IP (your MTA, your vendor, a mystery). Unknown high-volume IPs block enforcement.

Task 8: Map a suspicious IP to a provider (reverse + ASN hint)

cr0x@server:~$ whois 198.51.100.25 | egrep -i 'OrgName|org-name|descr|netname|origin|aut-num' | head
NetName:        EXAMPLE-NET
OrgName:        Example Email Services
OriginAS:       AS64500

Meaning: That IP likely belongs to a vendor or at least an identifiable network.

Decision: If it’s not yours, figure out why it’s sending mail claiming to be you. Either authorize and align it, or block it with DMARC enforcement.

Task 9: Check whether your subdomains have their own DMARC records

cr0x@server:~$ for d in marketing.yourbrand.com status.yourbrand.com hr.yourbrand.com; do
  echo "== $d =="
  dig +short TXT _dmarc.$d
done
== marketing.yourbrand.com ==
"v=DMARC1; p=none; rua=mailto:dmarc-rua@yourbrand.com"
== status.yourbrand.com ==

== hr.yourbrand.com ==

Meaning: One subdomain has its own policy; others inherit from organizational domain unless sp= is set on the parent.

Decision: Decide whether you want different enforcement for subdomains. If you don’t, remove stray subdomain DMARC records that conflict with your plan.

Task 10: Simulate a policy change safely (use pct=10 with quarantine)

cr0x@server:~$ cat <<'EOF'
_dmarc.yourbrand.com. 3600 IN TXT "v=DMARC1; p=quarantine; pct=10; adkim=r; aspf=r; rua=mailto:dmarc-rua@yourbrand.com"
EOF
_dmarc.yourbrand.com. 3600 IN TXT "v=DMARC1; p=quarantine; pct=10; adkim=r; aspf=r; rua=mailto:dmarc-rua@yourbrand.com"

Meaning: This is the record you propose to publish: quarantine, but only for 10% of failing mail.

Decision: If your org can’t tolerate any misclassification, keep pct low for longer and fix alignment first. If you’re under active spoofing, ramp faster.

Task 11: Verify DNS propagation from multiple resolvers

cr0x@server:~$ for r in 1.1.1.1 8.8.8.8 9.9.9.9; do
  echo "== resolver $r =="
  dig +short @$r TXT _dmarc.yourbrand.com
done
== resolver 1.1.1.1 ==
"v=DMARC1; p=quarantine; pct=10; adkim=r; aspf=r; rua=mailto:dmarc-rua@yourbrand.com"
== resolver 8.8.8.8 ==
"v=DMARC1; p=quarantine; pct=10; adkim=r; aspf=r; rua=mailto:dmarc-rua@yourbrand.com"
== resolver 9.9.9.9 ==
"v=DMARC1; p=quarantine; pct=10; adkim=r; aspf=r; rua=mailto:dmarc-rua@yourbrand.com"

Meaning: The change is visible from major public resolvers.

Decision: If resolvers disagree for hours, your DNS is caching badly or you published multiple records. Don’t ramp policy until DNS is stable.

Task 12: Watch mail logs for DMARC-related bounces (Postfix example)

cr0x@server:~$ sudo grep -E 'dmarc|policy|reject|quarantine' /var/log/mail.log | tail -n 20
Jan 04 10:21:16 mx1 postfix/smtp[18233]: host gmail-smtp-in.l.google.com[142.250.102.27] said: 550-5.7.26 Unauthenticated email from yourbrand.com is not accepted due to domain's DMARC policy. (in reply to end of DATA command)

Meaning: A receiver rejected a message explicitly due to your DMARC policy. This is either a spoof being blocked (good) or a legit sender failing alignment (bad).

Decision: Pull the queued message, inspect headers, identify the actual sending system, and either fix alignment or stop it from using your From domain.

Task 13: Confirm a third-party is signing with aligned DKIM

cr0x@server:~$ grep -Eo 'dkim=[a-z]+|header.i=@[^;]+|header.s=[^;]+' sample-vendor.eml
dkim=pass
header.i=@vendor-mail.example
header.s=s1

Meaning: DKIM passed, but it’s signed as vendor-mail.example, not your domain. That won’t align with From yourbrand.com.

Decision: Either configure “custom DKIM” on the vendor to sign as your domain (preferred), or move that traffic to a subdomain you control for that vendor (also fine), or change From to a domain they own (often politically hard, technically clean).

Task 14: Detect “From domain” vs “envelope from” mismatch in an outbound message

cr0x@server:~$ egrep -i '^(From:|Return-Path:)' sample.eml
Return-Path: <bounce@mg.yourbrand.com>
From: Billing <billing@yourbrand.com>

Meaning: Envelope is mg.yourbrand.com and visible From is yourbrand.com. SPF alignment depends on whether relaxed alignment treats mg.yourbrand.com as aligned (it does, under relaxed, since it’s a subdomain). Strict alignment would fail.

Decision: If you plan to go strict (aspf=s), you need envelope-from to match exactly (or rely on DKIM alignment).

Task 15: Confirm your DMARC record includes an explicit subdomain policy decision

cr0x@server:~$ dig +short TXT _dmarc.yourbrand.com | tr -d '"' | tr ';' '\n' | sed 's/^ *//'
v=DMARC1
p=quarantine
pct=10
adkim=r
aspf=r
rua=mailto:dmarc-rua@yourbrand.com

Meaning: There is no sp= tag. Subdomains inherit p= by default, unless they publish their own DMARC record.

Decision: If you have many “wild” subdomains, consider sp=none while parent goes quarantine/reject. Or do the opposite if subdomains are abused.

Task 16: Smoke-test outbound from each known system (minimal, but effective)

cr0x@server:~$ swaks --to dmarc-test@externalmailbox.example --from noreply@yourbrand.com --server smtp.office365.com --auth-user noreply@yourbrand.com --auth-password 'REDACTED' --data "Subject: DMARC smoke test

hello"
=== Trying smtp.office365.com:587...
=== Connected to smtp.office365.com.
<** 220 ...
>** EHLO ...
<** 250-...
>** MAIL FROM:<noreply@yourbrand.com>
<** 250 2.1.0 Sender OK
>** RCPT TO:<dmarc-test@externalmailbox.example>
<** 250 2.1.5 Recipient OK
>** DATA
<** 354 Start mail input; end with <CRLF>.<CRLF>
>** .
<** 250 2.0.0 OK

Meaning: The message is accepted by your outbound system. The real check happens at the receiver when you inspect Authentication-Results.

Decision: Do this for each platform (O365, Gmail, marketing vendor, ticketing system). If any can’t produce aligned mail, fix it before reject.

Fast diagnosis playbook

When you tighten DMARC and something breaks, you will get vague reports: “emails aren’t arriving.”
Your job is to turn that into a single failing flow and a single failing alignment condition fast.

First: determine whether it’s rejection, quarantine, or something else

  • Ask for a bounce. If there’s a bounce message, read it. If the bounce mentions DMARC or “unauthenticated,” you’re in the right neighborhood.
  • Check receiver’s SMTP response in logs. Your MTA logs usually have the exact status code and text.
  • Check whether the user is just missing it (quarantine). If policy is quarantine, it may be landing in spam folders.

Second: identify which sender is actually sending the message

  • Pull the message from the sending system if possible (queued mail, archived sent items, application logs).
  • Extract Return-Path, From, and DKIM d=.
  • Cross-check with RUA reports to find volume and failure rate for that source IP.

Third: decide whether you fix SPF alignment, DKIM alignment, or the From domain

  • If DKIM is present and fails: signature broke (content rewriting, bad key, wrong selector) or vendor misconfiguration.
  • If DKIM passes but is unaligned: vendor is signing as themselves; you need custom DKIM or a subdomain strategy.
  • If SPF passes but DMARC fails: envelope-from domain isn’t aligned with From, or forwarding caused SPF failure and you were depending on SPF.

Fourth: control blast radius while you fix

  • Lower pct temporarily if needed (especially during quarantine ramp).
  • For emergencies, move back from reject to quarantine while you repair—but treat this like a rollback, not a lifestyle.
  • Communicate clearly: which sender, which flows, and expected time to restore.

Checklists / step-by-step plan: from none → quarantine → reject

The safest DMARC rollout is a controlled migration with measurable gates. Here is the plan that tends to survive corporate reality.

Phase 0: Monitoring that actually monitors (1–4 weeks)

  • Publish DMARC with p=none, rua, and (optional) ruf if you can handle sensitive forensic data. Many orgs skip ruf.
  • Ensure SPF exists and DKIM is enabled for your primary platform(s).
  • Stand up a workflow for aggregate reports:
    • Daily review during the first week.
    • Weekly review afterward until stable.
  • Create an inventory:
    • Every legitimate sender.
    • Which domains they use in From and envelope-from.
    • Which DKIM domain they sign with.
    • Who owns the configuration.

Gate to move on

  • You can attribute the top 90–95% of DMARC-seen volume to known systems.
  • For the known systems, you have an explicit plan to fix any failing alignment.
  • You have at least one “external mailbox” you can use for header checks.

Phase 1: Quarantine with a low percent (1–3 weeks)

  • Set p=quarantine; pct=10 (or 5 if you’re cautious).
  • Keep alignment relaxed (aspf=r; adkim=r) unless you have a reason to go strict.
  • Monitor:
    • RUA failure rates by source.
    • Helpdesk tickets mentioning missing emails or spam folder changes.
    • Outbound bounce logs.

Gate to increase pct

  • No unknown high-volume sources failing DMARC.
  • All business-critical senders (transactional, billing, auth, HR) are passing DMARC reliably.
  • User impact is manageable and understood (quarantine false positives are tracked to a sender and fix).

Phase 2: Quarantine at 25 → 50 → 100 (2–6 weeks)

  • Increase to 25%, then 50%, then 100% with at least several days between steps.
  • Every step should have:
    • A change ticket with rollback instructions.
    • A named owner watching RUA and mail logs.
    • A list of known “watchlist senders” (vendors, legacy apps).

Phase 3: Reject with pct ramp (1–4 weeks)

  • Move to p=reject; pct=10, then ramp as above.
  • Keep quarantine as your rollback step (faster than going back to none).
  • Once stable at reject, consider:
    • Strict alignment for SPF/DKIM if your ecosystem supports it.
    • Locking down subdomain behavior with sp=.

What not to do

  • Don’t jump from none to reject because “we turned on DKIM in Microsoft 365.” You have more senders than you think.
  • Don’t use DMARC to paper over “we don’t know who sends mail.” DMARC will force you to know. That’s the point.
  • Don’t set strict alignment early unless you are very sure about envelope-from domains and vendor DKIM.

Three corporate mini-stories (anonymized, painfully plausible)

Mini-story 1: The incident caused by a wrong assumption

A mid-sized fintech decided it was time for p=reject. They had been at p=none for months, saw plenty of spoofing, and felt pressure from security audits.
The email team’s working assumption was simple: “All mail comes from Microsoft 365, plus the marketing platform we already DKIM-signed.”

On Monday morning they flipped to reject at 100%. Within an hour, customer onboarding emails stopped arriving at several major consumer mailbox providers.
Sales called it “a deliverability issue.” Support called it “the email system is down.” Engineering called it “we didn’t change anything.”

The root cause was a third system: an identity provider sending “magic link” sign-ins. It used From: noreply@yourbrand.com but signed DKIM as the vendor’s domain.
SPF passed too—also for the vendor’s domain. Under p=none, receivers delivered anyway. Under reject, DMARC failed alignment and got refused.

The fix wasn’t heroic. They enabled the vendor’s custom DKIM for yourbrand.com and adjusted the envelope-from to an aligned subdomain.
The hard part was organizational: the identity team owned that vendor, and the email team hadn’t been invited to the implementation.

The lasting lesson: your biggest DMARC risks are not the systems you know. It’s the ones that were bought with a credit card and a deadline.

Mini-story 2: The optimization that backfired

A global retailer had a complicated SPF record: multiple includes, regional senders, and a few legacy IPs.
Someone tried to “optimize” by flattening SPF into a long list of IPs to avoid DNS lookup limits and reduce receiver latency.

It worked for a while. Then a vendor rotated outbound IPs. Because the flattening process was manual and poorly documented, the SPF record lagged reality.
Some receivers started failing SPF; DMARC still passed sometimes thanks to DKIM, but not always—because a few systems didn’t DKIM-sign consistently.

When the team finally moved to p=quarantine, those marginal cases started going to spam. The most annoying part:
it was intermittent, tied to which outbound IP the vendor happened to use that hour.

They rolled back to p=none temporarily. Then they did the unsexy work:
standardize DKIM across transactional senders, automate SPF updates where necessary, and stop relying on SPF as the only aligned method.

Optimization lesson: if you “simplify” SPF in a way that makes it less maintainable, you haven’t simplified anything. You’ve just moved the pain into incident response.

Mini-story 3: The boring but correct practice that saved the day

A B2B software company ran a slow DMARC rollout. Security wanted reject. Marketing was nervous. Finance was louder than both.
The email owner insisted on a change calendar and small pct ramps with a rollback plan and an explicit watchlist of senders.

During the quarantine ramp from 25% to 50%, aggregate reports showed a new failing source IP with low volume but a high failure rate.
It wasn’t a spoof. It was a new customer success tool sending “meeting summaries” as from=yourbrand.com on behalf of staff.

Because the rollout had gates, nothing catastrophic happened. The team paused at 50% and didn’t proceed.
They routed that tool to use a dedicated subdomain, enabled custom DKIM, and verified alignment with test messages.

Two weeks later they resumed the ramp, reached reject, and nobody outside the email team noticed—my favorite kind of success.

Quote (paraphrased idea) from Gene Kranz: “Failure isn’t an option” is less a slogan than a discipline—prepare so you don’t need luck.

Common mistakes: symptoms → root cause → fix

These are the repeat offenders. You can spot them from the complaint pattern.

1) Symptom: “Only some recipients don’t get our emails” after moving to reject

Root cause: Mixed sending paths. One path aligns (DKIM or SPF), another doesn’t (often a vendor or region-specific system).

Fix: Use RUA reports to segment by source IP and identify the failing system. Enable aligned DKIM for that sender or move From to an aligned subdomain.

2) Symptom: Emails land in spam right after quarantine, but DMARC passes in your tests

Root cause: Quarantine doesn’t guarantee spam placement only for DMARC failures; it changes receiver scoring behavior. Also, your tests might cover only one sender.

Fix: Test each major sender path. Confirm DMARC pass and alignment in Authentication-Results. If pass is consistent, look at reputation/content, not DMARC policy.

3) Symptom: DMARC fails even though SPF says “pass” in headers

Root cause: SPF passed for a different domain than the visible From (misalignment). Common with vendors using their own bounce domain.

Fix: Configure a custom return-path / envelope-from domain under your domain (aligned subdomain) or rely on aligned DKIM.

4) Symptom: DKIM passes sometimes and fails other times for the same system

Root cause: Message modification in transit (footers, disclaimers, link rewriting), multiple DKIM signers with inconsistent config, or key/selector mismatch during rotation.

Fix: Sign after modification (on the last hop you control), reduce downstream rewriting, and ensure selectors and keys are deployed before switching signers.

5) Symptom: DMARC failure spikes after enabling strict alignment

Root cause: Strict alignment requires exact domain match. Subdomain envelope-from (e.g., mg.yourbrand.com) no longer aligns with yourbrand.com for SPF.

Fix: Keep relaxed alignment unless you have strong reasons. If going strict, ensure DKIM signs with the exact From domain, or change envelope-from accordingly.

6) Symptom: Some forwarded mail (especially to personal accounts) starts failing after reject

Root cause: Forwarders can break SPF and sometimes DKIM. DMARC then fails at the final receiver.

Fix: Prefer DKIM alignment for important mail and consider ARC-aware flows. For mailing lists, consider list configuration that respects DMARC (may involve From rewriting).

7) Symptom: RUA reports are empty or extremely low volume

Root cause: rua address not accepted by receivers (some validate), mailbox issues, DNS typo, or you have very little mail traffic through receivers that send reports.

Fix: Verify rua is correct, mailbox receives mail, and DMARC record is visible. Consider adding multiple RUA mailboxes if operationally useful.

8) Symptom: You publish DMARC but nothing changes

Root cause: You’re testing with mail that already passes DMARC, or receivers ignore policy due to malformed record, multiple DMARC TXT records, or wrong domain.

Fix: Validate a single DMARC TXT record at _dmarc.yourbrand.com and test a known failing message (from a non-authorized sender) carefully and ethically.

Joke #2: Email authentication is the only security project where you can be “fully compliant” and still lose to a forwarded newsletter.

FAQ

1) When should I switch from quarantine to reject?

Switch when your aggregate reports show that legitimate high-volume senders pass DMARC consistently, and unknown failing sources are low volume or clearly malicious.
Practically: when you can name every meaningful sender and you have an owner for each configuration.

2) Is it safe to go straight from p=none to p=reject?

Only if you have a very small, tightly controlled sending surface and you’ve already validated alignment for every sender.
Most organizations think they are small and controlled. Most are wrong. Use quarantine and pct ramps unless you’re in an active spoofing crisis.

3) What does pct actually do?

pct requests that receivers apply the policy to only a percentage of messages that fail DMARC evaluation.
It’s not a guaranteed sampling algorithm and different receivers implement it differently, but it’s still useful as a gradual enforcement lever.

4) Do I need both SPF and DKIM for DMARC?

Strictly: no, DMARC can pass with either SPF or DKIM. Operationally: yes, you want both.
DKIM is especially important because SPF is fragile under forwarding and relaying.

5) Should I set aspf=s and adkim=s (strict alignment)?

Not early. Start relaxed. Strict alignment is for when you want to reduce edge-case abuse and you have strong control over vendors and subdomains.
Strict alignment is also a great way to discover hidden dependencies at 2 a.m.

6) What about subdomains—do they inherit the parent’s policy?

By default, subdomains use the organizational domain DMARC policy unless they publish their own DMARC record.
If you set sp= on the parent record, you can define a separate policy specifically for subdomains.

7) Why do some vendors “support DMARC” but still fail alignment?

Many vendors mean “we support SPF and DKIM for our own domain.” That’s not enough if you want to send as your domain.
You typically need custom DKIM (signing with your domain) and sometimes a custom return-path under your domain.

8) Will DMARC stop all phishing using my brand?

It stops direct-domain spoofing (attacker uses From: ceo@yourbrand.com while sending from elsewhere) for receivers that enforce DMARC.
It does not stop lookalike domains, display-name spoofing, or compromised legitimate accounts.

9) What’s the biggest operational risk of DMARC reject?

Breaking legitimate mail from a system you didn’t know was using your From domain, or from a vendor that can’t align.
This hits transactional email first, which is exactly the mail you cannot afford to lose.

10) If I’m under active spoofing today, what’s the fastest safe move?

Move to p=quarantine; pct=100 quickly if you have basic alignment for your main platforms, then accelerate remediation and ramp to reject.
If you can confidently assert DKIM alignment for your core mail, you can go reject faster—but do it with eyes open and monitoring staffed.

Conclusion: next steps you can execute this week

DMARC quarantine and reject are not philosophical positions. They’re enforcement modes.
Quarantine is how you learn without taking the business down. Reject is how you cash in that learning and make spoofing materially harder.

Practical next steps:

  1. Check your current DMARC/SPF/DKIM DNS records and confirm there is exactly one DMARC record.
  2. Turn on RUA reporting if it’s missing and start collecting aggregate reports daily.
  3. Build your sender inventory from RUA source IPs and Authentication-Results headers.
  4. Fix the top failing legitimate sender first (it’s usually a vendor with unaligned DKIM).
  5. Move to p=quarantine; pct=10 with a rollback plan, then ramp deliberately.
  6. Graduate to p=reject once your known critical flows pass DMARC consistently and unknown sources are clearly not yours.

The win condition is quiet: fewer spoofed messages get delivered, fewer users have to guess, and your email stops being a shared hallucination between senders and receivers.

← Previous
WordPress “Allowed memory size exhausted”: fix it for good
Next →
Proxmox storage “not available on node”: why it exists but you can’t use it

Leave a comment