Configure Postfix to use Mailgun SMTP Relay on Ubuntu

Mailgun is an awesome free service for sending email safely from your WordPress server. They have a WordPress plugin that uses the Mailgun HTTP API so you can conceal your web server’s IP address – you should never host email on your web server for security reasons like spam, exploitation and risk your server IPs getting blacklisted as a result.

If you are using Monit, CSF ConfigServer Firewall or Linux Malware Detect and would like email reports, then this guide is for you. CSF Firewall’s lfd (login failure daemon) needs postfix or sendmail to send your alerts about system load, login attempt failures and so on. With this guide you will be able to configure Postfix to use Mailgun as an SMTP relay. We will also be setting up postfix forwarding so any local email address (e.g. root@localhost) is automatically forwarded to your gmail account – or any email address you choose.

You will need a Mailgun account to complete this tutorial and the ability to change your postfix settings.

This tutorial was tested on Debian 7, 8 and Ubuntu 16.04.

Configure Postfix to use Mailgun SMTP Relay on Ubuntu

Installation overview

  • Install Postfix
  • Configure Postfix SMTP Relay
    • Set all emails to be forwarded
  • Test Postfix SMTP relay
  • Configure Firewall Exceptions

Install Postfix on Ubuntu

First install postfix and the necessary SASL modules for authenticating with the Mailgun server

sudo apt-get update
sudo apt-get install postfix libsasl2-modules -y

Choose inetd when prompted, you do not need to use your full domain name and it can actually cause issues (relay=local in logs) if you do.

Configure Postfix Mailgun SMTP Relay

Open the postfix config

sudo nano /etc/postfix/main.cf

Your configuration should look something like this, the #comments explain what the lines do.

You will want to make sure you are using your Mailgun postmaster password in the smtp_sasl_password_maps line.

# See /usr/share/postfix/main.cf.dist for a commented, more complete version


# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

myhostname = wp-bullet.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = wp-bullet.com, mail.wp-bullet.com, localhost.localdomain, localhost
relayhost =  [smtp.mailgun.org]:587
#limit to loopback address
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
#limit to loopback address
inet_interfaces = loopback-only
local_recipient_maps = proxy:unix:passwd.byname $alias_maps
#where we specify the forwarding address to e.g. google
virtual_maps = regexp:/etc/postfix/virtual-regexp
#allow inet interfaces for SMTP - also allow submission inet in master.conf
smtpd_client_restrictions = permit_inet_interfaces
smtp_sasl_auth_enable = yes
#set to your mailgun credentials
smtp_sasl_password_maps = static:postmaster@mg.wp-bullet.com:3de4626206c0cbecea409fde2f49147e4
#this is required for authentication to prevent the FROMTO error
smtp_sasl_security_options = noanonymous

Now open the postfix master configuration

sudo nano /etc/postfix/master.cf

Enable the submission line by removing the #

submission inet n       -       -       -       -       smtpd

Ctrl+X, Y and Enter to Save and Exit.

Make sure your mailname is set to your domain

sudo nano /etc/mailname

Paste your domain name

wp-bullet.com

Ctrl+X, Y and Enter to Save.

Test your Postfix configuration syntax to make sure there are no errors

sudo postfix check

Then restart postfix

sudo service postfix restart

Now you can verify postfix is listening on the loopback adapter 127.0.0.1 only

sudo netstat -lntp | grep master

You should see this output that ports 25, 465 and 587 are only running on the loopback adapter which means no external users can access it from its internet IP address.

This is the safest way to send mail from your VPS or dedicated server as an SMTP send only server.

tcp        0      0 127.0.0.1:465           0.0.0.0:*               LISTEN                                                                                                                                                                   3458/master
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN                                                                                                                                                                   3458/master
tcp        0      0 127.0.0.1:587           0.0.0.0:*               LISTEN                                                                                                                                                                   3458/master
tcp6       0      0 ::1:465                 :::*                    LISTEN                                                                                                                                                                   3458/master
tcp6       0      0 ::1:25                  :::*                    LISTEN                                                                                                                                                                   3458/master
tcp6       0      0 ::1:587                 :::*                    LISTEN

Configure Postfix Email Forwarding

Many programs will send email alerts to root@localhost by default. In this section we will configure postfix to forward all emails on the system to your desired email address at gmail or wherever you like

sudo nano /etc/postfix/virtual-regexp

The most common use case is to have emails that are being sent to root@localhost to be forwarded to your gmail address.

