# If an outgoing message looks like I meant to attach something, and there
# isn't an attachment, prompt me to make sure I haven't forgotten it.
# I normally don't like this sort of nagging, but I'm making an exception in
# this case, as I really do trip up on this a lot. The default pattern of just
# 'attach' is a bit too aggressive, so I write a slightly softer one that
# reflects the usual way I refer to attachments.
#
set abort_noattach = ask-no
set abort_noattach_regexp = "attached (are|is)|(find|i have|i've|see) attached"
# Don't assume I don't want to continue editing a message if I didn't change
# anything to it; if I want to send a message with just my signature, that's my
# right.
#
unset abort_unmodified
# Put the alias file in a nice XDG location, distinct from the muttrc, so that
# we don't end up losing them each time the dotfiles are reinstalled; `man
# 5 muttrc` points out that this file needs to be explicitly sourced, too.
#
set alias_file \
= ~/.config/mutt/aliases
source $alias_file
# Don't send terminal bells on errors, but do send them when new mail arrives,
# because that should light up either my terminal emulator window or my tmux
# window label.
#
unset beep
set beep_new
# Don't prompt me for confirmation if I move messages into an existing mailbox;
# just do it.
#
unset confirmappend
# Switch to a subject format for forwarded messages that's more familiar to
# most mail users.
#
set forward_format = 'Fw: %s'
# Cache message headers for speed; this really helps.
#
set header_cache \
= ~/.cache/mutt/headers
# Save command history; this saves other kinds of history as well, but all
# I really want is to be able to run the same commands again even after I quit
# Mutt. We can afford to keep 2^8 of these, since it's the future and all.
#
set history_file \
= ~/.cache/mutt/history
set history = 256
set save_history = $history
# Always put a quoted copy of the whole message in a reply text for me to chop
# up and respond to in Vim--no need to prompt me (the default does that).
#
set include
# Tweak the index format to include spam tagging information, if any, with the
# %H format string
#
set index_format = '%4C %Z %{%b %d %Y} %-15.15L (%?l?%4l&%4c?) %?H?[%H] ?%s'
# Set a custom mailcap, rather than leaning on the system's
#
set mailcap_path \
= ~/.config/mutt/mailcap
# When displaying messages with multiple alternatives for display, prefer any
# plain text one, but failing that, fall back to enriched text (hey, it could
# happen...)
#
alternative_order \
text/plain \
text/enriched \
text/html \
application/pdf \
*
# Decode any text/html and application/pdf parts with .mailcap's specified
# programs.
#
auto_view \
text/html \
application/pdf
# Don't show any nasty little markers at the start of wrapped lines. That's
# the sort of thing Vim cares about, if need be.
#
unset markers
# Created mailboxes are in Maildir format everywhere I deploy this, so I may as
# well set it in here rather than get annoyed when Mutt starts dropping files
# in mbox format everywhere if I leave it out of muttrc.d/*.rc.
#
set mbox_type = Maildir
# Show a few messages of the index when in pager mode to give a little context
# around the message. I should have been doing this years ago. Oh well.
#
set pager_index_lines = 6
# Don't move on to the next message if we're at the end of the current one just
# because I executed <next-page>.
#
set pager_stop
# Use the abook program for finding and completing addresses with ^T. I do use
# the aliases system for regular correspondents, too.
#
set query_command = 'abook --mutt-query %s'
# Check with me whether I really want to quit, just in case I've hit "q" too
# many times trying to get out of e.g. the aliases menu.
#
set quit = ask-yes
# I prefer a slightly stricter pattern to match what is and isn't a quote; this
# avoids flagging things like closing braces on new lines in code blocks as
# quotes.
#
set quote_regexp = '^(>[ \t]*)+'
# Don't offer to resume a postponed message when I hit <mail>; I'll use
# <recall-message> for that.
#
unset recall
# If I have an alias configured for someone, use that in the index display, in
# preference to whatever the From: line actually says.
#
set reverse_alias
# Don't delay on switching or altering mailboxes so that I see the messages;
# just do it straight away.
#
set sleep_time = 0
# Only use the headers with proper references to link messages in a thread;
# don't try to use pattern matches on subjects, which might be rubbish like
# "hi". If I need to link a thread together because it's been broken somehow,
# I'll do that manually.
#
set strict_threads
# Use format=flowed, continuing paragraphs for lines that end with a single
# space, and use that wrapping information to use the full width of the
# terminal for the wrapping display.
#
set text_flowed
set reflow_wrap = 0
# Don't wait for me to press a key after running a command if it exited
# successfully; this still warns me if something failed, though.
#
unset wait_key
# Use the GPGME library for PGP; sign replies to messages that are themselves
# signed (whether encrypted or not), and encrypt when we have a key for every
# recipient (opportunistic).
#
set crypt_use_gpgme
set crypt_opportunistic_encrypt
set crypt_replysign
set crypt_replysignencrypted
# Use a default key for self-encrypting both sent and draft messages so that
# they're protected but legible. This defaults to the $GPG_KEYID environment
# variable, so be careful to set that lest you send useless OpenPGP headers!
# My kingdom for muttrc(5) conditionals...
#
set pgp_default_key = $GPG_KEYID
set postpone_encrypt
# Always include OpenPGP header with the selected default key, regardless of
# whether the message is protected or not:
#
# <https://datatracker.ietf.org/doc/draft-josefsson-openpgp-mailnews-header/>
#
# This RFC has expired and doesn't seem to have seen widespread adoption, but
# it looks like Thunderbird's Enigmail extension is still sending key IDs with
# it, and it doesn't do any harm.
#
my_hdr OpenPGP: id=$pgp_default_key\; \
preference=signencrypt\; \
url=https://keys.openpgp.org/vks/v1/by-fingerprint/$pgp_default_key
# Reset whatever ignore/unignore settings we've been passed by the system
# config, and use our own basic set, excluding User-Agent and other generally
# uninteresting fields.
#
ignore *
unignore date: from: to: cc: subject:
# Also show List-Archive and X-List-Archive headers, both to show the source
# list, and to provide me with a web link to it to pass on to anyone
# interested.
#
unignore list-archive: x-list-archive:
# Because I (personally) never want to encrypt mail without signing it, add in
# a hook for sending or changing a message that forces a signature if it's
# encrypted but not signed. This may not suit anyone else reading.
#
send-hook '~G !~g' \
'push <pgp-menu>s'
send2-hook '~G !~g' \
'push <pgp-menu>s'
# Because of the order in which opportunistic encryption is applied, we queue
# up a no-op change by opening the PGP menu and then doing nothing (pressing
# Enter), to trigger send2-hooks to run and turn signatures on if opportunistic
# encryption happens to have decided to switch encryption on.
#
send-hook '!~G !~g' \
'push <pgp-menu><enter>'
# Failing all of the above, maybe autocrypt will passively give us a key to
# use, but don't store its keys in our primary keyring.
#
set autocrypt
set autocrypt_dir \
= ~/.local/share/mutt/autocrypt
# Set custom filter to generate an HTML part for plain-text messages in
# Markdown style; defaults to off, per God's will and common decency.
#
set send_multipart_alternative_filter \
= ~/.local/libexec/mutt/filters/markdown-to-html
# Toggle multipart sending option manually and display the new setting
macro generic,index,browser,pager \\h '\
<enter-command>toggle send_multipart_alternative<enter>\
<enter-command>set ?send_multipart_alternative<enter>' \
'Toggle multipart/alternative sending'
# Shortcuts to jump to mailboxes
macro generic,index,browser,pager \\b \
'<change-folder>-<enter>' \
'Change to previous'
macro generic,index,browser,pager \\i \
'<change-folder>!<enter>' \
'Change to inbox'
macro generic,index,browser,pager \\r \
'<change-folder><<enter>' \
'Change to sent'
# Shortcuts to save to mailboxes
macro generic,index,browser,pager \\\Cb \
'<save-message>-<enter>' \
'Move message to previous'
macro generic,index,browser,pager \\\Ci \
'<save-message>!<enter>' \
'Move message to inbox'
macro generic,index,browser,pager \\\Cr \
'<save-message><<enter>' \
'Move message to sent'
# Shortcut to add addresses to abook
macro index,pager \\a \
'<pipe-message>abook --add-email-quiet<enter>' \
'Add sender address to abook'
# Janky notmuch-mutt search macro, cleaned up a little
macro index \\l '\
<enter-command>set \
my_pipe_decode=$pipe_decode \
my_wait_key=$wait_key \
nopipe_decode \
nowait_key<enter>\
<shell-escape>notmuch-mutt --prompt search --remove-dups<enter>\
<change-folder-readonly>~/.cache/notmuch/mutt/results<enter>\
<enter-command>set \
pipe_decode=$my_pipe_decode \
wait_key=$my_wait_key<enter>' \
'notmuch: search mail'
# Shortcut to reload configuration
set my_muttrc \
= ~/.config/mutt/muttrc
macro generic,index,browser,pager \\R '\
<enter-command>unhook *<enter>\
<enter-command>source $my_muttrc<enter>\
<enter-command>echo "Reloaded $my_muttrc"<enter>' \
"Clear hooks and reload"
# I often want thread display when having to keep track of multiple
# conversations at once with multiple people replying to one another, as is
# regularly the case when reading mailing lists, but for my personal mail it's
# generally nicer to sort the messages simply by date. This macro uses
# user-defined variables to toggle $sort between "threads" (default) and
# "date".
#
set sort = threads
set my_sort_alt = date-received
macro index \\t '\
<enter-command>set my_sort_tmp = $sort<enter>\
<enter-command>set sort = $my_sort_alt<enter>\
<enter-command>set my_sort_alt = $my_sort_tmp<enter>\
<enter-command>unset my_sort_tmp<enter>\
<enter-command>set ?sort<enter>' \
"Toggle thread display"
# When threads are on, sort them by the date the most recent message within
# them was received.
#
set sort_aux = last-date-received
# Set a few simple colors just for a quick visual cue of which tool I'm looking
# at and for some visual distinction between text, signature, and quote. The
# navigation bar is a nice dark green.
#
color attachment \
brightyellow default
color hdrdefault \
brightcyan default
color quoted \
brightgreen default
color signature \
cyan default
color status \
default color22
# Load machine-specific or account-specific settings from the helper script in
# muttrc.d, and we're done.
#
source ~/.config/mutt/muttrc.d/src|