= Use Mutt for email in your Linux Terminal

I'm a Mutt user.
I like viewing and composing emails in the convenience of my Linux terminal.
With a lightweight and minimal client like Mutt, I know that I can have my email available to me regardless of system specifications or access to the Internet.
And because I have a Linux terminal open more often than not, my email client essentially has no footprint on my desktop real estate.
It's hidden away in https://opensource.com/article/21/5/linux-terminal-multiplexer[a terminal tab or multiplexer pane], so I can ignore it when I don't need it but get to it quickly when I do need it.

A commonly perceived problem with Mutt is that most of us use hosted email accounts these days and interact with actual email protocols on only superficially.
Mutt (and ELM before it) was admittedly created back in simpler times, when checking email was a call to `uucp` and a glance `/var/mail`.
However, it's adapted nicely to developing technology and works well with all sorts of modern protocols like POP, IMAP, and even LDAP, so you can use Mutt even if you're using Gmail as your email host.

Because it's relatively rare to run your own email server today, and because Gmail is very common, this article assumes you're using Mutt with Gmail.
If you're concerned about email privacy, you should consider opening an account with https://protonmail.com[ProtonMail] or https://tutanota.com[Tutanota], both of which provide fully encrypted email.
https://github.com/tutao/tutanota[Tutanota has many open source components], and ProtonMail provides an https://protonmail.com/bridge/[IMAP bridge] for paid users so you don't have to work around accessing your email outside of a browser.
However, many companies and schools and organizations don't run their own email services and just use Gmail, so you may well have a Gmail account whether you want one or not.

If you are https://www.redhat.com/sysadmin/configuring-email-server[running your own email server], then setting up Mutt is even easier than what I demonstrate in this article, so just dive right in.

== Install

On Linux, you can install Mutt from your distribution's software repository, and then create a `.mutt` file to hold configuration files:

[source, bash]
----
$ sudo dnf install mutt
$ mkdir ~/.mutt
----

On macOS, use https://opensource.com/article/20/11/macports[MacPorts] or https://opensource.com/article/20/6/homebrew-mac[Homebrew].

On Windows, use https://opensource.com/article/20/3/chocolatey[Chocolatey].

Mutt is a mail user agent (MUA), meaning its job is to read, compose, and send email to an outbound.
It's the job of some other application or service to actually transfer a message to or from a mail server.
Understanding this separation of tasks can help configuration make a little more sense.

It also explains why, in addition to Mutt, you must have helper applications depending on what service you need to communicate with.
For this article, I use IMAP so my local copy of email and my email provider's remote copy of mail remains synchronized.
Should you decide to use POP instead, that configuration is even easier to cnofigure, and can be done with no external tools.
IMAP integration, however, requires OfflineIMAP, a Python application available from https://github.com/OfflineIMAP/offlineimap3[github.com/OfflineIMAP/offlineimap3].

Eventually, you'll be able to install it with the `python3 -m pip` command, but at the time of this writing, you must install OfflineIMAP manually because it's still technically in the process of being ported from Python2 to Python3.

OfflineIMAP requires `imaplib2`, which is also in heavy development at the time of this writing, so I prefer a manual install of that as well.
The process is the same: clone the source code repository with Git, change into the directory, and install with `pip`.

First, install the `rfc6555` dependency:

[source, bash]
----
$ python3 -m pip install --user rfc6555
----

Next, install `imaplib2` from source:

[source, bash]
----
$ git clone git@github.com:jazzband/imaplib2.git
$ pushd imaplib2.git
$ python3 -m pip install --upgrade --user .
$ popd
----

Finally, install OfflineIMAP from source:

[source, bash]
----
$ git clone git@github.com:OfflineIMAP/offlineimap3.git
$ pushd offlineimap3.git
$ python3 -m pip install --upgrade --user .
$ popd
----

If you're using Cygwin on Windows, then you must also install https://pypi.org/project/portalocker[Portalocker].

== Configuring OfflineIMAP

OfflineIMAP reads the configuration file `~/.offlineimaprc` by default.
A template for this file, named `offlineimap.conf`, is included in the Git repository you cloned to install OfflineIMAP.
Move the example file to your home directory:

[source, bash]
----
$ mv offlineimap3.git/offlineimap.conf ~/.offlineimaprc
----

Open the file in your favourite text editor, and read through it.
It's a well-commented file, and it's good to get familiar with the options available.

Here's my `.offlineimaprc` as an example, with comments removed for brevity.
Some values may be slightly different for you, but this gives you a reasonable idea of what your end product ought to look like:

[source, text]
----
[general]
ui = ttyui
accounts = %your-gmail-username%
pythonfile = ~/.mutt/password_prompt.py
fsync = False

[Account %your-gmail-username%]
localrepository = %your-gmail-username%-Local
remoterepository = %your-gmail-username%-Remote
status_backend = sqlite
postsynchook = notmuch new

[Repository %your-gmail-username%-Local]
type = Maildir
localfolders = ~/.mail/%your-gmail-username%-gmail.com
nametrans = lambda folder: {'drafts':  '[Gmail]/Drafts',
                            'sent':    '[Gmail]/Sent Mail',
                            'flagged': '[Gmail]/Starred',
                            'trash':   '[Gmail]/Trash',
                            'archive': '[Gmail]/All Mail',
                            }.get(folder, folder)

