Selectively forwarding email with Postfix
You may not always want to send every email though Sendamatic. Perhaps you only want to initially forward a small percentage of mail to test the service, or you may need to handle certain types of messages via different forwarders.
You can do this using Postfix header_checks
.
Configure your forwarders
In these examples we'll only create one forwarder, Sendamatic. However, you can add more forwarders in the same fashion. Postfix will continue to directly deliver any mail not specifically matched by the header_checks
patterns.
Create the credential files
Add the following line to /etc/postfix/sasl_passwd
# Create the postfix hashmap
sudo postmap hash:/etc/postfix/sasl_passwd
# Secure the credential files, only allow root to ready them
sudo chown root:root /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
sudo chmod 0600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
Configure Postfix
sudo postconf -e "header_checks = regexp:/etc/postfix/header_checks" \
"smtp_sasl_auth_enable = yes" \
"smtp_sasl_security_options = noanonymous" \
"smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd" \
"smtp_use_tls = yes"
# CA certificates for Debian / Ubuntu
sudo postconf -e "smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt"
# CA certificates for Redhat / CentOS
sudo postconf -e "smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt"
Add regex patterns
In /etc/postfix/header_checks
, add regular expressions to match headers to forwarders.
These patterns may also match within the body of an email, so bear that in mind if you can't trust the email contents
Routing based on email subject
Here Postfix forwards only password reset and invoice emails through Sendamatic.
/^[sS]ubject:.*Password reset.*$/ FILTER smtp:[in.smtp.sendamatic.net]:587
/^[sS]ubject:.*Invoice.*$/ FILTER smtp:[in.smtp.sendamatic.net]:587
Routing a percentage of email
If you can configure the sending application to add a header a percentage of the time, that can then drive the Postfix routing.
import smtplib
import random
from email.message import EmailMessage
msg = EmailMessage()
msg.set_content('Hello world')
msg['Subject'] = 'Test message'
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
# Let Postfix forward percentage_chance % of email
percentage_chance = 0.05
if random.random() < percentage_chance:
msg['X-Forwarder'] = 'sendamatic'
s = smtplib.SMTP('postfix-host')
s.send_message(msg)
s.quit()
Reload Postfix
Finally, reload the Postfix configuration to make your changes take effect
Verifying the changes
Swaks is a great tool for testing SMTP. Quickly adding headers is easy:
swaks --header 'X-Forwarder: sendamatic' -f '[email protected]' -t '[email protected]' --server 'postfix-host'
In the postfix logs, you can check the relay
value to verify the routing works as expected.