I've been using mutt for my email for probably a year and a half now, and I'm a pretty big fan.
There are a whole bunch of benefits:
(If you genuinely enjoy your webmail, or want it to tie directly into other Google or Microsoft tools, or whatever, there are downsides as well--but I definitely prefer the terminal.)
However, it can be intimidating to start using a CLI mail tool. This post is intended to walk through some of the infrastructure you'll need to set up. As always, the Arch Wiki is an excellent source of information on these as well.
All configurations in this post are taken from my dotfiles.
We're going to need three pieces of software for this.
The first is a tool that doesn't seem to have a formal category name, but which I will call a "mail fetcher". It syncs mail between your local machine that you're reading and writing mail on, and the server that is hosting that mail. We'll install mbsync for this purpose.
The second is a "mail transfer agent", which sends mail through a mail server. We'll install msmtp for this purpose.
The third is a "mail user agent", which functions as a mail client where we can read and write mail. We'll install mutt for this purpose.
Mbsync and msmtp should be mostly background tools after they're first set up; you should only rarely need to interact directly with them. The bulk of your interactions as a user will be with the MUA, mutt.
Quick contextual notes: IMAP is a protocol for fetching email from a server. It supplanted the older POP3. SMTP is a protocol for sending email. A MUA is a "mail user agent"; it's basically a mail client that lets you look at and interact with mail. It may or may not have other features, like fetching or sending mail. An MTA is a "mail transfer agent"; it sends mail.
Mbsync is a tool for fetching mail to your local computer ("Mail Box Sync"). It can be run on-demand or in a service, and will keep your mailbox up-to-date for you. It also sends your changes (deleting messages, sending messages, etc.) back up to the server. It should be available from your distro's package repository; sometimes, for reasons that are unclear to me, it is called "isync" instead.
The configuration here is intended to establish your authentication information, what email to sync, and how to put it onto your local machine.
This is one account, taken from my config. We'll go through it line-by-line.
~/.mbsyncrc
IMAPAccount migadu
Host imap.migadu.com
User jordan@jnewport.dev
PassCmd "cat ~/.config/passwords/migadu-email"
SSLType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore migadu-remote
Account migadu
MaildirStore migadu-local
Subfolders Verbatim
Path ~/Mail/migadu/
Inbox ~/Mail/migadu/INBOX
Channel migadu
Far :migadu-remote:
Near :migadu-local:
Patterns *
Create Both
Remove Both
SyncState *
IMAPAccount migadu
: Starts the account configuration section for an account
named "migadu". This name can be referred to elsewhere, including from the
command line.
Host imap.migadu.com
: This is the IMAP URL for my mail provider. Most
providers (even Gmail and Outlook) have one; you should be able to find it in
their documentation.
User jordan@jnewport.dev
: This is my email address.
PassCmd "cat ~/.config/passwords/migadu-email"
: This fetches my email
account's password from another file. I have it set up this way so I can
publish my dotfiles without leaking my password. The simpler alternative if
you don't intend to publish your email dotfiles is just Pass "your_password"
. The more complex alternative if you don't want your password
stored in plaintext anywhere on your computer is to use a more complex PassCmd
that uses encryption in some way. This can be aggravating because then you
need to enter your gpg password every time you want your email, and it will be
more difficult to run mbsync as a service.
I would argue that it's smart to keep your password out of this file even if you don't intend to publish it; if I were writing a virus to infect personal Linux boxes, ~/.mbsyncrc is definitely a file I would check for to see if I could get your password. Your choice, though.
SSLType IMAPS
: How you want your IMAP traffic encrypted. Your email provider
will tell you if it should be something other than IMAPS.
CertificateFile /etc/ssl/certs/ca-certificates.crt
: Where your system
certificate store is located. Your distro will know this better than I will,
but you can come up with a guess by running "openssl version -d
" and then
appending "/certs/ca-certificates.crt
".
IMAPStore migadu-remote
: Defines the name of your IMAP store, which will be
needed later.
Account migadu
: Which account is associated with this IMAP store.
MaildirStore migadu-local
: Defines the name of your maildir store, which is
associated with where your email goes on the computer you're checking it on.
Subfolders Verbatim
: Defines how subfolders will appear; "Verbatim" is the
only remotely intuitive option.
Path ~/Mail/migadu/
: Where your mail will be downloaded to on your computer.
Inbox ~/Mail/migadu/INBOX
: Where your Inbox (a special folder in the Maildir
format, hence its special treatment here) should be located. It can be, but
does not have to be, inside the Path.
Channel migadu
: Names a channel to actually check mail with.
Far :migadu-remote:
: The IMAP store associated with this channel; defined
above.
Near :migadu-local:
: The Maildir store associated with this channel; defined
above.
Patterns *
: Which mailboxes to check. *
means all of them.
Create Both
: creates missing mailboxes on both sides (so if you make a new
folder, it will propagate both to and from this machine).
Remove Both
: Removes deleted mailboxes, thereby propagating their deletion.
Note that there is a special "deleted" flag, so the software can distinguish
between deleted and not-yet-created mailboxes.
SyncState *
: Stores a sync-state file called ".mbsyncstate
" in each
mailbox (folder). You could also provide a path to append to the mailbox name.
A couple general notes:
You can run mbsync
directly from the command line, to check your config or to
check your email before your service is set to trigger. This is easy; you just
run "mbsync <your IMAPAccount name>
" to check one mailbox or "mbsync -a
" to
check all of them. The -V
flag will give you verbose output, which can help
debug issues.
You can run mbsync as a systemd service, cron job, or whatever else, which will keep your inbox perpetually up-to-date and save you time when you want your email. Here are my systemd files (I won't annotate these, because this is less valuable, but they may still be helpful). You may have to fight systemd a little to get user services running; you can't just start them like you can system services.
~/.config/systemd/user/mbsync.service
[Unit]
Description=Mailbox synchronization service
[Service]
Type=oneshot
ExecStart=/usr/bin/mbsync -a
~/.config/systemd/user/mbsync.timer
[Unit]
Description=Mailbox synchronization timer
[Timer]
OnCalendar=*:0/10
Unit=mbsync.service
[Install]
WantedBy=timers.target
Msmtp is a tool for sending mail (an MTA) from your local computer using the smtp protocol. It can be run directly or hooked from your email client. I can't imagine a Linux distro that wouldn't provide this in its repo, so install away.
The configuration here is intended to establish which extra SMTP features you need and your authentication information.
Here's part of my config; we'll go through it line-by-line.
~/.msmtprc
# Always use security
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
protocol smtp
timeout 10
account migadu
host smtp.migadu.com
tls_starttls off
port 465
from jordan@jnewport.dev
user jordan@jnewport.dev
passwordeval "cat ~/.config/passwords/migadu-email"
account default : migadu
defaults
: Says we'll be defining defaults for all accounts until it hits an
"account
" line. Aren't context-sensitive configs great?
auth on
: Uses authentication. SMTP is very old, so the protocol doesn't
actually require this and we must explicitly configure it. Good luck finding a
publicly accessible SMTP server that lets you get away with it, but you do
have to explicitly configure this.
tls on
: Uses security, which is another thing that SMTP doesn't provide so
we have to explicitly tack it on here.
tls_trust_file /etc/ssl/certs/ca-certificates.crt
: Your system certificate
store; this is the same one from mbsync.
protocol smtp
: You could theoretically use LMTP instead, but if you're
sending normal email you almost certainly want SMTP.
timeout 10
: Waits for 10 seconds before failing to send a message. This is
super important, so you don't lock your mail client indefinitely because your
network connection dropped or you need to connect to a VPN.
account migadu
: Starts the configuration for an account named "migadu".
host smtp.migadu.com
: Your email provider's SMTP URL. Most providers should
have one.
tls_starttls off
: Controls whether or not you should be using StartTLS,
which is a different method of encrypting email. Not all providers support it
(mine doesn't, it's not especially important); yours will tell you whether or
not it does.
port 465
: Which port to use on your SMTP URL; this is something your email
provider will tell you. Typically either 465 or 587 depending on StartTLS
support.
from jordan@jnewport.dev
: This is my return address.
user jordan@jnewport.dev
: This is my email address for authentication.
passwordeval "cat ~/.config/passwords/migadu-email"
: This is the same
technique used above to get my authentication password while allowing me to
publish my config; all the same commentary applies. The lazy person's
alternative is "password
".
It's worth noting here that some mail providers (organization-managed Gmail, among others) have you use a different password for sending email than doing everything else.
account default : migadu
: Sets my default account to send email from, if
it's not otherwise specified.
General notes:
You can test your msmtp config or send simple emails by piping the contents of your email into:
msmtp -a <account> <recipient email address>
There are more complex tasks that can be done from the command line, but that's up to you to figure out.
Now that we've set up our infrastructure for checking and sending email, we can set up a program to view our emails (a "mail user agent"). This won't go into anywhere near all the features that our chosen program, mutt, possesses, but it should get you far enough that you can see your email (and you can configure further from there). If you want to see a more fleshed-out mutt config, mine is available in my dotfiles. Mutt is available in most distros' package repositories. Be careful to not confuse mutt and neomutt; in my experience, neomutt doesn't work as well as plain old mutt.
The most relevant true quote I can find about mutt is on its homepage:
"All mail clients suck. This one just sucks less." -the creator of Mutt, circa 1995
Mutt's configuration is mostly about usability and pointing it at the right files. In general, mutt will work regardless of its configuration, so long as you point it at a valid maildir.
Here is a simple config, based on mine. A lot of it is centered around making mutt more similar to other mail clients you may have used. We'll walk through it piece by piece. This one was tricky to make, because it's hard to balance which features are needed versus which are just nice to have, but this should get you started.
~/.mutt/muttrc
# set up default folders; this could technically be done in the account-specific config
set mbox_type=maildir
set mbox="~/Mail/migadu/INBOX"
set spoolfile="~/Mail/migadu/INBOX"
set folder="~/Mail/migadu/"
set record="~/Mail/migadu/Sent/"
# default account is migadu
source ~/.mutt/accounts/migadu
# switch between mines and migadu accounts
folder-hook migadu/* source ~/.mutt/accounts/migadu
folder-hook mines/* source ~/.mutt/accounts/mines
macro index M "<change-folder>~/Mail/mines/INBOX<enter>" "go to Mines Inbox"
macro index I "<change-folder>~/Mail/migadu/INBOX<enter>" "go to Migadu Inbox"
# never check for email directly from mutt; that's mbsync's job
set mail_check = 0
# set mail to be from me
set envelope_from
# aliases is your address book; mailcap is how to open attachments
set alias_file = ~/.mutt/aliases
set mailcap_path = ~/.mutt/mailcap
# These make mutt behave in a reasonable/expected manner when doing basic mail tasks
unset move
set delete
unset confirmappend
set quit
unset mark_old
# Sort
set sort = threads
set sort_aux = reverse-last-date-received
set sort_re
# HTML
# don't automatically view attachments
unset implicit_autoview
# the preferred text type order
alternative_order text/plain text/enriched text/html
# If there's only an html part and no plaintext, open it automatically
auto_view text/html
# Composing
# use $EDITOR for composing messages
set editor = `echo \$EDITOR`
# unsetting this allows you to forward messages inline rather than as attachments
unset mime_forward
# your forwarded-message subject line
set forward_format = "Fwd: %s"
# includes replied/forwarded message in your message
set include
# Prepends a > to each quoted line
set forward_quote
# Aliases
# Actually use your alias file/address book
source ~/.mutt/aliases
# Handle html attachments better
macro index,pager E "v/html<enter>s<kill-line>/tmp/mutt.html<enter>" "save html part in /tmp/mutt.html"
set up default folders
: This block sets up which folders mutt should open
to, look in for mail, copy sent mail to, and so on. This could be done in the
account-specific config, but I have them included here as well.
source ~/.mutt/accounts/migadu
: This sources my account-specific config,
located at accounts/migadu. The effect of this is basically to make migadu my
default email account when mutt is opened.
switch between mines and migadu accounts
: These lines set up the hooks and
macros to change between different accounts, so I can use multiple accounts
with mutt. You could remove all of this if you only want to use mutt with one
email account.
set mail_check = 0
: This disables mutt's built-in mail checking
functionality, since I already have mbsync doing that for me.
set envelope_from
: This sets my account's email address as the return
address for msmtp to use.
set alias_file = ~/.mutt/aliases
: Sets my alias file (effectively, my
address book).
set mailcap_path = ~/.mutt/mailcap
: Tells mutt how to open some attachments.
These make mutt behave in a reasonable/expected manner
: These lines control
some common functionality and make mutt behave in the way any modern mail
client does by default. Some of these are defaults already in more modern
versions of mutt, but just in case you're trapped in obsolete RHEL 6 hell,
here they are.
Sort
: These set the default sort of mutt to date received, with new messages
at the top. They also keep threads together, as otherwise you would get each
reply separately, with only the subject lines to clue you in that they were
replies at all.
HTML
: Something you may or may not have known about email is that some email
is sent with only a plaintext part, some is sent with both a plaintext and
html part, and some is sent with only an HTML part. For much more
(opinionated) detail on how this works and why it's terrible, see Use
Plaintext Email. The purpose of these lines is
to default to the plaintext view, show you the HTML view when there is no
plaintext view available, and not automatically view any attachments (making
you open them yourself if you want them).
It's worth noting that Outlook completely mangles plaintext emails when replying to them, so if you send email to outlook accounts often, it may be worth fiddling with these.
Composing
: These lines set you up to write and reply to emails. They set up
which editor you'll write email in, how to handle the text of the message
you're replying to, and how your forwards will look. Relating to the above,
it's also worth noting that mutt will send all email as plaintext unless you
explicitly resave your email as html.
Aliases
: This actually sets you up to use your aliases.
Handle html attachments better
: This macro saves the html part of the email
you're currently looking at to your /tmp directory, so you can open it with
"firefox file:///tmp/mutt.html
" (or whatever you prefer). This is useful for
messages containing images, or messages that need a full graphical browser to
render them well. You can invoke the macro on any email using the E key.
I won't discuss all of them in much detail, but it's worth including some other
config files sourced by the main muttrc
as well.
~/.mutt/aliases
alias Jordan_Newport Jordan Newport <jordan@jnewport.dev>
alias Some_Name Some Name <some.name@example.com>
alias my_friends Jordan_Newport, Some_Name
This is an example of an alias file (analogous to an address book; a defined
name "aliases" to an email address or list of addresses). Alias names must be
one word. The "body" of an alias must be either a target to send email to (with
an optional name and mandatory <email address>) or a list of other aliases.
The client will automatically create aliases for you and append them to this
file if you hit a
on a message.
~/.mutt/mailcap
text/html; lynx -assume_charset=%{charset} -display_charset=utf-8 -dump %s; nametemplate=%s.html; copiousoutput
# PDF documents
application/pdf; zathura %s
# Images
image/jpg; feh -. %s
image/jpeg; feh -. %s
image/pjpeg; feh -. %s
image/png; feh -. %s
image/gif; feh -. %s
# Office Suites
application/msword; libreoffice %s;
application/vnd.ms-word.document.12; libreoffice %s;
application/vnd.openxmlformats-officedocument.wordprocessingml.document; libreoffice %s;
application/vnd.oasis.opendocument.text; libreoffice %s;
This mailcap file tells mutt how to open attachments. If a MIME type is not defined here, mutt will try to show the file in the terminal, with typically-bad results. If it is defined here, then mutt will use the specified command. Terminal browsers such as lynx or w3m will typically have specific mailcap lines they want you to use that are documented somewhere.
%s
is the filename mutt will supply to the program. copiousoutput
means
that depending on your config options (particularly implicit_autoview
),
mutt may open the attachment automatically.
If this all sounds too complicated for you, or if you get an attachment not in
your mailcap, mutt can also just save attachments to the filesystem to open
elsewhere at your leisure (use the s
key in the attachments view).
~/.mutt/accounts/migadu
# vim: ft=muttrc
set realname = "Jordan Newport"
set from = "Jordan Newport <jordan@jnewport.dev>"
set sendmail = "msmtp -a migadu"
set mbox = "~/Mail/migadu/Archive"
set postponed = "~/Mail/migadu/Drafts"
set record = "~/Mail/migadu/Sent"
set signature = "~/.mutt/signatures/migadu"
macro index,pager 's' '<save-message>?<change-dir><kill-line>~/Mail/migadu<enter>/'
macro index 'c' '<change-folder>?<change-dir><kill-line>~/Mail/migadu<enter>/'
macro index,pager d "<save-message>~/Mail/migadu/Trash<enter>" "Move message to the trash"
This file is used for specifying account-specific options, including the name and email address for this account, the particular files to use for some commands, and so on.
The first line is a modeline to tell vim it's editing a mutt config file (vim automatically knows this for files named "muttrc", but otherwise you have to tell it). This gives you syntax highlighting and such.
The next set of lines sets my name, from-line (name and email address for the email to show up with; you can spoof this), the command to send mail, the mail folders to use for this account, and the default signature for the account. The signature is literally just a text file that will be appended to all of your emails; it can contain things like your name, email address, title, or pronouns.
The next few lines set macros to override mutt's default behavior for, respectively, moving an email to a folder ("saving"), changing folders, and deleting. These configurations are nice to have for any account, since mutt defaults to doing these things in a slightly weird way, but absolutely critical for Gmail users since otherwise the Gmail server's default behavior will produce all kinds of weirdness.
General notes:
autocmd BufRead /tmp/mutt-* setlocal tw=72
autocmd BufRead /tmp/mutt-* setlocal spell spelllang=en_us
Mutt can be run from your command line as mutt
. Keybindings are reasonably
discoverable (and there are a few tutorials online); if you get lost, you should
use the ?
key. 90% of the time, you can search for what you want, and the
other 10% of the time, you have to read every command until you find one that
looks relevant, because mutt predates the commonly used name of the thing you
want to do. That's just the way it is. All mail clients suck. Mutt just sucks
less. Get ready.
So you've installed mbsync, msmtp, and mutt. You've copied the configurations I put here and replaced all the values with the ones associated with your own account.
Great!
To get started, it should be as simple as checking your configs on the command
line, running "mbsync -a
" once to download your email initially, and opening
mutt. The first mbsync will take forever, just FYI. IMAP is not a fast protocol
for mass syncs; it's optimized for small updates, not wholesale downloads.
If something doesn't work, it could be anything but is probably related to authentication. Check your passwords and URLs.
That is, strictly speaking, all you need to get started using mutt
on the
command line for your email. However, if you want more information, read on!
Throughout this post, I've used a "migadu" config as my default. Migadu is an email provider I use that is pretty friendly to using alternative clients like mutt. It has great configuration guides for stuff like this. It lets you use your own domain, and tells you how to set up the DNS for that. It has mildly-okay webmail. It's simple, cheap, and has no drama and little confusion. It isn't selling your data. I've never (to my knowledge) had an email get flagged as spam or fail to deliver, which is a problem that people often have when self-hosting email or using small providers. It is hosted in Switzerland (I don't know how you feel about this, but it might be relevant). If you're looking into committing to a terminal-email workflow, I would seriously consider a provider like Migadu. I would recommend them.
In this post, I discuss mbsync to fetch email, msmtp to send email, and mutt to use as a client/MUA. There are some alternatives to each of these. I don't have any configs to show as examples or much opinion on the user experience, but I'll mention them.
Fetching email: The most common alternative is offlineimap
. I have used
it; it works (and was the "standard" for many years), but has significantly
worse performance than mbsync
, particularly if you have a lot of folders.
Sending email: msmtp really is the standard here; a lot of your alternatives will be forks of msmtp that add some specific feature and haven't been merged.
Mail clients: There are a huge amount of alternatives here. Some are listed on Use Plaintext Email; others are listed in all sorts of places. Mutt isn't necessarily the best one to use; it's just popular and not-terrible.
Something that may be useful to know is that when you delete or move emails in mutt, many mail providers misbehave (this isn't the fault of anyone in particular; it's just that "move to Trash" being the common deletion behavior is tricky to get right), so it may be nice to have a phone client that is compatible. The one I use is K-9 Mail.
Total solutions: Mutt (and some other MUAs) can actually be used as the MUA, MTA, and email fetcher by logging into the server during use. The configuration for this looks totally different, I don't have one for you to look at, and it requires that you be online (and on the VPN, and so on) all the time. The advantage here is that you don't need to install a mail fetcher or MTA.
Comments? Questions? Email me at jordan@jnewport.dev!