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.phpand 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.comfor the DMARC record,dig +short TXT example.comfor the SPF record,dig +short TXT selector._domainkey.example.comfor the DKIM public key,dig +short TXT _smtp._tls.example.comfor 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:
- Audit and remove stale includes (often half the includes were added for a project that has since migrated elsewhere). Try this first.
- 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.
- Consolidate senders — move from multiple SaaS providers to one. Each provider removed reclaims at least one include: slot.
- Rely on DKIM — for
low-volume senders that you cannot
flatten, accept SPF
none/permerrorand 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:
- 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. - 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.
- 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
- Read aggregate reports weekly. Anomalies appear as new failing sources or volume spikes. A weekly cadence catches misconfigurations within days of introduction.
- Capture full raw headers for every user-reported missed-mail incident. Forwarded message body without headers is unactionable.
- Distinguish authentication failure from alignment failure early in every diagnosis. They have different fixes.
- Verify DNS from an external
resolver
(
dig @1.1.1.1) before concluding a record is broken. Local caching masks DNS issues. - 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. - Enable custom-domain DKIM at every SaaS sender during onboarding, not later. Retrofitting alignment after you publish p=reject is incident-grade work.
- Maintain a sending-source inventory. Every SaaS, every on-prem MTA, every automated job. Without the inventory you cannot reason about which failures matter.
- 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.
- Document mailing-list / forwarding as a known-failing path. Operations teams hit this question repeatedly; a written stance saves cycles.
- 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
- 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.
- Publishing the DMARC record at
the apex (example.com) instead
of at
_dmarc.example.com. Receivers look at the underscore-prefixed name only. - Leaving a second DMARC TXT record in place after editing — both the old and new are returned, the receiver disables DMARC.
- 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.
- 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.
- Diagnosing a single failing message without capturing the full raw headers. Body-only or summary-only information rules out 80 percent of diagnostic paths.
- Jumping straight to
p=rejectwithout clearing failures observed underp=none— see the rollout page. - Assuming forwarding will "just work" under p=reject. Forwarding is a known-failing path; plan ARC, SRS, or acceptance.
- Adding senders to SPF without checking the lookup count. Each new include: nudges you toward the permerror ceiling.
- Confusing
5321.Fromwith5322.From. SPF authenticates the envelope (5321); DKIM signs the body and verifies a signature carrying ad=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.