Postfix on OSX: Revisited
A few years back, I had written a post on enabling the Postfix MTA as a relay server on OSX, which was quite well received. The article was originally written for OS X Lion, though it remained valid for OSX Mountain Lion, and more recently on
OSX Mavericks as well.
However, things have changed on the OS since the last two versions, which warrants a revisit of the instructions, and a refresh of some of the steps. While the old set of instructions still work, there are changes needed that will keep the configuration future-proof.
The key changes since the article was posted (in February 2012) are:
- The launchd configuration has changed somewhat, and a few elements of the launchctl plist file are now deprecated. The old configuration in the
org.postfix.master.plist
needs to be refreshed - The old configuration depended on local mail-drop in the Postfix queues for the MTA daemon to be started. While this is quite correct (this is Unix, after all), there is another common scenario where the daemon is launched when a client connects to the SMTP ports (default port 25) on the
local machine.
The Updated launchd Configuration
We would like to retain running the daemon on a mail-drop in the queue, but also enable running the MTA when a connection is made to the SMTP port (default 25). The updated org.postfix.master.plist
configuration file listed below does this for us.
In addition, the redundant and deprecated plist tags have also been removed.
You can replace the existing copy with this version as a drop-in replacement at /System/Library/LaunchDaemons/
by using the following shell commands in Terminal.app (assuming you have downloaded the new version at ~/Desktop
):
$ cd /System/Library/LaunchDaemons/ $ sudo cp org.postfix.master.plist org.postfix.master.plist.old $ sudo cp ~/Desktop/org.postfix.master.plist .
The actual configuration file:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//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>ProgramArguments</key> <array> <string>/usr/libexec/postfix/master</string> <string>-e</string> <string>60</string> </array> <key>Sockets</key> <dict> <key>Listeners</key> <dict> <key>SockServiceName</key> <string>smtp</string> <key>SockType</key> <string>stream</string> </dict> </dict> <key>QueueDirectories</key> <array> <string>/var/spool/postfix/maildrop</string> </array> <key>AbandonProcessGroup</key> <true/> </dict> </plist>
Once the file has been copied into the correct location (perhaps by using sudo
), we need to reload the configuration into launchd
:
$ cd /System/Library/LaunchDaemons/ $ sudo launchctl unload org.postfix.master.plist $ sudo launchctl load -w org.postfix.master.plist
This should be sufficient to reload the new configuration.
Testing out the configuration
We can test the changes via the shell itself by trying to connect via telnet to the smtp port and trying out a few basic SMTP commands (HELO
for checking a response, and QUIT
to logout of the SMTP session):
$ cd ~ # Lets get back to $HOME directory $ mail <your_id> # Send yourself an email to check mail-drop $ telnet localhost smtp # Now lets telnet into the server Trying ::1... Connected to localhost. Escape character is '^]'. 220 localhost.local ESMTP Postfix HELO 501 Syntax: HELO hostname QUIT 221 2.0.0 Bye Connection closed by foreign host.
In the sample SMTP session above, the third line (starting with “220” response) indicates that the Postfix MTA is running, and is ready for accepting mail drops via the SMTP port (as opposed to the mail-drop via the mail
command).
First off, thanks for the walkthrough. Works like a charm for me to test email scripts locally i spite of Comcast blocking port 25. 😐
However, I do want to point out a typo in the updated plist here; it gave me a brief roadblock until I found out how to check the syntax with plutil. On line 5, the element isn’t closed properly:
Label
should be
Label
Thanks again for the tutorial!
Philip,
Thanks a lot for catching this typo. I have fixed the plist accordingly.
Awesome. Works like a charm.
Everything works except getting the SMTP server to respond on port 25. Strangely, it works as described when I telnet via 127.0.0.1 to port 25 but not via localhost or an external interface. The telnet connection is opened in all cases — it’s just that I only get the ESMTP server prompts and responses on the 127.0.0.1 interface.
I don’t have any firewall enabled (and I don’t think it would connect at all if that were the issue). This seems to be some issue within Postfix itself.
The problem was I needed the following line in my main.cf:
inet_interfaces = $myhostname, localhost
The default or explicit ‘inet_interfaces = all” did not work because my MacPro has two NICs. When I tried “inet_interfaces = all” Postfix would fail to start with error messages about failing to bind to 0.0.0.0:25. Go figure.
With Yosemite I had to edit /etc/postfix/main.cf and add this beneath the other sasl options:
smtp_sasl_mechanism_filter = plain
You’ll know if you need the above if you see lines like this in mail.log:
postfix/smtp[5351]: Untrusted TLS connection established to smtp.gmail.com[173.194.79.108]:587: TLSv1 with cipher RC4-SHA (128/128 bits)
postfix/smtp[5351]: 7EC2A29B0B8: SASL authentication failed; cannot authenticate to server smtp.gmail.com[173.194.79.108]: generic failure
Thanks!
I have updated the main.cf in the post accordingly.
Everythink is working with maindrop but when I try Telnet I only get :
MBPBureau:postfix admin$ telnet localhost 25
Trying ::1…
Connected to localhost.
Escape character is ‘^]’.
Connection closed by foreign host.
Anyone can help?