DMARC Troubleshooting: Diagnosing and Fixing DMARC Failures (SPF Permerror, DKIM Body Hash, Alignment, Forwarding)

A practitioner troubleshooting guide for DMARC failures: how to read aggregate (rua) reports and Authentication-Results headers, the 7 canonical DMARC failure patterns each mapped to a root cause and remediation, the SPF / DKIM / alignment failure classes with diagnostic commands, DNS record syntax pitfalls, forwarding and mailing-list breakage, mailbox-provider-specific quirks, and the complete diagnostic toolkit (dig commands, header analysis, postmaster portals).

This reference is provided in English. DMARC, SPF, and DKIM are specified in English-language RFCs (RFC 7489, RFC 7208, RFC 6376, RFC 8617, RFC 8601) and the canonical vocabulary (permerror, temperror, DKIM-Signature, Authentication-Results, 5321.From, 5322.From, cv=pass, "alignment", "envelope sender", "body hash") does not translate. We keep the body in the source language so technical terms remain consistent with the specifications.

TL;DR

  • DMARC failures fall into three root-cause classes: SPF failure (no authorized IP / lookup limit / syntax), DKIM failure (no signature / body hash mismatch / key not found), or ALIGNMENT failure (SPF and DKIM both verify but neither domain matches the From: header). The third is the single most common DMARC anomaly.
  • Read aggregate (rua) reports for the failure inventory. Every receiver emits a daily XML report describing which IPs produced which SPF / DKIM / alignment results. DMARC Analyzer ingests these via includes/DmarcParser.php and surfaces per-source-IP failure rates in the dashboard.
  • Read message headers for a single- message diagnosis. The Authentication-Results: header at the receiving MTA contains the verdict (spf=pass / dkim=fail / dmarc=fail) plus the matched domain. DMARC Analyzer's Email Header Analyzer (header_analyzer.php) parses this for you.
  • The 7 canonical failure patterns: (1) SaaS sender without custom-domain DKIM; (2) SPF 10-lookup permerror; (3) DKIM body modified by mailing list; (4) DKIM key not found (selector or DNS error); (5) DNS record at wrong name / duplicate TXT; (6) Forwarding breaks both SPF and DKIM; (7) Subdomain inheriting overly strict sp= policy.
  • SPF permerror is the silent killer. Exceeding 10 DNS lookups (RFC 7208 §4.6.4) makes every recipient return permerror and every message fail SPF. Fix by SPF flattening, consolidating senders, or DKIM-only auth.
  • Alignment failure looks like authentication failure. SaaS senders that sign with their own domain pass SPF and DKIM but fail DMARC. Enable custom-domain DKIM at every SaaS provider during DMARC rollout.
  • Forwarding is a known-failing path for DMARC at p=reject. Deploy ARC (RFC 8617) at the forwarding hop OR accept that mailing-list traffic will be refused.
  • Diagnostic commands: dig +short TXT _dmarc.example.com for the DMARC record, dig +short TXT example.com for the SPF record, dig +short TXT selector._domainkey.example.com for the DKIM public key, dig +short TXT _smtp._tls.example.com for the TLS-RPT record.

1. Reading the failure signal

DMARC failures surface through three distinct diagnostic channels. Each carries different information and demands a different troubleshooting workflow.

Channel 1 — Aggregate reports (rua=)

Daily XML reports from every major receiver (Google, Microsoft, Yahoo, Mail.ru, La Poste, plus DMARC reporting services such as Cloudflare and Postmark). Defined in RFC 7489 §7.2. Each report describes which sending IPs produced mail claiming to be from your domain during a 24-hour window, what SPF / DKIM / DMARC results each IP produced, and whether the receiver applied your published policy. The full schema walk-through is on the dedicated aggregate reports page.

What aggregate reports tell you:

  • WHO is sending mail using your domain (legitimate senders + spoofers).
  • WHICH IPs fail SPF, DKIM, or alignment.
  • HOW MANY messages were affected (volume per IP + result combination).
  • WHAT receiver action was taken (policy_evaluated.disposition).

What aggregate reports do NOT tell you:

  • The original message content (rua reports are privacy-preserving aggregates).
  • The specific recipients affected.
  • Which DKIM selector signed the message (only the result, not the signature header).

Channel 2 — Authentication-Results headers

