Setting up Postfix + Mailgun for multiple outgoing domains

For quite some time I’ve been having trouble with Gmail categorically classifying most of my outgoing mail as spam purely on the basis of my SMTP host being on a Linode VPS. No matter how much care and feeding went into my SPF+DKIM configuration, the Almighty Google would just arbitrarily decide that no, my email is not to be trusted after all. (This is pretty much the biggest reason why email is bad.)

After a brief kvetch about this with David, he pointed me at Mailgun, an enterprise-level SMTP relay (among other things). I’d looked at SMTP relays in the past but most of them are ridiculously expensive, but Mailgun has one very compelling feature:

It costs 80 cents per 1000 outgoing emails.

I send about 50 emails per month, so that means Mailgun will cost me a whopping… 4 cents per month.

I think I can afford that.

Anyway, the tricky bit was actually setting up my Postfix relay, since I have multiple domains that I serve but Mailgun only uses a single relay host for all of them. There’s a whole bunch of tutorials of varying quality out there (and the Postfix docs are, well, very FOSS), but after stumbling through the documentation for a bit and doing a web search on some of the options I managed to find a smattering of things that seem to have a working setup! This gist by zmwangx was particularly helpful, although it only covers relaying specific users and not entire domains.

The first step, of course, is to set up a Mailgun account, and set up the domains you want relays for and apply the new DNS settings for them.

Now go to the “Sending > Domain Settings” section of the Mailgun dashboard, and select the “SMTP credentials” tab.

Create a file on the server, /etc/postfix/sasl_passwd. Now go through each domain on the Mailgun dashboard, and for each one, click “reset password,” then select the “copy” link that flashes in the corner of the screen. Now add a line to the sasl_passwd file in the form of @domain user@domain:password. So, your file should look something like this:

/etc/postfix/sasl_passwd
@domain1.example postmaster@domain1.example:JSLDAJFS3897ur9owuOWEu
@domain2.example postmaster@domain2.example:jaopeijSDJO89o32uo252352

Save the file and then run chmod 600 /etc/postfix/sasl_passwd as an extra bit of security.

The next bit is to configure the relay hosts per outgoing domain; this goes into a file, /etc/postfix/sender_relay:

/etc/postfix/sender_relay
@domain1.example [smtp.mailgun.org]:587
@domain2.example [smtp.mailgun.org]:587

Now, run the command postmap /etc/postfix/sasl_passwd /etc/postfix/sender_relay. This will generate two new files, /etc/postfix/sasl_passwd.db and /etc/postfix/sender_relay.db. (You’ll need to rerun this command every time you add an entry to those files, incidentally.)

Finally, configure Postfix to use these relays, by adding the following into /etc/postfix/main.cf:

/etc/postfix/main.cf
relayhost=[smtp.mailgun.org]:587
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options=noanonymous
smtp_use_tls=yes
smtp_sender_dependent_authentication=yes
sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay

(In theory the sender_relay stuff shouldn’t be necessary, but in practice it seems to be.)

Anyway, now postfix reload and send some test emails.

Also, note that the above configuration stuff is simply for adding Mailgun relaying to an existing working Postfix configuration. It is still your responsibility to ensure that you’re only accepting email from authorized users in the first place! Some useful configuration directives that might be helpful for that:

/etc/postfix/main.cf
smtpd_recipient_restrictions = permit_mynetworks,
    permit_sasl_authenticated,
    reject_invalid_hostname,
    reject_unknown_recipient_domain,
    reject_unauth_pipelining,
    check_client_access hash:/etc/postfix/rbl_override,
    reject_unauth_destination
smtpd_data_restrictions = reject_unauth_pipelining
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_tls_security_options = noanonymous

You’ll also need some settings for smtpd_sasl_type and smtpd_sasl_path. Explaining that is outside of the scope of this article (but for what it’s worth I use dovecot’s mechanism, configured to use PAM login).

Oh, and another nice benefit of this setup: no longer having to manage my own hecking DKIM signing. Thank goodness for that in particular.

Comments

Before commenting, please read the comment policy.

Avatars provided via Libravatar