💾 Archived View for wilw.capsule.town › notes › aerc.gmi captured on 2024-12-17 at 09:47:11. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

🏡 Home

Back to notes

Email client (aerc)

Last updated on 20 October 2024

This note documents my current setup for email.

It includes:

- aerc [1] as an email client

1

- vdirsyncer [2] for syncing contacts

2

- khard [3] for reading and searching locally-synced contacts

3

- mbsync [4] for syncing email to a local Maildir

4

- notmuch [5] for organising and searching locally-synced email

5

Pre-start: Handling local credentials

To securely store credentials for syncing, I use `pass` [6]. I recommend installing this for your system and setting it up with a GPG key.

6

One issue I had whilst using `pass` was that it would frequently timeout, and the GPG dialog would fail to work or would interfere with the running mail client. As such, I extended the TTLs of the agent by adding these lines to my `~/.gnupg/gpg-agent.conf`:

default-cache-ttl 34560000
max-cache-ttl 34560000

Once set-up, add the needed credentials for your various mail accounts to `pass`. For some services (e.g. Fastmail and Google) an app-specific password should be generated for this. E.g.:

pass insert Email/fastmail

Step 1: Managing contacts (`vdirsyncer` and `khard`)

I use `vdirsyncer` to sync contacts to a local directory. This allows `khard` to read and search contacts locally and surface them to `aerc`.

To install both of these, use Homebrew on a Mac: `brew install vdirsyncer khard`.

`vdirsyncer` setup

Once installed, create a new configuration file for vdirsyncer at `~/.config/vdirsyncer/config`:

[general]
status_path = "~/.config/vdirsyncer/status/"

# Personal Contacts
[pair personal_addressbook]
a = "personal_addressbook_local"
b = "personal_addressbook_remote"
collections = ["from a", "from b"]
metadata = ["displayname"]

[storage personal_addressbook_local]
type = "filesystem"
path = "~/.config/khard/personal/"
fileext = ".vcf"

[storage personal_addressbook_remote]
type = "carddav"
auth = "basic"
url = "https://carddav.fastmail.com/dav/addressbooks/user/USERNAME@fastmail.com/Default"
username = "USERNAME@fastmail.com"
password.fetch = ["command", "pass", "Email/fastmail"]

This syncs my Fastmail (i.e. personal, non-work) contacts to `~/.config/khard/personal/`. The final three blocks of the config file (the `pair` and two `storage` blocks) can be repeated for each account you wish to sync contacts for.

I use it with both Fastmail and Google, and it works well. For Google contacts, the `url` I use is: `https://www.googleapis.com/carddav/v1/principals/USERNAME@DOMAIN.COM/lists`.

`khard` setup

For `khard`, create a new config file at `~/.config/khard/khard.conf` with contents along the lines of the example on the website [7]. Specifically, for the `[addressbooks]` section, I use the `~/.config` dir primarily out of laziness, as this auto-syncs with my dotfiles.:

7

[addressbooks]
[[personal]]
path = ~/.config/khard/personal/Default
[[work]]
path = ~/.config/khard/work/default
...

In the latter example, the `default` is lowercase as this is how Google names its default address books.

Testing contacts

To test this is all working, run a sync and then try searching for a contact:

vdirsyncer sync
khard list john

If you have a contact named John, you should see them listed.

Step 2: Syncing email (`mbsync`)

Although `aerc` can directly connect to IMAP servers, I prefer to have mail synced locally. This allows me to manage it using local tools (such as `notmuch`) but it also enables me to back things up more easily.

I use `mbsync` for syncing IMAP accounts to a local Maildir directory. It is part of a package called `isync` and can be installed with Homebrew: `brew install isync`.

To set it up, create a file at `~/.mbsyncrc`. I find the `mbscync` config file fiddly and unintuitive, but have set my personal Fastmail IMAP account up as follows. These blocks can be repeated for your other IMAP accounts (just ensure to use unique names for the accounts, stores, and channels).

IMAPAccount personal
Host imap.fastmail.com
Port 993
User USERNAME@fastmail.com
PassCmd "pass Email/fastmail"
TLSType IMAPS
AuthMechs LOGIN

IMAPStore personal-remote
Account personal

