Frédéric Santos' notebook
Emacs and R tricks for anthropologists and archaeologists.
24 avril 2020

Reading and sending mails from within Emacs: a tutorial for mu4e

There are several ways to handle (i.e., to read and send) all your emails directly from within Emacs. As you can read on this reddit thread, there are essentially three candidates: the built-in Emacs tools (Rmail and Gnus), mu4e and NotMuch. mu4e is a solution I find especially convenient and easy to use. In this post, I’ll propose a quick tutorial and a reasonable mu4e configuration. Another tutorials out there are really well done, such as this one (the present post is essentially a modified and extended version of this excellent tuto), but most of them are quite old, and do not necessarily play well with the latest versions of mu. This tutorial works for mu 1.4.x (and, I hope, later versions).

What are mu and mu4e?

This is a three-story building :

  1. “mu is a tool for dealing with e-mail messages stored in the Maildir-format, on Unix-like systems” (from the official mu website)
  2. mu4e is an Emacs-based client built on top on mu
  3. Both of them need a tool such as isync/mbsync to synchronise your emails between your remote email server and a local folder on your computer

1 Install all the necessary stuff

In this section, I’ll assume that you are a Linux user, but it should (?) be possible to find an équivalent of this for Mac OS or Windows.

  1. First, you should install SSL development libraries, that are called slightly differently from one Linux distro to another. For instance, Linux Manjaro users can execute:

    sudo pacman -S openssl

    but this library may also be called openssl-devel or libssl-dev if you are using another distro.

  2. Then, you can install mu and isync/mbsync. Although they are available on Git repositories and can be manually installed, using the package manager of your Linux distro is the easiest way. Manjaro users can execute the following commands:

    pacaur -S mu
    sudo pacman -S isync

    The official manual of mu gives further instruction for other Linux distros.

2 Configure isync/mbsync

You need to store your login information in an encrypted file on your computer so that your server can (safely) recognize you.

2.1 Password info

  1. In your .emacs.d/ folder, create a file .mbsyncpass and simply write your password in it.
  2. This file needs to be encrypted, so that this private information can be safely stored on your computer. You can encrypt this file with gpg2 by running the following command into the .emacs.d/ folder:

    gpg2 --output .mbsyncpass.gpg --symmetric .mbsyncpass

    A new encrypted file .mbsyncpass.gpg has been created in this folder.

  3. But now, do not forget to remove the temporary file .mbsyncpass you had to create in step 1!

    rm .mbsyncpass

2.2 Mail account info

  1. Create a file ~/.authinfo directly in the root of your home directory. In this file, you’ll have to store your mail account info, by using in this template:

    machine login myname port 587 password mypassword

    Simply replace by your SMTP server, myname by your user name, mypassword by your password, and keep the remaining characters unchanged.

  2. Let’s do it again: you’ll also need to encrypt this file, since it contains your password. You can run:

    gpg2 --output ~/.authinfo.gpg --symmetric ~/.authinfo

    to create an encrypted version of this file, and then simply remove the temporary file you had to create:

    rm .authinfo

2.3 Configuration file for isync/mbsync

You’ll have to create a configuration file for isync. Let’s create a file .mbsyncrc in your .emacs.d/ folder. Here is a template you can fill in:

IMAPAccount nameaccount
Host your.imap.server
User yourname
PassCmd "gpg2 -q --for-your-eyes-only --no-tty -d ~/.emacs.d/.mbsyncpass.gpg"
Port 993
AuthMechs *
CertificateFile /etc/ssl/certs/ca-certificates.crt

IMAPStore nameaccount-remote
Account nameaccount

MaildirStore nameaccount-local
Path ~/email/mbsyncmail/
Inbox ~/email/mbsyncmail/INBOX
SubFolders Verbatim

Channel nameaccount
Master :nameaccount-remote:
Slave :nameaccount-local:
Patterns *
Create Slave
Sync All
Expunge None
SyncState *

The mbsync documentation is very complete and you should find easily the meaning of each parameter. But in particular, the following ones are important:

  • Path is the name of the local folder mbsync will use your computer to store your emails. Here, I chose to store them in a folder called /email/mysyncmail.
  • Patterns * means that I want to synchronise all the folders contained in my mailbox. If you want to synchronise only the folders INBOX, Sent and Trash (for instance), simply replace this line by Patterns "Sent" "INBOX" "Trash".
  • PassCmd is the command that mbsync must execute to retrieve your password. Here, I simply indicate that mbsync must decrypt the file ~/.emacs.d/.mbsyncpass.gpg you created in section 2.1, in which you stored your (encrypted) password. In you chose a different location for this file, adapt this instruction accordingly in your .mbbsyncrc file.

Finally, run the following command (and adapt it: replace nameaccount by the value you chose as the name account in your .mbsyncrc file), so that this config file can take effect. All your emails will be downloaded from the server, and then indexed locally:

mbsync --config ~/.emacs.d/.mbsyncrc nameaccount
mu init --maildir=~/email/mbsyncmail/
mu index

Now, you’re ready to use mu4e!

3 Basic configuration of mu4e

