Preface
Mailcow is an awesome self-hosted, container-based email solution.
SRS (Sender Rewriting Framework) (from Wikipedia):
For a mail transfer agent (MTA), the Sender Rewriting Scheme (SRS) is a scheme for rewriting the envelope sender address of an email message, in view of remailing it. In this context, remailing is a kind of email forwarding. SRS was devised in order to forward email without breaking the Sender Policy Framework (SPF), in 2003.
Mailcow does not include support for SRS which causes problems with email aliases that point to external email addresses.
This article show how I have ‘hacked’ SRS into Mailcow using postsrsd. Most of the Postfix configuration was taking from this postsrsd issue.
Updated 2023-05-21: PostSRSd has been upgraded to 2.x in Alpine 3.18+ - The article has been updated to work with PostSRSd 2.x. - I am currently not running Mailcow, so I cannot confirm if it works or not.
Container
I have created a container with postsrsd.
First, add a new container to docker-compose.override.yml
postsrsd-mailcow:
image: ajoergensen/postsrsd:latest
restart: always
environment:
- SRS_DOMAIN=mydomain.dom
- SRS_SECRET=<secret>
networks:
mailcow-network:
ipv4_address: ${IPV4_NETWORK:-172.22.1}.42
SRS_DOMAIN
is the domain to be used as sender domain for the rewritten emails.
SRS_SECRET
is the key used to generate the hashed rewritten sender addresses.
This should be treated with same care as a password as knowledge of this secret would allow someone to use your mailserver as an open relay. It is generated using this command:
dd if=/dev/random bs=18 count=1 | base64
After adding the container, start it:
docker-compose up -d postsrsd-mailcow
The container’s configuration is documented on Docker Hub.
Postfix configuration
In the file data/conf/postfix/extra.cf
(relative to where the Mailcow git repository is checked out), add these lines:
sender_canonical_maps = socketmap:inet:172.22.1.42:10003:forward
sender_canonical_classes = envelope_sender
recipient_canonical_maps = socketmap:inet:172.22.1.42:10003:reverse, proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf
recipient_canonical_classes = envelope_recipient, header_recipient
In the file data/conf/postfix/master.cf
, add these lines:
# SRS config
cleanup-srs unix n - - - 0 cleanup
-o sender_canonical_maps=socketmap:inet:172.22.1.42:10003:forward
-o sender_canonical_classes=envelope_sender
-o recipient_canonical_maps=regexp:/opt/postfix/conf/regex_sender_canonical_srs
127.0.0.1:10029 inet n - - - - smtpd
-o cleanup_service_name=cleanup-srs
-o smtpd_tls_security_level=none
-o content_filter=smtp:
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_milters=
In the file data/conf/postfix/regex_sender_canonical_srs
, add this line:
/^srs=(.*)@(.*)$/ ${1}@${2}
In the file data/conf/postfix/custom_transport.pcre
, add this line:
/^srs=.*@.*$/ smtp:127.0.0.1:10029
Finally, restart the Postfix container:
docker-compose restart postfix-mailcow / docker compose restart postfix-mailcow
Add external aliases
Any external email address must be prefixed with “srs=” in order for it to be routed through postsrsd:
And do not worry, the srs= part is stripped before the email leaves the server.