Contributing to the aerc email client

Posted on

Aerc is an open-source email client that runs in your terminal. During 2019 and early 2020, I contributed 32 patches to the project. Many of them were minor enhancements, bug fixes, and documentation updates, but I also contributed a number of more substantial features as well.

While I no longer use aerc regularly, I found it really rewarding to work with the other contributors and to interact with the community of people who were using software I helped write.

Maildir backend

When I first encountered aerc, it only supported browsing via IMAP. At the time, however, all of my email was synced to my machine and stored in a Maildir (essentially, a specific directory structure where each file represents an email message). Because I wanted to use aerc, and I didn’t want to lose my offline mail reading capabilities, I decided to add support for Maildir backends in addition to the existing IMAP.

While the maintainer had already planned to support multiple backends, including Maildir, only the IMAP backend had been implemented. This meant that there were a few places where the UI layer was tightly coupled with IMAP-specific functionality, so my first task was to extract slightly more generic models that could be used by various backends.

For example, many IMAP operations specify messages by their UID, which is a server-assigned unique identifier. The UI layer had initially been implemented in a way that used UIDs to distinguish between messages. However, in the context of a Maildir, messages don’t have server-assigned UIDs, but the UI layer still needs some way to keep track of which message(s) are being selected in the browser.

After a few revisions, my patch set for Maildir support was applied.

:unsubscribe command

Aerc is somewhat vim-like in its keyboard interface. Users type commands into a command line (or use keybindings to enter common commands more quickly), and then press the Return/Enter key to perform the action. Some of the common commands include things like :reply, :send, :attach, etc.

At this point, I think most people are probably familiar with “Unsubscribe” links that are included in messages from mailing lists. Astute users of certain mail readers like Gmail or Apple Mail may have even noticed that the mail application itself sometimes gives you a convenient “Unsubscribe” button, outside of the email display itself:

An unsubscribe button in the iOS Mail app An unsubscribe link in Gmail

I had always assumed that these were being parsed out of the message body1, but it turns out that RFC 2369 defines a List-Unsubscribe mail header that senders can add to their messages to provide a convenient way for people to unsubscribe.

The List-Unsubscribe header can contain one or multiple URLs. A mailto: URL can be used to specify an unsubscribe address, or a HTTP URL can specify a web page to visit in order to unsubscribe. I sent a patch to add an :unsubscribe command to aerc.

Address book integration

The third major feature I contributed was support for integrating an address book or contact list. Because many of aerc’s users tend to be familiar with or already use this sort of terminal-oriented utility, I took a lot of inspiration from the way mutt (another command line email client) handles contact integration.

I added an address-book-cmd configuration option that enabled users to configure an external command which aerc could run to fetch address completions. This command was expected to print out email addresses from the user's address book, and aerc would present the options in its tab completion system.

For my own personal use of this feature, I also created a janky little program that would print out completions for use in aerc by hitting a CardDAV endpoint.


  1. And maybe in some cases, they actually are — I don’t have any visibility into how these email clients are implemented! ↩︎


More in Computer Networks:
More in Projects: