Skip to content

DMARC Enforcement Migration — From p=none to p=reject in 90 Days

Going from no DMARC to p=reject all at once breaks your own legitimate mail. The 3-stage migration (none → quarantine → reject) is the safe path. This guide walks the 90-day plan, what to monitor at each stage, when to roll back.

Why staged migration

Jumping straight to p=reject (strict enforcement) is risky:

  • If your SPF or DKIM has any misconfigurations, your own mail gets rejected
  • Forwarded mail (newsletters → mailing lists → recipient inboxes) often fails SPF — sudden rejection means lost engagement
  • Third-party services that legitimately send-on-behalf (Salesforce, Marketo, AcelleMail itself) may not be in your SPF — sudden rejection breaks integrations

The staged migration: p=none (monitor) → p=quarantine (junk folder) → p=reject (bounce). 30 days at each stage. Validate before stepping up.

Stage 1: p=none (Days 0-30)

Publish:

TXT _dmarc.yourdomain.com  "v=DMARC1; p=none; rua=mailto:[email protected]; ruf=mailto:[email protected]; fo=1; pct=100"

What happens:

  • Receivers send you aggregate reports daily (via rua=) — each contains: SPF/DKIM pass rate per source IP, per sending domain
  • Failed messages still arrive in recipient inboxes — p=none doesn't enforce, just observes
  • You discover surprises: forgotten third-party senders, mis-aligned envelope-senders, broken DKIM signing

Monitor:

  1. Read the daily DMARC aggregate reports (XML files; use a parser)
  2. In AcelleMail, watch the bounce log for any 5.7.x DSN codes (auth issues):

Bounce log — DSN reasons

  1. Check your sending-server auth chips remain green:

The auth chips on the sending-server detail

Open Settings → Sending servers → click your active server. The toolbar shows the live SPF / DKIM / DMARC chip status:

Sending server detail with auth chips

  • Green chips on all three = receiving servers can confirm you're authorized to send from this domain.
  • Any chip red = receiving servers immediately downgrade reputation. Click Verify domain in the toolbar to walk through the DNS-fix wizard.

Validate before Stage 2:

  • DMARC pass rate ≥99% in aggregate reports (last 7 days)
  • No unauthorized "spoofing" sources in aggregate (all source IPs are recognized as yours)
  • No 5.7.x bounce-spike in AcelleMail

If pass rate <99%: investigate the failing sources before proceeding.

Stage 2: p=quarantine (Days 30-60)

Update to:

TXT _dmarc.yourdomain.com  "v=DMARC1; p=quarantine; rua=mailto:[email protected]; fo=1; pct=100"

What happens:

  • Failed-DMARC messages now go to recipient's Junk folder (not Inbox)
  • Legitimate but mis-aligned messages start visibly degrading — engagement drops on poorly-authenticated sources
  • Aggregate reports continue daily

Monitor:

  1. Pass rate should stay ≥99% (your fixes from Stage 1 took effect)
  2. AcelleMail's bounce log: 5.7.x rate should be near 0%
  3. Open rate / click rate on your campaigns — should be flat (not dropping due to junk-foldering)

Validate before Stage 3:

  • 14 consecutive days at pass rate ≥99.5%
  • No customer complaints about "missing emails" routed to spam
  • Aggregate reports show NO unauthorized sources

Stage 3: p=reject (Day 60+)

Update to:

TXT _dmarc.yourdomain.com  "v=DMARC1; p=reject; rua=mailto:[email protected]; fo=1; pct=100"

What happens:

  • Failed-DMARC messages are now BOUNCED — neither inbox nor junk
  • Maximum enforcement; phishing attempts using your domain hit the wall
  • Receiving servers reject at SMTP level (visible in your bounce log if you misconfigure)