MaildirStore personal-local
Path ~/Syncthing/Maildir/personal/
Inbox ~/Syncthing/Maildir/personal/INBOX
SubFolders Verbatim

Channel personal
Far :personal-remote:
Near :personal-local:
Patterns *
Expunge None
CopyArrivalDate yes
Sync All
SyncState *
Create Both

You may notice that I reference a Maildir in my Syncthing directory. This is to ensure my mail is backed-up to other machines.

To test this is working, run `mbsync -a` and check the Maildir directory for your account. You should see your mail syncing.

Step 3: Organising email (`notmuch`)

`notmuch` is a tool I use for parsing and searching email in a local Maildir. It's super fast and works well with `aerc`.

To install it, use Homebrew (on a Mac): `brew install notmuch`.

To set it up, run `notmuch`. This will prompt for a few bits of info and setup a database at the root of your Maildir and a configuration file at `~/.notmuch-config`.

The defaults for the config are pretty good, but for reference I add mine below:

[database]
# Path to your Maildir
path=/Users/will/Syncthing/Maildir

[user]
# I don't think this affects much unless you use notmuch for sending mail too
primary_email=USER@DOMAIN.COM
other_email=email1;email2;

[new]
# default tags for new messages
tags=unread;inbox;
ignore=

[search]
# how to manage searches (i.e. ignore deleted/spam mail)
exclude_tags=deleted;spam;

[maildir]
# sync some notmuch tags with maildir flags (e.g. read/unread)
synchronize_flags=true

I also ensure to add the following to `~/Syncthing/.stignore` to prevent Syncthing from syncing the `notmuch` database (which is huge, but can be rebuilt):

.notmuch/xapian

notmuch hooks [8] can be set up to run commands alongside `notmuch`. For example, to add/remove tags before or after mail is processed.

8

My approach is simple, and I just have a single `post-new` hook in `~/Syncthing/Maildir/.notmuch/hooks/post-new` to make my mail management a little easier:

#!/bin/bash

# Reference Maildir folders for tagging
notmuch tag +personal "folder:/personal/"
notmuch tag +account2 "folder:/account2/"

# Handle sent and spam mail by IMAP folders
# e.g. if Gmail marks it as spam, tag it as spam
notmuch tag +sent "folder:/Sent/" and not tag:sent
notmuch tag +spam "folder:/Spam/" and not tag:spam

# Handle customer specific tags
notmuch tag +customer1 from:customer1.com
notmuch tag +customer2 from:customer2.com and tag:personal

# Remove the new tag from all new emails
notmuch tag -new tag:new

