Email with mu4e
This article is published ahead of its scheduled time. Thus, some pre-requisites (like installing packages) are not yet covered in the previously published chapters.
Zawinski's law of software envelopment (also known as Zawinski's law) comments on the phenomenon of software bloating with popular features: "Every program attempts to expand until it can read mail. Those programs which cannot so expand are replaced by ones which can."
Naturally, Emacs can handle email. One popular extension is mu4e, an Emacs interface to mu email client. Today we'll set up an email workflow with the following assumptions:
- Standard IMAP email provider. If you use Gmail, everything in this article will work, but since Gmail uses its own, non-standard implementation of IMAP when it comes to labels and folders, you may get unexpected results in certain situations.
- Enough HDD space for the full mailbox sync.
The setup consists of the following parts:
- IMAP server. This doesn't require any special configuration.
- mbsync — a command-line utility which syncs IMAP server with a local directory in Maildir format. This has nothing to do with Emacs. Even if you're not interested in doing email in Emacs, having a full local copy of your mailbox may be a good idea. mbsync does exactly that. In can sync both ways, so if you just move a file (which corresponds to a single message) from folder to folder, and then run mbsync again, this change will propagate to the server.
- mu — a command line email client which works with Maildir storage. It doesn't deal with the server directly, instead, it just read your local file system. It's very fast!
- mu4e — Emacs package that comes with mu. Provides an interface to mu.
Gmail
If you use Gmail, you need to set the following things first:
- Enable IMAP.
- Use two factor authorization?
- If yes, make an App Password.
- If no, enable less secure apps.
Installing and configuring mbsync
Install mbsync with your OS package manager or build from source. Confusingly, the package is called isync, but the binary is called mbsync
. MacOS users should use homebrew:
brew install isync
Mbsync uses ~/.mbsyncrc
for configuration. This page describes all options. Here's a simple, with comments:
# First section: remote IMAP account
IMAPAccount fastmail
Host imap.fastmail.com
Port 993
User myemailaddress@mydomain.com
# For simplicity, this is how to read the password from another file.
# For better security you should use GPG https://gnupg.org/
PassCmd "cat ~/.mbsync-fastmail"
SSLType IMAPS
SSLVersions TLSv1.2
IMAPStore fastmail-remote
Account fastmail
# This section describes the local storage
MaildirStore fastmail-local
Path ~/Maildir/
Inbox ~/Maildir/INBOX
# The SubFolders option allows to represent all
# IMAP subfolders as local subfolders
SubFolders Verbatim
# This section a "channel", a connection between remote and local
Channel fastmail
Master :fastmail-remote:
Slave :fastmail-local:
Patterns *
Expunge None
CopyArrivalDate yes
Sync All
Create Slave
SyncState *
Few details about the channel options worth mentioning:
Patterns *
— sync all folders. Alternatively, you can select only certain folders to sync.Expunge None
— don't destroy messages neither locally, nor remotely. Details later.CopyArrivalDate
— makes sure the date of the arrival stays the same when you move messages around. Without this option, moving a message to another folder will reset the date of the message.Create Slave
— when new folders are added on server, create them locally.
Now run mbsync
and wait for it to download messages:
mbsync -a
With a normal internet connection, around 50k messages sync in a few minutes.
Installing and configuring mu and mu4e
First, verify that which emacs
points to a valid Emacs executable, and emacs --version
shows the correct version:
→ which emacs
/usr/local/bin/emacs
→ ls -la /usr/local/bin/emacs
/usr/local/bin/emacs -> /Applications/Emacs.app/Contents/MacOS/Emacs.sh
→ emacs --version
GNU Emacs 26.3
Now, install mu. On macOS:
brew install mu
And let it index the Maildir:
mu index --maildir=~/Maildir
Now you can check if everything worked by trying a command-line search:
mu find hello
mu comes with mu4e by default. To verify, check for presence of elisp files in /usr/local/share/emacs/site-lisp/mu/mu4e
:
→ ls /usr/local/share/emacs/site-lisp/mu/mu4e
mu4e-actions.el mu4e-contrib.elc mu4e-main.el ...
Now load these files in Emacs and enable mu4e. Put the following in your Emacs config:
(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu/mu4e")
(require 'mu4e)
And add some configuration.
(setq
mue4e-headers-skip-duplicates t
mu4e-view-show-images t
mu4e-view-show-addresses t
mu4e-compose-format-flowed nil
mu4e-date-format "%y/%m/%d"
mu4e-headers-date-format "%Y/%m/%d"
mu4e-change-filenames-when-moving t
mu4e-attachments-dir "~/Downloads"
mu4e-maildir "~/Maildir" ;; top-level Maildir
;; note that these folders below must start with /
;; the paths are relative to maildir root
mu4e-refile-folder "/Archive"
mu4e-sent-folder "/Sent"
mu4e-drafts-folder "/Drafts"
mu4e-trash-folder "/Trash")
;; this setting allows to re-sync and re-index mail
;; by pressing U
(setq mu4e-get-mail-command "mbsync -a")
That's it! Run M-x mu4e
and after a few final setup questions mu4e should be running. Check out keybindings for it.
Caveat: deletion vs. expunge
By default, when you mark a message to be deleted, mu4e will apply the "Trashed" flag. Fastmail and other standard IMAP providers automatically destroy the messages flagged this way.
If instead of total deletion you want to move messages to the "Trash" folder, there are several options. You can simply use "move" command of mu4e, but it'd be nicer to use d
button (deletion) for that. The following piece of elisp remaps the d
button to "move to Trash folder" action. This way, neither mu4e nor your email provider destroy the message.
(fset 'my-move-to-trash "mTrash")
(define-key mu4e-headers-mode-map (kbd "d") 'my-move-to-trash)
(define-key mu4e-view-mode-map (kbd "d") 'my-move-to-trash)
Sending mail
mu4e re-uses Gnus’ message-mode
for writing mail and inherits its configuration. For sending via SMTP, mu4e uses smtpmail
. Minimal configuration looks like this:
(setq
message-send-mail-function 'smtpmail-send-it
smtpmail-default-smtp-server "smtp.fastmail.com"
smtpmail-smtp-server "smtp.fastmail.com")
When using SMTP for the first time, Emacs prompts you for the user name and password to use, and then offers to save the information. By default, Emacs stores authentication information in a file ~/.authinfo
.