This regular expression will match any user at localhost and forward it to test@wp-bullet.com

/.+@localhost/ test@wp-bullet.com

If you want to match any email user at any email domain and forward it to test@wp-bullet.com use the regular expression below.

Warning this will forward all email users and domains to test@wp-bullet.com

/.+@.+/ test@wp-bullet.com

Now we need to postmap it so postfix is aware of forwarding rules

postmap /etc/postfix/virtual-regexp

Reload postfix service

sudo service postfix reload

Testing Postfix Mailgun SMTP Relay

In this section we are going to test that the Mailgun SMTP relay is working. First we will send an email to your desired email address (e.g. test@wp-bullet.com). Afterwards we will send an email to root@localhost to make sure it is forwarded to our desired email address (e.g. test@wp-bullet.com).

Install mail utilities

sudo apt-get install mailutils -y

This will send a an email to test@wp-bullet.com with the subject Postfix Mailgun and the body text ‘This is testing SMTP Relay’

echo "This is testing SMTP Relay." | mail -s "Postfix Mailgun" test@wp-bullet.com

You should get the email immediately, you can check the last 100 lines of your postfix mail logs

tail -n 100 /var/log/mail.log

You should see these logs indicating the Mailgun successfully delivered it (250 Great success).

Aug  4 19:50:58 wp-bullet postfix/pickup[9265]: D83B480985: uid=0 from=
Aug  4 19:50:58 wp-bullet postfix/cleanup[9804]: D83B480985: message-id=<20160804195058.D83B480985@wp-bullet.com>
Aug  4 19:50:58 wp-bullet postfix/qmgr[9266]: D83B480985: from=<root@wp-bullet.com>, size=472, nrcpt=1 (queue active)
Aug  4 19:50:59 wp-bullet postfix/smtp[9799]: D83B480985: to=<test@wp-bullet.com>, relay=smtp.mailgun.org[173.203.37.114]:587, delay=1, delays=0.04/0/0.43/0.53, dsn=2.0.0, status=sent (250 Great success)
Aug  4 19:50:59 wp-bullet postfix/qmgr[9266]: D83B480985: removed

Now you can send an email to root@localhost and see if it is automatically forwarded to your desired email address test@wp-bullet.com

echo "This is testing forwarding." | mail -s "Postfix Mailgun Forward" root@localhost

Check your logs again and you can see the email is being forwarded. Here the orig_to is being forwarded to test@wp-bullet.com

Aug  9 13:34:23 htpcguides postfix/pickup[6103]: B719B81163: uid=0 from=
Aug  9 13:34:23 htpcguides postfix/cleanup[8799]: B719B81163: message-id=<20160809113423.B719B81163@htpcguides.com>
Aug  9 13:34:23 htpcguides postfix/qmgr[3466]: B719B81163: from=<root@wp-bullet.com>, size=461, nrcpt=1 (queue active)
Aug  9 13:34:24 htpcguides postfix/smtp[8801]: B719B81163: to=<test@wp-bullet.com>, orig_to=<root@localhost>, relay=smtp.mailgun.org[104.130.177.23]:587, delay=0.83, delays=0.06/0.03/0.36/0.38, dsn=2.0.0, status=sent (250 Great success)
Aug  9 13:34:24 htpcguides postfix/qmgr[3466]: B719B81163: removed

Troubleshooting Postfix Mailgun SMTP Relay Errors

If you see this error can be fixed with the smtp inetd submssion line in master.conf set in the previous section

Aug  4 19:45:53 wp-bullet postfix/qmgr[9266]: BB9FB80B6B: from=<>, size=2332, nrcpt=1 (queue active)
Aug  4 19:45:53 wp-bullet postfix/submission/smtpd[9284]: connect from wp-bullet.com[178.62.198.10]
Aug  4 19:45:53 wp-bullet postfix/smtp[9280]: BB9FB80B6B: to=<test@wp-bullet.com>, orig_to=<root@wp-bullet.com>, relay=smtp.mailgun.org[104.130.177.23]:587, delay=0.01, delays=0/0/0.01/0, dsn=5.7.0, status=bounced (host smtp.mailgun.org[104.130.177.23] said: 530 5.7.0 Must issue a STARTT LS command first (in reply to MAIL FROM command))
Aug  4 19:45:53 wp-bullet postfix/submission/smtpd[9284]: disconnect from wp-bullet.com[173.62.198.10]
Aug  4 19:45:53 wp-bullet postfix/qmgr[9266]: BB9FB80B6B: removed

