In a previous article I mentioned the ability to handle mailto: URI (described in RFC 6068) from Emacs. In this article I'll detail how I configured and connected the bits to make it work. Today these links are much less in use (due to spam concerns1), however when one such link is found it's useful to correctly handle it, sometimes they're pretty complex (for example reply-to links in mailing list).
I use an Emacs email client (mu4e) and the desired workflow is:
- Emacs as a daemon is running (example:
emacs --fg-daemon),mu4eis loaded. - I click a
mailto:link in a web page (or any other application) - A new Emacs buffer should open with an email draft pre-populated using parameters from the link
§ What is a "mailto:" URI?
Short digression for the curious ones, everyone else can skip this paragraph.
My understanding is that MIME types (Multipurpose Internet Mail Extensions) are a way to recognize file formats incoming from a network connection. For example .jpg files have MIME type image/jpeg. Usually we want to always trigger the same action for the same file. Everytime we double click on a .jpg file we want Gimp to open it. It is my understanding that these MIME types were adopted also to handle file associations for desktop applications. The associations between MIME types and applications is defined here.
A "mailto:" URI is handled with the MIME type x-scheme-handler/mailto and has the following syntax (newlines for clarity):
mailto:recipient@domain.com \
[?Subject=this is the subject] \
[&Reply-To=Jane Doe <jane.doe@domain.org>] \
[&Cc=John Doe <john.doe@domain.org>] \
[&OtherField=...]
A real world example could look like this garbled urlencoded mess:
mailto%3Arecipient%40domain.com%3FSubject%3Dthis%20is%20the%20subject%26Reply-To%3DJane%20Doe%20%3Cjane.doe%40domain.org%3E%26Cc%3DJohn%20Doe%20%3Cjohn.doe%40domain.org%3E
Will translate to the following email:
To: recipient@domain.com
Subject: this is the subject
Cc: John Doe <john.doe@domain.org>
Reply-To: Jane Doe <jane.doe@domain.org>§ The bits needed to make it work
What do I need to make it work? The steps are relatively simple but taken globally, there's a bit of context to figure out.
- configure the XDG Desktop handler for the MIME type, this will bind an action when the "mailto:" is clicked
- configure mu4e to handle the receiving "payload"
- tell the web browser (Firefox, in my case) which handler to use when the user clicks a "mailto:" link
MIME types association with applications are stored in $XDG_CONFIG_HOME/mimeapps.list.
XDG .desktop files are a (hopefully) accepted standard on Linux to assign custom extended handlers for MIME types. For example, I might not just simply want to open Gimp for a .jpg, I want to define a desktop icon, a description and other properties for this association. Desktop files are documented in the freedesktop.org (source: ArchWiki).
§ Configure the XDG Desktop handler for the MIME type
In my Debian installation, .desktop files are in /usr/share/applications (system-wide) or ~/.local/share/applications (user-specific). Unsure why, but the Emacs package installs some more in /usr/share/emacs/30.1/etc (which we will ignore):
$ ls -la /usr/share/{applications,emacs/30.1/etc}/emacs*.desktop
-rw-r--r-- 1 root root 839 Mar 30 07:26 /usr/share/applications/emacsclient.desktop
-rw-r--r-- 1 root root 737 Jul 7 15:00 /usr/share/applications/emacsclient-mail.desktop
-rw-r--r-- 1 root root 542 Mar 30 07:26 /usr/share/applications/emacs.desktop
-rw-r--r-- 1 root root 256 Mar 30 07:26 /usr/share/applications/emacs-mail.desktop
-rw-r--r-- 1 root root 510 Mar 30 07:26 /usr/share/applications/emacs-term.desktop
-rw-r--r-- 1 root root 834 Feb 24 08:14 /usr/share/emacs/30.1/etc/emacsclient.desktop
-rw-r--r-- 1 root root 616 Feb 24 08:14 /usr/share/emacs/30.1/etc/emacsclient-mail.desktop
-rw-r--r-- 1 root root 256 Feb 24 08:14 /usr/share/emacs/30.1/etc/emacs-mail.desktop
Firefox by default uses emacs-mail.desktop which opens a new instance of Emacs. I want to switch to using emacsclient-mail.desktop. Let's change that:
# increase debugging level
$ export XDG_UTILS_DEBUG_LEVEL=2
$ xdg-mime default emacsclient-mail.desktop x-scheme-handler/mailto
make_default_kde: No kde runtime detected
make_default_generic emacsclient-mail.desktop x-scheme-handler/mailto
Updating /home/$USER/.config/mimeapps.list
Good! The file ~/.config/mimeapps.list has been updated with a new entry:
[Default Applications]
...
x-scheme-handler/mailto=emacsclient-mail.desktop§ Configure mu4e
Now let's ensure that mu4e behaves as the standard email agent when the .desktop file invokes (message-mailto URL SUBJECT):
(setq
mail-user-agent #'mu4e-user-agent
message-mail-user-agent t)§ Tell the web browser to use the other handler
Last step, I need to switch handler in Firefox:
§ Conclusions
And that's basically it: now clicking a mailto: link in Firefox should open a new mu4e compose buffer in Emacs.
One further change I would like to implement is using my own $XDG_DATA_HOME/applications/emacsclient-mail.desktop with a custom emacsclient launcher, but that turns out to be a bit finnicky. I'll maybe update this blog post if I figure this out.
Hope it was useful! Let me know what you think.
§ Resources
- XDG Spec "Association between MIME types and applications"
- XDG Spec "Desktop Entries"
- ArchWiki XDG Desktop entries
- Archwiki XDG MIME Applications
- Archwiki
xdg-utils
this is why we can't have nice things