SMTP Sender-Dependent SASL Authentication in Postfix

3 minute read

Published:

In a previous article I discussed how to use Mailgun as a relay in Postfix. This works great if you are only sending email from one website on your server, often times however you will have multiple websites sending email on a single server. In these cases, websites NOT belonging to the sender domain will say sent via SENDER_DOMAIN: wes@example.com via necrux.com

To avoid this situation you can configure Postfix for sender-dependent authentication so that emails are properly relayed through their respective domain. In my examples we will be using Mailgun, however you can use any relay of your choosing; you can even use different relays for different domains!

Configure Postfix Manually

To configure Postfix you will need the following set-up in /etc/postfix/main.cf:

smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sender_dependent_authentication = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay

The above settings specify a separate file to declare the relay hosts, however if you are only using one relay (e.g. Mailgun), you can replace that setting with the standard relayhost parameter:

relayhost = [smtp.mailgun.org]:587

Configure Postfix with postconf

Alternatively you may want to configure /etc/postfix/main.cf with the postconf command. Using postconf offers a couple of advantages:

  1. It warns about possible mis-typed parameter names.
  2. It avoids accidentally creating duplicate entries.

To configure the main.cf with postconf run the following:

postconf -e "smtp_sasl_auth_enable = yes"
postconf -e "smtp_sasl_security_options = noanonymous"
postconf -e "smtp_sender_dependent_authentication = yes"
postconf -e "smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd"

Single relayhost

postconf -e "relayhost = [smtp.mailgun.org]:587"
postconf -# sender_dependent_relayhost_maps

Multiple relayhosts

postconf -e "sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay"
postconf -# relayhost

Configure the Password Maps File

The smtp_sasl_password_maps file contains a mapping of all domains to the appropriate SMTP credentials. The syntax must be as follows:

@<domain> <smtp_user>@<domain>:<smtp_password>
@<domain> <smtp_user>@<domain>:<smtp_password>

Example:

@necrux.com postmaster@necrux.com:password

Note: The @domain parameter can contain regex.

Next you must run postmap against /etc/postfix/sasl_passwd to create a Postfix lookup table:

postmap /etc/postfix/sasl_passwd

Configure the Relayhost Maps File

The /etc/postfix/sender_relay file contains a mapping of all domains to the appropriate relay. This option is not necessary if you are using a single relay. The syntax must be as follows:

@<domain> <relay>
@<domain> <relay>

Example:

@necrux.com [smtp.mailgun.org]:587

Note: The @domain parameter can contain regex.

As with smtp_sasl_password_maps, you must run postmap against /etc/postfix/sasl_passwd to create a Postfix lookup table:

postmap /etc/postfix/sender_relay

Configuring a Catchall Domain

There are times when you may deem it necessary to configure a catchall domain so that any sender domain NOT explicitly defined can still relay email. To do this you will need to define the relayhost parameter in /etc/postfix/main.cf and configure a catchall relay in /etc/postfix/sasl_passwd.

postconf -e "relayhost = [smtp.mailgun.org]:587"
echo "[smtp.mailgun.org]:587 <smtp_user>@<domain>:<smtp_password>" >> /etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd

Where and are the credentials for the catchall .

Testing the Solution

The quickest way to test the solution is to send a couple of emails from the command line using the mail command.

echo "Here is my relay test email." |\
mail -s "Mailgun Relay" -r <sender>@<sender_domain> <recipient>@<recipient_domain>

If the emails are not being sent/received, first check the local log at /var/log/maillog to see if the message was sent. If it left the server but never arrived at the destination, refer to the logs at Mailgun. Otherwise double-check your configuration settings and make certain that you restarted Postfix!

Automating the Solution

Configuring Postfix can be tedious work, especially if you are dealing with multiple domains. I have a bash script on GitHub that will automate this process, all you need is your Mailgun API key.