This error is because of a firewall blocking the connection (some fixes are below in the Firewall Exceptions section)

Aug  4 18:01:49 wp-bullet postfix/error[4861]: D926D80BA1: to=<htpcguidez@gmail.com>, orig_to=<root@wp-bullet.com>, relay=none, delay=27839, delays=27839/0.05/0/0.02, dsn=4.4.1, status=deferred (delivery temporarily suspended: connect to smtp.mailgun.org[104.130.177.23]:587: Connection timed out)

This error is because smtp_sasl_security_options = noanonymous isn’t set in main.cf enabling plain text SASL authentication.

warning: SASL authentication failure: No worthy mechs found
Aug  4 19:22:30 wp-bullet postfix/smtp[7719]: 8821B81A11: to=<blindpet@gmail.com>, relay=smtp.mailgun.org[173.203.37.114]:587, delay=0.68, delays=0.03/0.02/0.63/0, dsn=4.7.0, status=deferred (SASL authentication failed; cannot authenticate to server smtp.mailgun.org[173.203.37.114]: no mechanism available)

If you see this error

Aug 11 07:11:00 wp-bullet postfix/local[29226]: 2B3E75FACF: to=<webmaster@wp-bullet.com>, orig_to=<root@wp-bullet.com>, relay=local, delay=0.01, delays=0/0/0/0, dsn=5.1.1, status=bounced (unknown user: "webmaster")
Aug 11 07:11:00 wp-bullet postfix/qmgr[2609]: 2B3E75FACF: removed

then remove the domain name (e.g. wp-bullet.com is missing now) from the mydestination line in /etc/postfix/main.cf

mydestination = guides.wp-bullet.com, localhost.wp-bullet.com, localhost

Configure Firewall Exceptions for Postfix

In this section I show how to prevent the timeout errors if you are using CSF ConfigServer Firewall or ufw firewall.

CSF ConfigServer Firewall Exception

Open your CSF ConfigServer Firewall configuration

sudo nano /etc/csf/csf.conf

Make sure port 587 is in TCP_IN and TCP_OUT

# Allow incoming TCP ports
TCP_IN = "20,21,25,53,80,110,143,443,465,587,993,995"

# Allow outgoing TCP ports
TCP_OUT = "20,21,25,53,80,110,113,443,587,993,995,3005"

Use Ctrl+W and enter SMTP_BLOCK to find this section.

Make your configuration match the one below to fix timeout errors.

If you have SMTP_PORTS include 587 it will be blocking the attempt causing the timeout

###############################################################################
# SECTION:SMTP Settings
###############################################################################
# Block outgoing SMTP except for root, exim and mailman (forces scripts/users
# to use the exim/sendmail binary instead of sockets access). This replaces the
# protection as WHM > Tweak Settings > SMTP Tweaks
#
# This option uses the iptables ipt_owner/xt_owner module and must be loaded
# for it to work. It may not be available on some VPS platforms
#
# Note: Run /etc/csf/csftest.pl to check whether this option will function on
# this server
SMTP_BLOCK = "1"

# If SMTP_BLOCK is enabled but you want to allow local connections to port 25
# on the server (e.g. for webmail or web scripts) then enable this option to
# allow outgoing SMTP connections to the loopback device
SMTP_ALLOWLOCAL = "1"

# This option redirects outgoing SMTP connections destined for remote servers
# for non-bypass users to the local SMTP server to force local relaying of
# email. Such email may require authentication (SMTP AUTH)
SMTP_REDIRECT = "0"

# This is a comma separated list of the ports to block. You should list all
# ports that exim is configured to listen on
SMTP_PORTS = "25,465"

# Always allow the following comma separated users and groups to bypass
# SMTP_BLOCK
#
# Note: root (UID:0) is always allowed
SMTP_ALLOWUSER = ""
SMTP_ALLOWGROUP = "mail,mailman"

Ctrl+X, Y and Enter to Save and Exit.

Restart CSF

sudo csf -r
sudo service csf restart

UFW Firewall Exception

If you are using ufw (Universal Firewall) you can create an exception for the postfix SMTP relay like this

sudo ufw allow 587/tcp

Sources

Postfix SMTP relay setup for Mailgun
Configure Postfix + Mailgun on a Cloud VPS
How to Install and Configure Postfix as a Send-Only SMTP Server on Ubuntu 16.04
SASL authentication failure: No worthy mechs found
Problem with outgoing mail from server
Must issue a STARTTLS command first when RECEIVING email