Indexing encrypted email with notmuch
Since version 0.26, the mail indexing tool that I use, notmuch, now makes it easy to index encrypted mail.
The original behavior was that notmuch did not index the contents of encrypted emails, as they were encrypted and it couldn't access them. This meant that you couldn't search inside encrypted emails (except for headers, e.g., the subject, recipient, etc.).
Now, notmuch is able to use gpg (and gpg-agent) to read and index the cleartext of encrypted emails. Of course, this means that notmuch's index can now be used to reconstruct encrypted emails; in particular, as notmuch stores the session keys for messages in its index, this means that any attacker who can access the index can decrypt the messages1. For my use case, I think that this security risk is acceptable: I essentially see GPG as a tool to ensure that messages are not altered between the sender and recipient, my notmuch index is stored on an encrypted partition anyway, and my GPG passphrase is usually cached by gpg-agent so an attacker who has control over my machine would be able to access the plaintext of encrypted messages quite easily.
So, if you also use notmuch, if you also have your passphrase cached by gpg-agent at least part of the time, and if you want notmuch to index the cleartext of your encrypted emails, here is what you should do. First, you should make sure that you have notmuch 0.26 or a more recent version. Second, you should tell notmuch that you want it to index the cleartext of encrypted email:
notmuch config set index.decrypt true
Beware, this configuration flag lives only in the database, not in the config file; hence, e.g., it will not be synchronized across multiple machines if you synchronize your config files from one machine to another.
Then you should reindex all encrypted email that notmuch knows about but hasn't indexed yet (this took around 15 mins in my case):
notmuch reindex tag:encrypted and not property:index.decryption=success
Of course, you will be prompted for your GPG passphrase if it isn't cached (and also possibly for the passphrase of other keys that you have used in the past). Once this has completed, you should check the encrypted messages that notmuch was still unable to index:
notmuch search tag:encrypted and not property:index.decryption=success
In my case, there were only a few that couldn't be indexed -- and usually it was because they hadn't been encrypted for my key because the sender had made some mistake.
From now on, notmuch new
should automatically index the cleartext of incoming
messages when your GPG passphrase is cached by gpg-agent. The last step is the
following: if your passphrase is not cached all the time, then you should
arrange for the notmuch reindex
command above to be executed regularly, so
that encrypted messages will eventually be indexed.
The setup described in this post lead to unpleasant side effects where
GPG invocations would hang, probably because notmuch tried to ask for a
passphrase. To avoid this, I had to ensure that the notmuch reindex
command,
when run regularly, never tried to ask for a passphrase if it wasn't currently stored by
the agent. I did this by setting PINENTRY_USER_DATA=none
and modifying my
custom pinentry script to
handle properly this value. (Of course, this means that encrypted messages will
not be correctly indexed when the GPG agent hasn't cached the passphrase, but
the hope is that they will eventually be indexed.)
Another problem that I had is that notmuch reindex
would waste
CPU time by trying to reindex each time the emails where it had previously
failed. To avoid this, I reviewed manually the mails that couldn't be indexed,
tagged them with a special tag, and then excluded mails with that tag from the
notmuch reindex
command. I also added a crontab entry to review periodically
the emails where indexing failed, so I will tag them appropriately if the
failure is expected. A more elaborate idea would be to exclude from the notmuch
reindex
command the emails that are too ancient; or maybe script things so that
when all GPG keys are available in the agent but notmuch cannot index a message
then it should tag it so as not to try again.
I'm still having problems with pinentry misbehaving, i.e., either not showing up anymore because a pinentry-curses is waiting for input somewhere, or having pinentry-gtk popping up uninvited. I can live with it for now but at some point I should investigate this and tidy it up.
-
In fact, the historical workaround to index encrypted email with notmuch was simply to arrange for it to be decrypted when it arrives. I would also be OK with the security implications of this, but I have never set it up, because it's complicated to do right, especially because my GPG passphrase isn't always available in gpg-agent's cache. Besides, I prefer to keep an original copy of the email that I receive, so I think it's cleaner to keep the encrypted messages as-is and have notmuch store in its index its additional information that it needs. ↩