Brool brool (n.) : a low roar; a deep murmur or humming

Using mu4e

| coding linux

A thread on Reddit nudged me to try the Emacs mail readers again. I have tried a bunch of them (Wanderlust, Gnus, mew) but found them either too idiosyncratic or painful to use, and for the most part just read my e-mail by logging into Google directly.

However, I just installed mu / mu4e and it works really well — well enough that I prefer reading e-mail in Emacs now, as opposed to just logging into Google mail and reading it there. I ended up archiving about 10 years of mail (approximately 10k of messages) off Gmail and mu can re-index it in seconds.

Installing offlineimap

I used offlineimap to sync everything with Gmail. Steal this configuration and put it in \~/.offlineimaprc (or whatever — but don’t name it .offlineimap, because that will cause errors). For my laptop I added:

maxage = 5
autorefresh = 15

… to keep only 5 days of mail and to automatically update it every 15 minutes.

Updated 2016-12-21: Well, scratch that. Unless you want to allow unsafe applications to access your data, you’re going to have to use Oauth.

The instructions are in the comments of this configuration file, but for posterity:

  1. Go to the Google Developer Console
  2. Create a new project
  3. On left bar, select Credentials
  4. Go to OAuth consent screen and fill in the minimum necessary to submit the form
  5. Go to Credentials tab and select “Oauth Client ID”
  6. Choose “other” application type and enter an appropriate name

So that gives you the client ID and the client secret. Wait, you’re not done. You need a refresh token.

  1. Clone out
  2. Run python/ --generate_oauth2_token --client_id=yourclient --client_secret=yoursecret
  3. This will have you go to your browser to get a verification token that you then enter. That will give you a refresh token.

In your .offlineimaprc, you’ll have something like:

[Repository Personal_Remote]
oauth2_client_id =
oauth2_client_secret = longstringofdigitsandnumbers
oauth2_request_url =
oauth2_refresh_token = 1/longstringofdigitsandnumbers

Installing mu4e

The version of mu4e available in Ubuntu 12.04LTS is really old and throws spurious errors, so you’ll need to build your own. Get mu from github and then rebuild. I needed a few extra libraries in my installation.

sudo apt-get install libglib2.0-dev libgmime-2.6-dev libxapian-dev
sudo apt-get install texinfo
autoreconf -i

Installing into Emacs

Change into mu4e, do a make / sudo make install. I used pretty much just the longer configuration in the documentation, although I put everything into a deferred load (code below), and there are the following caveats:

