mail: Update to new neomutt structure

Updated notmuch to only be available for full-text search. Removed
complete afew configuration.

Added msmtp as mail sending agent.

Added structured neomutt configuration with custom bindings, built for
my personal gmail account, without any plaintext passwords revealed,
etc.

This is a reasonably well working mail setup,
which should provide a stable starting point for further refinements.

Additionally, added some functionality to `mail-check` script:
Allowed user to choose sync target for each run, by
passing in mbsync target (group/channel/..) as the argument.
Also, allows setting password file to use for script through env var,
and made imapfilter location less hard-coded to my system.
This commit is contained in:
Marty Oehme 2021-10-20 09:19:48 +02:00
parent 7a7ce3a296
commit a99982028e
Signed by: Marty
GPG key ID: B7538B8F50A1C800
9 changed files with 279 additions and 187 deletions

View file

@ -1,24 +0,0 @@
# filter creation
[InboxDumpingFilter(Filter)]
query = (tag:dump or folder:Dump) and (tag:inbox or tag:unread or tag:new)
tags = -new;-inbox;-unread;+dump
message = removing dumped mails from inbox
[KillThreadsFilter]
[FolderNameFilter]
folder_explicit_list = Dump
folder_transforms = Dump:dump
maildir_separator = /
[ArchiveSentMailsFilter]
sent_tag=sent
[InboxDumpingFilter.0]
[InboxFilter]
# moving mode
[MailMover]
folders = Inbox Dump
rename = True
max_age = 15
# rules
Inbox = 'tag:dump':Dump 'NOT tag:inbox AND NOT tag:dump AND NOT tag:spam':'[Google Mail]/All Mail' 'tag:deleted':'[Google Mail]/Trash'
Dump = 'NOT tag:spam AND NOT tag:dump AND tag:inbox':Inbox

18
mail/.config/msmtp/config Normal file
View file

@ -0,0 +1,18 @@
# Set default values for all following accounts.
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
# logfile ~/.msmtp.log
# Gmail
account personal-gmail
host smtp.gmail.com
port 587
from marty.oehme@gmail.com
user marty.oehme@gmail.com
# password plain-text-password-goes-here
passwordeval "gpg --quiet --for-your-eyes-only --no-tty --decrypt $XDG_DATA_HOME/pass/misc/aerc-gmail-app-password.gpg"
# Set a default account
account default : personal-gmail

View file

@ -0,0 +1,16 @@
# Account settings
# local maildir settings
set mbox_type = Maildir
set folder = ~/documents/mail # This has the shortcut '+' or '='
set spoolfile = "+inbox" # This has the shortcut '!'
set postponed = "+drafts"
set trash = "+trash"
# Disable saving outgoing mail since Gmail saves them by default.
unset record
mailboxes ! \
"+important" \
"+sent" \
"+drafts" \
"+trash" \
"+archive"

View file

@ -0,0 +1,69 @@
# taken from https://gideonwolfe.com/posts/workflow/neomutt/intro/
# Header colors:
color header blue default ".*"
color header brightmagenta default "^(From)"
color header brightcyan default "^(Subject)"
color header brightwhite default "^(CC|BCC)"
mono bold bold
mono underline underline
mono indicator reverse
mono error bold
color normal default default
color indicator brightyellow default # currently selected message. default makes bar clear, disabled arrow to save space.
color sidebar_highlight red default
color sidebar_divider brightblack black
color sidebar_flagged red black
color sidebar_new green black
color normal brightyellow default
color error red default
color tilde black default
color message cyan default
color markers red white
color attachment white default
color search brightmagenta default
color status brightyellow black
color hdrdefault brightgreen default
color quoted green default
color quoted1 blue default
color quoted2 cyan default
color quoted3 yellow default
color quoted4 red default
color quoted5 brightred default
color signature brightgreen default
color bold black default
color underline black default
color normal default default
color body brightred default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+" # Email addresses
color body brightblue default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+" # URL
color body green default "\`[^\`]*\`" # Green text between ` and `
color body brightblue default "^# \.*" # Headings as bold blue
color body brightcyan default "^## \.*" # Subheadings as bold cyan
color body brightgreen default "^### \.*" # Subsubheadings as bold green
color body yellow default "^(\t| )*(-|\\*) \.*" # List items as yellow
color body brightcyan default "[;:][-o][)/(|]" # emoticons
color body brightcyan default "[;:][)(|]" # emoticons
color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon?
color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon?
color body red default "(BAD signature)"
color body cyan default "(Good signature)"
color body brightblack default "^gpg: Good signature .*"
color body brightyellow default "^gpg: "
color body brightyellow red "^gpg: BAD signature from.*"
mono body bold "^gpg: Good signature"
mono body bold "^gpg: BAD signature from.*"
color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]"
# Default index colors:
color index yellow default '.*'
color index_author red default '.*'
color index_number blue default
color index_subject cyan default '.*'
# For new mail:
color index brightyellow black "~N"
color index_author brightred black "~N"
color index_subject brightcyan black "~N"
color progress black cyan

