Why Email Forwarding Breaks SPF (and What SRS and ARC Do)
Forwarded mail fails SPF because the forwarder's IP is not in the sender's record. How SRS, DKIM and ARC change the result, and what DMARC makes of it.
Published: · 7 min read
Email forwarding breaks SPF because SPF compares the connecting IP address with the record of the envelope sender's domain, and a plain forwarder changes the first without changing the second. The final receiver sees the forwarder's server delivering mail "from" example.com, finds that server nowhere in example.com's SPF record, and returns fail. Nothing is misconfigured on either side: this is how SPF is designed. Whether the message still passes DMARC depends almost entirely on DKIM.
This guide follows one message through a forwarder and shows what SRS, DKIM and ARC each change.
What SPF actually checks
An SMTP delivery has two sender identities:
- the envelope sender, given in the
MAIL FROMcommand and recorded later asReturn-Path. Bounces go there. - the From header, which the recipient's mail client displays.
SPF (RFC 7208) only knows the first one. The receiver takes the domain of the envelope sender (or the HELO name as a fallback, for example when the envelope sender is empty, as in bounces), fetches its SPF record and asks: is the IP address that is connecting to me right now listed?
Direct delivery:
alice@example.com -> mail server of example.com (192.0.2.10) -> receiver
MAIL FROM:<alice@example.com> connecting IP 192.0.2.10 spf=pass
What a plain forwarder does
A plain forwarder is an alias, a .forward file, a "forward all mail to" rule, or the email forwarding that comes with a domain at many registrars. It accepts the message and re-sends it to another address, keeping the original envelope sender so that bounces go back to the author.
alice@example.com -> forwarder (203.0.113.7) -> bob's real mailbox
MAIL FROM:<alice@example.com> connecting IP 203.0.113.7 spf=fail
203.0.113.7 belongs to the forwarder. example.com has never heard of it and should not list it: a sender cannot know every address its recipients forward to.
SRS: repairing SPF for the forwarder
The Sender Rewriting Scheme changes the envelope sender to an address in the forwarder's own domain before re-sending:
MAIL FROM:<SRS0=HHH=TT=example.com=alice@forwarder.example>
HHH is a short hash, TT a timestamp, and the original domain and local part are kept so that a bounce sent to this address can be unpacked and passed on to alice@example.com. The hash stops third parties from abusing the forwarder as a bounce relay.
Now the receiver checks forwarder.example's SPF record, which does list 203.0.113.7. SPF passes.
Two things to know about SRS:
- It is not an IETF standard. It is a community specification that came out of the SPF project, and implementations differ in detail.
- It fixes SPF and not DMARC. After the rewrite, the SPF-authenticated domain is
forwarder.example, while the From header still saysexample.com. DMARC requires the authenticated domain to align with the From domain, so the SPF leg of DMARC still fails. It merely fails quietly instead of loudly.
DKIM: the part that survives
A DKIM signature is part of the message, not of the connection. It covers the body and a chosen set of headers and is verified with a public key in the signer's DNS. A forwarder that passes the message on unchanged leaves the signature valid, whatever IP it connects from. If the signing domain (d=) aligns with the From domain, DMARC passes on the DKIM leg alone.
DKIM breaks when a signed part changes:
- a mailing list adds
[list-name]to the subject or a footer to the body - a gateway rewrites the body, for example by adding a disclaimer or rewriting links
- a system re-encodes the message in a way the signature's canonicalisation does not tolerate
Plain forwarding does none of these. Mailing lists do the first one all the time.
Scenario table
Assume example.com publishes SPF, signs with d=example.com and has p=reject.
| Scenario | SPF result | DKIM result | DMARC result |
|---|---|---|---|
| Direct delivery | pass, aligned | pass, aligned | pass |
| Plain forward, message untouched | fail | pass, aligned | pass (via DKIM) |
| Plain forward, sender has no DKIM | fail | none | fail |
| Forward with SRS, message untouched | pass for forwarder, not aligned | pass, aligned | pass (via DKIM) |
| Forward with SRS, sender has no DKIM | pass for forwarder, not aligned | none | fail |
| Mailing list that modifies subject or body | pass for the list, not aligned | fail (broken) | fail, unless the list rewrites From |
| Same, with an ARC chain the receiver trusts | as above | as above | fail, but the receiver may override locally |
The second and fifth rows are the ones that matter in practice: SRS cannot rescue a sender who has no aligned DKIM, and a sender with aligned DKIM does not need SRS for DMARC to pass.
ARC: passing on what the intermediary saw
Authenticated Received Chain (RFC 8617, Experimental status) addresses the mailing-list rows. An intermediary that handles the message records the authentication results it observed on arrival and signs that record. Each hop adds a set of three headers with an instance number:
ARC-Authentication-Results: i=1; lists.example.org;
spf=pass smtp.mailfrom=example.com; dkim=pass header.d=example.com;
dmarc=pass header.from=example.com
ARC-Message-Signature: i=1; a=rsa-sha256; d=lists.example.org; s=arc1; …
ARC-Seal: i=1; a=rsa-sha256; cv=none; d=lists.example.org; s=arc1; …
A second intermediary adds i=2, and so on. The final receiver can validate the chain and see that the message passed DMARC when it reached lists.example.org, before the list changed it.
The important word is can. ARC tells the receiver what a sealer claims to have seen. Whether to believe that sealer is local policy: receivers MAY honour a chain from an intermediary they trust, and they are free to ignore it. ARC is not a guarantee of delivery.
Because of this uncertainty, mailing lists commonly take a blunter approach for senders whose domains enforce DMARC: they rewrite the From header to an address in the list's own domain, so the message aligns with the list's own SPF and DKIM.
Reading the Authentication-Results header
Send a message through the forwarder to a mailbox you control, open the original, and find the Authentication-Results header added by the final receiver (the topmost one):
Authentication-Results: mx.receiver.example;
spf=pass smtp.mailfrom=forwarder.example;
dkim=pass header.d=example.com header.s=s2026;
dmarc=pass header.from=example.com;
arc=pass
Return-Path: <SRS0=a1b2=XY=example.com=alice@forwarder.example>
| Field | What it tells you |
|---|---|
smtp.mailfrom= |
The domain SPF was checked against. If it is the forwarder's, SRS is in use. |
spf= |
Result for that domain and the connecting IP. fail with the original domain means a plain forwarder. |
header.d= |
The domain whose DKIM signature validated. Compare it with header.from. |
dmarc= |
The verdict after alignment. This is the one that decides. |
arc= |
Whether an ARC chain was present and validated. |
If you would rather paste the headers than read them, the email header analyzer breaks them down.
Advice for senders
- Sign everything with DKIM, aligned to your From domain. Every service that sends as you: mailbox provider, newsletter tool, invoicing, helpdesk. This is what makes your mail survive forwarding. SPF alone never will.
- Do not add forwarders' IP addresses to your SPF record. You cannot know them all, they change, and each include you add counts against the 10-lookup limit.
- Move to
p=rejectonly when DMARC reports show DKIM alignment for all your legitimate sources. A domain atp=rejectthat relies on SPF alone will have its forwarded mail refused. - Expect a small residue of failures from mailing lists. The rollout order in MX, SPF, DKIM and DMARC explained accounts for it.
Advice if you forward mail
- Use a forwarder that implements SRS, and ideally ARC sealing. Without SRS, every message from a domain with
-allarrives withspf=fail. - Consider fetching instead of forwarding. If the destination mailbox can collect mail from the old account over POP or IMAP, no re-sending happens and no authentication is disturbed.
- Do not forward spam. The final receiver sees your forwarder's IP delivering it and holds that against the forwarder. Filter before forwarding.
- Consider hosting the mailbox instead of forwarding it. A domain that only forwards to a free mailbox is the fragile setup in most "my mail is missing" reports: see the DNS checklist for mail going to spam.
Common mistakes
- Treating
spf=failon a forwarded message as proof of spoofing. Look atdkim=anddmarc=before deciding. - Believing SRS fixes DMARC. It fixes SPF for the forwarder's domain; alignment is still gone.
- Adding
include:entries for recipients' forwarders to your own SPF record. - Going to
p=rejectwith SPF-only authentication because "SPF passes in all our tests". Tests rarely include a forwarder. - Assuming ARC forces the receiver to accept. It is evidence offered to a receiver that may or may not trust the sealer.
- Appending a disclaimer at an outbound gateway after DKIM signing. That breaks your own signature before the message has left.
Check it with OrbitProbe
The OrbitProbe SPF checker shows the SPF record a domain publishes and flags the usual structural problems: several records, +all, a missing all mechanism, too many DNS lookups. For a forwarding problem, check two names: the original sender's domain (does it end in -all, which makes plain forwarding fail hard?) and the forwarder's domain (does it have a valid record at all, so that SRS-rewritten mail can pass?). A DNS check reads published policy. What happened to one particular message is recorded only in that message's Authentication-Results header, so read both.