The Sender Rewriting Scheme, so forwarded mail still passes SPF: the envelope sender is rewritten into an address at the forwarder's own domain, and bounces to that address are turned back into the original sender.
{:ok, srs} = Sovite.SRS.forward("alice@example.com", "fwd.example.net", secrets: ["s3cret"])
#=> "SRS0=HHHH=TT=example.com=alice@fwd.example.net"
Sovite.SRS.reverse(srs, secrets: ["s3cret"])
#=> {:ok, "alice@example.com"}This is the Shevek scheme as libsrs2 and postsrsd implement it, so addresses can be reversed by either side:
SRS0=HHHH=TT=domain=local@srs-domainfor a plain address.TTis the day number (days since the Unix epoch, mod 1024) in two base32 characters.HHHHis the first four characters of the base64 HMAC-SHA1, keyed with the secret, ofTT <> domain <> locallower-cased (ASCII only).- An address that is already
SRS0athop1becomesSRS1=HHHH=hop1==HHHH=TT=domain=local@srs-domain, so the bounce goes back tohop1rather than through every forwarder. The hash is overhop1 <> "=HHHH=TT=domain=local", again lower-cased. - An
SRS1address keeps its first hop; only the hash is replaced.
Bounces may come back with the local part case-mangled, so hashes are compared without regard to case, like libsrs2 does.
Summary
Functions
Rewrites address into an SRS address at srs_domain.
Turns an SRS address back into the address it was made from: an
SRS0 address into the original sender, an SRS1 address into the
SRS0 address at the first forwarder.
Whether address (or a bare local part) is an SRS address.
Functions
Rewrites address into an SRS address at srs_domain.
An address already at srs_domain is returned unchanged.
Options
@spec reverse(String.t(), keyword()) :: {:ok, String.t()} | {:error, :not_srs | :malformed | :bad_hash | :expired}
Turns an SRS address back into the address it was made from: an
SRS0 address into the original sender, an SRS1 address into the
SRS0 address at the first forwarder.
The separator after SRS0/SRS1 may be =, + or -.
Options
:secrets- required. Every secret is tried.:max_age- how many days anSRS0address stays valid. Defaults to 21.:now- theDateTimeto check the age against. Defaults to now.
Whether address (or a bare local part) is an SRS address.
iex> Sovite.SRS.srs?("srs0+HHHH=TT=example.com=alice@fwd.example.net")
true
iex> Sovite.SRS.srs?("alice@example.com")
false