Automatically Find PGP Keys in Mu4e

meysamazad1 pts0 comments

Automatically Find PGP Keys in Mu4e

Published:<br>03 July 2026 / 15 Messidor 234<br>Last Edited:<br>10 July 2026<br>/ 22 Messidor 234

Automatically Find PGP Keys in Mu4e

I have found a peculiar delight in encryption, and particularly in<br>using pgp-based asymmetric cryptography. This is especially useful for<br>securing email communications, but doing so requires remembering to<br>run M-x mml-secure-sign or mml-secure-encrypt in Mail Utilities For<br>Emacs (Mu4e) before sending the message. For this reason I have been<br>wanting to write a quick method that automatically adds signing<br>capabilities and encryption only when the recipient has a public<br>key. Thankfully, I did not have to do so because of Nicolas<br>Cavigneaux&rsquo;s recent post Sign Always, Encrypt When Possible where he<br>showcases his functions for doing exactly that. It prompted me to tweak<br>it slightly, and to add the functionality to automatically discover<br>public keys that I have yet to import.

Cavigneaux&rsquo;s post sets up an elegant arrangement: email should always<br>be signed with your pgp key, and you should &ldquo;upgrade&rdquo; from there to<br>encryption only if your correspondent can handle encrypted mail and<br>has shared their public key with you. This is done by using Emacs&rsquo;<br>built-in Easy Privacy Guard (epg) tooling to compare the owners of the<br>imported public keys on the machine with the list of recipients in an<br>email.1 If you have the public key for all recipients, the message<br>will be automatically encrypted — otherwise it will merely be signed<br>to prove that you are the author.

This was exactly what I had wanted, and I quickly incorporated this<br>functionality into my own configuration. Testing it out, I felt a bit<br>uneasy sending encrypted mail automatically. Because it is not the<br>default, I felt that fully automated encryption made me unsure whether<br>the mail has been encrypted or not — even when I know I have the<br>recipient&rsquo;s public key. I thus made the slight modification of<br>prompting for both encryption and signing:

(defun kudu/message-sign-encrypt-if-all-keys-available ()<br>"Add MML tag to encrypt message when there is a key for each recipient,<br>sign it otherwise."<br>(if (bounga/message-all-epg-keys-available-p)<br>(if (y-or-n-p "Encrypt? ")<br>(mml-secure-message-sign-encrypt)<br>(when (y-or-n-p "Sign? ")<br>(mml-secure-message-sign)))<br>(when (y-or-n-p "Sign? ")<br>(mml-secure-message-sign))))

In practice I will probably always be pressing Y when prompted, but<br>this adds a level of certainty that the code is running correctly. It<br>reminds me of an advertising gimmick for housewives in the 1950s: when<br>cake mix first became available, it was not appreciated because it was<br>perceived as being &ldquo;too easy&rdquo; — it did not feel like baking a cake<br>yourself. And so the recipe was tweaked to simply require an extra egg<br>to be added. In practice this was a trivial change, but it meant that<br>you felt more responsible for the finished work.

But there is an additional step I want to automate that Cavigneaux<br>alluded to, but did not implement. He writes:

[T]he policy is only as good as my keyring. Encryption depends on<br>having imported the right public keys; nothing here fetches them for<br>me.

I have recently been having more correspondence with people using the<br>Swiss-based email provider Protonmail. Proton provides support for the<br>Web Key Directory (wkd) method of providing keys, where the dns<br>settings of a domain point to a file containing a public key for a<br>specific user. This allows the email itself to &ldquo;provide&rdquo; its own<br>public key for encryption. The public key of any @protonmail.com or<br>@pm.me address can be quickly imported in a second using gpg<br>--locate-external-keys email@pm.me. Proton will similarly use wkd to<br>get your public key, and so you will receive encrypted mail as well.<br>This is still easy to set up for any other email provider, as long as<br>you can edit the domain settings.2

Sadly, epg does not come with any options for Gnupg&rsquo;s --locate-keys or<br>--locate-external-keys flags. This might be a good addition. In the<br>meantime, we can write a quick and dirty function to do the job for us<br>in the background when opening any new email:

(defun kudu/message-locate-keys ()<br>"Tries to find the public keys of 'bounga/message-recipients' via WKD through --locate-keys."<br>(dolist (recipient (string-to-list (bounga/message-recipients)))<br>(let ((recipient-email (cadr recipient))<br>(proc (make-process<br>:name "gpg-locate-keys"<br>:command (list epg-gpg-program "--no-tty" "--locate-keys" (cadr recipient))<br>:connection-type 'pipe<br>:filter (lambda (proc string)<br>(process-put proc 'output<br>(concat (or (process-get proc 'output) "") string)))<br>:sentinel (lambda (proc event)<br>(when (eq (process-status proc) 'exit)<br>(let ((output (process-get proc 'output))<br>(email (process-get proc 'email)))<br>(if (and output (string-match-p "imported: [1-9]" output))<br>(message "Public key imported for %s" email))))))))<br>(process-put proc 'email recipient-email))))

We use --locate-keys because the...

keys email public message sign proc

Related Articles