59
mail/.config/neomutt/maps Normal file
View file

@ -0,0 +1,59 @@
# index navigation
bind index l display-message
bind index L limit
bind index,pager g noop # don't send group-replies with g
bind index gg first-entry
bind index G last-entry
bind index <space> collapse-thread
bind index,pager \CF next-page
bind index,pager \CB previous-page
bind index,pager N search-opposite # vim-like search
bind index s toggle-new
macro index \CS "T~U<enter><tag-prefix><clear-flag>N<untag-pattern>.<enter>" "mark all messages as read"
# Email completion bindings
bind editor <Tab> complete-query
bind editor ^T complete
# Press A to add contact to Khard address book
macro index,pager A \
"<pipe-message>khard add-email<return>" \
"add the sender email address to khard"
# mailbox navigation
macro index,pager gi "<change-folder>=inbox<enter>" "go to inbox"
macro index,pager gm "<change-folder>=important<enter>" "go to important"
macro index,pager gs "<change-folder>=sent<enter>" "go to sent"
macro index,pager gd "<change-folder>=drafts<enter>" "go to drafts"
macro index,pager gt "<change-folder>=trash<enter>" "go to trash"
macro index,pager ga "<change-folder>=archive<enter>" "go to archive"
# sidebar navigation
bind index,pager B sidebar-toggle-visible
bind index,pager <down> sidebar-next
bind index,pager <up> sidebar-prev
bind index,pager <right> sidebar-open
# search navigation
macro index a "<limit>all\n" "show all messages (undo limit)"
# notmuch search navigation
bind index \\ vfolder-from-query # notmuch search
# pager navigation
bind pager,attach h exit
bind pager l view-attachments
bind pager k previous-line
bind pager j next-line
bind pager gg top
bind pager G bottom
# compose postpone
bind compose p postpone-message
# since we unbound the original g
bind index,pager R group-reply
# open urls found in the e-mail
macro index,pager \CU "|urlview<enter>" "call urlview to open links"
# Refresh far imap email
macro index O "<sync-mailbox><shell-escape>export MBSYNC_PRE=true; mail-check<enter><sync-mailbox>" "refresh all e-mail"
macro index o "<sync-mailbox><shell-escape>export MBSYNC_PRE=true; mail-check gmail-inbox<enter><sync-mailbox>" "refresh inbox e-mail"
# Saner copy/move dialogs
macro index C "<copy-message>?<toggle-mailboxes>" "copy a message to a mailbox"
macro index M "<save-message>?<toggle-mailboxes>" "move a message to a mailbox"

View file

