Enabling postfix for outbound relay via Gmail on OS X Lion (and newer OSX versions)

Update on Oct 25, 2014: Updated For OS X Yosemite.

Update on Dec 21, 2013: I have posted an update to the launchd setup for postfix. You should still read through this post, as most of the setup remains common to both posts.

The background

Mac OSX comes with the postfix MTA, which is a fully featured SMTP server. Under normal circumstances, there is usually no need to enable or configure this software, as most email access is usually done via GUI clients such as the Mail.app – which uses the POP/IMAP and SMTP settings to connect with the email service provider.

However, there are certain circumstances in which having a local SMTP server is very useful, such as:

  1. Allowing the batch logs and output from the cron daemon or other scripts to be sent via Internet email (this is otherwise delivered locally)
  2. Testing email based code; which requires a local sendmail like SMTP server to be present

For such use cases, the postfix server is ideal, as it provides all the features needed (and much more), and is also a nice drop-in replacement for the sendmail program.

While postfix can be used as a full-fledged SMTP server that connects directly to the mail-servers on the Internet, for the use cases above, it is usually better to redirect (i.e., relay) the emails via an authenticated and known server (such as Gmail), as this helps avoid a lot of constraints around open-relays, which are mostly blocked these days to prevent email spam.

Note that configuration of postfix does require dropping down to the command-line, and fiddling with system files. While not complicated, it is definitely not for faint of the heart (though much easier than configuring sendmail).

What you need to know (pre-requisites)

Some of the basic pre-requisites are:

  1. Understanding of the shell prompt and the Terminal.app program
  2. Usage of the sudo program (all the configuration files are owned by root, and hence usage of sudo is essential)
  3. Usage of any command line editor such as vim, Emacs, nano, or any other editor of your choice, that can be invoked with super-user rights (usually via sudo)
  4. A basic understanding of the Apple launchd service manager
  5. The configuration files
  6. A Gmail email ID (actually, any SMTP server credentials will do)

While this article will go step-by-step with the configuration process, knowledge of the above will allow a deeper understanding of the “why” for the changes done.

In the steps below. the $ character before any command represents the shell prompt. Also, I will assume usage of the vim editor in the steps below.

The configuration Files

The configuration files that will be changed are:

 
Name Location Purpose
org.postfix.master.plist /System/Library/LaunchDaemons launchd Configuration for postfix
main.cf /etc/postfix The main postfix configuration
aliases /etc/postfix Local recipient aliases
generic /etc/postfix Sender aliases (for external mail)
passwd /etc/postfix/sasl Relay host authentication

Note that the “/etc/postfix/sasl” directory might not exist, in which case, we will need to create it from the shell prompt:

$ sudo mkdir /etc/postfix/sasl

Step 1: Update the launchd configuration

Update Dec 21, 2013 : While this setup still works, you might want to also see an alternate configuration of postfix’s launchd setup, which I have documented in a follow-up article. The new configuration also allows postfix to be launched when network activity happens on the local SMTP port 25.

The org.postfix.master.plist file located at /System/Library/LaunchDaemons/ is used to start or stop the postfix program on demand, as and when any email is submitted to the mail system for processing. The basic Apple setup is fine, but may need a little tweaking (in my case, the file had a couple of tags which prevented postfix from being started.)

We need to edit the file (as a super user) to match the following content:

$ sudo vim /System/Library/LaunchDaemons/org.postfix.master.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>org.postfix.master</string>
        <key>Program</key>
        <string>/usr/libexec/postfix/master</string>
        <key>ProgramArguments</key>
        <array>
                <string>master</string>
                <string>-e</string>
                <string>60</string>
        </array>
        <key>QueueDirectories</key>
        <array>
                <string>/var/spool/postfix/maildrop</string>
        </array>
        <key>AbandonProcessGroup</key>
        <true/>
        <key>OnDemand</key>
        <true/>
</dict>
</plist>

Step 2: Edit the /etc/postfix/main.cf file

The next step is to edit the main configuration file for postfix. Do make a backup of the current file before editing.

$ cd /etc/postfix
$ sudo cp main.cf main.cf.orig
$ sudo vim main.cf

