Emacs - Notmuch

Introduction

Notmuch is a mail system1. It can efficiently manage a fairly large number of emails. Particularly, it supports fast email searching and filtering based on tags, which is extremely similar to Gmail's tags whereby various virtual folders can be flexibly realized.

This post is composed just to summarize the basic installation and configuration of notmuch-based mail system.

Installation

pacman -S notmuch

Configuration

~/.notmuch-config

The basic configuration can be performed by either

  • an interactive guidance which can be provoked by
notmuch setup
  • or a manually composed ~/.notmuch-config as follows
[database]
# Mail storage in maildir format
path=/MAIL/REPO

[user]
name=NAME
primary_email=EMAILADDRESS

[new]
tags=unread;inbox;
ignore=

[search]
exclude_tags=deleted;spam;

[maildir]
synchronize_flags=true

[crypto]
gpg_path=gpg

~/.emacs.d/init.el

Add following content to the configuration of Emacs.

  (require 'notmuch)
  (setq user-full-name "NAME"
        user-mail-address "EMAILADDRESS")

  (setq mail-user-agent 'message-user-agent
        message-kill-buffer-on-exit t
        mm-text-html-renderer 'w3m)

  (setq notmuch-search-oldest-first nil
        notmuch-show-all-multipart/alternative-parts nil
        mail-interactive t
        notmuch-always-prompt-for-sender nil
        notmuch-show-indent-messages-width 3)

  (setq mail-specify-envelope-from t
        message-sendmail-envelope-from 'header
        mail-envelope-from 'header)

  (setq message-directory "."
        notmuch-fcc-dirs ".")

  (setq message-send-mail-function 'smtpmail-send-it
        smtpmail-smtp-server "SMTPSERVER"
        smtpmail-stream-type 'ssl
        smtpmail-smtp-service PORT)

  (setq notmuch-saved-searches '((:name "inbox"
                                        :query "tag:inbox"
                                        :count-query "tag:inbox and tag:unread"
                                        :sort-order newest-first)

Hooks

Additionally, notmuch supports hooks which are essentially scripts in /MAIL/REPO/.notmuch/hooks whereby users can specify and customize the behaviors of notmuch. Currently, following scripts and hooks are available.

pre-new
Hook/script provoked before command notmuch new, which is usually used to fetch mails.
#!/bin/sh
/usr/bin/offlineimap -c /PATH/TO/OFFLINEIMAPRC -a ACCOUNT

or

#!/bin/sh
/usr/bin/getmail --new --getmaildir=/PATH/TO/GETMAILRC --rcfile=GETMAILRC
post-new
Hook/script provoked after command notmuch new, which is usually used to tag the newly imported mails.
#!/bin/sh
notmuch tag -inbox +ML -- to:MAILLIST@EXAMPLE.COM
notmuch tag -inbox +SOMEONE -- from:SOMEONE@EXAMPLE.COM
/usr/bin/notmuch search --output=files tag:deleted OR tag:spam | xargs -r rm
post-insert
Hook/script called after command notmuch insert, which is provoked after mails are delivered, imported into database and labelled with initial tags.
#!/bin/sh
notmuch tag -inbox -unread +sent -- from:MYEMAILADDRESS
/usr/bin/notmuch search --output=files tag:deleted OR tag:spam | xargs -r rm

Automatics

  • Add new intended task by crontab -e with following content
*/5 * * * * /usr/bin/notmuch new

where the first line is for periodical fetching mail every 3 minutes and the second line to remove the mails deleted (tagged by deleted) at every boot.

  • Enable and start the service cronie.
systemctl enable cronie.service
systemctl start cronie.service

CJK Support

By default, notmuch cannot separate Chinese correctly, Japanese, or Korean words due to the non-space separator. A workaround is to set a environment variable as follows.

export XAPIAN_CJK_NGRAM=1

Key binding

KeyFunction and description
n/pNext/previous message, notmuch-tree-next-matching-message
M-n/pNext/previous thread, notmuch-tree-next-thread
wSave attachments, notmuch-show-save-attachments
mWrite a new mail, notmuch-mua-new-mail
rReply a mail, notmuch-show-reply-sender
RReply all, notmuch-show-reply
fForward a mail, notmuch-show-forward-message
C-c C-aAttach a file, mml-attach-file
=Refresh current buffer, notmuch-refresh-this-buffer
M-=Refresh all buffer, notmuch-refresh-all-buffers
zDisplay threads matching query in tree view, notmuch-tree
ZTree view for the current query, notmuch-tree-from-search-current-query
+Change (add by default) tags for the current thread or region, notmuch-search-add-tag
-Change (remove by default) tags for the current thread or region, notmuch-search-remove-tag

Footnotes

Table of Contents