Here are some of the mu4e-related instructions I have in my Emacs init.el file. They are convenient for me, they may not be convenient for you. You may want to dig into the mu4e manual to find the variables you would like to customize in a way you like.

  1. The first thing to do is to ensure that mu4e can be found by Emacs. On my computer, mu4e has been installed in the folder /usr/share/emacs/site-lisp/mu4e. Therefore, I must add this folder to my load-path, and load mu4e:

    ;; Add mu4e to the load-path:
    (add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
    (require 'mu4e)
  2. Configure some SMTP settings according to the information from tour mail provider. Modify the following template using your own information:

    ;; SMTP settings:
    (setq send-mail-function 'smtpmail-send-it)    ; should not be modified
    (setq smtpmail-smtp-server "your.smtp.server") ; host running SMTP server
    (setq smtpmail-smtp-service 587)               ; SMTP service port number
    (setq smtpmail-stream-type 'starttls)          ; type of SMTP connections to use
  3. Specify the name of the draft, sent and trash folders (they must exist and begin by a /):

    ;; Mail folders:
    (setq mu4e-drafts-folder "/Drafts")
    (setq mu4e-sent-folder   "/Sent")
    (setq mu4e-trash-folder  "/Trash")
  4. Specify how mu4e should get and display your incoming emails:

    ;; The command used to get your emails (adapt this line, see section 2.3):
    (setq mu4e-get-mail-command "mbsync --config ~/.emacs.d/.mbsyncrc nameaccount")
    ;; Further customization:
    (setq mu4e-html2text-command "w3m -T text/html" ; how to hanfle html-formatted emails
          mu4e-update-interval 300                  ; seconds between each mail retrieval
          mu4e-headers-auto-update t                ; avoid to type `g' to update
          mu4e-view-show-images t                   ; show images in the view buffer
          mu4e-compose-signature-auto-include nil   ; I don't want a message signature
          mu4e-use-fancy-chars t)                   ; allow fancy icons for mail threads
  5. Some possible other tweaks. For example, if you never want to include yourself when you choose “reply to all”, you can customize the variable `mu4e-compose-reply-ignore-address’:

    ;; Do not reply to yourself:
    (setq mu4e-compose-reply-ignore-address '("no-?reply" "your.own@email.address"))

    If you do not want to use auto-fill-mode when writing your emails:

    ;; Do not use auto-fill-mode for emails:
    (defun auto-fill-mode-off ()
      (auto-fill-mode 0))
    (add-hook 'mu4e-compose-mode-hook 'auto-fill-mode-off)

    mu4e also allows to modify the expression used to introduce a quoted email. As a native french speaker, I chose this one:

    ;; Modify the expression introducing a quoted email:
    (setq message-citation-line-function 'message-insert-formatted-citation-line)
    (setq message-citation-line-format "Le %Y-%m-%d à %T %Z, %f a écrit :\n")
  6. It’s up to you ! :)

4 Launch mu4e

Simply execute M-x mu4e (or bind this to a convenient shortcut): you’re done! mu4e.png

In the main *mu4e-headers* buffer, you just have to become familiar with some shortcuts:

Key Action
C Compose a new email
R Reply to an email
F Forward an email
j Jump to a given folder
RET Open email in a new buffer
C-c C-u Manually retrieve incoming emails from the server

5 Get desktop alerts for new emails

Thanks to the setting (setq mu4e-update-interval 300), mu4e is asked to retrieve emails every 300 seconds. But you’re not really notified in a very clear way. Users migrating from an email client such as Thunderbird for example, may like to have pretty desktop alerts. A very nice Emacs package, mu4e-alert, allows this kind of notification.

This package is clearly documented, and easy to customize. I wanted something a bit different from the standard behavior, that I found sometimes a bit intrusive. Most often, when I start Emacs for the first time on the morning, checking my incoming emails is one of the first things I do, and I’m happy to be notified when I have new emails. But in other contexts, when I need to focus and do not want to be disturbed, or simply when I’m working in a train with a bad connection, I simply want Emacs to stop with all the email stuff (retrieval, notifications and so on). I wanted an “on-demand” behavior: either automatic and periodic retrieval of new emails with desktop alerts, or nothing at all.

The following instructions allow me to do that. When I start Emacs, it will first consider that it should not handle all the email stuff, and will not behave at all as an email client, unless I press F2. As soon as I press F2, and until the end of the Emacs session, Emacs will retrieve emails and display nice desktop alerts.

May you be interested by such a customization, here are the required instructions. (Warning: they make use of use-package.)

;; Configure desktop notifs for incoming emails:
(use-package mu4e-alert
  :ensure t
  (defun perso--mu4e-notif ()
    "Display both mode line and desktop alerts for incoming new emails."
    (mu4e-update-mail-and-index 1)        ; getting new emails is ran in the background
    (mu4e-alert-enable-mode-line-display) ; display new emails in mode-line
    (mu4e-alert-enable-notifications))    ; enable desktop notifications for new emails
  (defun perso--mu4e-refresh ()
    "Refresh emails every 300 seconds and display desktop alerts."
    (mu4e t)                            ; start silently mu4e (mandatory for mu>=1.3.8)
    (run-with-timer 0 300 'perso--mu4e-notif))
  :after mu4e
  :bind ("<f2>" . perso--mu4e-refresh)  ; F2 turns Emacs into a mail client
  ;; Mode line alerts:
  (add-hook 'after-init-hook #'mu4e-alert-enable-mode-line-display)
  ;; Desktop alerts:
  (mu4e-alert-set-default-style 'libnotify)
  (add-hook 'after-init-hook #'mu4e-alert-enable-notifications)
  ;; Only notify for "interesting" (non-trashed) new emails:
  (setq mu4e-alert-interesting-mail-query
         "flag:unread maildir:/INBOX"
         " AND NOT flag:trashed")))
Tags: emacs