Emacs The Ultimate: Mail reader - Setting up notmuch with emacs
I’ve been using the Emacs editor for the last six years and haven’t regreted the choice for a moment. Emacs is truly the programmers editor since it allows you to easily extend it and mold it to your own liking. It is also very versatile editor with modes and programs for most anything that you would want to do, this is powerful since it allows one to not switch to another program for most tasks.
For example there is no need to switch between emacs and the shell since I can just have a shell open in an emacs buffer!
One of the last holdouts of things I hadn’t integrated in my emacs workflow was email. I started looking at Gnus but that didn’t really appeal to me so I left it there for a while and continued using Thunderbird as my email client. One of the main issues that I have been having with thunderbird (besides it not being emacs..) is that working with mailing-lists have been a pain.
So last week I put a side a couple of hours and got my email into emacs! There are three parts to this.
- Getting the emails from my server
- Reading/Writing emails
- Sending emails
Something like thunderbird takes care of all these points and Gnus does to. But I went with using notmuch (https://notmuchmail.org/) and that pretty much only does efficient search and tagging, but there is an emacs package for notmuch that allows you to read and interact with your mail archive. It also means we have to do point 1 and 3 some other way!
Getting email
To fetch my emails from my server I went with the old standard fetchmail program. This is super easy to install and setup. I just added a .fetchmailrc in my home directory with the server and login information and it was ready to fetch some mail. One issue with fetchmail is that it can’t keep the emails on the server for n days and then delete them and since I for now also get emails directly to my phone this is somewhat of a problem.
The fetchmail configuration file looks like this:
poll <host>
protocol pop3
timeout 600
port <port>
username <username> password <password>
keep
ssl
mda "/usr/bin/procmail - '<location of procmail configuration>'"
Procmail is the mail delivery agent which puts the fetched emails in the correct directory.
My procmail configuration looks like
LOGFILE=$HOME/.procmail.log
MAILDIR=$HOME
VERBOSE=on
:0
Maildir/
We then need to get the emails into notmuch. This can just be done with notmuch new
. I then use a program called afew (https://github.com/teythoon/afew) that does initial tagging of emails. For example it tags each different mailing-list with the correct name of the list. My afew config looks like:
[SpamFilter]
[KillThreadsFilter]
[ListMailsFilter]
[SentMailsFilter]
sent_tag = sent
[ArchiveSentMailsFilter]
[Filter.1]
message = "Get mailing lists out"
query = 'tag:lists'
tags = +unread;-new;
[InboxFilter]
And I run afew with afew -tn
.
I then run notmuch tag -inbox tag:inbox AND tag:lists
. This removes the inbox tag from mails
that come from a mailing-list.
I’ve put all of these commands in a cronjob that runs once every hour. My file looks like:
fetchmail
notmuch new
afew -tn
notmuch tag -inbox tag:inbox AND tag:lists
exit 0
Reading/Writing Emails
As I mentioned above there is the notmuch package for emacs which allows you to interact with notmuch. To retrieve emails from notmuch one searches for the desired emails/tags and notmuch will show the matched emails to you. You can also set default searches with keyboard shortcuts to get to common searches fast! For example hitting j i
in the notmuch buffer will get all the emails with the inbox tag.
Sending emails
Emacs has the built in message mode that can be reached by hitting m in the notmuch buffer or r on an email to reply to that specific email. When you have finished writing your email you need to send it to the server that can relay the message to the recipient. Emacs as usual has some builtin functionality to do this with sendmail.el but for flexibility I wanted to use an external program. I chose to use msmtp for its simplicity. Again you just need to install msmtp, add the correct server configurations and tell emacs to use msmtp to send email with.
The configuration of msmtp is similar to fetchmail.
# Set default values for all following accounts
defaults
port <port>
# TLS should always be used
tls on
account example
host smtp.example.org
from tester@example.org
auth on
user tester
password best-password
account default : example
We then need to tell emacs about msmtp and configure it to set the correct headers. In my emacs configuration file I set these variables:
(setq mail-host-address "example.org")
(setq user-full-name "Tester Testington")
(setq user-mail-adress "tester@example.org")
(setq mail-user-agent 'message-user-agent)
(setq message-send-mail-function 'message-send-mail-with-sendmail)
(setq message-kill-buffer-on-exit t)
(setq mail-specify-envelope-from t)
(setq sendmail-program "/usr/bin/msmtp"
mail-specify-envelope-from t
mail-envelope-from 'header
message-sendmail-envelope-from 'header)
It is important to set the mail-host-address otherwise emacs will set the Message-Id header to something like “Message-ID: 8737m2q8na.fsf@localhost.i-did-not-set--mail-host-address--so-tickle-me”
And that is it, I just put all of the shell commands in a file and use cron to get and ingest mail every hour!
I’m now be comforted by the fact that I don’t have to leave emacs to read and write emails ever again!