Checking email with gmailieer + notmuch + Emacs

In my continuing investigation of Emacs, I'm experimenting with checking email locally (i.e. on my computer) rather than using a web browser. I've used Gmail's web interface for my email for probably eight years at this point. Several years ago my friend recommended checking out notmuch for email; I poked around with it at the time but didn't understand what I was doing. Here's what I've figured out in trying to set this up again.

1 Concepts

Where we're going is:

  1. gmi (gmailieer) is going to check gmail, both pulling messages and synchronizing labels/tags
  2. notmuch is going to own the local machine's email indexing/tagging
  3. The Notmuch Emacs interface is going to own the actual MUA (mail user agent) work such as finding and reading emails
  4. Emacs's message-mode will be used to send emails

2 Failed attempts

I tried to use offlineimap for this first. However, (a) I didn't know what I was doing at all and (b) getting Gmail's labels to align to notmuch's labels required lots of nametrans and folderfilter lambda functions.

3 Shell work

Before Emacs is involved, a bunch of applications have to be installed and configured. First, notmuch and gmailieer have to be installed.

These instructions are OS X+Macports specific, but hopefully they are easy to understand and adapt to other platforms. These instructions also assume you have python-3.6, virtualenv, and virtualenvwrapper installed and virtualenvwrapper has been sourced in your current shell (i.e. you are actually using virtualenvwrapper).

# Make sure notmuch is installed:
sudo port install notmuch
cat > ~/.notmuch-config <<EOF
name=John Borwick
# Create & then use virtualenv. (mkvirtualenv does this)
mkvirtualenv --python=python3.6 gmailieer
mkdir -p ~/build
cd ~/build
# install notmuch libraries. ideally this would be from the same
# notmuch source as the above, but this works:
git clone
cd notmuch/bindings/python
python install
  # install gmailieer:
cd ~/build
git clone
cd gmailieer
python install
# create notmuch database:
mkdir ~/Mail
cd ~/Mail
notmuch new
# ... ideally get a Google developer API certificate and call
#  gmi auth -c your-client-secrets.json
gmi init
# This changes gmi to pull the "promotions", "updates", etc tags:
gmi set --ignore-tags-remote ""
# This is the step that takes forever:
gmi pull
# make notmuch call gmi when 'notmuch new' is called:
mkdir -p .notmuch/hooks
cat > .notmuch/hooks/pre-new <<EOF
source ~/.virtualenvs/gmailieer/bin/activate
cd ~/Mail
gmi sync
chmod +x .notmuch/hooks/pre-new

If all goes well, gmi pull will show a progress bar and when done, your gmail email will be on your computer with the same labels (notmuch "tags") that you have in gmail.

4 Emacs setup

The other big step is configuring Emacs. Here's what I've done, all in my ~/.emacs.d/init.el:

; If I'm going to send email then I would like address completion. Therefore I'm going to
; use Big Brother database, for contacts:
(when (not (require 'bbdb nil t))
           (package-install 'bbdb))
; Notmuch for Emacs:
(when (not (require 'notmuch nil t))
           (package-install 'notmuch))
; want org-plus-contrib to get org-notmuch:
(add-to-list 'package-archives '("org" . "") t)
(when (not (require 'org-plus-contrib nil t))
           (package-install 'org-plus-contrib))
(require 'bbdb)
(require 'org-notmuch)

; configure outgoing SMTP (so you can send messages):
(setq smtpmail-smtp-server ""
      smtpmail-smtp-service 587)

I wouldn't be surprised if there are other things missing from the above, but I think that's most of the config. Once everything is set up, you should be able to run M-x notmuch.

Within notmuch, G calls notmuch new, which due to the pre-new script in Shell work, above, will call gmi sync to receive new mail and send any label changes.

5 Next steps

I've begun to build my notmuch-specific tags:

cd ~/Mail
cat > .notmuch/hooks/post-new <<EOF
notmuch tag +to_me -- and -tag:to_me
notmuch tag +to_me -- and -tag:to_me
chmod +x ~/.notmuch/hooks/post-new

# Run this script for the first time:
# Synchronize these new labels with gmail:
gmi sync

The post-new script can be used to add other tags. Also, the above configuration gives every message a notmuch new tag (that isn't synchronized to Google); you can add that tag to your logic if you only want to parse emails that have recently come in. You can also add other labels (such as this to_me label) to your local labels to ignore; please check the gmailieer documentation on how to do this.