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.
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:
So that gives you the client ID and the client secret. Wait, you’re not done. You need a refresh token.
python/oauth2.py --generate_oauth2_token --client_id=yourclient --client_secret=yoursecret
.offlineimaprc, you’ll have something like:
[Repository Personal_Remote] ... oauth2_client_id = longstringofdigitsandnumbers.apps.googleusercontent.com oauth2_client_secret = longstringofdigitsandnumbers oauth2_request_url = https://accounts.google.com/o/oauth2/token oauth2_refresh_token = 1/longstringofdigitsandnumbers
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
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 () (interactive) (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 (setq 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 '(("smtp.gmail.com" 587 nil nil)) smtpmail-auth-credentials '(("smtp.gmail.com" 587 "user@domain" nil)) smtpmail-default-smtp-server "smtp.gmail.com" smtpmail-smtp-server "smtp.gmail.com" 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 "smtp.gmail.com" smtpmail-smtp-server "smtp.gmail.com" 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) (imagemagick-register-types)) ;;; message view action (defun mu4e-msgv-action-view-in-browser (msg) "View the body of the message in a web browser." (interactive) (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 (insert "" "" html)) (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") ) (mu4e) ) (defalias 'org-mail 'org-mu4e-compose-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
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) ] #+END_SRC 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 library(ggplot2) ggplot(data=dat, aes(x=V1, y=V2))+geom_point() #+END_SRC
… to get
Comments are moderated whenever I remember that I have a blog.