Drowning in Email; mu4e to the Rescue.

Posted on January 13, 2014

What is mu4e?

mu4e is an emacs-based email client. It is fully search-based, with a UI optimised for speed with quick key stroked for common actions. Emails can be composed with rich-text using org-mode. Email addresses auto-completion is supported. Actions are asynchronous, so heavy actions never block emacs.

The basic idea is this: you configure an offline IMAP client to synchronise your remote email server with your local computer. Two possibilities for an IMAP synchroniser are mbsync and offlineimap. This post describes a setup using mbsync.

Configure mbsync
  1. Install SSL development files, required by mbsync for SSL authentication. With RPM based package managers, sudo yum install openssl-devel or if using dnf (e.g. with Fedora 22+), then run sudo dnf install openssl-devel. With debian machines, sudo apt-get install libssl-dev.

  2. Install mbsync, either from a release tarball or from git.

  3. Create a temporary file .mbsyncpass and store your plain text password in there. Next, gpg2 --output .mbsyncpass.gpg --symmetric .mbsyncpass. Move mysyncpass.gpg in ~/.emacs.d and remove the .mbsyncpass file.

  4. Create a temporary file ~/.authinfo and store the following plain text in there, replacing host, username, password & port information for your settings:

machine mail.example.com login myusername port 587 password mypassword

  1. Generate the encrypted file with gpg2 --output ~/.authinfo.gpg --symmetric ~/.authinfo. Remove the ~/.authinfo file.

  2. Create a .mbsyncrc file. I have it in my ~/.emacs.d/ directory so that it is version controlled to use easily across my machines. Check on the work server the exact directory names you wish to syncronise (e.g. is it “Sent” or “Sent Items”?). Choose the location for your local mail directory. I chose ~/email/mysyncmail. Add the following to the .mbsyncrc file:

IMAPAccount uni
Host mail.example.com
User me@example.com
PassCmd "gpg2 -q --for-your-eyes-only --no-tty -d ~/.emacs.d/.mbsyncpass.gpg"
Port 993
AuthMechs Login
CertificateFile /etc/ssl/certs/ca-bundle.crt

IMAPStore uni-remote
Account uni

MaildirStore uni-local
Path ~/email/mbsyncmail/
Inbox ~/email/mbsyncmail/INBOX

Channel uni
Master :uni-remote:
Slave :uni-local:
Patterns "Sent Items" "INBOX" "Deleted Items"
Create Slave
Sync All
Expunge Both
SyncState *
  1. Run the mbsync command, to synchronise your IMAP inbox: mbsync -c ~/.emacs.d/.mbsyncrc work
Configure mu4e
  1. Install mu4e, either using a package manager, from a tarball, or from git. Details here.

  2. Now set up your mu4e configuration. Check out the mu4e documentation on the variables. Make sure the following is stored in an .el file that is loaded by emacs, e.g. by the ~.emacs file.

(add-to-list 'load-path "~/place/to/your/mu4e")
(require 'smtpmail)

; smtp
(setq message-send-mail-function 'smtpmail-send-it
      '(("mail.example.com" 587 nil nil))
      smtpmail-default-smtp-server "mail.example.com"
      smtpmail-smtp-server "mail.example.com"
      smtpmail-smtp-service 587
      smtpmail-debug-info t)

(require 'mu4e)

(setq mu4e-maildir (expand-file-name "~/email/mbsyncmail"))

(setq mu4e-drafts-folder "/Drafts")
(setq mu4e-sent-folder   "/Sent Items")
(setq mu4e-trash-folder  "/Trash")
(setq message-signature-file "~/.emacs.d/.signature") ; put your signature in this file

; get mail
(setq mu4e-get-mail-command "mbsync -c ~/.emacs.d/.mbsyncrc work"
      mu4e-html2text-command "w3m -T text/html"
      mu4e-update-interval 120
      mu4e-headers-auto-update t
      mu4e-compose-signature-auto-include nil)

(setq mu4e-maildir-shortcuts
      '( ("/INBOX"               . ?i)
         ("/Sent Items"   . ?s)
         ("/Trash"       . ?t)
         ("/Drafts"    . ?d)))

;; show images
(setq mu4e-show-images t)

;; use imagemagick, if available
(when (fboundp 'imagemagick-register-types)

;; general emacs mail settings; used when composing e-mail
;; the non-mu4e-* stuff is inherited from emacs/message-mode
(setq mu4e-reply-to-address "me@example.com"
    user-mail-address "me@example.com"
    user-full-name  "Rob Stewart")

;; don't save message to Sent Messages, IMAP takes care of this
; (setq mu4e-sent-messages-behavior 'delete)

;; spell check
(add-hook 'mu4e-compose-mode-hook
        (defun my-do-compose-stuff ()
           "My settings for message composition."
           (set-fill-column 72)
  1. Then, you must index that directory with mu:

mu index --maildir=~/email/mbsyncmail/

  1. Now it’s time to try out mu4e. Open up emacs and type M-x mu4e.

Check out the mu4e shortcuts:

The complete list of mu4e key bindings is listed here.

Choosing Offline IMAP client: mbsync vs offlineimap

The more popular approach is offlineimap, and I tried this for a week. I later tried mbsync, and this is working much better for me. People have opted for offlineimap because of its ability to a invoke python file to prompt a user for a password, thus avoiding plain text passwords being stored locally. Fortunately, this has now been implemented in mbsync, which is what the PassCmd entry in .mbsyncrc is for.

Zawinski’s Law “Every program attempts to expand until it can read mail. Those programs which cannot so expand are replaced by ones which can.” Law of Software Envelopment, Jamie Zawinski.