Every receiving MTA stamps an Authentication-Results: header onto the message (RFC 8601). This header contains the receiver's verdict on SPF, DKIM, DMARC, and any ARC chain validation. Capture the full raw headers of a known-failing message — recipient forwards it to you, you check the spam folder, or you find it in your Sent Items — and read the receiver's verdict directly.

Example failure header:

Authentication-Results: mx.google.com;
       spf=pass (google.com: domain of bounces@em.sendgrid.net designates 168.245.21.20 as permitted sender)
       dkim=pass header.i=@sendgrid.net header.s=s1 header.b=AbC123
       dmarc=fail (p=REJECT sp=REJECT dis=REJECT) header.from=example.com

Reading: SPF passed authentication (the IP is authorized), DKIM passed cryptographically (the signature verifies), but DMARC failed because neither identifier ALIGNS with the From: header domain example.com — both used sendgrid.net instead. This is the canonical SaaS-sender-without-custom-domain-DKIM pattern from Section 3.

Channel 3 — User reports (missed mail)

The most operationally urgent signal: a user reports that legitimate mail did not arrive. Common phrasings during rollout: "my password reset email never came", "the partner says they sent the invoice but I do not see it", "newsletter subscribers are not receiving anything". This channel surfaces ENFORCEMENT consequences (legitimate mail blocked by the receiver) rather than visibility (aggregate-report data points). Workflow: collect the sender, the recipient, the approximate send time, the recipient's mailbox provider, and any bounce message the sender received — then correlate with aggregate reports from that receiver during that window.

2. The 7 canonical DMARC failure patterns

The keystone reference for this page: every DMARC failure observed in the wild maps to one of seven canonical patterns. Each pattern has a recognizable signature, a root cause, and a known remediation.

