SRS — Sender Rewriting Scheme
Sender Rewriting Scheme (SRS0 / SRS1) — when a forwarder retransmits a message it received, SPF on the next hop will typically fail because the envelope-from sender is the original sender's domain, but the message is now coming from the forwarder's IP. SRS rewrites the envelope-from local-part to encode the original sender + a HMAC signature; the receiver verifies + reverses to deliver bounces correctly.
Wire format (SRS0):
SRS0=HHH=TT=domain=local@forwarder.example
Where: - HHH is the first 4 chars of base32(HMAC-SHA-256(secret, lowercase(TT=domain=local))) — short-tag binding the rewrite to the operator's signing secret - TT is a 2-character base32 day-of-time stamp (mod-1024 day rotation; rejects rewrites older than ~30 days) - domain is the original sender's domain - local is the original sender's local-part - forwarder.example is the rewriting forwarder's domain
Wire format (SRS1 — the multi-hop chain case):
SRS1=HHH=priorForwarder==
When an already-SRS0 (or SRS1) address is forwarded again, srs1Rewrite(srsAddress) wraps it: it keeps the original SRS0 body verbatim, prepends the preceding forwarder's domain, and binds the pair with this forwarder's own HMAC tag — no new timestamp, no repeated original local-part. reverse() detects SRS1, verifies this hop's tag, and unwraps exactly one hop back to the prior forwarder's SRS0 address so the bounce re-routes to it.
b.mail.srs.create({ secret, forwarderDomain }) returns { rewrite, srs1Rewrite, reverse }. rewrite(originalSender) produces the SRS0 address; srs1Rewrite(srsAddress) chains a further hop as SRS1; reverse(srsAddress) decodes an SRS0 back to the original sender (verifying HMAC + expiry) or unwraps an SRS1 one hop back to the prior forwarder.
b.mail.srs.create(opts) #
{
secret: string, // operator's HMAC-SHA-256 signing secret (>=32 bytes recommended)
forwarderDomain: string, // the forwarder's own domain (where bounces land)
expiryDays: number, // default 30 — reject reverse() of rewrites older than this
}
Build an SRS rewriter bound to the operator's forwarder domain + HMAC signing secret. Returns { rewrite, srs1Rewrite, reverse } — rewrite produces an SRS0 origin address, srs1Rewrite chains an already-SRS0/SRS1 address as SRS1 for a further forwarding hop, and reverse decodes either form (SRS0 → original sender with HMAC + expiry checks; SRS1 → the prior forwarder's address, one hop back).
var srs = b.mail.srs.create({
secret: b.crypto.generateToken(64),
forwarderDomain: "forwarder.example",
});
// Inbound: alice@bob.com → forwarder → carol@dest.com
var rewritten = srs.rewrite("alice@bob.com");
// → "SRS0=HHHH=TT=bob.com=alice@forwarder.example"
// Bounce arrives back at SRS0=...; decode to deliver
var original = srs.reverse(rewritten);
// → "alice@bob.com"
// A further forwarding hop chains the already-SRS0 address as SRS1
var hop2 = srs.srs1Rewrite(rewritten);
// → "SRS1=HHHH=forwarder.example==HHHH=TT=bob.com=alice@forwarder.example"
srs.reverse(hop2); // → the prior-hop SRS0 address, re-routed one hop back
Last updated 2026-08-08T16:39:49.652Z by seeder.