(Note: after creating this file for the first time, be sure to ensure it's executable: `chmod +x ~/Syncthing/Maildir/.notmuch/hooks/post-new`)

Because our config file auto-applies the `unread` tag, we don't need to handle it here, but we could if we wanted to.

If you now run `notmuch new`, the Maildir will be processed according to the config and any hooks you've setup.

You can now try running a search to show how fast it runs:

notmuch search from:domain1.com
notmuch search tag:personal

Step 4: Setting-up `aerc`

I now talk about installing and setting-up `aerc`, which will bring all of this together into one place.

Installation

Although it's installable from Homebrew, the distributed binary does not include `notmuch` support. As such, I compile `aerc` from source using the headers installed as part of the `notmuch` installation from earlier.

First, make sure to have `go` installed (according to the website [9]).

9

Clone the `aerc` repo and change into it:

git clone https://git.sr.ht/~rjarry/aerc
cd aerc

Set some flags so the build process knows where to find the `notmuch` headers and so the linker can find the library. In my case (and versions), this was done using:

export CPATH=/opt/homebrew/Cellar/notmuch/0.38.3/include
export LIBRARY_PATH=/opt/homebrew/Cellar/notmuch/0.38.3/lib

Now compile `aerc` with the `notmuch` tag:

gmake GOFLAGS=-tags=notmuch

Mail sync script

To help automate some of the mail fetching and tagging tasks, I added a script (largely taken from the example on the aerc wiki [10]). This script will be invoked whenever `aerc` wants to fetch new mail (as we'll set up later):

10

#!/bin/sh

MBSYNC=$(pgrep mbsync)
NOTMUCH=$(pgrep notmuch)

if [ -n "$MBSYNC" -o -n "$NOTMUCH" ]; then
    echo "Already running one instance of mbsync or notmuch. Exiting..."
    exit 0
fi

# Actually delete the emails tagged as deleted
notmuch search --format=text0 --output=files tag:deleted | xargs -0 --no-run-if-empty rm -v

mbsync -a
notmuch new

I save this in `~/.config/aerc/mail-sync`. As above, ensure this script is executable: `chmod +x ~/.config/aerc/mail-sync`.

Accounts setup

The `aerc` accounts setup is highly flexible. The man page (like this Arch Wiki one) [11] is a good reference.

11

Below is a sample of mine (in `~/.config/aerc/accounts.conf`), which demonstrates `notmuch` and `khard` integration:

[Combined]
source        = notmuch://~/Syncthing/Maildir
query-map     = ~/.config/aerc/map.conf
default       = INBOX
from          = Will Webberley <USERNAME@DOMAIN.COM>
check-mail-cmd = ~/.config/aerc/mail-sync
check-mail    = 2m
check-mail-timeout = 30s

[Personal]
source        = notmuch://~/Syncthing/Maildir
outgoing      = smtps://USERNAME%40fastmail.com@smtp.fastmail.com:465
maildir-store = ~/Syncthing/Maildir
maildir-account-path = personal
outgoing-cred-cmd = pass Email/fastmail
check-mail-cmd = mbsync personal && notmuch new
check-mail    = 2m
default       = INBOX
from          = Will Webberley <USERNAME@DOMAIN.COM>
cache-headers = true
copy-to       = Sent
address-book-cmd = khard email -a personal --parsable --remove-first-line %s

[Work1]
source        = notmuch://~/Syncthing/Maildir
... etc.

This setup includes a Combined account which is optional but I like it for having a single view across all my accounts. You can also see this account invoking the `mail-sync` script we created earlier.

The `khard` integration offers auto-complete suggestions as you type a name or email address into the mail composer.

The Combined account also makes use of a query map which maps "folders" onto `notmuch` queries. My `~/.config/aerc/map.conf` looks like this:

Inbox=tag:inbox
Todo=tag:todo and not tag:archived and not tag:deleted
All=not tag:archived and not tag:deleted and not tag:spam
Sent=tag:sent
Spam=tag:spam

General `aerc` configuration

I created a `~/.config/aerc/aerc.conf` file to set some general options. This file is also hugely configurable [12]. Mine is very basic by comparison:

12

[general]
default-save-path=~/Downloads
log-file=~/.aerc.log

[ui]
styleset-name=nord
fuzzy-complete=true
icon-new=✨
icon-attachment=📎
icon-old=🕰️
icon-replied=📝
icon-flagged=🚩
icon-deleted=🗑️

[statusline]

[viewer]
alternatives=text/plain,text/html
header-layout=From,To,Cc,Bcc,Date,Subject

[compose]
header-layout=From,To,Cc,Subject
reply-to-self=false
empty-subject-warning=true
no-attachment-warning=^[^>]*attach(ed|ment)

[multipart-converters]
text/html=pandoc -f markdown -t html --standalone

[filters]
text/html=pandoc -f html -t plain
text/plain=colorize
text/calendar=calendar
message/delivery-status=colorize
message/rfc822=colorize
.headers=colorize

[openers]

[hooks]

[templates]

An interesting part of this is the filter for HTML. By default `aerc` cannot display HTML emails. This makes emails impossible to view if there is no `text/plain` alternative. In my example I use `pandoc` to convert HTML to plain text, which works OK for me. Other solutions might involve `w3m` or other tools.

The `multipart-converters` section allows for specifying how non-plain parts of the email can be generated. Once an email is written (in `text/plain`) an HTML part can then be generated by running `:multipart text/html` when in review mode.

Running `aerc`

`aerc` can now be run: `/path/to/aerc -C ~/.config/aerc/aerc.conf -A ~/.config/aerc/accounts.conf`.

Run `:check-mail` in the Combined account to check that's working, try sending mail, check out the autocomplete of contacts via Khard, and try searching for emails.

For day-to-day use, I strongly recommend reading through the `aerc` wiki and man pages, and also experimenting with the setups published by other people.

Back to notes