@ -1,140 +1,6 @@
# Identity source colors
# source settings
set realname = "Marty Oehme" source maps
set from = "marty.oehme@gmail.com"
# # If you have another address:
# alternates "^neomutt@example\.com$"
# # Or, if you use the entire domain:
# alternates "@example\.com$"
# set reverse_name
# Account settings source account
# local maildir settings
set mbox_type = Maildir
set folder = ~/documents/mail # This has the shortcut '+' or '='
set spoolfile = "+inbox" # This has the shortcut '!'
set postponed = "+drafts"
set trash = "+trash"
# Disable saving outgoing mail since Gmail saves them by default.
unset record
mailboxes ! \
"+important" \
"+sent" \
"+drafts" \
"+trash" \
"+archive"
set mail_check = 60
set mail_check_stats
# Basic settings
set quit # at least for rapid prototyping
unset mark_old # things should only be new/unread or I actually looked at them
set pipe_decode # get rid of headers when passing messages along
set wait_key = no # don't wait for user input after shell cmds, auto-view, piping, etc
# set
set sort_re # thread based on regex below
# set reply_regex = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"
# display
set sort = threads
set sort_aux = reverse-last-date-received
set date_format = "%z/%m/%d %I:%M%p"
# set date_format = "%m/%d"
set index_format = "%4C [%Z] %{%y/%b %d} %-20.20F %s"
# sidebar view options
set sidebar_visible = yes
set sidebar_width = 18
set sidebar_format = "%B%?F? [%F]?%* %?N?%N/?%S"
color sidebar_new color221 color233
# statusbar view options
set status_chars = " *%A"
set status_format = "───[ Folder: %f ]───[%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]───%>─%?p?( %p postponed )?───"
# pager view options
set pager_index_lines = 5
set pager_context = 3
set pager_stop # do not go to next msg if at bottom of pager
set menu_scroll = yes
set tilde # show tildes for blank lines
unset markers # no + markers for wrapped stuff
# hide headers except for those explicitly unignored
ignore *
unignore From To Cc Bcc Date Subject Message-ID
unhdr_order *
unignore From To Cc Bcc Date Subject Message-ID
# index navigation
bind index,pager g noop # don't send group-replies with g
bind index gg first-entry
bind index G last-entry
bind index <space> collapse-thread
# mailbox navigation
macro index,pager gi "<change-folder>=inbox<enter>" "go to inbox"
macro index,pager gm "<change-folder>=important<enter>" "go to important"
macro index,pager gs "<change-folder>=sent<enter>" "go to sent"
macro index,pager gd "<change-folder>=drafts<enter>" "go to drafts"
macro index,pager gt "<change-folder>=trash<enter>" "go to trash"
# sidebar navigation
bind index,pager <down> sidebar-next
bind index,pager <up> sidebar-prev
bind index,pager <right> sidebar-open
# bind index,pager \CO sidebar-open
# pager navigation
bind pager k previous-line
bind pager j next-line
bind pager gg top
bind pager G bottom
# since we unbound the original g
bind index,pager R group-reply
# mark all read
macro index \CN "T~U<enter><tag-prefix><clear-flag>N<untag-pattern>.<enter>" "mark all messages as read"
# open urls found in the e-mail
macro pager \CU "|urlview<enter>" "call urlview to open links"
# Sync email
macro index O "<sync-mailbox><shell-escape>mbsync -c $XDG_CONFIG_HOME/isync/mbsyncrc -a<enter><sync-mailbox>" "refresh all e-mail"
macro index o "<sync-mailbox><shell-escape>mbsync -c $XDG_CONFIG_HOME/isync/mbsyncrc gmail-inbox<enter><sync-mailbox>" "refresh inbox e-mail"
# Saner copy/move dialogs
macro index C "<copy-message>?<toggle-mailboxes>" "copy a message to a mailbox"
macro index M "<save-message>?<toggle-mailboxes>" "move a message to a mailbox"
# pager settings
# filetypes and mailcap
set mailcap_path = "~/.config/neomutt/mailcap:~/.mailcap:/usr/share/neomutt/mailcap:/etc/mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap"
# Prefer plain text to html.
# However, for brain dead clients that bundle attachments inside a
# multipart/alternative, prefer that alternative.
alternative_order multipart/mixed multipart/related text/plain
alternative_order text/plain text/enriched text/html
# Consult mime.types for determining types of these attachments
mime_lookup application/octet-stream
# This requires a ~/.mailcap entry with the copiousoutput flag, such as:
# text/html; lynx -dump -width ${COLUMNS:-80} %s; nametemplate=%s.html; copiousoutput
auto_view text/html
# Remember to `mkdir -p ~/.neomutt/hcache` first:
set header_cache= "~/.neomutt/hcache"
###############
# Message composition settings
#
set edit_headers
# set editor = "emacsclient -a emacs -t"
# set editor = "vim"
set mime_type_query_command = "xdg-mime query filetype"
# msmtp is a solid SMTP client.
# neomutt also has built-in SMTP, or you can use an MTA like exim4 or postfix.
set sendmail = "/usr/bin/msmtp"
# lbdb is a versatile contact query tool.
# Invoke via ctrl-t in an address prompt
set query_command = "/usr/bin/lbdbq"