(defun email () 

  (when (not (featurep 'mu4e))
    (add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu4e/")

    (require 'mu4e)
    (require 'org-mu4e)

    ;; defaults

    (setq mu4e-maildir "~/Maildir")
    (setq mu4e-drafts-folder "/gmail/[Gmail].Drafts")
    (setq mu4e-sent-folder   "/gmail/[Gmail].Sent Mail")
    (setq mu4e-trash-folder  "/gmail/[Gmail].Trash")

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

    ;; setup some handy shortcuts
    ;; you can quickly switch to your Inbox -- press ``ji''
    ;; then, when you want archive some messages, move them to
    ;; the 'All Mail' folder by pressing ``ma''.

    (setq mu4e-maildir-shortcuts
          '( ("/gmail/INBOX"               . ?i)
             ("/gmail/[Gmail].IMPORTANT"   . ?!)
             ;; ("/gmail/[Gmail].Sent Mail"   . ?s)
             ;; ("/gmail/[Gmail].Trash"       . ?t)
             ("/gmail/[Gmail].All Mail"    . ?a)))

    ;; allow for updating mail using 'U' in the main view:
    ;; I have this running in the background anyway
    ;; (setq mu4e-get-mail-command "offlineimap")

    ;; something about ourselves
     user-mail-address "user@domain"
     user-full-name  "username"
     message-signature nil)

    ;; sending mail -- replace USERNAME with your gmail username
    ;; also, make sure the gnutls command line utils are installed
    ;; package 'gnutls-bin' in Debian/Ubuntu

    (require 'smtpmail)

    (if (string< emacs-version "24")
        (setq message-send-mail-function 'smtpmail-send-it
              starttls-use-gnutls t
              smtpmail-starttls-credentials '(("" 587 nil nil))
              '(("" 587 "user@domain" nil))
              smtpmail-default-smtp-server ""
              smtpmail-smtp-server ""
              smtpmail-smtp-service 587)

      ;; alternatively, for emacs-24 you can use:
      (setq message-send-mail-function 'smtpmail-send-it
            smtpmail-stream-type 'starttls
            smtpmail-default-smtp-server ""
            smtpmail-smtp-server ""
            smtpmail-smtp-service 587)

    ;; don't keep message buffers around
    (setq message-kill-buffer-on-exit t)

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

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

    ;;; message view action
    (defun mu4e-msgv-action-view-in-browser (msg)
      "View the body of the message in a web browser."
      (let ((html (mu4e-msg-field (mu4e-message-at-point t) :body-html))
            (tmpfile (format "%s/%d.html" temporary-file-directory (random))))
        (unless html (error "No html part for this message"))
        (with-temp-file tmpfile
        (browse-url (concat "file://" tmpfile))))

    (add-to-list 'mu4e-view-actions
                 '("View in browser" . mu4e-msgv-action-view-in-browser) t)

    ;; convert org mode to HTML automatically
    (setq org-mu4e-convert-to-html t)

    ;; need this to convert some e-mails properly
    (setq mu4e-html2text-command "html2text -utf8 -width 72")

(defalias 'org-mail 'org-mu4e-compose-org-mode)

Handy Keys in mu4e

Org Mode

One of the neat things about mu4e is the fact that you can send messages built in org-mode, although the current implementation is a little flaky. Unless you do things the right way you’ll often get “Error 70,” and a plain unadorned e-mail will be sent out. Unfortunately, my friends and associates are not yet at that advanced stage of development that they’ll read org-mode format directly.

To use org-mode via compose, you:

Yeah, not ideal. But hopefully fixable and it isn’t too hard in practice; only a small percentage of the e-mails I send out are rich text.

You may want to change the default formatting options; I found that having a Table of Contents in my e-mails was a bit too pretentious, and the formatting for code blocks left too much white space. Apply the following diff:

diff --git a/mu4e/org-mu4e.el b/mu4e/org-mu4e.el
index 44d5ea1..6697486 100644
--- a/mu4e/org-mu4e.el
+++ b/mu4e/org-mu4e.el
@@ -170,7 +170,9 @@ and images in a multipart/related part."
            ;; because we probably don't want to export a huge style file
            (org-export-htmlize-output-type 'inline-css)
            ;; makes the replies with ">"s look nicer
-           (org-export-preserve-breaks t)
+           (org-export-preserve-breaks nil)
+            ;; turn off table of contents
+            (org-export-with-toc nil)
            ;; dvipng for inline latex because MathJax doesn't work in mail
            (org-export-with-LaTeX-fragments 'dvipng)
            ;; to hold attachments for inline html images

Org Mode Example

And, okay, to be honest it’s not entirely useful in the day to day, but it is pretty neat that if you need to you can send an e-mail via:

Remember we were talking about functions of the form $f(x) = x^2$ the other day?  I wanted to show you what it looked like.

#+name: python-data
#+BEGIN_SRC python :exports both :results replace
return [ (ix, ix*ix) for ix in xrange(0,11) ]

It's hard to visualize this, though, so it helps to look at the graph.

#+BEGIN_SRC R :var dat=python-data :exports both :results output graphics :file graph.png
ggplot(data=dat, aes(x=V1, y=V2))+geom_point()

… to get


Comments are moderated whenever I remember that I have a blog.

Steve Dowe | April 06, 2013
Thanks for this post. I think mu4e is going to be THE email client of 2013 - there seems to be growing interest on the web, if Google is anything to go by. :-) Anyway, thanks to your post I have set up a mu4e environment that suits me - your handy tips about configuration gave me some ideas which I used in my own .emacs file. One thing I have found is that on debian wheezy, mu (v 0.9.8) doesn't seem to index my Maildir properly. The newest version ( does a much better job.
songzw | September 04, 2013
nice post! and how to get that beautiful look from org mode at the very end of your post? I can't get it from my email account by testing the org-mode code. e.g., no code highlight, can't generate image from R source code. PS, I use gmail web client to check the mail. any clue here... Thank you!
songzw | September 04, 2013
well, I know how it works!
Gabor | October 02, 2014
Hello! LaTeX and R plots in email, very cool. I'm trying to reproduce this for the fun of it, but something must have changed in mu4e since you wrote this. I got as far as sending HTML emails with org-mu4e-compose-org-mode, but when I start including the LaTeX formula, but when I try to include the LaTeX formulas, the rendered LaTeX .png fragments are removed before mu4e sends the email, and so aborts saying: mm-insert-file-contents: Opening input file: no such file or directory, /tmp/ltxpng/...png How can I delay removing the temporary files, until mu4e finishes sending the email? I posted the question on Stackoverflow:
LaloHao | August 24, 2015
This is awesome! Just a fix for html render, setting it to mu4e default: (require 'mu4e-contrib) (setq mu4e-html2text-command 'mu4e-shr2text) html2text python on newest versions (> 2015.6.12) require that codification be set after file name Usage: html2text [(filename|url) [encoding]] I have no idea how to do that since (setq mu4e-html2text-command "html2text -b 72") is only set BEFORE the file name How did you manage to include pictures? For example this code #+begin_src gnuplot :var data=basic-plot :exports both :file /tmp/file.png set title "Putting it All Together" set xlabel "X" set xrange [0:1] set xtics 0,0.1,1 set ylabel "Y" set yrange [0.2:0.5] set ytics 0.2,0.05,0.5 plot data u 1:2 w p lw 2 title 'x vs. y1', \ data u 1:3 w lp lw 1 title 'x vx. y2' #+end_src Gets translated to this html and doesn't seem to get included in the email Obviously since its concatenating yet again the file name _tmp_file:_tmp_file2.png
LaloHao | August 24, 2015
Sorry html didn't show up in previous message <!-- --> <!-- --> <!-- --> <!-- --> Perhaps commenting it will do?
Add a comment