avatar

Andres Jaimes

Reading gmail email on macOS using fetchmail, postfix, sendmail, and alpine

By Andres Jaimes

This post describes the process for setting up macOS to read and store email locally –without deleting it from the remote server. The downloaded email can be read with a local application like Alpine.

The process goes like this:

  1. fetchmail pulls emails from gmail
  2. fetchmail hands the emails to postfix for local delivery
  3. use alpine to read our locally delivered email
  4. use alpine to write an email, which uses postfix to relay it via gmail
  5. we can use sendmail for any other application that requires us to send emails

Configuring the hostname

  1. From the Apple menu, open System Settings, and look for hostname. It should be under the Sharing settings.
  2. Update the hostname to something that is easy to remember/type/etc. Mine, for example, is set to macos.local
  3. Save the changes, open a terminal, and check the new name shows up with the following command:
hostname

Allowing app access to gmail

Read this article.

Installing Alpine

alpine can be replaced with other mail clients, like mutt, or good old mail.

brew install alpine

Run alpine, and send an email to your local account. Typing your own username in the To field should be enough. It should work, but don’t worry if it does not, keep reading.

Configuring postfix

postfix is the application in charge of delivering email locally. When running, it listens for requests on port 25.

It’s expected to have a working copy of postfix on every mac. We should get some output from the following command to give us a clue whether it’s there or not.

postconf -d | head -n 1

Type the following commands to read its current configuration, and status:

postconf -n
sudo postfix status

We may get something like the following, but it’s ok. Keep reading.

postfix/postfix-script: the Postfix mail system is not running

Start postfix, and check it’s listening on localhost:

sudo postfix start
sudo lsof -i :25

We should get output like the following:

master 12345 root  ... TCP localhost:smtp (LISTEN)

if not, re-read its config:

sudo postfix reload

Installing fetchmail

fetchmail is the application we’ll use to download the email. This program automatically uses the local process listening on port 25 –postfix in our case– to deliver email locally. Both pieces, fetchmail and postfix, coordinate to deliver the email to our local file.

Install fetchmail:

brew install fetchmail

Create a ~/.fetchmailrc configuration using the following contents as a guide:

# Replace "local_user" with your local username
set logfile "/Users/local_user/.fetchmail/fetchmail.log"
poll imap.gmail.com proto IMAP
# Use gmail app password, not regular email password
user "gmail-user@gmail.com"
pass "gmail-app-password"
# Local user to deliver mail to. Replace "local_user" with your local username
is "local_user"
# Force secure connection.
ssl
# Keep a copy of the mail on the server.
keep
# Gmail folder to fetch from.
folder "INBOX"
# Fetch limit
fetchlimit 10

Restrict permissions to others:

chmod 600 ~/.fetchmailrc

Try it:

fetchmail -v --fetchlimit 1

Verify with Alpine that the email is there. Alternatively, we can check our mail file in /var/email, for example:

# Replace "local_user" with your local username
less /var/mail/local_user

Visit the fetchmail manual for additional configurations.

Starting postfix in daemon mode

Simply invoking

fetchmail -d 900

will poll every 15 minutes all the hosts described in our ~/.fetchmailrc file. As an alternative, we can update the configuration file to set a polling value:

# Poll every 10 minutes
set daemon 600

If we do this, fetchmail will always start in daemon mode unless overriden with the command-line option --daemon 0 or -d0. Only one daemon process is permitted per user.

Read the daemon mode section in the fetchmail manual for additional options.

Sending email

Warning: Work in progress. There are additional steps needed to prevent postfix from relaying email sent to the local computer. Don’t try it until complete, since it may affect other applications logging process, like cron’s.

Edit /etc/postfix/main.cf:

relayhost = [smtp.gmail.com]:587

smtp_use_tls = yes
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_CAfile = /etc/ssl/cert.pem

Create /etc/postfix/sasl_passwd:

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

Secure the file and compile it:

sudo chmod 600 /etc/postfix/sasl_passwd
sudo postmap /etc/postfix/sasl_passwd

Reload the configuration:

sudo postfix reload

And try it by sending a message to an external account with alpine.

References