[Repository %your-gmail-username%-Remote]
maxconnections = 1
type = Gmail
remoteuser = %your-gmail-username%@gmail.com
remotepasseval = '%your-gmail-API-password%'
## remotepasseval = get_api_pass()
sslcacertfile = /etc/ssl/certs/ca-bundle.crt
realdelete = no
nametrans = lambda folder: {'[Gmail]/Drafts':    'drafts',
                            '[Gmail]/Sent Mail': 'sent',
                            '[Gmail]/Starred':   'flagged',
                            '[Gmail]/Trash':     'trash',
                            '[Gmail]/All Mail':  'archive',
                            }.get(folder, folder)
folderfilter = lambda folder: folder not in ['[Gmail]/Trash',
                                             '[Gmail]/Important',
                                             '[Gmail]/Spam',
                                             ]

----

There are two replaceable values in this file: `%your-gmail-username%` and `%your-gmail-API-password%`.
Replace the first with your Gmail user name.
That's the part of your email address on the left of the `@gmail.com` part.
The second value, you must acquire from Google through a 2-factor Authentication (2fA) setup process (even though you don't need to actually use 2fA to check email).

== Set up 2-factor Authentication for Gmail

Google expects its users to use the Gmail website for email, and so when you attempt to access your email outside of the Gmail interface, you're essentially doing so as a developer (even if you don't consider yourself a developer.)
In other words, you're creating what Google considers an "app".
To obtain a developer-level "app password", you must setup 2-factor authentication, and through that process you're provided with an app password, which Mutt can use to login outside the usual browser interface.
 
For safety, you can also add a recovery email address.
To do that, go to https://myaccount.google.com/security and scroll down to the *Recovery Email*.
To set up 2-factor Auth, go to https://myaccount.google.com/security and click on the *2-step Verification* link to activate and configure.
This requires a mobile phone for setup.

After activating 2fA, you get a new option on https://myaccount.google.com/security.
Click on *App passwords* to create a new app password for Mutt.
Google generates a password for you, so copy it and paste it into your `.offlineimaprc` file in the place of the `%your-gmail-API-password%` value.

Placing your API password in your `.offlineimaprc` file stores it in plain text, which can be dangerous.
For a long while, I did this and felt fine about it because my home directory is encrypted.
However, in the interest of better security, I now encrypt my API password with GnuPG.
That's somewhat beyond the scope of this article, but I've written LINK-TO-PYTHON-GNUPG-ARTICLE[an article demonstrating exactly how to set up GPG password integration] for yourself.

== Enabling IMAP in Gmail

There's one last thing before you can say good-bye to the Gmail web interface forever: you must enable IMAP access to your Gmail account.

To do this, go to the Gmail web interface and click the Cog icon in the upper right corner of the UI, and select *Settings*.
In Gmail *Settings*, click the *POP/IMAP Download* tab, and enable the radio button next to *Enable IMAP*.
Save your settings.

Now Gmail is configured to give you access to your email outside of a web browser.

== Configuring Mutt

Now that you're all setup for Mutt, you'll be happy to learn that the configuration for Mutt itself is actually the easy part.
Like https://opensource.com/article/18/9/handy-bash-aliases[`.bashrc`] and https://opensource.com/article/19/9/adding-plugins-zsh[`.zshrc`] and `.emacs` files, there are many examples of very good `.muttrc` files available on the Internet.
My own configuration file has borrowed options and ideas from Kyle Rankin and Paul Frields and many others, so I've abbreviated my `.muttrc` file to just the essentials in the interest of simplicity:

[source,text]
----
set ssl_starttls=yes
set ssl_force_tls=yes

set from='tux@example.com'
set realname='Tux Example'

set folder = imaps://imap.gmail.com/
set spoolfile = imaps://imap.gmail.com/INBOX
set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
set smtp_url="smtp://smtp.gmail.com:25"
set move = no
set imap_keepalive = 900
set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"

# Paths 
set folder           = ~/.mail
set alias_file       = ~/.mutt/alias
set header_cache     = "~/.mutt/cache/headers"
set message_cachedir = "~/.mutt/cache/bodies"
set certificate_file = ~/.mutt/certificates
set mailcap_path     = ~/.mutt/mailcap
set tmpdir           = ~/.mutt/temp
set signature        = ~/.mutt/sig
set sig_on_top       = yes

# Basic Options
set wait_key = no
set mbox_type = Maildir
unset move               # gmail does that

# Sidebar Patch
set sidebar_visible = yes
set sidebar_width   = 16
color sidebar_new color221 color233

## Account Settings
# Default inbox
set spoolfile = "+example.com/INBOX"

# Mailboxes to show in the sidebar.
mailboxes +INBOX \
          +sent \
          +drafts

# Other special folder
set postponed = "+example.com/drafts"

# navigation
macro index gi "<change-folder>=example.com/INBOX<enter>" "Go to inbox"
macro index gt "<change-folder>=example.com/sent" "View sent"
----

Nothing in this file requires changing, but consider replacing the fake name `Tux Example` and the fake address `example.com` with something that applies to you.
Copy and paste this text into a file and save it as `~/.mutt/muttrc`.

== Launching Mutt

Before launching Mutt, run `offlineimap` from a terminal to sync your computer with the remote server.
The first run of this takes _a long time_, so leave it running over night.

Once your account has syncronized, you can launch Mutt:

[source,bash]
----
$ mutt
----

Mutt prompts you for permission to create the directories it needs to organize your email activity, and then displays a view of your inbox.

== Learn Mutt

Learning Mutt is a mixture of exploring the application and finding your favourite hacks for your `.muttrc` config.
My config file integrates Emacs for composing messages, LDAP so I can search through contacts, GnuPG so I can encrypt and decrypt messages, link harvesting, HTML views, and much more.
You can make Mutt anything you want it to be (as long as you want it to be an email client), and the more you experiment, the more you discover.