Monitor:

  1. Pass rate should remain ≥99.5%
  2. Watch for any third-party-sender issues you missed (Salesforce, Mailchimp, etc. — if they send-as-you and weren't authorized)
  3. Customer complaint volume

This is the target state. BIMI requires this stage (or quarantine minimum) before logos display.

Rollback criteria

If at any stage:

  • DMARC pass rate <99% AND you can't identify the failing source
  • Customer complaints about "emails going to spam" spike
  • Critical third-party-sender stops working

Roll back to previous stage. Update DNS to previous p= value. Wait 24-48h for cache propagation.

Diagnose the failure, fix, then re-attempt the step-up.

Reading DMARC aggregate reports

Aggregate reports arrive at your rua= address as XML (often zipped). Sample:

<feedback>
  <policy_published>
    <domain>yourdomain.com</domain>
    <p>quarantine</p>
  </policy_published>
  <record>
    <row>
      <source_ip>54.240.0.10</source_ip>
      <count>1247</count>
      <policy_evaluated>
        <disposition>none</disposition>
        <dkim>pass</dkim>
        <spf>pass</spf>
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from>yourdomain.com</header_from>
    </identifiers>
    <auth_results>
      <dkim>
        <domain>yourdomain.com</domain>
        <result>pass</result>
      </dkim>
      <spf>
        <domain>yourdomain.com</domain>
        <result>pass</result>
      </spf>
    </auth_results>
  </record>
  ...
</feedback>

Parse via:

  • dmarcian.com (free tier)
  • dmarcanalyzer.com (free tier)
  • EasyDMARC (free trial + paid)
  • Postmark DMARC Digests (free; daily email digest)
  • Manual XML parse (DIY; possible but tedious)

The free / freemium tools show:

  • Per-source-IP send volume + pass rate
  • Unauthorized senders trying to use your domain (phishing attempts)
  • Per-recipient-domain breakdown (Gmail vs Outlook vs Yahoo)

Common DMARC migration issues

Symptom Likely cause Fix
Pass rate stuck at 90-95% in Stage 1 Third-party sender not in your SPF Add to SPF: include:vendor.com
Pass rate drops on weekends Weekly automation script sends from unauthorized IP Identify in aggregate report; whitelist or fix
AcelleMail sends pass; Mailchimp sends fail Mailchimp's DKIM doesn't sign with your domain Set up Mailchimp's "authenticate your domain" feature
Aggregate reports say "DKIM domain mismatch" DKIM signing different domain than From: header Ensure consistent domain alignment
Forwarded mail through old mailing-list fails Forwarders break SPF Move to DKIM-aligned sending OR set up ARC at the forwarder
Customer complaint: legitimate email in spam Premature p=quarantine step Roll back to p=none; investigate; resume

What pct= does

pct=50 applies the policy to 50% of failing messages, lets 50% through. Useful for gradual rollout within a stage:

Week 1 of p=quarantine: pct=10  (10% to junk, 90% to inbox)
Week 2: pct=25
Week 3: pct=50
Week 4: pct=100  (full quarantine)

If problems surface, dial back without losing the staged-rollout progress.

Advanced: subdomain DMARC policies + ARC for forwarding + multi-tenant DMARC at scale

Subdomain DMARC policies:

The apex _dmarc.brand.com record applies to ALL subdomains by default. To override per-subdomain:

TXT _dmarc.brand.com         "v=DMARC1; p=quarantine; sp=reject; ..."
                                                    ^^^^^^^^^^
                                                    Subdomain policy

The sp= parameter sets the subdomain policy. Useful for strict subdomain enforcement (transactional subdomain) while keeping the apex at quarantine.

For explicit per-subdomain DMARC:

TXT _dmarc.mail.brand.com  "v=DMARC1; p=quarantine"

Overrides whatever the apex DMARC says for mail.brand.com specifically.

ARC (Authenticated Received Chain) for forwarders:

When email is forwarded (e.g. recipient's filter forwards to another address), the original SPF + DKIM can break. ARC records the original auth state so the final receiver knows it was legit at the original hop.

ARC-Authentication-Results: i=1; ...
ARC-Seal: i=1; a=rsa-sha256; ...
ARC-Message-Signature: ...

If you operate a mailing list / forwarder, configure ARC on your relay. AcelleMail signs ARC automatically when relevant.

Multi-tenant DMARC at scale:

For SaaS platforms sending on behalf of many customers, each customer's domain needs its own DMARC. The platform doesn't manage customer DMARC directly — customers do — but the platform must:

  1. Provide each customer with proper SPF includes
  2. Ensure DKIM signing uses customer's domain
  3. Document the staged migration process (this article!) for customer guidance

Some platforms offer "managed DMARC" — paid feature where the platform monitors customer DMARC reports and adjusts policies.

DMARC monitoring automation:

#!/bin/bash
# Daily aggregate report processor
# Pulls DMARC reports from inbox, parses, aggregates pass-rate

mailbox_check_dmarc_reports
parse_xml_reports
calculate_pass_rate_last_24h

if [ $pass_rate -lt 99 ]; then
  notify_slack "DMARC pass rate dropped to $pass_rate% — investigate"
fi

if [ $pass_rate -ge 99 ] && [ "$current_policy" = "none" ] && [ $days_at_stage -ge 30 ]; then
  notify_slack "Stage 1 complete — ready to step up to p=quarantine"
fi

Phasing in pct= for ultra-conservative rollout:

Week 1: pct=5
Week 2: pct=10
Week 3: pct=25
Week 4: pct=50
Week 5: pct=75
Week 6: pct=100

12-week journey from p=none → p=reject with maximum conservatism. Reasonable for risk-averse industries (financial services, healthcare).

DMARC SaaS platforms:

If managing DMARC across 5+ domains:

  • EasyDMARC — comprehensive, $50-200/month
  • DMARCLY — budget-friendly, $20-100/month
  • Red Sift OnDMARC — enterprise, $200+/month
  • Postmark DMARC Digests — free; daily email summary

Most provide one-pane visibility + automated alerts + recommendations.

Related articles

16 bình luận

11 bình luận

  1. danrey.dev
    The SPF flattening explanation finally made it click for me. I'd been hitting the 10-lookup limit and didn't understand why nesting includes counted.
  2. v.petrova.ru
    Worth noting: our DNS provider (Cloudflare) caches negative responses for 1 hour. We added a TXT record, dig showed it, but mail-tester said missing for another 40 minutes. Almost lost our minds. TTL was set to 300 but the parent zone NS cache held
    1. admin
      Thanks for the detail — adding the kernel-reboot edge case to the article on the next update...
  3. i.rossi.mil
    Easy win: set up dmarcian.com (free tier) to receive your DMARC RUA reports. The first 2 weeks of reports tell you everything you didnt know about who's sending as you.
  4. tranminh.devop…
    Thanks for the explicit cautionary tales. The alignment-vs-pass distinction is exactly where I lost a week last year.
    1. admin
      Glad it landed. Drop suggestions in the comments and we'll incorporate them on the next refresh...
  5. hung.nguyen.it
    Hit the 10-lookup SPF limit when we tried to layer SES on top of an existing Google Workspace setup. Flattened with a tool (spfwizard.com) and it's been fine since. That tool's worth a mention...
  6. joel.anders.se
    How do you handle DNS for clients in white-label setups? The customer would need to add records to their domain — is there a clean way to bulk-verify those?
    1. admin
      good question — and one that comes up often enough we should add an faq section. short answer: yes for the common case; the exception is when youre running custom plugins that override the default behavior.
  7. linhpm.devs
    whats your recommendation for sub-domains? We send from mail.example.com AND notifications.example.com. Same DKIM selector or separate?
    1. admin
      good question. the campaign:rerun audit writes to laravel.log only when the audit decides to force-resume — pure noop runs are silent. we'll add an info-level heartbeat in a future acelle release to make it easier to monitor.
  8. aisha.khan.pak
    quick question: do receivers actually enforce the SPF -all hard fail, or do most just downrate? I've heard mixed things and I'm hesitant to switch from ~all
    1. admin
      We don't recommend that approach in production. It works in dev but has subtle race conditions under concurrent lad. Stick with the documented pattern
  9. priya.iyer.ops
    If you use Vercel or Netlify for the apex, watch out — they sometimes override TXT records via their auto-DNS feature. Bit us once with a stripped SPF record
  10. lucas.bernard.…
    dns setup is one of those things where you don't know what you don't know. this article should be required reading for anyone running their own mail.
  11. y.yamamoto
    Our DKIM rotation broke for 2 days because we updated the active selector first, then waited to delete the old. Should be the other way — publish new, wait 48h for cache, switch sending, THEN remove old.

More in DNS & Domain Setup