# Symptom Root cause Remediation
1 spf=pass, dkim=pass, dmarc=fail for a SaaS sender. SaaS signs DKIM with its own domain (sendgrid.net, mailgun.org). Envelope uses provider-bounce domain. Neither aligns with your From: header. Enable CUSTOM-DOMAIN DKIM at the SaaS provider. Both SaaS providers publish documentation on the CNAME / TXT records required.
2 spf=permerror on every message, regardless of sending IP. SPF record exceeds the 10-DNS-lookup limit (RFC 7208 §4.6.4). Common when you add too many include: directives. SPF FLATTENING (replace include: chains with explicit ip4: ranges), or consolidate to fewer senders, or rely on DKIM for alignment.
3 dkim=fail with "body hash did not verify". Message body modified in transit — mailing list footer, antivirus banner, security gateway annotation. The signature verifies but the body hash no longer matches. Switch to c=relaxed/relaxed canonicalization. Remove the modifying middlebox. Deploy ARC (RFC 8617) so downstream receivers see the pre-modification verdict.
4 dkim=permerror or "key not found in DNS". DKIM selector record missing or malformed at selector._domainkey.example.com. Common after a key rotation that missed the public-key DNS publish step, or a typo in the selector name. Verify with dig +short TXT selector._domainkey.example.com. Republish the public key. Check the p= base64 value matches the signing private key.
5 "No DMARC record found" despite the operator publishing one. Record published at example.com instead of _dmarc.example.com; OR multiple TXT records at _dmarc.example.com (RFC 7489 §6.6.3 says any count != 1 disables DMARC); OR DNS panel fragmented the long record. Verify with dig +short TXT _dmarc.example.com from an external resolver (dig @1.1.1.1). Must return exactly one record starting with v=DMARC1.
6 Forwarded mail fails DMARC at p=reject while direct mail passes. Forwarding rewrites the envelope MAIL FROM (breaking SPF — the forwarder's IP is not in your SPF record). Mailing list modifies the body (breaking DKIM body hash). Deploy ARC (RFC 8617) at the forwarding hop. Or use SRS at the forwarder so SPF aligns. Or accept forwarded mail is a known-failing path.
7 Subdomain mail fails DMARC even though the apex passes. The sp= tag inherits a stricter policy to all subdomains without those subdomains having their own SPF / DKIM. Common with marketing subdomains (mailings.example.com) that send via a SaaS without custom-domain auth. Either publish a SUBDOMAIN-specific DMARC record at _dmarc.subdomain.example.com with the appropriate policy, or fix the SPF / DKIM at the subdomain to meet the sp= policy.

Patterns 1 and 2 account for roughly 60 percent of observed DMARC failures in the wild — SaaS-sender alignment plus SPF lookup overflow. Pattern 3 (DKIM body hash) accounts for most of the remainder. Patterns 4 through 7 are edge cases that nevertheless block specific user-visible mail flows and must be diagnosed individually.

3. SPF root causes

SPF failures fall into a small number of distinct categories. Each has a recognizable signature in aggregate reports and message headers.

SPF permerror (the 10-DNS-lookup ceiling)

Defined in RFC 7208 §4.6.4. Every include:, a, mx, ptr, exists, and redirect counts as one lookup. Nested includes count recursively. Once the lookup count exceeds 10, the receiver returns permerror for every message and DMARC's SPF authentication input is permanently broken until the record is fixed.

Common causes of overflow: layered SaaS deployments (each include: adds 1-3 lookups), legacy on-prem MTAs still in the record after migration, redundant ranges that already overlap a SaaS include:. Diagnose with the Domain Security Checker (domain_checker.php) which reports the exact lookup count alongside the record syntax.

Fix options ranked by maintainability:

  1. Audit and remove stale includes (often half the includes were added for a project that has since migrated elsewhere). Try this first.
  2. SPF flattening — a flattening service (e.g. SPF macros + a managed DNS provider) replaces include: chains with explicit ip4:/ip6: ranges so each include becomes a single zero-lookup mechanism. Costs money and adds a vendor dependency.
  3. Consolidate senders — move from multiple SaaS providers to one. Each provider removed reclaims at least one include: slot.
  4. Rely on DKIM — for low-volume senders that you cannot flatten, accept SPF none / permerror and ensure DKIM aligns. DMARC passes if EITHER SPF or DKIM aligns; you do not need both.

SPF temperror

Transient DNS failure — the receiver could not resolve a name in the SPF record (SERVFAIL, timeout, recursive resolver limit). Most receivers treat temperror as none, meaning DMARC falls back to DKIM. Diagnose by checking your authoritative nameservers for the failing record, then your nameserver provider's status page. Recurring temperror indicates an unreliable nameserver and warrants a provider conversation.

SPF none (no SPF record published)

Means the domain in the envelope MAIL FROM (the 5321.From) has no SPF record. Two cases. First, the sender ACTUALLY has no SPF — publish one. The SPF record generator in DNS Record Generator builds a syntactically-correct record for your inventory of senders. Second, you THOUGHT you had SPF but the envelope sender uses a different domain than the From: header (typical of SaaS bounce-domain delegation). In that case, SPF is present on the bounce domain but does not align with your From: — fix by enabling custom-domain DKIM instead.

SPF softfail (~ qualifier)

The IP is not authorized, but the sender requested the message be delivered anyway (probably to spam). DMARC treats softfail and fail equivalently — both produce an spf=fail result. The ~all default at the end of most SPF records is a transitional safety setting; once your SPF is accurate, tighten to -all (hardfail).

SPF passes authentication but does not align

The envelope MAIL FROM has SPF authorization for the sending IP, but the envelope domain (5321.From) does not match the visible From: header domain (5322.From) under the aspf alignment mode. Pattern 1 from Section 2. Most common with SaaS senders using provider bounce domains. The alignment deep dive walks through this in detail.

4. DKIM root causes

DKIM failures fall into four categories: missing signature, key not found, body hash mismatch, and signature verification failure. Each has a distinct diagnostic signature.

No DKIM-Signature header present

Receiver result: dkim=none. The message has no DKIM-Signature header at all — the sending MTA did not sign the message. Common causes: the SaaS sender requires explicit DKIM activation in the dashboard; on-prem MTA signing not configured; automated job using a third-party email API without DKIM enabled. Fix at the source: enable DKIM signing for the sending domain. Defined in RFC 6376 §3.5.

DKIM key not found (selector lookup failure)

Receiver result: dkim=permerror with "key not found in DNS". The DKIM-Signature header carries the selector (s=) and signing domain (d=); receivers look up {selector}._domainkey.{d} for the public key. If that name has no TXT record, DKIM cannot verify. Common after a key rotation that forgot to publish the new public key, or a typo in the selector name.

Diagnose with:

dig +short TXT selector._domainkey.example.com

Expected response: "v=DKIM1; k=rsa; p=MIIBIjANBgkq...". No response means the record does not exist publicly — republish it.

DKIM body hash did not verify

Receiver result: dkim=fail with "body hash did not verify". The DKIM-Signature includes a bh= tag containing a base64-encoded hash of the message body canonicalized per the c= canonicalization mode. The receiver re-canonicalizes the body as received and compares the hashes — mismatch means the body changed in transit.

Body modification sources:

  • Mailing lists appending a footer ("To unsubscribe, click here") or rewriting subject prefixes.
  • Antivirus / security gateways adding a banner ("EXTERNAL: This email originated outside the organization") or replacing links with click-tracker URLs.
  • Transfer encoding rewrites — quoted-printable to 8bit, line-ending normalization on a misbehaving MTA.
  • Strict canonicalization (c=simple/simple) that fails on innocuous whitespace differences.

Remediation: switch to c=relaxed/relaxed (the recommended and most tolerant), eliminate the modifying middlebox if possible, or deploy ARC at the modifying hop so the original DKIM verdict is preserved for downstream receivers.

DKIM signature verification failed

Receiver result: dkim=fail with "signature did not verify". The body hash matched (body intact) but the RSA / Ed25519 signature itself failed to verify against the published public key. Causes: the public key was rotated but the private key on the signing MTA was not updated (or vice versa); the published key uses a different algorithm than the signing key; key corruption during a copy-paste publish.

Fix by re-deriving the public key from the signing private key and republishing the DNS record. The DNS Record Generator (dns_generator.php) builds a syntactically-correct DKIM record once you provide the public-key material.

DKIM passes but does not align

Pattern 1 from Section 2. The DKIM-Signature d= tag does not match the From: header domain under the adkim alignment mode. The signature verifies — DKIM has done its job — but DMARC alignment fails. Fix by enabling custom-domain DKIM at the sender so the d= tag matches your domain.

5. Alignment root causes

Alignment is the difference between AUTHENTICATION (SPF and DKIM both verify cryptographically) and DMARC (the verified domain matches the visible From: header). The alignment deep dive covers the full concept; this section documents the failure modes you see in practice.

SaaS senders signing with their own domain

Pattern 1, the dominant cause of DMARC failures in the field. SendGrid, Mailgun, Postmark, Marketo, HubSpot, ServiceNow, Zendesk, Salesforce, ActiveCampaign — all default to signing DKIM with their own domain (sendgrid.net, mailgun.org, postmarkapp.com) until you complete a custom-domain DKIM onboarding step. Until then DKIM passes (the signature verifies for sendgrid.net) but does not align with your example.com From: header.

Remediation is provider-specific but follows a common shape: log into the SaaS dashboard, navigate to "Sending Authentication" or "Domain Authentication", enter your sending domain, and publish the CNAME or TXT records the provider issues. The provider's signing MTA then uses your domain in the d= tag, aligning DKIM with the From: header.

Provider bounce-domain breaks SPF alignment

SaaS providers rewrite the envelope MAIL FROM (5321.From) to a provider-controlled address (e.g. bounces@em.sendgrid.net) so they can receive bounce-back notifications. SPF passes because em.sendgrid.net authorizes the SaaS-owned IP; but the envelope domain (em.sendgrid.net) does not align with the visible From: header (example.com) under the aspf mode. Fix by enabling custom bounce-domain delegation at the SaaS (a subdomain of your domain, e.g. bounces.example.com, that CNAMEs to the provider's bounce infrastructure).

Subdomain From: header without aligned auth

Marketing teams send from marketing.example.com via a SaaS that signs with sendgrid.net. The _dmarc.example.com record applies via sp= inheritance, mail fails alignment, and gets rejected once you publish sp=reject. Fix by either publishing a permissive _dmarc.marketing.example.com record overriding the apex sp=, or fixing the SaaS to sign with marketing.example.com (or example.com — strict alignment vs relaxed determines whether the parent organizational domain counts).

Header From: rewrites by middleboxes

Rare but devastating: some legacy security gateways rewrite the From: header on incoming mail (e.g. inserting a display name). Authentication-Results headers may be stripped or replaced by the gateway. ARC (RFC 8617) is designed to defend against this — the gateway seals the pre-rewrite verdict so the downstream receiver can trust it.

6. DNS record syntax errors

A surprisingly large fraction of "DMARC not working" reports trace back to a syntactically- invalid record at the DNS layer — invisible to the operator who published it but invisible to receivers too.

Wrong record location

DMARC records live at _dmarc.example.com, not at example.com. SPF lives at example.com (the apex), not at _spf.example.com. DKIM lives at {selector}._domainkey.example.com. BIMI lives at default._bimi.example.com. MTA-STS advertisement lives at _mta-sts.example.com (with the policy file at https://mta-sts.example.com). Publishing at the wrong name is the single most common DNS-level error.

Multiple TXT records at the same name

RFC 7489 §6.6.3 requires receivers to treat any DMARC name with two or more v=DMARC1 TXT records as if no DMARC record exists. The same rule applies to SPF (RFC 7208 §4.5). Some DNS panels publish the long record fragmented across two TXT entries; some operators leave an old DMARC record behind when adding a new one. Both produce silent DMARC disablement.

Diagnose with:

dig +short TXT _dmarc.example.com

Must return EXACTLY ONE quoted string starting with v=DMARC1. Two or more responses, or one fragmented response with no DMARC1 prefix, means receivers see no DMARC.

Long TXT record RDATA quoting

DNS TXT RDATA limits a single quoted string to 255 characters; longer records must be split into multiple quoted strings concatenated by the resolver. Some DNS panels handle this automatically; some require manual splitting. A DKIM public key longer than 255 bytes published without proper quoting produces an invalid record. Verify with dig +short TXT — the output should show multiple quoted strings on the same line, which dig concatenates.

Trailing whitespace and embedded newlines

Some DNS panels accept multi-line input and preserve embedded newlines literally — the record value becomes "v=DMARC1;\np=none;..." and receivers cannot parse it. Always paste the record on a single line.

DNS TTL and propagation delay

After publishing a new DMARC / SPF / DKIM record, receivers continue to use the cached old record (or cached NXDOMAIN) until the previous record's TTL expires. Default TTLs are typically 1 hour to 1 day. Before declaring "DMARC not working", confirm the record propagated by querying an external resolver (dig @1.1.1.1 or dig @8.8.8.8).

7. Forwarding and mailing lists

Forwarding is the canonical hard case for DMARC. Plain forwarding (mailbox-level forwarding rule) breaks SPF because the forwarding server's IP is not in the original sender's SPF record. Mailing lists break DKIM because they modify the body (footer, unsubscribe link, subject prefix). Once you publish p=reject, every forwarded copy that fails BOTH SPF and DKIM alignment is refused at the receiver.

The three remediation strategies

Ranked by completeness:

  1. ARC (RFC 8617) — the forwarding hop seals the pre-modification authentication result for downstream receivers. The receiver validates the ARC chain (cv=pass) and, if the sealing entity is trusted (e.g. Gmail trusts a known-good mailing list), uses the sealed verdict instead of the post-modification verdict. The ARC deep dive covers the full mechanism.
  2. SRS (Sender Rewriting Scheme) at the forwarder — the forwarder rewrites the envelope MAIL FROM to one that points back to the forwarder's domain, so SPF aligns with the new envelope domain. The forwarder accepts the bounces. Solves SPF but not DKIM body modification.
  3. Accept forwarding as a known-failing path at p=reject — educate users to subscribe to high-value mailing lists with personal addresses, publish operational documentation that mailing-list forwarding may fail under DMARC, accept the user-friction cost.

Receiver-specific behavior

Major mailbox providers (Gmail, Outlook, Yahoo) trust major ARC sealers (other major mailbox providers, some well-known mailing list operators). A message ARC-sealed by a recognized sealer with cv=pass can pass DMARC at the final receiver even though the post-modification SPF and DKIM both fail. Less well-known forwarders may not be trusted as ARC sealers; their seals are evaluated but do not override the post-modification verdict.

8. Mailbox-provider-specific issues

Every mailbox provider implements DMARC consistently with RFC 7489, but each surfaces different operational diagnostics and has quirks worth knowing.

Google (Gmail / Google Workspace)

Google publishes Postmaster Tools (postmaster.google.com) with per-domain spam rate, IP / domain reputation, feedback loop signals, and authentication breakdown. Google's Authentication-Results header is the most informative in the industry — it explicitly lists the matched domain for SPF (spf=pass smtp.mailfrom=) and DKIM (dkim=pass header.i=) so alignment is easy to verify. The DMARC for Google Workspace deployment guide covers the Workspace-specific setup. As of February 2024, Google enforces DMARC for any domain sending more than 5000 messages per day to gmail.com.

Microsoft (Outlook.com / Microsoft 365 / Exchange Online)

Microsoft uses CNAME-based DKIM with two selectors (selector1 / selector2) for automatic key rotation. The most common M365 DMARC failure is the onmicrosoft.com signing pattern: if you have not enabled custom-domain DKIM in the Microsoft 365 Defender portal, Exchange Online signs outbound mail with tenant.onmicrosoft.com instead of your domain, and DKIM never aligns. The DMARC for Microsoft 365 deployment guide walks through the Set-DkimSigningConfig PowerShell workflow.

Microsoft also publishes SNDS (Smart Network Data Services) for sending-IP reputation and JMRP (Junk Mail Reporting Program) for feedback loop signals. Both are required operational signals for high-volume senders.

Yahoo / AOL (Verizon Media Group)

Yahoo was the FIRST major mailbox provider to enforce strict DMARC on consumer addresses (publishing p=reject for yahoo.com / aol.com in 2014), which broke many mailing lists overnight and motivated the ARC standard. Yahoo's enforcement bar follows Google's lead — as of February 2024, Yahoo enforces DMARC for high-volume senders.

Mail.ru and Yandex (Russian providers)

Both implement DMARC and emit aggregate reports. Authentication-Results headers are in English. Reporting destinations sometimes drop rua= mail; check that your reporting destination is not blacklisted at these providers.

ProtonMail / Tutanota / privacy-focused providers

Enforce DMARC strictly. ProtonMail end-to-end encrypts message bodies, so DKIM body modification is rare (encrypted blob transits unchanged). Authentication-Results headers are present and informative.

9. Diagnostic toolkit

The minimum set of tools and commands every DMARC operator should keep within reach.

Command-line DNS queries

# DMARC record
dig +short TXT _dmarc.example.com

# SPF record (TXT at the apex)
dig +short TXT example.com | grep -i spf

# DKIM public key (replace selector with the value from the DKIM-Signature s= tag)
dig +short TXT selector._domainkey.example.com

# BIMI record
dig +short TXT default._bimi.example.com

# MTA-STS advertisement record
dig +short TXT _mta-sts.example.com

# TLS-RPT record
dig +short TXT _smtp._tls.example.com

# CAA records (CA authorization)
dig +short CAA example.com

# Query from a specific public resolver to bypass local caching
dig @1.1.1.1 +short TXT _dmarc.example.com

DMARC Analyzer integrated tools

  • Domain Security Checker — live DNS lookups for DMARC, SPF, DKIM, BIMI, MTA-STS, TLS-RPT, and CAA in one report. Includes SPF lookup count for the 10-DNS-lookup limit.
  • Email Header Analyzer — paste any message's full headers and see SPF, DKIM, DMARC results, ARC chain validation, and alignment evaluation. Built on includes/EmailHeaderParser.php.
  • DNS Record Generator — generate syntactically-correct DMARC, SPF, DKIM, BIMI, MTA-STS, TLS-RPT, and CAA records from a guided wizard.
  • Blacklist Checker — check sending IPs against major RBLs / DNSBLs. Poor IP reputation drives spam-folder placement even with DMARC pass.

Aggregate-report ingestion

DMARC Analyzer ingests aggregate (RUA) reports via includes/DmarcParser.php (RFC 7489 §7.2 schema) and surfaces per- source-IP failure rates in the dashboard. Publish rua=mailto:dmarc-reports@example.com and forward the reports into the platform via the upload UI or IMAP / Microsoft Graph ingestion (includes/ImapFetcher.php / includes/GraphFetcher.php). Forensic (RUF) failure reports per RFC 6591 are parsed by includes/ForensicReportParser.php when the receiver supports ruf= emission.

Mailbox-provider postmaster portals

  • Google Postmaster Tools (postmaster.google.com) — domain / IP reputation, spam rate, authentication breakdown.
  • Microsoft SNDS (sendersupport.olc.protection.outlook.com/snds) — IP-level data for Microsoft 365 / Outlook.com.
  • Microsoft JMRP — junk mail reporting program (feedback loop).

10. Troubleshooting best practices

  1. Read aggregate reports weekly. Anomalies appear as new failing sources or volume spikes. A weekly cadence catches misconfigurations within days of introduction.
  2. Capture full raw headers for every user-reported missed-mail incident. Forwarded message body without headers is unactionable.
  3. Distinguish authentication failure from alignment failure early in every diagnosis. They have different fixes.
  4. Verify DNS from an external resolver (dig @1.1.1.1) before concluding a record is broken. Local caching masks DNS issues.
  5. Audit the SPF lookup count proactively. The 10-DNS-lookup limit is silent — you can be at 11 lookups and not know until aggregate reports show universal spf=permerror.
  6. Enable custom-domain DKIM at every SaaS sender during onboarding, not later. Retrofitting alignment after you publish p=reject is incident-grade work.
  7. Maintain a sending-source inventory. Every SaaS, every on-prem MTA, every automated job. Without the inventory you cannot reason about which failures matter.
  8. Test new senders at p=none first. A new SaaS deployment at p=reject in the apex record can drop legitimate mail on day one.
  9. Document mailing-list / forwarding as a known-failing path. Operations teams hit this question repeatedly; a written stance saves cycles.
  10. Run the Domain Security Checker monthly. Records drift — someone adds an include:, someone publishes a stale DKIM key. The checker catches drift early.

11. Common diagnostic mistakes

  1. Treating SPF pass + DKIM pass as "DMARC must be fine". Alignment is a separate check — both can pass authentication while neither aligns. See Pattern 1.
  2. Publishing the DMARC record at the apex (example.com) instead of at _dmarc.example.com. Receivers look at the underscore-prefixed name only.
  3. Leaving a second DMARC TXT record in place after editing — both the old and new are returned, the receiver disables DMARC.
  4. Trusting that "the DNS panel saved the record" without verifying with dig. Some panels save records with embedded newlines, trailing whitespace, or wrong record type.
  5. Skipping aggregate-report review because rua= is published and reports are being received. Receiving reports is necessary but not sufficient — reading them is the operational work.
  6. Diagnosing a single failing message without capturing the full raw headers. Body-only or summary-only information rules out 80 percent of diagnostic paths.
  7. Jumping straight to p=reject without clearing failures observed under p=none — see the rollout page.
  8. Assuming forwarding will "just work" under p=reject. Forwarding is a known-failing path; plan ARC, SRS, or acceptance.
  9. Adding senders to SPF without checking the lookup count. Each new include: nudges you toward the permerror ceiling.
  10. Confusing 5321.From with 5322.From. SPF authenticates the envelope (5321); DKIM signs the body and verifies a signature carrying a d= tag; DMARC alignment compares against the visible From: header (5322). The alignment deep dive walks through the distinction.

12. Frequently asked questions

Why is my DMARC failing even though SPF and DKIM pass?
This is the single most common DMARC question and almost always indicates an ALIGNMENT failure rather than an authentication failure. SPF passes when the envelope MAIL FROM (5321.From) matches an authorized IP. DKIM passes when the DKIM-Signature verifies cryptographically. DMARC additionally requires that the domain used by SPF and/or DKIM ALIGNS with the visible From: header domain (5322.From). A SaaS sender that signs DKIM with sendgrid.net and uses bounces@em.sendgrid.net as the envelope passes both SPF and DKIM but FAILS DMARC because neither identifier aligns with your@example.com in the From: header. Fix by enabling custom-domain DKIM at the SaaS sender.
What does SPF permerror mean and how do I fix it?
SPF permerror is a permanent error in SPF evaluation, almost always caused by exceeding the 10-DNS-lookup limit defined in RFC 7208 §4.6.4. Every include:, a, mx, ptr, exists, and redirect mechanism counts as one DNS lookup. Nested include directives count recursively. Once your record requires 11 or more lookups, every recipient returns permerror and DMARC fails because SPF cannot produce a usable verdict. Fix by SPF flattening (replacing include: chains with literal ip4:/ip6: ranges using a flattening service), consolidating SaaS senders, or moving low-volume senders to DKIM-only authentication.
What does DKIM body hash mismatch mean?
DKIM body hash mismatch means the message body the receiver sees does not match the body hash (bh= tag) recorded in the DKIM-Signature when the message was signed. The signature itself may verify but DKIM still fails because the body changed in transit. Root causes: a mailing list appended a footer or unsubscribe link; an antivirus / security gateway modified the body (added a banner); the canonicalization mode is too strict (c=simple/simple cannot survive whitespace changes); the message was transcoded from quoted-printable to 8bit. Fix by using c=relaxed/relaxed canonicalization, removing modifying middleboxes, or deploying ARC (RFC 8617) so downstream receivers see the original DKIM verdict preserved across the modifying hop.
My DMARC record looks correct but receivers say no DMARC record found. Why?
Three common causes. (1) The TXT record is published at the wrong name: DMARC records live at _dmarc.example.com, not at the apex example.com. (2) Multiple TXT records at _dmarc.example.com — RFC 7489 §6.6.3 mandates that receivers treat multiple DMARC TXT records as if no record exists. Some DNS panels publish a fragmented record across two TXTs without warning. (3) DNS TTL not yet expired and a stale negative cache exists at the receiver. Verify with dig +short TXT _dmarc.example.com from an external resolver (e.g. dig @1.1.1.1) — if you see zero or two records, the problem is at your DNS panel; if you see one correct record, wait for the TTL.
How do I troubleshoot a single failing message from an aggregate report?
Aggregate (RUA) reports are sampled — they tell you which IP/result combinations are failing in aggregate, but they do not contain the original message. To debug a specific message: (1) identify the failing sender IP and result combination in the aggregate report; (2) check inside your sending estate (SaaS dashboards, on-prem MTA logs) for a message sent from that IP during the report-date window; (3) capture the full raw RFC 5322 headers — From:, DKIM-Signature:, Authentication-Results:, Return-Path:; (4) feed the headers into DMARC Analyzer's Email Header Analyzer (header_analyzer.php) which decodes SPF, DKIM, DMARC alignment, and the ARC chain for that specific message.
Why does my mail land in spam even though DMARC passes?
DMARC pass does not guarantee inbox placement. DMARC only verifies that the From: header domain is authorized; receivers still apply content-based spam scoring, reputation scoring, engagement scoring, and provider-specific signals. Pass plus poor reputation equals spam folder. Diagnostic checklist: (1) sending IP reputation (RBL/DNSBL listings — use the Blacklist Checker); (2) sender domain reputation (Google Postmaster Tools, Microsoft SNDS); (3) authenticated FBL signals (high spam complaint rate); (4) reverse DNS / PTR record matches the HELO hostname; (5) BIMI deployed and a valid VMC published; (6) content triggers (excessive caps, suspicious links, missing List-Unsubscribe header).
What is the difference between SPF temperror and SPF permerror?
SPF temperror is a TRANSIENT failure (DNS server returned SERVFAIL or a timeout) — the receiver may retry and SPF may eventually pass. Most receivers treat temperror as neutral, meaning DMARC falls back to DKIM. SPF permerror is a PERMANENT failure (record syntactically invalid, exceeded 10-lookup limit, contains a deprecated mechanism like ptr) — every recipient returns permerror until you fix the record. Permerror is a DMARC-fail signal because it indicates the sender owner published a broken record. Diagnose with: dig +short TXT example.com | grep spf1 plus an online SPF validator that counts lookups (we recommend running the Domain Security Checker at domain_checker.php).
Why does forwarded mail fail DMARC after I enable p=reject?
Forwarding breaks SPF (the forwarding server's IP is not in the original sender's SPF record) and can break DKIM (mailing lists modify the body, breaking the body hash). Once you publish p=reject, every forwarded copy that fails both SPF and DKIM alignment is refused — affecting users who forward from corporate to personal mailboxes, mailing list subscribers, and security gateways with mail rewriting. Three remediations: (1) deploy ARC (RFC 8617) so the forwarding server can preserve the original authentication result for downstream receivers; (2) ask the forwarding service to use SRS (Sender Rewriting Scheme) so SPF still aligns; (3) accept that mailing-list forwarding is a known-failing path under strict DMARC and educate users to subscribe with personal addresses for high-value list traffic.

14. Diagnose your DMARC issue now

DMARC Analyzer ingests aggregate (rua) reports via the includes/DmarcParser.php pipeline and surfaces per-source-IP failure rates in the dashboard — the inventory you need to root-cause Patterns 1, 2, and 7 from Section 2. The Email Header Analyzer (header_analyzer.php, built on includes/EmailHeaderParser.php) decodes individual failing messages for Patterns 3, 4, and 6. The Domain Security Checker (domain_checker.php, built on includes/DnsChecker.php) runs live DNS queries for Pattern 5 diagnostics including the exact SPF lookup-count.

Check my domain configuration Sign up — Free plan