I want my Mac to email me when a cron job fails. By default it can’t: macOS installs Postfix but leaves it unconfigured for outbound mail. Here I point Postfix at Gmail’s SMTP (Simple Mail Transfer Protocol) relay so system mail leaves the machine.

I first set this up on macOS Catalina. The same steps still work on current macOS because Postfix remains the default mail transfer agent.

If you run Unix or Linux instead, follow my Unix/Linux version of this guide.

Why would you want to do this?

  • You have cron jobs running on your system and need email when they fail.
  • You want an email when certain things happen on your system.

Before you start

  • Administrator (sudo) access on the Mac.
  • A Gmail account with 2-Step Verification enabled.
  • A Google app password generated for this Mac.
  • About 10 minutes.

Back up the Postfix config

I always back up system files before editing them so I can roll back if mail breaks.

sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.bak

Store the Gmail credentials

Create the password map file:

sudo vi /etc/postfix/sasl_passwd

Add one line, substituting your Gmail address and app password:

[smtp.gmail.com]:587 your-email@gmail.com:your-app-password

Compile the password map so Postfix can read it:

sudo postmap /etc/postfix/sasl_passwd

Confirm the compiled .db file exists:

ls -l /etc/postfix/sasl_passwd.db

You should see the file listed. If it is missing, postmap failed and the test email later will silently drop.

Lock down permissions so only root can read the password:

sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db

Point Postfix at the Gmail relay

Edit the main Postfix config:

sudo vi /etc/postfix/main.cf

Append this block to the bottom of the file. It tells Postfix to authenticate via SASL (Simple Authentication and Security Layer) and encrypt with TLS (Transport Layer Security). The upstream Postfix SASL README documents every directive:

# Gmail SMTP relay
relayhost = [smtp.gmail.com]:587

# Enable SASL authentication in the Postfix SMTP client.
smtpd_sasl_auth_enable = yes
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options =
smtp_sasl_mechanism_filter = AUTH LOGIN

# Enable Transport Layer Security (TLS), i.e. SSL.
smtp_use_tls = yes
smtp_tls_security_level = encrypt
tls_random_source = dev:/dev/urandom

Reload Postfix so it picks up the new config:

sudo postfix reload

You should see postfix/postfix-script: refreshing the Postfix mail system with no errors.

Test delivery

Send yourself a test message:

date | mail -s "Test Email" your-email@gmail.com

The email should arrive within a minute. If it does, you are done. Otherwise, read on.

Troubleshooting

If the test email never arrives, tail Postfix’s logs while you resend the test:

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

Common error strings and their fixes:

  • 535-5.7.8 Username and Password not accepted: the app password is wrong, or the Gmail account lacks 2-Step Verification. Regenerate the app password, rewrite /etc/postfix/sasl_passwd, then re-run sudo postmap /etc/postfix/sasl_passwd.
  • SSL_connect error or TLS handshake failures: smtp_use_tls = yes and smtp_tls_security_level = encrypt are missing or misspelled in main.cf.
  • no mechanism available: smtp_sasl_mechanism_filter = AUTH LOGIN is missing, or smtp_sasl_security_options = was omitted. Double-check the block above.
  • Nothing appears in the log at all: the mail command never reaches Postfix. Confirm Postfix is running with sudo launchctl list | grep postfix.

Roll back

Restore the original config and clear the credentials:

sudo cp /etc/postfix/main.cf.bak /etc/postfix/main.cf
sudo rm /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
sudo postfix reload

References