Encrypting Email By Default with Mutt
I’d like my email to be encrypted by default when I address an email to a contact with a key in my keyring. Conversely, I don’t want to be prompted for a key ID if I address an email to someone without a key in my keyring. Here’s how to do that.
I use mutt for my email, and I like to encrypt my email with GPG. It’s relatively easy to encrypt on a per-email basis, but I’d like to encrypt my emails by default.
I can ensure that my replies to encrypted emails are always encrypted with:
set crypt_replyencrypt = yes
This is useful because it helps me avoid inadvertently responding to an encrypted email in plaintext.
However, I’d like to ensure that every email thread I start will also be encrypted. The recommended solution seems to be:
set crypt_autoencrypt=yes
This technically works, but I don’t like it. Mutt prompts me for the recipient’s key ID every time I send an email to a user that isn’t in my keyring. That might be fine if I only corresponded with GPG users, but I’m mostly communicating with regular folks without keys. That prompt is almost always an inconvenience.
Ideally, I’d like mutt to check my GPG keyring every time I draft an email and encrypt it only if I have the recipient’s key.
Mutt has send-hooks which can support that behavior on a per-recipient
basis. For example, suppose I always want to always encrypt messages to
foo@example.com
:
send-hook "!~l ~t foo@example.org" "set crypt_autoencrypt"
(The !~l
ensures that known mailing lists are excluded.)
We’d like to have such a hook in place for every email address in our keyring.
We can write a simple Ruby script that will print a send-hook for each of those
addresses to STDOUT
:
#!/usr/bin/env ruby
def raw_key_dump
`gpg --list-keys --with-colons --fixed-list-mode --no-secmem-warning`
end
def email_matcher
/.*\<(.*)\>/
end
def gpg_email_addresses
raw_key_dump.scan(email_matcher).flatten.uniq
end
gpg_email_addresses.each do |address|
puts "send-hook \"!~l ~t #{address}\" \"set pgp_autoencrypt\""
end
This doesn’t do anything too complex; it just finds and formats all the email
addresses in gpg --list-keys
. We can download this script and run it to
verify that it prints out a bunch of formatted send-hooks.
Let’s save it as ~/.mutt/gpg_keyring_send_hooks.rb
and make it executable.
Then we can add a couple lines in our muttrc
to load it when we start mutt:
send-hook . 'reset pgp_autoencrypt'
source "~/.mutt/gpg_keyring_send_hooks.rb|"
That first hook will reset encryption for every email address, and the second
will execute the script we wrote and evaluate the results as part of the mutt
configuration (that’s what the trailing “|
” indicates).
That’s it! Our crypto-capable contacts will now get encrypted emails by default. Our plaintext contacts won’t.
I’ve done this in my dotfiles and it seems to work just fine; you can check out the commit to verify the configuration.
You might like these textually similar articles: