Forwarding Issues with SPF Explained: Why Forwarding Breaks SPF, the Four Canonical Scenarios, SRS, ARC, and Mailing-List Mitigations (RFC 7208 section 10.3 + RFC 8617)
A focused operational deep dive on the #1 reason SPF breaks in production: forwarding. SPF authenticates the FIRST SMTP hop only (RFC 7208 section 10.3) and every forwarding scenario — transparent SMTP-level forwarding, user-level rules, mailing list expansion, third-party forwarders — introduces a SECOND SMTP hop that the original senders SPF record cannot authorise. Documents the four canonical forwarding scenarios, the Sender Rewriting Scheme (SRS) that fixes forwarding at the forwarder side, the Authenticated Received Chain (ARC, RFC 8617) that fixes it at the receiver side, mailing-list mitigations including From-header munging and ARC sealing for Mailman 3 / Discourse / Google Groups / GitLab, the detection workflow in DMARC aggregate (RUA) reports, the four canonical operational fixes ranked by deployment scope, a per-symptom troubleshooting decision matrix, and real-world examples. Differentiation from the sibling SPF pillar: the pillar gives a brief overview of the forwarding edge case in its limitations section; this page is the focused operational deep dive operators need when debugging a live forwarding-related SPF fail in production.
This reference is provided in English. SPF + SRS + ARC are specified in English-language RFCs (RFC 7208, RFC 8617, and the OpenSPF SRS informational draft) and the canonical vocabulary (SRS, ARC-Seal, ARC-Message-Signature, ARC-Authentication-Results, Authenticated Received Chain, From-header munge, MAIL FROM, return-path, dmarc_mitigate_action) does not translate. We keep the body in the source language so technical terms remain consistent with the specifications.
TL;DR
- SPF authenticates the FIRST SMTP hop only. Defined in RFC 7208 section 10.3, SPF checks the connecting SMTP clients IP against the MAIL FROM domains authorised IP list. Any second hop (forwarding, mailing list expansion, third-party forwarders) is a NEW SMTP connection from a different IP and the SPF check fails by design.
- Four canonical forwarding scenarios break SPF: (1) transparent SMTP-level forwarding (.forward files, server aliases, /etc/aliases), (2) user-level forwarding via sieve / Outlook rules / Gmail filter forwarding, (3) mailing list expansion (Mailman 3, Discourse, Google Groups, Sympa, GitLab), (4) third-party forwarding services (iCloud Mail Drop, Hide My Email, Gmail Fetcher, ProtonMail forwarding, FastMail rules).
- Sender Rewriting Scheme (SRS) is the forwarder-side operational fix. SRS rewrites the SMTP MAIL FROM at the forwarder so the receiving SPF check authenticates the forwarder, not the original sender. Implemented in Postfix (postsrsd), Exim (native), Sendmail, and Exchange 2007+.
- Authenticated Received Chain (ARC, RFC 8617) is the receiver-side answer: intermediaries cryptographically attest to the SPF / DKIM / DMARC verdicts they observed BEFORE forwarding, and trusted-intermediary verdicts can override downstream SPF or DKIM failures. ARC is validated by Gmail, Microsoft 365, Yahoo, AOL, Comcast, and Apple.
- Mailing lists need From-header MUNGE OR ARC sealing. Modifying the message body (footer, list-id header, expanded attachments) breaks the original DKIM signature — so neither SPF nor DKIM authenticates the original senders domain anymore. Mailman 3 + GNU Mailman dmarc_mitigate_action support munge_from and wrap_message modes; modern deployments prefer ARC sealing where downstream receivers validate it.
- DMARC alignment can survive transparent forwarding when the forwarder does NOT modify the message body and DKIM still passes. This is the dominant case for .forward and /etc/aliases: SPF fails, DKIM passes (body unchanged), DMARC aligns via DKIM. The break case is content-rewriting forwarders.
- Detection in DMARC aggregate (RUA) reports: watch for low-volume, high-IP- diversity records where spf=fail and source IP belongs to known forwarding-service ASNs (iCloud, Gmail, Microsoft 365, Mailman list servers). The DMARC Analyzer Top Source IPs table surfaces these patterns; click any record to see the per-message SPF / DKIM verdict breakdown.
- Operational rule of thumb: do NOT try to authorise every forwarder in your SPF record (infeasible at scale — the 10- lookup cap of RFC 7208 section 4.6.4 bounds the include count). Instead publish a permissive DMARC policy initially (p=none with rua=mailto:dmarc@example.com), monitor the forwarding traffic, and graduate to p=quarantine pct=10 → p=quarantine pct=100 → p=reject only after you have ARC-validating receivers handling the bulk of legitimate forwarded mail.
1. Overview: why forwarding is the operational #1 SPF complaint
Sender Policy Framework (SPF), defined in
RFC 7208,
authenticates email by binding the SMTP envelope
senders domain (the
MAIL FROM bounce address) to an
authorised list of sending IP addresses published
as a DNS TXT record. Every receiver opens the
SMTP connection, reads the
MAIL FROM command, performs a DNS
lookup for the SPF record at that domain, and
checks whether the connecting clients IP is on
the authorised list. The model is elegant for
direct point-to-point email — a message sent from
Microsoft 365 to a Gmail user takes exactly one
SMTP hop and SPF authenticates that hops IP.
But the moment a message is FORWARDED, the model
breaks. Forwarding by definition introduces a
SECOND SMTP hop: a new TCP connection from a new
IP address, opened by the forwarding server to
the receiving server. The receivers SPF check
still tests the same
MAIL FROM domain — but now against
the forwarders IP, which is NOT in the original
senders SPF record. The result is
spf=fail. This is the operational
#1 SPF complaint: "I have a perfectly valid SPF
record, but mail forwarded from my alias goes
to spam at Gmail."
The forwarding-breaks-SPF problem was identified in the original SPF specification (RFC 4408 in 2006 and obsoleted by RFC 7208 in 2014) and is explicitly called out in RFC 7208 section 10.3: "the address of the mediator will be used, rather than the address of the SMTP server that sent the message to the mediator" The IETF proposed two operational answers over the following decade:
- The Sender Rewriting Scheme (SRS),
a forwarder-side rewriting protocol originally
proposed by Meng Weng Wong (same author as the
original SPF spec) in 2003. SRS lets the
forwarder rewrite the
MAIL FROMat the moment of forwarding so the receiving SPF check authenticates the forwarder, not the original sender. - The Authenticated Received Chain (ARC), an IETF standard defined in RFC 8617 in 2019. ARC lets intermediaries cryptographically attest to the SPF, DKIM, and DMARC verdicts they OBSERVED before forwarding, and downstream receivers can trust that chain to override otherwise-failing verdicts.
Beyond SRS and ARC, three operational patterns have emerged for the SPECIFIC case of mailing- list forwarding (which also breaks DKIM because the list typically modifies the message body): From-header munging (rewrite the From: header to a list-owned address so DMARC aligns against the list), message wrapping (encapsulate the original message as a message/rfc822 attachment with a new outer envelope), and ARC sealing (the mailing-list operators preferred answer where downstream receivers validate ARC).
This page documents the four canonical forwarding scenarios, the SPF break model in each, the SRS and ARC mitigations, the mailing-list-specific MUNGE patterns Mailman 3 / Discourse / GitLab / Google Groups use, the detection workflow in DMARC aggregate reports, and the operational troubleshooting decision matrix. It is the focused operational deep dive operators need when debugging a live forwarding-related SPF fail in production.
2. The SPF first-hop authentication model
To understand why forwarding breaks SPF, start with the precise mechanism the receiver runs. RFC 7208 section 2.4 specifies the SPF check:
- The receiver accepts an SMTP connection from
a client IP address. Call this
<ip>. - The receiver reads the
MAIL FROM:<sender@domain.tld>SMTP command. Call the domain part<mail-from-domain>. - The receiver looks up the SPF record at
<mail-from-domain>by querying the TXT record at that name and finding a record beginning withv=spf1. - The receiver evaluates each mechanism in the
SPF record (in order:
+/-/~/?qualifier, followed byall,ip4,ip6,a,mx,ptr,exists,include,redirect). - If
<ip>matches any positive-qualifier mechanism, the result ispass. If it matches a hard-fail mechanism, the result isfail. Soft-fail and neutral producesoftfailandneutralrespectively. If no mechanism matches, the trailingallqualifier produces the result.
The CRITICAL property of this model: the
receiver authenticates the CONNECTING IP
against the
MAIL FROM domains record. The
receiver does NOT examine the
Received: headers, does NOT
follow the X-Forwarded-For chain,
and does NOT consult any out-of-band information
about who SENT the message originally. SPF is a
SINGLE-HOP authentication mechanism by design.
The
RFC 7208 section 10.3
text states this explicitly:
"Because SPF evaluation is based on the IP address of the "last" sending SMTP server, the address of the mediator will be used, rather than the address of the SMTP server that sent the message to the mediator. Some mediators retain the email address from the original message, while some use a new address."
The forwarder enters this model as a third party that opens a NEW SMTP connection on the way to the final receiver. Three properties distinguish the forwarders connection from the original senders connection:
- The source IP is different. The forwarder uses its OWN outbound mail server IP, not the original senders.
- The MAIL FROM is typically unchanged. The forwarder, by default, transmits the original bounce address verbatim so bounce messages route back to the original sender. (SRS is the protocol that rewrites this to break the SPF failure.)
- The From: header is typically unchanged. The forwarder preserves the original From: so the recipient sees the original sender as the apparent author of the message. (From-header MUNGE in mailing lists is the protocol that rewrites this to break the DMARC failure.)
The combination — original MAIL FROM and From:
surviving the forwarders new SMTP hop — is what
makes the receivers SPF check fail. The
receiver looks up the original senders SPF
record, tests the forwarders IP against it,
finds no match, and returns
spf=fail.
3. The four canonical forwarding scenarios
Four operational forwarding patterns account for virtually all SPF-breaks-on-forwarding incidents. Each subsection below opens with the canonical three-part labelled structure that gives generative engines a quotable extract:
3.1 Transparent SMTP-level forwarding (.forward, /etc/aliases, server-side forward rules)
Scenario: A server-level
alias or .forward file at the recipients
primary mail server forwards every incoming
message to a different external mailbox.
Example: info@example.com on a
Postfix server has
/etc/aliases entry
info: bob@external.com — every
message to info@example.com is
re-sent to bob@external.com by
the example.com Postfix server.
Why SPF breaks: The
example.com Postfix server opens a new SMTP
connection to external.com using its own
outbound IP. The connection presents the
original
MAIL FROM: alice@sender.org and
the original
From: alice@sender.org. The
external.com SPF check looks up sender.org
SPF, tests example.coms IP against it, and
gets spf=fail because
example.com is not in sender.orgs
authorised list. This is the textbook
case the RFC 7208 10.3 quote describes.
Operational fix: Enable
Sender Rewriting Scheme (SRS) on the
forwarder. After SRS, the
MAIL FROM becomes something
like
SRS0=HHH=TT=sender.org=alice@example.com;
the external.com SPF check now tests
example.coms IP against example.coms own
SPF record (which it controls and can
publish correctly) and gets
spf=pass. Postfix integrates
SRS via the postsrsd daemon
and the
sender_canonical_maps +
recipient_canonical_maps
configuration. The downside is that bounces
sent to the rewritten address must be
reverse-decoded by postsrsd and forwarded
back to the original sender, which adds
operational complexity.
Alternative operational fix: enable ARC sealing on the forwarder (see §5). Downstream receivers that validate ARC (Gmail, Microsoft 365, Yahoo) will trust the forwarders attestation that the message passed SPF / DKIM / DMARC at the forwarder BEFORE the forward, and may override the downstream SPF fail.
3.2 User-level forwarding (sieve, Outlook rules, Gmail filter forwarding, FastMail rules)
Scenario: A user-configured rule in the recipients mailbox forwards specific messages or all messages to a different address. Example: a Gmail user configures Settings > Forwarding and POP/IMAP > "Forward a copy of incoming mail to bob@external.com". Or an Outlook user creates a server-side rule "When I receive a message, redirect it to alice@partner.com".
Why SPF breaks: Functionally
identical to §3.1 transparent SMTP-level
forwarding — the users mail provider opens
a new SMTP connection to the external
destination, the original
MAIL FROM is preserved by
default, and the destinations SPF check
fails against the providers IP. The
operational difference is that the
forwarder is NOT under operator control: the
end user enabled the forward, and a SaaS
mailbox provider operates the relay.
Operational fix: The forwarder must implement SRS or ARC sealing natively. Gmail (since 2019) and Microsoft 365 (since 2020) seal forwarded messages with ARC by default; FastMail, ProtonMail, Apple iCloud, and most enterprise hosted providers also seal with ARC. Self-hosted Postfix / Exim / Sendmail installations must be configured to either rewrite MAIL FROM with SRS (postsrsd, native Exim SRS support, sendmail-srs) or seal with ARC (OpenARC milter for Postfix and Sendmail, Exim native arc_sign at the time of forwarding).
3.3 Mailing list expansion (Mailman 3, Discourse, Google Groups, Sympa, GitLab notifications)
Scenario: A mailing list
receives a message at
list@list.example.com, the
list software expands the recipient list to
the subscriber addresses, and re-sends the
message to every subscriber. Typical
modifications: add a List-Id header (RFC
2919), append an unsubscribe footer, prepend
a subject-line tag like
[Dev], add ARC headers (modern
deployments), rewrite From: to a
list-owned address (legacy
DMARC-mitigation deployments).
Why SPF breaks: Plus an
additional DKIM breakage. The list servers
IP is not in the original posters SPF
record (SPF fail). The footer / subject /
list-id modifications change the message
body and headers, so the original DKIM
signature (which protects the body hash and
a specific header set) no longer validates
(DKIM fail). Both authentication mechanisms
fail, so DMARC alignment fails too. For
posters with
p=quarantine or
p=reject DMARC policies, the
message is spam-foldered or bounced for
every subscriber — which historically
broke high-volume engineering mailing
lists like
netdev@vger.kernel.org and
tls@ietf.org in the 2014-2018
era when Yahoo and AOL first published
p=reject.
Operational fix: Two
canonical answers. Option A: From-
header MUNGE — the list rewrites
the From: header to a list-owned address
("Alice via Dev List" <dev@list.example.com>)
with the original sender in Reply-To. SPF
and DKIM now authenticate the list-owned
domain and DMARC aligns. Mailman 3 supports
this via
dmarc_mitigate_action: munge_from.
Option B: ARC sealing —
the list adds ARC headers attesting that
the original message passed SPF + DKIM +
DMARC at the list server BEFORE
modification. Downstream receivers that
validate ARC (Gmail, Microsoft 365, Yahoo,
AOL, Comcast, Apple) trust the chain and
may override the otherwise-failing
downstream verdict.
ARC is the modern preferred answer because
From-header MUNGE has display-quality
downsides (the From: no longer cleanly
shows the original poster, breaking some
mail-client features and surprising
reply-all users). The Mailman 3 release
notes from 3.3.5+ recommend ARC sealing
over MUNGE where downstream receivers
validate it. Discourse defaults to MUNGE.
Google Groups defaults to MUNGE + ARC.
GitLab incident notifications default to
sending from
noreply@gitlab.com (list-
owned From: by design).
3.4 Third-party forwarding services (iCloud Mail Drop, Hide My Email, Gmail Fetcher, ProtonMail forwarding, custom alias services)
Scenario: A third-party
SaaS forwarding service hosts an alias and
forwards mail to a private downstream
address. Examples: Apple iCloud Mail Drop
(@icloud.com) and Hide My Email
(@privaterelay.appleid.com);
Gmail Fetcher (Settings > Accounts and
Import > Check mail from other accounts);
ProtonMail forwarding to external address;
FastMail alias forwarding; custom
alias-as-a-service providers like
SimpleLogin, AnonAddy, DuckDuckGo Email
Protection.
Why SPF breaks: Same as §3.1 — the SaaS provider opens a new SMTP connection from its own infrastructure IP, which is not in the original senders SPF record. The added complexity is that some third-party forwarders (iCloud, Hide My Email, DuckDuckGo Email Protection, SimpleLogin) STRIP X-headers and tracking pixels before forwarding for privacy reasons, which can also break DKIM if the DKIM signature covered those headers.
Operational fix: Trust the forwarders ARC sealing. All major third-party forwarders seal forwarded messages with ARC (iCloud since 2019, Apple Hide My Email at launch in 2021, SimpleLogin since 2022, DuckDuckGo Email Protection at launch in 2022). Downstream receivers that validate ARC trust the chain. For self-hosted alias services (privately operated SimpleLogin instances, custom rspamd or Postfix alias setups), the operator must implement either SRS or ARC sealing — modern deployments choose ARC because the SRS bounce-handling complexity is significant. Gmail Fetcher is a special case because it uses POP3 / IMAP polling rather than SMTP forwarding; the SPF failure model is subtly different (see FAQ §11).
4. Sender Rewriting Scheme (SRS) — the forwarder-side fix
The Sender Rewriting Scheme (SRS) is the original operational answer to forwarding- breaks-SPF, proposed in 2003 by Meng Weng Wong (the same author as the original SPF specification) and documented in the OpenSPF SRS informational draft. SRS is implemented in most mainstream mail servers and is the dominant deployment pattern for SMTP-level forwarders (server-side aliases, .forward files, /etc/aliases).
The core SRS idea: the forwarder REWRITES the
SMTP MAIL FROM at the moment of
forwarding so that the receiving SPF check
authenticates the FORWARDER, not the original
sender. The rewritten address must encode enough
information that bounces sent back to it can be
reverse-decoded and routed to the original
sender.
SRS address format
The SRS specification defines two address formats: SRS0 (for messages traversing a single forwarder) and SRS1 (for messages traversing multiple forwarders in a chain). The SRS0 format is:
SRS0=HHH=TT=original-domain=original-localpart@forwarder-domain
Where:
SRS0is the literal prefix signaling a single-hop SRS rewrite.HHHis a base32-encoded HMAC of the rest of the address, computed with a secret key the forwarder holds. The HMAC prevents attackers from forging SRS-encoded addresses to bypass bounce routing.TTis a base32-encoded timestamp limiting the rewrites validity (typically 21 days). Old SRS-encoded addresses expire so bounces cannot be relayed indefinitely.original-domainis the domain part of the originalMAIL FROM.original-localpartis the local-part of the originalMAIL FROM.forwarder-domainis the forwarders own domain.
Concrete example: an original
MAIL FROM: alice@sender.org
forwarded by example.com becomes
SRS0=HHH=TT=sender.org=alice@example.com.
SRS1 format for multi-hop chains
The SRS1 format is for messages traversing multiple forwarders. The format is:
SRS1=HHH=intermediate-forwarder==SRS0-payload@final-forwarder
SRS1 lets each forwarder in a chain rewrite without losing the original-sender information. In practice multi-hop SRS is rare because most deployments terminate at a single forwarding tier and ARC has displaced SRS for multi-intermediary chains.
Bounce reverse-decoding
Bounces sent to the SRS-encoded address must be reverse-decoded. The forwarder:
- Receives a bounce addressed to
SRS0=HHH=TT=sender.org=alice@example.com. - Validates the HMAC
HHHagainst the forwarders SRS secret to confirm the address was genuinely SRS-encoded by this forwarder. - Validates the timestamp
TThas not expired (typically <21 days). - Reconstructs the original address
alice@sender.orgfrom the encoded fields. - Re-sends the bounce to
alice@sender.org.
The HMAC validation is critical: without it an
attacker could send arbitrary mail to
SRS0=fake=fake=sender.org=alice@example.com
addresses and the forwarder would dutifully
relay them to alice@sender.org,
making the forwarder an open relay.
Implementations
- Postfix: via the
postsrsddaemon (separate package; runs as a TCP service on localhost; integrates viasender_canonical_mapsandrecipient_canonical_maps). - Exim: native SRS support
via the
srs_ACL conditions and thesrs_secretconfiguration option. - Sendmail: via the
sendmail-srsmilter or via custommcconfiguration. - Microsoft Exchange: since
Exchange 2007, SRS is automatic for
accepted-domain forwarding (the SRS prefix
is the literal
BPMrather thanSRS0, but the mechanism is equivalent). - qmail: via the
qmail-srspatch (legacy).
SRS limitations
- SRS rewrites only the
MAIL FROM; it does NOT touch theFrom:header. So while SPF passes, DMARC alignment is only achieved if DKIM also passes (the body is unchanged) — this is typically true for transparent forwarders. - SRS does not help mailing lists, which modify the message body. Mailing lists need From-header MUNGE or ARC.
- SRS bounce reverse-decoding adds operational complexity. Bounces lost in the reverse-decoding chain confuse senders.
- SRS-rewritten addresses expire (typically 21 days), so very-delayed bounces cannot be reverse-decoded.
- SRS does not address the privacy concern that the forwarders domain leaks in the rewritten address.
For modern deployments handling many forwarding intermediaries (corporate mail gateways, SaaS forwarding aggregators, multi-region routing), ARC has largely displaced SRS as the operational answer because ARC handles multi-hop chains natively and does not require bounce reverse-decoding. SRS remains the dominant pattern for self-hosted single-hop forwarders (the .forward / /etc/aliases case).
5. Authenticated Received Chain (ARC) — the receiver-side answer
The Authenticated Received Chain (ARC), defined in RFC 8617 (July 2019), is the IETF standard answer to forwarding-breaks-SPF and forwarding-breaks-DKIM. ARC lets intermediaries (forwarders, mailing lists, mail-relay services) cryptographically attest to the SPF, DKIM, and DMARC verdicts they OBSERVED at the moment they received the message — and let downstream receivers trust that chain to override otherwise-failing verdicts when their own SPF and DKIM checks fail because of forwarding.
The three ARC headers
Each intermediary in an ARC-aware path adds
three header fields, all carrying the same
incremental instance number
i=N (1 for the first hop, 2 for
the second, etc.):
- ARC-Authentication-Results
(
arc-authentication-results): the SPF, DKIM, and DMARC verdicts the intermediary observed when it received the message. Mirrors the syntax of the Authentication-Results header (RFC 8601). - ARC-Message-Signature
(
arc-message-signature): a DKIM-like signature over the message contents AT THE TIME the intermediary handled it. Lets downstream receivers verify the message has not been modified since this intermediarys checkpoint. - ARC-Seal
(
arc-seal): a signature over the ARC headers themselves (the ARC-Authentication-Results and ARC-Message- Signature for this hop, plus all previous ARC-Seal headers in the chain). Prevents intermediaries from tampering with earlier hops attestations.
The chain accumulates as the message
traverses intermediaries: hop 1 adds three
headers with i=1; hop 2 adds three
more with i=2 covering hop 1s
chain in the ARC-Seal; hop 3 adds three more
with i=3 covering hops 1 and 2; and
so on. The final receiver validates the chain
by verifying every ARC-Seal in sequence and
every ARC-Message-Signature against the
message state observed at that hop.
How downstream receivers use ARC
When a downstream receiver evaluates DMARC and finds that SPF and DKIM have both failed (the classic forwarding-broken case), it consults the ARC chain:
- Validate every
ARC-Sealin the chain. If any seal fails to verify, the chain is broken (cv=fail) and ARC cannot rescue the message. - Validate every
ARC-Message-Signatureagainst the message state at the corresponding hop. If any signature fails, the chain is broken. - Inspect the
ARC-Authentication-Resultsfrom the FIRST hop (the originating intermediary). If this hop attests that SPF + DKIM + DMARC passed at the time it received the message, the receiver MAY treat the message as if the original authentication had passed. - Apply local trust policy. The receiver maintains an internal allow-list of trusted ARC sealers (typically major forwarders like icloud.com, mailman lists, googlegroups.com). If the originating intermediary is in the allow-list, the receiver overrides the otherwise-failing DMARC verdict and delivers the message.
Validators in production
The major mailbox providers validate ARC and use it to rescue forwarded mail:
- Gmail — ARC validation since 2017 (pre-RFC pilot deployment), full RFC 8617 conformance since 2019. Gmail treats trusted intermediaries (icloud.com, major mailing lists, FastMail, ProtonMail) as authority for SPF / DKIM rescue.
- Microsoft 365 / Outlook.com — ARC validation since 2020. Microsoft documents the ARC-aware path under the ARC trusted-sealer configuration in the Defender for Office 365 portal.
- Yahoo — ARC validation since 2019.
- AOL — ARC validation since 2019 (now operated by Yahoo / Verizon Media / Apollo, same validator stack).
- Apple iCloud — both seals and validates ARC since 2019.
- Comcast — validates ARC since 2021.
- ProtonMail, FastMail, Mailfence — validate ARC in their hosted mail services.
Sealers in production
Most major forwarders and mailing-list software seal forwarded messages with ARC:
- Apple iCloud Mail Drop — seals all forwarded messages.
- Apple Hide My Email — seals all forwarded messages.
- Gmail filter-based forwarding — seals when forwarding to external addresses.
- Microsoft 365 transport rules — seals when configured.
- Mailman 3 — seals when
configured (
[ARC] enabled: yesinmailman.cfg). - Google Groups — seals all list traffic by default.
- Discourse — seals when
the
SiteSetting.email_in_arc_sealingflag is enabled. - SimpleLogin, DuckDuckGo Email Protection, AnonAddy — seal all forwarded mail by default.
- Self-hosted Postfix and Sendmail — via the OpenARC milter.
- Self-hosted Exim — via
native
arc_signat the time of forwarding.
ARC failure modes
ARC chains can fail in three ways:
- cv=fail — chain validation failed. A previous intermediary either signed incorrectly or modified a message already signed by an earlier hop without re-sealing. The receiver MUST NOT use ARC to rescue.
- cv=none — no ARC chain was found. The message did not traverse an ARC-sealing intermediary. The receiver falls back to plain SPF / DKIM / DMARC.
- cv=pass — the chain validates. The receiver MAY use the first-hop attestation to rescue otherwise-failing SPF / DKIM verdicts, gated by local trust policy.
The most common ARC failure mode in production is double-modification: hop 1 seals, hop 2 modifies the body without resealing (because it does not understand ARC), and hop 3 validates and finds the ARC-Message- Signature from hop 1 broken. The fix is for hop 2 to either reseal (preferred) or pass through without modification.
6. Mailing list mitigations: From-header MUNGE, message wrapping, ARC sealing
Mailing lists are a special case because the list software modifies the message body (footer, subject tag, List-Id header), so BOTH SPF AND DKIM fail at the downstream receiver. Three mitigations have emerged:
Mitigation A: From-header MUNGE (Mailman 3, Discourse legacy)
The list rewrites the RFC 5322
From: header so the From address
is owned by the list rather than the original
poster. Example:
From: "Alice Carpenter via Dev List" <dev@list.example.com>
Reply-To: alice@example.com
Sender: dev-bounces@list.example.com
List-Id: <dev.list.example.com>
Effects:
- SPF check passes — the list server is
authorised by
list.example.coms SPF record. - DKIM signature from the list server validates the modified body.
- DMARC alignment passes against
list.example.com(the new From: domain).
Mailman 3 implements this via the
dmarc_mitigate_action per-list
setting:
dmarc_mitigate_action: munge_from
dmarc_mitigate_unconditionally: False
Discourse implements this via
SiteSetting.email_in_munge_from_address
(legacy, deprecated in favor of ARC sealing in
Discourse 3.0+).
Downsides: the From: no longer cleanly displays the original poster. Mail clients show "Alice Carpenter via Dev List" rather than "Alice Carpenter". Reply-all may route incorrectly. Address-book auto-add picks up the list address rather than the posters. Some MUAs collapse threads incorrectly because the From: identity changes per list.
Mitigation B: Message wrapping
The list encapsulates the original message as
a message/rfc822 attachment
inside a new outer envelope. The outer
envelope is From: the list, addressed to the
subscriber, with a multipart/mixed body that
contains the original message as an
attachment.
Effects:
- SPF and DKIM authenticate the OUTER envelope (list-owned, passes).
- DMARC aligns against the outer From: (list-owned, passes).
- The original message is preserved intact inside the attachment.
Downsides: severe UX degradation. Subscribers
receive a confusing "message contains
attachment" presentation. Many mail clients
do not render embedded
message/rfc822 attachments
inline. Message-wrapping is rarely chosen in
modern deployments; Mailman 3 supports it via
dmarc_mitigate_action: wrap_message
but the documentation marks it as legacy.
Mitigation C: ARC sealing (modern preferred)
The list seals the message with ARC headers attesting that the original message passed authentication at the list server. Downstream receivers that validate ARC trust the chain and override the failing SPF / DKIM / DMARC verdict.
Effects:
- From: header is preserved (good UX).
- Original author is visible in mail clients.
- Reply-all works correctly.
- Downstream receivers that validate ARC (Gmail, Microsoft 365, Yahoo, Apple, Comcast) accept the message; receivers that do NOT validate ARC apply the published DMARC policy.
Mailman 3 enables ARC sealing via
[ARC] enabled: yes in
mailman.cfg. Discourse 3.0+
enables ARC sealing via
SiteSetting.email_in_arc_sealing.
Google Groups seals all list traffic by
default. The IETF mailing-list infrastructure
(tools.ietf.org /
mailman.ietf.org) seals all list
traffic by default.
Choosing between MUNGE and ARC
The current operational guidance from Mailman 3 maintainers (2024 release notes):
- If subscribers primarily use Gmail, Microsoft 365, Yahoo, Apple iCloud, or Comcast — choose ARC sealing. These receivers validate ARC and rescue forwarded mail.
- If subscribers use older receivers that do not validate ARC — choose MUNGE. The display-quality downsides are preferable to spam-foldering.
- If unsure — enable both. Mailman 3
supports
dmarc_mitigate_action: munge_fromAND[ARC] enabled: yessimultaneously. ARC-validating receivers rescue based on the chain; non-ARC receivers fall back to MUNGE.
7. Detecting SPF forwarding failures in production
SPF forwarding failures show up in three diagnostic surfaces. Operators should monitor all three to triage the prevalence and impact of forwarding-related authentication failures in their environment.
Surface 1: DMARC aggregate (RUA) reports
DMARC aggregate reports, defined in
RFC 7489 section 7,
are daily XML reports that DMARC-honouring
receivers send back to the
rua= mailbox listed in your DMARC
record. Each report contains per-source-IP
aggregates of:
- Message count.
- SPF result code (pass / fail / softfail / neutral / temperror / permerror / none).
- SPF authenticated identifier (which domain SPF actually authenticated, when there is one).
- DKIM result code, signing domain, and selector.
- DMARC disposition (none / quarantine / reject).
The forwarding-failure pattern in aggregate reports:
- Low volume per source IP (often 1-5 messages per day per forwarding intermediary).
- High diversity of source IPs over time (different forwarding-service nodes, different mailing-list IPs).
- Source IP belongs to a known forwarding- service ASN (Apple AS714 for iCloud, Google AS15169 for Gmail, Microsoft AS8075 for Microsoft 365, list-server hosting providers).
- spf=fail combined with EITHER dkim=pass (transparent-forwarder case) OR dkim=fail (body-modifying-forwarder case).
The DMARC Analyzer dashboard surfaces this distinction in the Top Source IPs table. Click any "Failures" row to see the per- record breakdown and look for the body of the report under the Reporter Detail view to see whether SPF, DKIM, or both failed.
Surface 2: Authentication-Results header (RFC 8601)
For end-to-end diagnosis of a SPECIFIC failed
message, inspect the
Authentication-Results: header
in the raw message source. The header is
added by the FIRST receiving mail server in
the path and surfaces the SPF, DKIM, DMARC,
and ARC verdicts that server observed.
Authentication-Results: mx.google.com;
dkim=pass header.i=@sender.org header.s=selector1 header.b=...;
spf=fail (google.com: domain of alice@sender.org
does not designate 198.51.100.42 as
permitted sender) smtp.mailfrom=alice@sender.org;
dmarc=pass (p=quarantine sp=quarantine dis=none)
header.from=sender.org;
arc=pass (i=1 spf=pass dkim=pass dmarc=pass)
smtp.remote-ip=198.51.100.42
Key signals in this header:
spf=failwith a parenthetical "does not designate <IP> as permitted sender" — the canonical forwarding break.dkim=passalongsidespf=fail— transparent forwarder (body unchanged); DMARC may align via DKIM.dkim=failalongsidespf=fail— body-modifying forwarder (mailing list or content-rewriting forwarder); DMARC cannot align and falls to the published policy.arc=passat the bottom — the chain validates and the receiver used ARC to rescue the message.arc=fail— the chain broke; ARC could not rescue.arc=none— no ARC chain was present; the message traversed non-ARC intermediaries.
The DMARC Analyzer Email Header Analyzer parses pasted Authentication-Results headers and surfaces each verdict individually with cross-references to the RFCs and the canonical failure-cause explanations.
Surface 3: Received: header chain
The Received: header chain
surfaces every SMTP hop the message
traversed. When triaging a forwarding
failure, the chain tells you:
- How many hops the message traversed
(count the
Received:headers). - What IPs handled each hop (look at the
fromandbyclauses). - When the message was relayed at each hop (look at the timestamps).
A typical forwarding chain:
Received: from mx.google.com by inbox.gmail.com
; Mon, 21 May 2026 08:32:11 -0700
Received: from forwarder.example.com (198.51.100.42)
by mx.google.com via SMTP
; Mon, 21 May 2026 08:32:09 -0700
Received: from mx.sender.org (203.0.113.7)
by forwarder.example.com via SMTP
; Mon, 21 May 2026 08:32:08 -0700
Received: from sender-mta.sender.org by mx.sender.org
; Mon, 21 May 2026 08:32:06 -0700
The forwarders IP (198.51.100.42) appears as
the from clause of the
SECOND-from-top
Received: header. Gmails SPF
check is performed against THIS IP — and
fails because 198.51.100.42 is not in
sender.orgs SPF record.
8. The four canonical operational fixes
The four operational answers to forwarding- breaks-SPF, ranked by deployment scope:
Fix 1: Implement SRS on the forwarder
Scope: SMTP-level forwarders under operator control (.forward, /etc/aliases, server-side alias rules, corporate mail gateways).
Postfix configuration via postsrsd:
# /etc/default/postsrsd
SRS_DOMAIN=example.com
SRS_EXCLUDE_DOMAINS=example.com,internal.example.com
SRS_SECRET=/etc/postsrsd.secret
SRS_FORWARD_PORT=10001
SRS_REVERSE_PORT=10002
# /etc/postfix/main.cf
sender_canonical_maps = tcp:localhost:10001
sender_canonical_classes = envelope_sender
recipient_canonical_maps = tcp:localhost:10002
recipient_canonical_classes = envelope_recipient,header_recipient
Exim configuration via native SRS:
# /etc/exim4/exim4.conf.template — under main configuration
srs_config = secret_text:LONG_RANDOM_SECRET_HERE
srs_maxlifetime = 21d
# under routers — forward router with SRS rewrite
forward_with_srs:
driver = redirect
domains = example.com
data = ${lookup{$local_part}lsearch{/etc/aliases}}
errors_to = ""
pipe_transport = address_pipe
file_transport = address_file
reply_transport = address_reply
qualify_preserve_domain
srs = forward
Fix 2: Implement ARC sealing on the forwarder
Scope: any forwarder (SMTP-level, mailing list, third-party). ARC is the modern preferred answer where downstream receivers validate it.
Postfix with OpenARC milter:
# /etc/openarc.conf
Mode sv
Domain example.com
Selector arc1
KeyFile /etc/openarc/keys/arc1.private
Socket inet:8893@localhost
SignatureAlgorithm rsa-sha256
Canonicalization relaxed/simple
AuthservID example.com
# /etc/postfix/main.cf
smtpd_milters = inet:localhost:8893
non_smtpd_milters = inet:localhost:8893
milter_default_action = accept
DNS publication for the ARC selector:
arc1._domainkey.example.com. IN TXT (
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..." )
Fix 3: Configure mailing-list software for DMARC-aware operation
Scope: mailing lists you operate.
Mailman 3 (preferred: ARC sealing):
# /etc/mailman3/mailman.cfg
[ARC]
enabled: yes
authserv_id: list.example.com
privkey: /etc/mailman3/arc.privkey
selector: arc1
domain: list.example.com
# per-list setting (mailman-cli or HyperKitty admin)
dmarc_mitigate_action: munge_from # fallback for non-ARC receivers
anonymous_list: no
subject_prefix: "[Dev] "
Discourse 3.0+ (preferred: ARC sealing):
# app.yml > env
DISCOURSE_EMAIL_IN_ARC_SEALING: true
DISCOURSE_EMAIL_IN_ARC_DOMAIN: discourse.example.com
DISCOURSE_EMAIL_IN_ARC_SELECTOR: arc1
DISCOURSE_EMAIL_IN_ARC_PRIVATE_KEY: /shared/arc/arc1.private
Fix 4: Publish a permissive DMARC policy and accept some forwarding loss
Scope: any organisation that cannot enforce SRS or ARC at every intermediary in the forwarding chain. The rule of thumb:
- Phase 1 (monitor):
v=DMARC1; p=none; rua=mailto:dmarc@example.com;— gather two to four weeks of aggregate reports to baseline forwarding-traffic prevalence in your domain. - Phase 2 (quarantine pct=10):
v=DMARC1; p=quarantine; pct=10; rua=mailto:dmarc@example.com;— start spam-foldering 10% of failing mail; monitor user-reported false positives. - Phase 3 (quarantine pct=100):
v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com;— full quarantine; receivers without ARC support spam-folder all failing mail. - Phase 4 (reject):
v=DMARC1; p=reject; rua=mailto:dmarc@example.com;— bounce all failing mail. Only graduate here after ARC-validating receivers handle the bulk of legitimate forwarded mail.
Critically: do NOT try to authorise every
forwarder in your SPF record. The 10-lookup
cap from
RFC 7208 section 4.6.4
makes this infeasible at scale — every
include:forwarder.example token
consumes one of your ten lookups, and a
typical organisation needs three to five
lookups for legitimate ESP / transactional /
Microsoft 365 includes already.
9. Symptom decision matrix
Use this matrix to identify the forwarding- related root cause from the symptoms you observe in production.
| Symptom | Likely cause | Operational fix |
|---|---|---|
| spf=fail + dkim=pass + dmarc=pass | Transparent forwarder; DMARC aligned via DKIM. No action needed. | None. This is the working case. |
| spf=fail + dkim=pass + dmarc=fail | Transparent forwarder, DKIM signs an unaligned domain. | Audit the DKIM signing domain — must align with the From: header organisational domain. |
| spf=fail + dkim=fail + dmarc=fail | Body-modifying forwarder (mailing list, content-rewriting gateway). | Enable ARC sealing at the forwarder; or From-header MUNGE; or accept the loss and stay at p=none. |
| spf=fail + arc=pass + dmarc=pass via ARC | ARC rescued the message at an ARC-validating receiver. | None. The chain worked. |
| spf=fail + arc=fail + dmarc=fail | ARC chain broken — a downstream intermediary modified the message without re-sealing. | Audit the intermediary chain for an unseal-aware forwarder; have it either reseal or pass through unmodified. |
| spf=fail recurring from icloud.com / apple.com IPs | iCloud Mail Drop or Hide My Email forwarding. | Trust iClouds ARC sealing; downstream receivers that validate ARC will rescue. No action needed at the sender. |
| spf=fail recurring from mail-server pool IPs in your own ASN | Internal /etc/aliases or .forward forwarding inside your own organisation. | Enable SRS on the internal mail server (postsrsd, Exim native, Exchange auto-SRS). |
| spf=fail recurring from list-server IPs (mailman, googlegroups.com, discourse) | Mailing list expansion without DMARC-aware mitigation. | Contact the list operator to enable ARC sealing or From-header MUNGE. |
| spf=fail + many duplicate Received: headers in chain | Forwarding loop or relay misconfiguration. | Audit the chain for a forwarder that does not detect its own outbound mail; configure loop detection. |
| spf=fail intermittently from same IP | DNS resolution issue at the receiver, not a forwarding issue. | Check for SPF temperror; see SPF permerror vs temperror. |
10. Real-world examples
Example 1: Corporate .forward to personal Gmail
A finance team member has
jane.doe@bigcorp.com with a
server-side .forward to
jane.doe.personal@gmail.com.
Vendors email
jane.doe@bigcorp.com from their
own infrastructure; bigcorp.coms Postfix
server relays each message to
jane.doe.personal@gmail.com.
Gmail performs an SPF check against the
vendors domain (the
MAIL FROM is still the
vendors), tests bigcorp.coms IP against
the vendors SPF record, and gets
spf=fail. Without SRS or ARC at
bigcorp.com, all vendor mail goes to Janes
Gmail spam folder.
Resolution: bigcorp.coms IT team enables
postsrsd on the Postfix relay. After SRS, the
MAIL FROM is rewritten to
SRS0=HHH=TT=vendor.com=billing@bigcorp.com.
Gmail tests bigcorp.coms IP against
bigcorp.coms SPF record (which lists
bigcorp.coms own IPs), gets
spf=pass, and delivers normally.
Example 2: Mailman 3 mailing list with strict-DMARC posters
An open-source projects mailing list
dev@list.example.com hosts
Mailman 3. A subscriber from a strict-DMARC
domain (p=reject at
sender.example.org) posts a question. Mailman
expands the recipient list, appends an
unsubscribe footer, adds
List-Id: <dev.list.example.com>,
and re-sends to 500 subscribers. The body
modification breaks the original DKIM
signature; the list servers IP is not in
sender.example.orgs SPF record; DMARC fails
at every receiver. With
p=reject at sender.example.org,
500 subscribers see the message bounced.
Resolution path A (legacy MUNGE):
list operator enables
dmarc_mitigate_action: munge_from.
The From: is rewritten to
"Original Poster via Dev List" <dev@list.example.com>.
SPF passes; DKIM passes (Mailman re-signs the
modified message with list.example.coms
DKIM key); DMARC aligns. 500 subscribers
receive the message but see a list-owned
From: address.
Resolution path B (modern ARC, preferred):
list operator enables
[ARC] enabled: yes + publishes
arc1._domainkey.list.example.com TXT. Mailman
seals every outgoing message with ARC headers
attesting that SPF + DKIM + DMARC passed at
the list server BEFORE modification. Downstream
Gmail / Microsoft 365 / Yahoo subscribers
receive the message normally with the
original From: preserved; downstream
non-ARC subscribers may still see the message
quarantined (the From: still says
sender.example.org with broken DKIM / SPF —
no rescue).
Example 3: iCloud Mail Drop with Outlook destination
A user has
alice@icloud.com with Mail Drop
forwarding to
alice@outlook.com. A vendor
sends
billing@vendor.com to
alice@icloud.com. iCloud receives
the message, performs SPF + DKIM + DMARC
verification (which all pass), seals the
message with an ARC chain, and forwards to
alice@outlook.com. Microsoft 365
performs SPF against vendor.coms record, gets
spf=fail (iClouds IP is not
authorised), but validates the ARC chain,
sees iCloud (a trusted intermediary) attesting
that authentication passed at receipt, and
delivers the message normally to Alice.
No operator action required. ARC handles this case end-to-end transparently because both iCloud (sealer) and Microsoft 365 (validator) deployed ARC support in 2019-2020.
11. FAQ
- Why does SPF fail when an email is forwarded?
- SPF authenticates the SMTP envelope sender (the RFC 5321 MAIL FROM, also called the bounce address or return-path) against the IP address of the connecting SMTP client. When a message is forwarded at the SMTP layer — for example, alice@example.com has a .forward file that pipes mail to bob@othersite.net — the forwarding server (example.com) opens a NEW SMTP connection to othersite.net using its OWN IP address as the SMTP client. The receiving server at othersite.net then performs an SPF check against the original MAIL FROM domain (the original senders bounce address, NOT the forwarders domain), and finds that the forwarders IP is NOT authorised by the original senders SPF record. The result is spf=fail. This is by design: SPF was specified in RFC 7208 to authenticate the FIRST SMTP hop only, and forwarding by definition introduces an additional hop. The Sender Rewriting Scheme (SRS) is the operational workaround at the forwarder side; the Authenticated Received Chain (ARC, RFC 8617) is the receiver-side answer.
- What is the Sender Rewriting Scheme (SRS)?
- The Sender Rewriting Scheme (SRS) is a technique by which a forwarding mail server REWRITES the RFC 5321 MAIL FROM (envelope sender) at the moment of forwarding, replacing the original bounce address with a forwarder-owned address that encodes the original. Example: alice@example.com forwards to bob@othersite.net via forwarder.com. Before SRS: MAIL FROM is alice@example.com — receiving SPF check against example.com fails because forwarder.com is not in example.com SPF record. After SRS: MAIL FROM is SRS0=HHH=TT=example.com=alice@forwarder.com — receiving SPF check against forwarder.com succeeds because forwarder.com publishes its own SPF record authorising its own outbound IPs. SRS was originally proposed in 2003 by Meng Weng Wong (the same author as the original SPF spec); the canonical reference is the OpenSPF SRS informational draft. SRS is implemented in most mainstream mail servers including Postfix (via postsrsd), Exim (native), Sendmail, qmail (via qmail-srs), and Microsoft Exchange (since Exchange 2007). The trade-off is that bounces sent to the rewritten address must be reverse-decoded and forwarded back to the original sender, which adds operational complexity.
- What is the Authenticated Received Chain (ARC)?
- The Authenticated Received Chain (ARC) is an IETF standard defined in RFC 8617 that lets intermediaries (forwarders, mailing lists, mail-relay services) cryptographically attest to the SPF, DKIM, and DMARC verdicts they observed AT THE TIME THEY RECEIVED the message — and let downstream receivers trust that chain when their own SPF and DKIM checks fail because of forwarding. Each intermediary adds three header fields: ARC-Authentication-Results (the verdicts they saw), ARC-Message-Signature (a DKIM-like signature over the message at the time they handled it), and ARC-Seal (a signature over the chain itself). Downstream receivers including Gmail, Microsoft 365, Yahoo, AOL, Comcast, and Apple validate the ARC chain; if the chain is intact and the originating intermediary is trusted (the receiver maintains an internal allow-list), the receiver MAY override an otherwise-failing DMARC verdict and deliver the message. ARC is the modern operational answer to forwarding breakage at scale and is the dominant deployment pattern in 2024 for mailing-list operators (Mailman 3, Discourse, Google Groups, GitLab) and major forwarders (iCloud Mail Drop, Gmail Fetcher, Microsoft 365 transport rules).
- How do mailing lists break SPF?
- A mailing list is conceptually a forwarder that fans out one incoming message to many subscribers. The list software (Mailman, Discourse, Google Groups, Sympa, Majordomo, GitLab incident notifications) receives the original message from the poster, re-sends it from the list server to each subscriber, AND typically modifies the message body (adds a footer, list-id header, unsubscribe link). Three SPF-breaking effects result: (1) the list server is a new SMTP hop with a different IP than the posters authorised SPF range, so receiver-side SPF check against the posters domain fails by default; (2) any DKIM signature applied by the poster over the modified body breaks because the body hash no longer matches; (3) the message arrives at subscriber inboxes with the original From: header (so DMARC alignment is still required), but neither SPF nor DKIM authenticates the posters domain anymore. The result is spf=fail + dkim=fail (body mismatch) + DMARC=fail. For DMARC policies of quarantine or reject, the message is dropped or spam-foldered for every subscriber. The two modern solutions are (a) From-header MUNGE rewriting (the list rewrites From: to a list-owned address such as list@list.example.com so DMARC aligns against the list-owned address) and (b) ARC sealing (the list seals the message with ARC and lets downstream receivers trust the chain).
- What is From-header munging and how does Mailman use it?
- From-header munging (also called From-rewriting or Reply-To munging in the variant case) is a mailing-list-software technique that rewrites the RFC 5322 From: header of every list message so that the From: address is owned by the list server rather than the original poster. Example: a message originally from alice@example.com posted to dev@list.example.com is sent to subscribers with From: "Alice via Dev List" <dev@list.example.com> and Reply-To: alice@example.com. The effect is that the SPF check now passes (list.example.com is authorised by list.example.com SPF record), the DKIM signature from the list server validates the body the list has modified, and DMARC alignment passes against the list-owned From: address. The trade-off is that the From: header no longer cleanly displays the original posters address, which breaks some mail-client features (one-click sender filtering, address-book auto-add) and may surprise reply-all users. Mailman 3 implements From-header MUNGE via the dmarc_mitigate_action setting (dmarc_mitigate_action: munge_from); Discourse implements it via the SiteSetting.email_in_munge_from_address flag; GitLab implements it via gitlab.yml > smtp.from_email. The standard alternative — preferred where downstream receivers validate ARC — is to seal the message with ARC instead of munging the From: header.
- Does iCloud Mail Drop break SPF?
- Yes, but iCloud Mail Drop also seals messages with ARC so downstream receivers can recover the authentication chain. iCloud Mail Drop is the @icloud.com and @me.com email-forwarding service (and as of macOS Ventura, the @hideMyEmail unique-address-per-app feature) that lets users receive mail at an iCloud-managed address and have it forwarded to a private external address such as alice@gmail.com. At the SMTP layer this is exactly equivalent to .forward forwarding: the iCloud server receives the message, opens a new SMTP connection to gmail.com using an iCloud-owned IP, and re-injects the message. The original senders SPF record does NOT authorise iCloud IPs, so spf=fail. However, iCloud seals every forwarded message with an ARC chain attesting that the message passed authentication at iCloud, so downstream receivers (Gmail, Outlook.com, Yahoo) that validate ARC see the chain and may override the SPF fail. The same architecture applies to the broader Apple Hide My Email feature where users get a unique <random>@privaterelay.appleid.com address per app; ARC sealing is the default.
- How does Gmail Fetcher break SPF?
- Gmail Fetcher (the "Check mail from other accounts" feature in Gmail Settings > Accounts and Import) is a POP3 / IMAP polling service rather than an SMTP forwarder, so the SPF break model is subtly different. Gmail Fetcher logs into a remote IMAP or POP3 mailbox (such as your work IMAP server) and DOWNLOADS messages, re-inserting them into your Gmail inbox via an internal mechanism. Because the message is not re-injected via SMTP, there is no second-hop SPF authentication failure in the strict sense. But Gmail STILL evaluates SPF retroactively against the original message metadata (the Received: header chain reveals the original sending IP), and if the original SPF check failed because the message had already been forwarded once before reaching the source IMAP mailbox, the chain may surface a fail. Operationally Gmail Fetcher messages are flagged with a "via" indicator and treated with reduced trust for spam-filtering purposes. The fix is the same as for SMTP forwarding: either (a) the source mailbox forwards via SMTP with SRS, or (b) the source mailbox seals with ARC, or (c) reconfigure Gmail to use OAuth-based IMAP rather than Fetcher so trust is delegated at the protocol level instead of inferred from headers.
- What is the relationship between SPF forwarding breakage and DMARC?
- DMARC, defined in RFC 7489, requires either SPF or DKIM to pass AND be aligned with the From: header organisational domain. When a message is forwarded and SPF breaks because of the new SMTP hop, DMARC alignment can still succeed if DKIM passes — assuming the forwarder did NOT modify the message body or any signed headers in a way that breaks the DKIM signature. This is the classic operational pattern for transparent forwarders that do not rewrite the message: SPF fails on the forwarders IP, DKIM passes because the forwarder is a faithful transcriber, DMARC alignment passes via DKIM. The problem cases are mailing lists (modify the body, add footers, expand attachments) and content-rewriting forwarders (iCloud strips X-headers; some corporate email gateways insert disclaimer text). For these the body hash in the original DKIM signature no longer matches and BOTH SPF and DKIM fail, so DMARC fails too. The receiver applies the published policy: none means deliver-and-report, quarantine means spam folder, reject means bounce. The two structural answers are ARC (RFC 8617 lets receivers trust an intermediarys attestation of pre-forwarding verdicts) and From-header MUNGE (the list rewrites From: so DMARC aligns against the list-owned address).
- How do I detect SPF forwarding failures in my DMARC aggregate reports?
- SPF forwarding failures show up in DMARC aggregate (RUA) reports as records where spf result is fail (or sometimes softfail) AND the source IP does NOT match any of your own authorised sending IPs. The pattern to watch for: a recurring source IP that belongs to a known forwarding service (iCloud, gmail.com, outlook.com, Mailman list servers, custom alias-forwarding services) sending small volumes of mail purporting to be from your domain. The forwarded-mail signal is typically (a) low volume per source IP (often 1-5 messages per day per forwarding intermediary), (b) high diversity of source IPs over time (different iCloud server hits, different list-server IPs), (c) high incidence of dkim pass + spf fail (the transparent-forwarder pattern) OR dkim fail + spf fail (the body-modifying-forwarder pattern). The DMARC Analyzer dashboard surfaces this distinction in the Top Source IPs table — click any "Failures" row to see the per-record breakdown, and look for the body of the report under the Reporter Detail view to see whether SPF, DKIM, or both failed. Operationally the right response is usually to publish a permissive DMARC policy (p=quarantine pct=10 or p=quarantine with explicit From-header MUNGE recommendations) rather than try to authorise every forwarder under SPF, which is infeasible at scale.
13. Verify your forwarding setup now
The DMARC Analyzer platform surfaces forwarding-related SPF failures in three places: the Domain Security Checker runs a live SPF lookup against the public DNS and reports any of the seven permerror cause classes plus the live lookup count; the Email Header Analyzer parses pasted Authentication-Results headers and surfaces the specific spf= verdict, the ARC chain status, and the per-hop Received: chain so you can identify exactly which forwarder broke authentication; the dashboard ingests DMARC aggregate (RUA) reports and surfaces per-record SPF result codes plus source-IP attribution at scale so you can monitor the forwarding-traffic prevalence and impact over time.
Check my SPF and ARC setup Analyze a forwarded-mail header Sign up — Free plan