View file

@ -0,0 +1,78 @@
# Identity
#
set realname = "Marty Oehme"
set from = "marty.oehme@gmail.com"
# # If you have another address:
# alternates "^neomutt@example\.com$"
# # Or, if you use the entire domain:
# alternates "@example\.com$"
# set reverse_name
set mail_check = 60
set mail_check_stats
# Basic settings
set quit # at least for rapid prototyping
unset mark_old # things should only be new/unread or I actually looked at them
set pipe_decode # get rid of headers when passing messages along
set wait_key = no # don't wait for user input after shell cmds, auto-view, piping, etc
# Pager settings
# filetypes and mailcap
set mailcap_path = "~/.config/neomutt/mailcap:~/.mailcap:/usr/share/neomutt/mailcap:/etc/mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap"
# Consult mime.types for determining types of these attachments
mime_lookup application/octet-stream
alternative_order multipart/mixed multipart/related text/plain
alternative_order text/html text/plain text/enriched text/*
# This requires a ~/.mailcap entry with the copiousoutput flag, such as:
# text/html; lynx -dump -width ${COLUMNS:-80} %s; nametemplate=%s.html; copiousoutput
# Prefer plain text to html but multipart to plain for those only sending that
auto_view text/html
# Remember to `mkdir -p ~/.neomutt/hcache` first:
set header_cache= "~/.neomutt/hcache"
# Compose settings
set edit_headers # allow editing headers while writing mail
set sig_dashes # separate signature from mail
set fast_reply # automatically fill in from and subject for replies
set forward_format = "Fwd: %s"
set reply_to # default send back to reply-to: header instead of from: header
set reverse_name # default to reply as person e-mail was originally sent to
set include # include original msg in reply
set forward_quote # include original msg as quote in fwd
# set editor = "emacsclient -a emacs -t"
# set editor = "vim"
set mime_type_query_command = "xdg-mime query filetype"
# send settings
set sendmail = "/usr/bin/msmtp -a personal-gmail"
set sendmail_wait = 0
# Display Settings
set sort = threads
set sort_re # thread based on regex below
set reply_regex = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"
set sort_aux = reverse-last-date-received
set date_format = "%z/%m/%d %I:%M%p"
# set date_format = "%m/%d"
set index_format = "%4C [%Z] %{%y/%b %d} %-20.20F %s"
# sidebar view options
set sidebar_visible = yes
set sidebar_width = 18
set sidebar_format = "%B%?F? [%F]?%* %?N?%N/?%S"
color sidebar_new color221 color233
# statusbar view options
set status_chars = " *%A"
set status_format = "───[ Folder: %f ]───[%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? ]───%>─%?p?( %p postponed )?───"
# pager view options
set pager_index_lines = 5
set pager_context = 3
set pager_stop # do not go to next msg if at bottom of pager
set menu_scroll = yes
set tilde # show tildes for blank lines
unset markers # no + markers for wrapped stuff
# hide headers except for those explicitly unignored
ignore *
unignore From To Cc Bcc Date Subject Message-ID
unhdr_order *
unignore From To Cc Bcc Date Subject Message-ID
set query_command = "khard email --parsable --search-in-source-files '%s'"
set nm_query_type = "threads" # Makes notmuch return threads rather than messages

View file

@ -48,7 +48,7 @@ other_email=mo82rimu@studserv.uni-leipzig.de;moehme@ruc.dk;
# in the mail store. # in the mail store.
# #
[new] [new]
tags=new tags=
ignore= ignore=
# Search configuration # Search configuration

View file

@ -1,13 +1,33 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# runs mbsync, with pre-hooks and post-hooks #
# by default, first runs imapfilter # Runs mbsync, with pre-hooks and post-hooks
# and after indexes with notmuch # by default, the pre-hook first runs imapfilter
# and afterwards the post-hook indexes with notmuch.
#
# At the very least, you will have to set up a gpg
# encrypted file containing the password for your
# remote mailbox. It can be set directly below or
# through the environment variable
# `MBSYNC_PASSWORD_FILE` and should point to any
# gpg decryptable file.
# #
# To run without invoking any hooks or retry attempts, # To run without invoking any hooks or retry attempts,
# run `checkmail raw` # run `checkmail raw`.
# this will simply invoke a single isync run on all # this will simply invoke a single isync run on all
# boxes with the correct config file set. # boxes with the correct config file set.
# #
# To invoke mbsync for a specific group or channel,
# simply run it with `checkmail <channelname>` and
# it will only sync the correspondingly named.
#
# To run your own commands as hooks overwrite the
# environment variables `MBSYNC_PRE` and
# `MBSYNC_POST`. If you want to not have anything run
# for either of them the easiest way is to set the
# corresponding environment variable to true.
# Be careful which commands you put here since they
# will be evaluated without any special precautions.
#
# for more advanced, per-account/channel hooks, see # for more advanced, per-account/channel hooks, see
# https://sourceforge.net/p/isync/feature-requests/8/ # https://sourceforge.net/p/isync/feature-requests/8/
@ -16,15 +36,16 @@
# MBSYNC_PRE="/bin/usr/cmd-to-run" # MBSYNC_PRE="/bin/usr/cmd-to-run"
# MBSYNC_POST="/bin/usr/cmd-to-run" # MBSYNC_POST="/bin/usr/cmd-to-run"
# MBSYNC_NOTIFY=1 # MBSYNC_NOTIFY=1
# MBSYNC_PASSWORD_FILE="/path/to/gpg/file.gpg"
PASSWORD_FILE="$HOME/.local/share/pass/misc/aerc-gmail-app-password.gpg" PASSWORD_FILE="${MBSYNC_PASSWORD_FILE:-$HOME/.local/share/pass/misc/aerc-gmail-app-password.gpg}"
prehook() { prehook() {
if [ -n "$MBSYNC_PRE" ]; then if [ -n "$MBSYNC_PRE" ]; then
eval "$MBSYNC_PRE" eval "$MBSYNC_PRE"
return 0 return 0
fi fi
imapfilter -c "${XDG_CONFIG_HOME:-/home/marty/.config}/imapfilter/config.lua" imapfilter -c "${XDG_CONFIG_HOME:-$HOME/.config}/imapfilter/config.lua"
} }
posthook() { posthook() {
@ -34,10 +55,6 @@ posthook() {
fi fi
notmuch new 2>/dev/null notmuch new 2>/dev/null
afew --tag --new
afew --move-mail --new
afew --tag --new
notmuch_foldertags
countnew countnew
} }
@ -55,7 +72,7 @@ fail() {
} }
checkmail() { checkmail() {
mbsync -c "${XDG_CONFIG_HOME:-$HOME/.config}/isync/mbsyncrc" -a mbsync -c "${XDG_CONFIG_HOME:-$HOME/.config}/isync/mbsyncrc" "${1:--a}"
} }
checkonline() { checkonline() {
@ -84,7 +101,7 @@ enablegpgagent() {
} }
# send out a notification on new mail, to libnotify and stdout # send out a notification on new mail, to libnotify and stdout
notifymail() { notify_on_new_mail() {
[ "${MBSYNC_NOTIFY:-1}" -eq 0 ] && return [ "${MBSYNC_NOTIFY:-1}" -eq 0 ] && return
if [ "${HASMAIL:-0}" -gt 0 ]; then if [ "${HASMAIL:-0}" -gt 0 ]; then
@ -105,18 +122,19 @@ notify() {
if [ "$1" = "raw" ]; then if [ "$1" = "raw" ]; then
checkmail checkmail
exit exit
# any other argument passed through selects mbsync targets
elif [ -n "$1" ]; then
selected_mailbox="$1"
fi fi
main() { main() {
checkwarnuser checkwarnuser
enablegpgagent enablegpgagent
prehook prehook
tries=0 tries=0
while true; do while true; do
if checkmail; then if checkmail "$selected_mailbox"; then
break break
fi fi
@ -128,15 +146,7 @@ main() {
unset tries unset tries
posthook posthook
notify_on_new_mail
notifymail
}
notmuch_foldertags() {
notmuch tag +dump -inbox -deleted -- folder:Dump and not folder:Inbox
notmuch tag +archived -inbox -deleted -- folder:Archive and not folder:Inbox
notmuch tag +deleted -inbox -archived -- folder:Trash and not folder:Inbox
notmuch tag -inbox -- not folder:Inbox
} }
main main