I wrote this post because there are lots of articles that describe how to set up postfix on OS X which recommend strange things, like disabling System Integrity Protection. I’ll show you how it can be achieved easily without any ugly hacks.

Here’s why you may want to use postfix on OS X:

  • if you are managing an OS X server (like in a build farm) and want to be able to send automated emails
  • if you use mutt or other mailer like mu4e and want a persistent outgoing mail queue that works offline
  • to write and debug scripts that use default system mailer

First thing you need to know about postfix in OS X is that it is already set up and running! If you open /System/Library/LaunchDaemons/com.apple.postfix.master.plist in your favorite editor, you can see that it is set up to restart every 60 seconds or so (the -e 60 argument). So it is started, runs for 60 seconds and then exits to be automatically respawned by launchd. This means that you don’t ever need to start or restart it yourself after you edit the configuration.

What confuses many people is that the Apple-flavored postfix doesn’t write logs into the places you expect it to (/var/log). This is because Apple rewrites some unix tools to use their own logging subsystem, and you just need to learn the proper incantation to filter through those logs. Theoretically you could do it with the tool called “Console”, but I didn’t have much luck with it. Instead I was successfully debugging problems with email delivery using this command in the terminal:

log stream --predicate '(process == "smtpd") || (process == "smtp") || (process == "master")' --info

Also, when you get to actually configuring postfix, you absolutely must make sure that your /etc/postfix/main.cf contains at least the following:

mail_owner=_postfix
setgid_group=_postdrop
myhostname=localhost.localdomain
compatibility_level = 2

The mail_owner and setgid_group must be like that because Apple has a bit different security model than regular unix.

The myhostname can be arbitrary, but it must be a fully-qualified domain name (with the domain part).

Without setting compatibility_level to 2 I just failed to make it work.

From here, you can proceed to configure postfix in any way you want.