SRS — sender rewriting for forwarded mail
Purpose. A forwarder (or a Sieve redirect) re-sends someone else’s message from this server. SPF-strict receivers see the original sender’s domain in the envelope and this server’s IP — an SPF fail, often a DMARC reject. SRS rewrites the envelope sender so the forwarded message passes SPF and bounces still find their way back.
Behaviour.
- Postfix rewrites the envelope sender of every message whose sender domain is not local through
postsrsd(sender_canonical_maps):alice@external.example→SRS0=HHH=TT=external.example=alice@<hostname>. That covers alias forwarders and Sieveredirect. Vacation replies are sent with an empty envelope sender (<>), so there is nothing to rewrite. Mail from local users (:587/:465, local domains) is never rewritten, andFrom:headers are untouched, so DKIM signatures of the original sender survive. - Inbound mail delivered to local mailboxes carries the rewritten address in
Return-Path:as well (the standard postsrsd layout); the original sender remains inFrom:and is recoverable from the SRS address. - Bounces to an
SRS0=…@<hostname>address are accepted (mydestination = $myhostname), decoded bypostsrsd(recipient_canonical_maps) and delivered to the original sender; addresses older than the SRS validity window are rejected. - Local domains are excluded from rewriting (
srs-exclude, rendered from the active domains with every configuration apply, DKIM rotation, domain create/delete), so a forward between two local domains keeps its sender. - The DNS record list gains
TXT <hostname> "v=spf1 a -all"(keyspf-host, recommended) — the rewritten envelope domain is the hostname, which therefore needs its own SPF record. With an outbound relay configured, this record and the per-domain one both gain the relay’s declared SPF term (DNS records & live verification → Outbound relays): the exclusion above is exactly why the per-domain record needs it — a hosted domain’s envelope sender is never rewritten, so it survives the relay and is what the receiver checks SPF for.
Configuration. SRS_SECRET in .env (generated by mailctl install; mailctl upgrade and restore generate one when it is absent or empty; the compose bundle supplies none, so Postfix refuses to start without it). Changing the secret invalidates in-flight SRS bounce addresses. No admin-facing settings.
Limits & edge cases.
postsrsd1.x reads its excluded-domain list at start, so the watcher restarts it on every apply (docker/postfix/srs.sh); a restart takes well under a second and Postfix retries the TCP map on a transient failure.- Forwarding to Gmail/Outlook still counts against this server’s reputation if the forwarded mail is spam; SRS makes forwarding pass, it does not make it wise. Rspamd scores are applied before forwarding.
- SRS addresses are up to ~90 characters; a few receivers truncate very long local parts.