parent
3e756eed3c
commit
89ff511993
@ -0,0 +1,16 @@ |
||||
[migadu] |
||||
# |
||||
# Switching back to notmuch (from maildir experiment) |
||||
# |
||||
source = notmuch:///home/adam/Maildir |
||||
maildir-store = /home/adam/Maildir |
||||
outgoing = /home/adam/.local/bin/aerc-notmuch-send migadu |
||||
default = INBOX |
||||
from = Adam Cooper <adam@theadamcooper.com> |
||||
|
||||
# notmuch does not support the copy-to directive |
||||
# copy-to = Sent |
||||
check-mail = 4m |
||||
check-mail-cmd = /home/adam/.local/bin/mail-sync.sh |
||||
check-mail-timeout = 20s |
||||
|
@ -0,0 +1,191 @@ |
||||
# |
||||
# aerc main configuration |
||||
|
||||
[ui] |
||||
# |
||||
# Describes the format for each row in a mailbox view. This field is compatible |
||||
# with mutt's printf-like syntax. |
||||
# |
||||
# Default: %D %-17.17n %Z %s |
||||
index-format=%D %-17.17n %Z %s |
||||
|
||||
# |
||||
# See time.Time#Format at https://godoc.org/time#Time.Format |
||||
# |
||||
# Default: 2006-01-02 03:04 PM (ISO 8601 + 12 hour time) |
||||
timestamp-format=2006-01-02 15:04 |
||||
|
||||
# |
||||
# Width of the sidebar, including the border. |
||||
# |
||||
# Default: 20 |
||||
sidebar-width=20 |
||||
|
||||
# |
||||
# Message to display when viewing an empty folder. |
||||
# |
||||
# Default: (no messages) |
||||
empty-message=(no messages) |
||||
|
||||
# Message to display when no folders exists or are all filtered |
||||
# |
||||
# Default: (no folders) |
||||
empty-dirlist=(no folders) |
||||
|
||||
# Enable mouse events in the ui, e.g. clicking and scrolling with the mousewheel |
||||
# |
||||
# Default: false |
||||
mouse-enabled=false |
||||
|
||||
# |
||||
# Ring the bell when new messages are received |
||||
# |
||||
# Default: true |
||||
new-message-bell=true |
||||
|
||||
# Marker to show before a pinned tab's name. |
||||
# |
||||
# Default: ` |
||||
pinned-tab-marker='`' |
||||
|
||||
# Describes the format string to use for the directory list |
||||
# |
||||
# Default: %n %>r |
||||
dirlist-format=%n %>r |
||||
|
||||
# List of space-separated criteria to sort the messages by, see *sort* |
||||
# command in *aerc*(1) for reference. Prefixing a criterion with "-r " |
||||
# reverses that criterion. |
||||
# |
||||
# Example: "from -r date" |
||||
# |
||||
# Default: "" |
||||
sort=-r date |
||||
|
||||
# Moves to next message when the current message is deleted |
||||
# |
||||
# Default: true |
||||
next-message-on-delete=true |
||||
|
||||
fuzzy-complete=true |
||||
|
||||
[viewer] |
||||
# |
||||
# Specifies the pager to use when displaying emails. Note that some filters |
||||
# may add ANSI codes to add color to rendered emails, so you may want to use a |
||||
# pager which supports ANSI codes. |
||||
# |
||||
# Default: less -R |
||||
pager=less -R |
||||
|
||||
# |
||||
# If an email offers several versions (multipart), you can configure which |
||||
# mimetype to prefer. For example, this can be used to prefer plaintext over |
||||
# html emails. |
||||
# |
||||
# Default: text/plain,text/html |
||||
alternatives=text/html,text/plain |
||||
|
||||
# |
||||
# Default setting to determine whether to show full headers or only parsed |
||||
# ones in message viewer. |
||||
# |
||||
# Default: false |
||||
show-headers=false |
||||
|
||||
# |
||||
# Layout of headers when viewing a message. To display multiple headers in the |
||||
# same row, separate them with a pipe, e.g. "From|To". Rows will be hidden if |
||||
# none of their specified headers are present in the message. |
||||
# |
||||
# Default: From|To,Cc|Bcc,Date,Subject |
||||
header-layout=From|To,Cc|Bcc,Date,Subject|Labels |
||||
|
||||
# Whether to always show the mimetype of an email, even when it is just a single part |
||||
# |
||||
# Default: false |
||||
always-show-mime=false |
||||
|
||||
# How long to wait after the last input before auto-completion is triggered. |
||||
# |
||||
# Default: 250ms |
||||
completion-delay=250ms |
||||
|
||||
# |
||||
# Global switch for completion popovers |
||||
# |
||||
# Default: true |
||||
completion-popovers=true |
||||
|
||||
[compose] |
||||
# |
||||
# Specifies the command to run the editor with. It will be shown in an embedded |
||||
# terminal, though it may also launch a graphical window if the environment |
||||
# supports it. Defaults to $EDITOR, or vi. |
||||
editor= |
||||
|
||||
# |
||||
# Default header fields to display when composing a message. To display |
||||
# multiple headers in the same row, separate them with a pipe, e.g. "To|From". |
||||
# |
||||
# Default: To|From,Subject |
||||
header-layout=To|From,Subject |
||||
|
||||
# |
||||
# Specifies the command to be used to tab-complete email addresses. Any |
||||
# occurrence of "%s" in the address-book-cmd will be replaced with what the |
||||
# user has typed so far. |
||||
# |
||||
# The command must output the completions to standard output, one completion |
||||
# per line. Each line must be tab-delimited, with an email address occurring as |
||||
# the first field. Only the email address field is required. The second field, |
||||
# if present, will be treated as the contact name. Additional fields are |
||||
# ignored. |
||||
address-book-cmd=khard email --parsable --remove-first-line %s |
||||
|
||||
[filters] |
||||
# |
||||
# Filters allow you to pipe an email body through a shell command to render |
||||
# certain emails differently, e.g. highlighting them with ANSI escape codes. |
||||
# |
||||
# The first filter which matches the email's mimetype will be used, so order |
||||
# them from most to least specific. |
||||
# |
||||
# You can also match on non-mimetypes, by prefixing with the header to match |
||||
# against (non-case-sensitive) and a comma, e.g. subject,text will match a |
||||
# subject which contains "text". Use header,~regex to match against a regex. |
||||
subject,~^\[PATCH=awk -f /usr/local/share/aerc/filters/hldiff |
||||
text/html=/usr/local/share/aerc/filters/html |
||||
text/*=awk -f /usr/local/share/aerc/filters/plaintext |
||||
image/*=catimg -w $(tput cols) - |
||||
|
||||
[triggers] |
||||
# |
||||
# Triggers specify commands to execute when certain events occur. |
||||
# |
||||
# Example: |
||||
# new-email=exec notify-send "New email from %n" "%s" |
||||
|
||||
# |
||||
# Executed when a new email arrives in the selected folder |
||||
new-email=exec notify-send "New email from %n" "%s" |
||||
|
||||
[templates] |
||||
# Templates are used to populate email bodies automatically. |
||||
# |
||||
|
||||
# The directories where the templates are stored. It takes a colon-separated |
||||
# list of directories. |
||||
# |
||||
# default: /usr/local/share/aerc/templates/ |
||||
template-dirs=/usr/local/share/aerc/templates/ |
||||
|
||||
# The template to be used for quoted replies. |
||||
# |
||||
# default: quoted_reply |
||||
quoted-reply=quoted_reply |
||||
|
||||
# The template to be used for forward as body. |
||||
# |
||||
# default: forward_as_body |
||||
forwards=forward_as_body |
@ -0,0 +1,106 @@ |
||||
# Binds are of the form <key sequence> = <command to run> |
||||
# To use '=' in a key sequence, substitute it with "Eq": "<Ctrl+Eq>" |
||||
# If you wish to bind #, you can wrap the key sequence in quotes: "#" = quit |
||||
<C-p> = :prev-tab<Enter> |
||||
<C-n> = :next-tab<Enter> |
||||
<C-t> = :term<Enter> |
||||
|
||||
[messages] |
||||
q = :quit<Enter> |
||||
|
||||
j = :next<Enter> |
||||
<Down> = :next<Enter> |
||||
<C-d> = :next 50%<Enter> |
||||
<C-f> = :next 100%<Enter> |
||||
<PgDn> = :next -s 100%<Enter> |
||||
|
||||
k = :prev<Enter> |
||||
<Up> = :prev<Enter> |
||||
<C-u> = :prev 50%<Enter> |
||||
<C-b> = :prev 100%<Enter> |
||||
<PgUp> = :prev -s 100%<Enter> |
||||
g = :select 0<Enter> |
||||
G = :select -1<Enter> |
||||
|
||||
J = :next-folder<Enter> |
||||
K = :prev-folder<Enter> |
||||
|
||||
v = :mark -t<Enter> |
||||
V = :mark -v<Enter> |
||||
|
||||
<Enter> = :view<Enter> |
||||
# Replace deletion key bindings to move items to the trash |
||||
# d = :prompt 'Really delete this message?' 'delete-message'<Enter> |
||||
# D = :delete<Enter> |
||||
d = :mv Trash<Enter> |
||||
D = :mv Trash<Enter> |
||||
A = :archive flat<Enter> |
||||
|
||||
C = :compose<Enter> |
||||
|
||||
rr = :reply -a<Enter> |
||||
rq = :reply -aq<Enter> |
||||
Rr = :reply<Enter> |
||||
Rq = :reply -q<Enter> |
||||
|
||||
c = :cf<space> |
||||
$ = :term<space> |
||||
! = :term<space> |
||||
| = :pipe<space> |
||||
|
||||
/ = :search<space> |
||||
\ = :filter<space> |
||||
n = :next-result<Enter> |
||||
N = :prev-result<Enter> |
||||
|
||||
[view] |
||||
q = :close<Enter> |
||||
| = :pipe<space> |
||||
D = :delete<Enter> |
||||
S = :save<space> |
||||
A = :archive flat<Enter> |
||||
|
||||
f = :forward<Enter> |
||||
rr = :reply -a<Enter> |
||||
rq = :reply -aq<Enter> |
||||
Rr = :reply<Enter> |
||||
Rq = :reply -q<Enter> |
||||
|
||||
H = :toggle-headers<Enter> |
||||
<C-k> = :prev-part<Enter> |
||||
<C-j> = :next-part<Enter> |
||||
J = :next<Enter> |
||||
K = :prev<Enter> |
||||
|
||||
[compose] |
||||
# Keybindings used when the embedded terminal is not selected in the compose |
||||
# view |
||||
$ex = <C-x> |
||||
<C-k> = :prev-field<Enter> |
||||
<C-j> = :next-field<Enter> |
||||
<tab> = :next-field<Enter> |
||||
|
||||
[compose::editor] |
||||
# Keybindings used when the embedded terminal is selected in the compose view |
||||
$noinherit = true |
||||
$ex = <C-x> |
||||
<C-k> = :prev-field<Enter> |
||||
<C-j> = :next-field<Enter> |
||||
<C-p> = :prev-tab<Enter> |
||||
<C-n> = :next-tab<Enter> |
||||
|
||||
[compose::review] |
||||
# Keybindings used when reviewing a message to be sent |
||||
y = :send<Enter> |
||||
n = :abort<Enter> |
||||
p = :postpone<Enter> |
||||
q = :abort<Enter> |
||||
e = :edit<Enter> |
||||
a = :attach<space> |
||||
|
||||
[terminal] |
||||
$noinherit = true |
||||
$ex = <C-x> |
||||
|
||||
<C-p> = :prev-tab<Enter> |
||||
<C-n> = :next-tab<Enter> |
@ -0,0 +1,37 @@ |
||||
#!/bin/sh |
||||
|
||||
OFFLINEIMAP=$(pgrep offlineimap) |
||||
NOTMUCH=$(pgrep notmuch) |
||||
|
||||
if [ -n "$OFFLINEIMAP" ] || [ -n "$NOTMUCH" ]; then |
||||
echo "Already running one instance of offlineimap or notmuch. Exiting..." |
||||
exit 0 |
||||
fi |
||||
|
||||
echo "Deleting messages tagged as *deleted*" |
||||
notmuch search --format=text0 --output=files tag:deleted | xargs -0 --no-run-if-empty rm -v |
||||
|
||||
offlineimap -o |
||||
notmuch new |
||||
|
||||
# retag all "new" messages "inbox" and "unread" |
||||
notmuch tag +inbox +unread -new -- tag:new |
||||
|
||||
# mailing lists |
||||
notmuch tag +mailinglist -- to:xmonad@haskell.org |
||||
notmuch tag +mailinglist -- to:guile-user@gnu.org |
||||
notmuch tag +mailinglist -- to:zsh-users@zsh.org |
||||
notmuch tag +mailinglist -- to:qutebrowser@lists.qutebrowser.org |
||||
notmuch tag +mailinglist -- to:~rjarry/aerc-discuss@lists.sr.ht |
||||
|
||||
# TODO: Confirm that we need to do this |
||||
# move tagged items across folders and retag |
||||
notmuch search --output=files tag:trash and not folder:Trash | xargs mv -t /home/adam/Maildir/Trash/cur/ |
||||
notmuch tag +trash -inbox -sent -archive -junk -drafts -- folder:Trash and not tag:trash |
||||
|
||||
# move unimportant institutional messages to the trash after a couple of days |
||||
notmuch tag +trash -inbox -- date:..2d and tag:mailinglist |
||||
notmuch tag +trash -inbox -- date:..2d and from:@facebookmail.com |
||||
notmuch tag +trash -inbox -- date:..2d and from:noreply@twitch.tv |
||||
notmuch tag +trash -inbox -- date:..2d and from:messages-noreply@linkedin.com |
||||
|
@ -0,0 +1,87 @@ |
||||
# .notmuch-config - Configuration file for the notmuch mail system |
||||
# |
||||
# For more information about notmuch, see https://notmuchmail.org |
||||
|
||||
# Database configuration |
||||
# |
||||
# The only value supported here is 'path' which should be the top-level |
||||
# directory where your mail currently exists and to where mail will be |
||||
# delivered in the future. Files should be individual email messages. |
||||
# Notmuch will store its database within a sub-directory of the path |
||||
# configured here named ".notmuch". |
||||
# |
||||
[database] |
||||
path=/home/adam/Maildir |
||||
|
||||
# User configuration |
||||
# |
||||
# Here is where you can let notmuch know how you would like to be |
||||
# addressed. Valid settings are |
||||
# |
||||
# name Your full name. |
||||
# primary_email Your primary email address. |
||||
# other_email A list (separated by ';') of other email addresses |
||||
# at which you receive email. |
||||
# |
||||
# Notmuch will use the various email addresses configured here when |
||||
# formatting replies. It will avoid including your own addresses in the |
||||
# recipient list of replies, and will set the From address based on the |
||||
# address to which the original email was addressed. |
||||
# |
||||
[user] |
||||
name=Adam Cooper |
||||
primary_email=adam@theadamcooper.com |
||||
|
||||
# Configuration for "notmuch new" |
||||
# |
||||
# The following options are supported here: |
||||
# |
||||
# tags A list (separated by ';') of the tags that will be |
||||
# added to all messages incorporated by "notmuch new". |
||||
# |
||||
# ignore A list (separated by ';') of file and directory names |
||||
# that will not be searched for messages by "notmuch new". |
||||
# |
||||
# NOTE: *Every* file/directory that goes by one of those |
||||
# names will be ignored, independent of its depth/location |
||||
# in the mail store. |
||||
# |
||||
[new] |
||||
|
||||
# Search configuration |
||||
# |
||||
# The following option is supported here: |
||||
# |
||||
# exclude_tags |
||||
# A ;-separated list of tags that will be excluded from |
||||
# search results by default. Using an excluded tag in a |
||||
# query will override that exclusion. |
||||
# |
||||
[search] |
||||
|
||||
# Maildir compatibility configuration |
||||
# |
||||
# The following option is supported here: |
||||
# |
||||
# synchronize_flags Valid values are true and false. |
||||
# |
||||
# If true, then the following maildir flags (in message filenames) |
||||
# will be synchronized with the corresponding notmuch tags: |
||||
# |
||||
# Flag Tag |
||||
# ---- ------- |
||||
# D draft |
||||
# F flagged |
||||
# P passed |
||||
# R replied |
||||
# S unread (added when 'S' flag is not present) |
||||
# |
||||
# The "notmuch new" command will notice flag changes in filenames |
||||
# and update tags, while the "notmuch tag" and "notmuch restore" |
||||
# commands will notice tag changes and update flags in filenames |
||||
# |
||||
[maildir] |
||||
synchronize_flags=true |
||||
|
||||
[index] |
||||
header.Context-Transfer-Encoding=Context-Transfer-Encoding |
@ -0,0 +1,25 @@ |
||||
[general] |
||||
accounts = main |
||||
pythonfile = /home/adam/.config/offlineimap/offlineimap.py |
||||
maxsyncaccounts = 1 |
||||
|
||||
[Account main] |
||||
localrepository = main-local |
||||
remoterepository = main-remote |
||||
# autorefresh = 0.5 |
||||
# quick = 10 |
||||
|
||||
[Repository main-local] |
||||
type = Maildir |
||||
localfolders = ~/Maildir |
||||
|
||||
[Repository main-remote] |
||||
type = IMAP |
||||
remotehost = imap.migadu.com |
||||
remoteuser = adam@theadamcooper.com |
||||
remotepasseval = get_pw_from_attrs("service", "migadu") |
||||
starttls = yes |
||||
ssl = yes |
||||
sslcacertfile = /etc/ssl/certs/ca-certificates.crt |
||||
# keepalive = 60 |
||||
# holdconnectionopen = yes |
@ -0,0 +1,151 @@ |
||||
''' |
||||
offlineimap.py |
||||
This provides a handful of functions for retrieving secrets from GNOME Keyring |
||||
using the libsecret API. See the documentation for each function |
||||
''' |
||||
|
||||
from gi import require_version |
||||
require_version('Secret', '1') |
||||
from gi.repository import Secret |
||||
|
||||
def get_pw_from_desc(pw_desc) : |
||||
''' |
||||
This function returns the password for an item in the default keyring |
||||
which contains the description provided. |
||||
Use this function if you created a password using the dialogue in Seahorse |
||||
''' |
||||
# Get service |
||||
service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS) |
||||
|
||||
# Get default keyring |
||||
keyring = Secret.Collection.for_alias_sync(service, "default", \ |
||||
Secret.CollectionFlags.NONE, None) |
||||
|
||||
# Get keyring items |
||||
items = keyring.get_items() |
||||
|
||||
# Load secrets |
||||
Secret.Item.load_secrets_sync(items) |
||||
|
||||
# Loop through items, find the matching one and return its password |
||||
password = None |
||||
for item in items : |
||||
if item.get_label() == pw_desc : |
||||
password = item.get_secret().get_text() |
||||
break |
||||
|
||||
# Close connection |
||||
service.disconnect() |
||||
|
||||
return password |
||||
|
||||
def get_pw_from_attrs(*attr_val_pairs) : |
||||
''' |
||||
This function returns the password for an item in the default keyring |
||||
which contains all of the attribute value pairs provided as arguments. |
||||
Use this function if you created a password using the secret-tool command |
||||
or another such program that interfaces with libsecret |
||||
''' |
||||
# Check the list of attr-val pairs is present and contains an even number |
||||
# of elements |
||||
if attr_val_pairs == () : |
||||
raise TypeError("get_pw_from_attrs() at least 1 attribute-value pair " \ |
||||
"must be supplied") |
||||
if len(attr_val_pairs) % 2 != 0 : |
||||
raise TypeError("get_pw_from_attrs() incomplete attribute-value " \ |
||||
"pair was supplied") |
||||
|
||||
# Get service |
||||
service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS) |
||||
|
||||
# Get default keyring |
||||
keyring = Secret.Collection.for_alias_sync(service, "default", \ |
||||
Secret.CollectionFlags.NONE, None) |
||||
|
||||
# Get keyring items |
||||
items = keyring.get_items() |
||||
|
||||
# Load secrets |
||||
Secret.Item.load_secrets_sync(items) |
||||
|
||||
# Loop through items, find the one which contains all supplied attr_val |
||||
# pairs and return its password |
||||
password = None |
||||
for item in items : |
||||
attrs = item.get_attributes() |
||||
match = True |
||||
for x in range(0, len(attr_val_pairs), 2) : |
||||
key = attr_val_pairs[x] |
||||
value = attr_val_pairs[x + 1] |
||||
try : |
||||
if attrs[key] != value : |
||||
match = False |
||||
break |
||||
except KeyError : |
||||
match = False |
||||
break |
||||
if match : |
||||
password = item.get_secret().get_text() |
||||
break |
||||
|
||||
# Close connection |
||||
service.disconnect() |
||||
|
||||
return password |
||||
|
||||
def get_val_from_attrs(attr, *attr_val_pairs) : |
||||
''' |
||||
This function returns the value for a given attribute. The first item |
||||
found that contains that attribute will be the one that is used. To ensure |
||||
that the correct item is chosen, any number of attribute-value pairs can |
||||
be optionally supplied as arguments and only the item which contains all |
||||
of those attr-val pairs (along with the main attr) will be used. |
||||
Use this function if you created a password using the secret-tool command |
||||
or another such program that interfaces with libsecret |
||||
''' |
||||
# Check the list of attr-val pairs contains an even number of elements |
||||
# if it exists |
||||
if attr_val_pairs != () : |
||||
if len(attr_val_pairs) % 2 != 0 : |
||||
raise TypeError("get_val_from_attrs() incomplete attribute-value " \ |
||||
"pair was supplied") |
||||
|
||||
# Get service |
||||
service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS) |
||||
|
||||
# Get default keyring |
||||
keyring = Secret.Collection.for_alias_sync(service, "default", \ |
||||
Secret.CollectionFlags.NONE, None) |
||||
|
||||
# Get keyring items |
||||
items = keyring.get_items() |
||||
|
||||
# Loop through items, find the one which contains the supplied attribute |
||||
# (plus any attr_val pairs if specified) and return that attribute's |
||||
# value |
||||
attr_value = None |
||||
for item in items : |
||||
attrs = item.get_attributes() |
||||
try : |
||||
attrs[attr] |
||||
except KeyError : |
||||
continue |
||||
match = True |
||||
for x in range(0, len(attr_val_pairs), 2) : |
||||
key = attr_val_pairs[x] |
||||
value = attr_val_pairs[x + 1] |
||||
try : |
||||
if attrs[key] != value : |
||||
match = False |
||||
break |
||||
except KeyError : |
||||
match = False |
||||
break |
||||
if match : |
||||
attr_value = attrs[attr] |
||||
break |
||||
|
||||
# Close connection |
||||
service.disconnect() |
||||
|
||||
return attr_value |
Loading…
Reference in new issue