Note that the main.cf file is a pretty large one, and has a lot of commented out sections, which should be left as is. Please add the following lines at end of the file.

# Set the relayhost to the Gmail Server.  Replace with your SMTP server as needed
relayhost = [smtp.gmail.com]:587
# Postfix 2.2 uses the generic(5) address mapping to replace local fantasy email
# addresses by valid Internet addresses. This mapping happens ONLY when mail
# leaves the machine; not when you send mail between users on the same machine.
smtp_generic_maps = hash:/etc/postfix/generic

# These settings (along with the relayhost setting above) will make
# postfix relay all outbound non-local email via Gmail using an
# authenticated TLS/SASL session.
smtp_tls_loglevel=1
smtp_tls_security_level=encrypt
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps=hash:/etc/postfix/sasl/passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_mechanism_filter = plain

Step 3: Edit the /etc/postfix/aliases file

We need to make a minor edit here, to allow mails sent to the root ID to your local user mailbox.

$ cd /etc/postfix
$ whoami                # This will provide your local user name
$ sudo cp aliases aliases.orig
$ sudo vim aliases
$ sudo newaliases

Find the line in the file which is:

#root:              you

and replace the “you” with the username provided by the whoami command above.  Also, remove the “#” from beginning of the line.

Remember to run the newaliases command (the last command above), or else changes will not take effect!

Step 4: Edit the /etc/postfix/generic file

This file maps the local user address (usually of the form yourid@machine.local) to a valid Internet email address you would like to use when sending mails to the outside world. In our case, it would basically map your Unix user name to the Gmail ID.

$ cd /etc/postfix
$ whoami                # This will provide your local user name
$ hostname              # This will provide your machine name
$ sudo cp generic generic.orig
$ sudo vim generic
$ sudo postmap generic

In the file, add the following lines at the end of the file (replacing the <username> with the output of the whoami command, and <machinename> with output of the hostname command):

# Translate my primary email address to the Gmail address
# This is ONLY for the outbound email, and does not apply to
# local email.
<yourusername>@<machinename>  <your gmail ID, e.g. user@gmail.com>
@<machinename>                <your gmail ID, e.g. user@gmail.com>

Remember to run the last command (postmap) as otherwise the changes will not be picked up!

Step 5: Edit/Create the /etc/postfix/sasl/passwd file

In this step, we store the SMTP authentication (user ID and password) for Gmail, so that postfix can connect as any other SMTP client to Gmail via an authenticated session.

Note that the file may not exist prior to this step, in which case we will create it.

$ sudo mkdir -p /etc/postfix/sasl    # In case the directory does not exist
$ cd /etc/postfix/sasl
$ sudo vim passwd
$ sudo postmap passwd

Create the following file, replacing <gmailusername> with the ID you use for Gmail (with the “@gmail.com” added at the end), and <gmailpassword> with the password you use to login to Gmail.

[smtp.gmail.com]:587    <gmailusername>:<gmailpassword>

Note that if you use two-factor authenication with Google, then the password to use will be a new application specific password generated via Google’s account settings.

Final Step: Test the settings

We are now good to go. Lets test our settings from the terminal:

$ cd /System/Library/LaunchDaemons
$ sudo launchctl load -w org.postfix.master.plist
$ cd ~                             # Just to be safe, move to your home directory
$ mail <your_id>  # Output of the `whoami' command
# Type in a test email and hit Control-D on a new line
$ mail
# Check whether the email has arrived. Hit 'q' on the '?' prompt to quit

$ mail <your gmail ID>       # Lets now try to send an external mail.
# Type in a test email and hit Control-D on a new line

After the second step above, check your Gmail account for the test mail. If it has arrived, then we have a good configuration.

Summary

Setting up the postfix system on OSX is not particularly hard, but does require some steps. Also, this is just the basic setup to get things up and running. Postfix is an industrial strength mail server has a lot of features (and a corresponding number of configurations). Thankfully, the documentation at http://www.postfix.org/documentation.html is pretty good.

For more details on this specific setup, additional documentation is available at http://www.postfix.org/SOHOREADME.html.

[Updated on 19th Feb 2012]: Corrected a typo.  Thanks to jamrok for pointing it out.