postfix: only enable sasl for some relays

Some mail hosts, like SendGrid, require you to use SASL authentication to relay mail through their systems. Many of those same hosts only want you to send mail for verified, double-opt-in squeaky clean recipients. But what if you have a subset of recipients that are not verified, and you want to continue sending mail to those yourself?

Seven (!) years ago, I covered basic content based routing in Postfix. You can use that same mechanism to route mail based on a custom header that you've inserted into your mail that designates a particular message as verified.

For example, from Python you might do the following in your application server code.

from django.core.mail get_connection
from django.core.mail EmailMessage

def send_message(to_user, from_addr, subject, body):
    connection = get_connection()
    headers = {"X-Recipient-Verified": to_user.is_verified}
    message = EmailMessage(
        subject, body, from_addr, [],
        connection=connection, headers=headers)

To configure Postfix, you just need to add a header_checks file. This particular class of emails will get routed through SendGrid.

# /etc/postfix/header_checks
/^X-Recipient-Verified: True$/ FILTER smtp:[]:587

In your Postfix config file, you need to point to the header_checks file, and provide the boilerplate SendGrid SASL config.

# /etc/postfix/

header_checks = regexp:/etc/postfix/header_checks

smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/smtp_sasl_password_maps
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = may
header_size_limit = 4096000

Where this config differs from the SendGrid documentation is the smtp_sasl_password_maps setting. They suggest you get started by using the static mapping. This works fine as long as you're ONLY sending through SendGrid. But in our case, we need to enable SASL conditionally.

To do this, we need another external file, smtp_sasl_password_maps. The key here is that if there is no hostname match in the SASL password map, then it proceeded without authentication.

# /etc/postfix/smtp_sasl_password_maps
[]:587 yourSendgridUsername:yourSendgridPassword

Then, you need to compile the text file smtp_sasl_password_maps into a binary smtp_sasl_password_maps.db, and restart postfix.

postmap /etc/postfix/smtp_sasl_password_maps
service postfix restart

If you fail to disable SASL for non-SendGrid relays, you will likely find that while mail to large hosts like gmail is fine, mail to smaller hosts that do not support SASL will fail:

deferred (SASL authentication failed: server[] offered no compatible authentication mechanisms for this type of connection security)

I'm currently working at NerdWallet, a startup in San Francisco trying to bring clarity to all of life's financial decisions. We're hiring like crazy. Hit me up on Twitter, I would love to talk.

Follow @chase_seibert on Twitter