office: Rename mail module to office module
Reflecting the somewhat expanding scope of the module, renamed it to office. Still keeps the old files and setups but also got a new README file.
This commit is contained in:
parent
593628b81d
commit
03684ce29f
27 changed files with 28 additions and 15 deletions
204
office/.config/glow/email.json
Normal file
204
office/.config/glow/email.json
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
{
|
||||
"document": {
|
||||
"block_prefix": "\n",
|
||||
"block_suffix": "\n",
|
||||
"color": "7",
|
||||
"margin": 2
|
||||
},
|
||||
"block_quote": {
|
||||
"indent": 0,
|
||||
"color": "3",
|
||||
"indent_token": "│ ",
|
||||
"italic": true,
|
||||
"margin": 1
|
||||
},
|
||||
"paragraph": {},
|
||||
"list": {
|
||||
"level_indent": 2,
|
||||
"color": "7"
|
||||
},
|
||||
"heading": {
|
||||
"block_suffix": "\n",
|
||||
"color": "4",
|
||||
"bold": true
|
||||
},
|
||||
"h1": {
|
||||
"prefix": " ",
|
||||
"suffix": " ",
|
||||
"color": "7",
|
||||
"background_color": "4",
|
||||
"bold": true
|
||||
},
|
||||
"h2": {
|
||||
"prefix": "## "
|
||||
},
|
||||
"h3": {
|
||||
"prefix": "### "
|
||||
},
|
||||
"h4": {
|
||||
"prefix": "#### "
|
||||
},
|
||||
"h5": {
|
||||
"prefix": "##### "
|
||||
},
|
||||
"h6": {
|
||||
"prefix": "###### ",
|
||||
"color": "5",
|
||||
"bold": false
|
||||
},
|
||||
"text": {},
|
||||
"strikethrough": {
|
||||
"crossed_out": true
|
||||
},
|
||||
"emph": {
|
||||
"italic": true,
|
||||
"color": "3"
|
||||
},
|
||||
"strong": {
|
||||
"bold": true,
|
||||
"color": "3"
|
||||
},
|
||||
"hr": {
|
||||
"color": "0",
|
||||
"format": "\n―――――――――――――――――――\n"
|
||||
},
|
||||
"item": {
|
||||
"block_prefix": "• "
|
||||
},
|
||||
"enumeration": {
|
||||
"block_prefix": ". ",
|
||||
"color": "6"
|
||||
},
|
||||
"task": {
|
||||
"ticked": "[✓] ",
|
||||
"unticked": "[ ] "
|
||||
},
|
||||
"link": {
|
||||
"color": "6",
|
||||
"underline": true
|
||||
},
|
||||
"link_text": {
|
||||
"color": "5",
|
||||
"bold": true
|
||||
},
|
||||
"image": {
|
||||
"color": "6",
|
||||
"underline": true
|
||||
},
|
||||
"image_text": {
|
||||
"color": "5",
|
||||
"format": "Image: {{.text}} →"
|
||||
},
|
||||
"code": {
|
||||
"color": "7",
|
||||
"prefix": " ",
|
||||
"suffix": " ",
|
||||
"background_color": "#44475a"
|
||||
},
|
||||
"code_block": {
|
||||
"color": "3",
|
||||
"margin": 2,
|
||||
"chroma": {
|
||||
"text": {
|
||||
"color": "#ansilightgray"
|
||||
},
|
||||
"error": {
|
||||
"color": "#ansilightgray",
|
||||
"background_color": "#ansidarkred"
|
||||
},
|
||||
"comment": {
|
||||
"color": "#ansidarkgray"
|
||||
},
|
||||
"comment_preproc": {
|
||||
"color": "#ansipurple"
|
||||
},
|
||||
"keyword": {
|
||||
"color": "#ansipurple"
|
||||
},
|
||||
"keyword_reserved": {
|
||||
"color": "#ansipurple"
|
||||
},
|
||||
"keyword_namespace": {
|
||||
"color": "#ansipurple"
|
||||
},
|
||||
"keyword_type": {
|
||||
"color": "#ansiteal"
|
||||
},
|
||||
"operator": {
|
||||
"color": "#ansipurple"
|
||||
},
|
||||
"punctuation": {
|
||||
"color": "#ansilightgray"
|
||||
},
|
||||
"name": {
|
||||
"color": "#ansiteal"
|
||||
},
|
||||
"name_builtin": {
|
||||
"color": "#ansiteal"
|
||||
},
|
||||
"name_tag": {
|
||||
"color": "#ansipurple"
|
||||
},
|
||||
"name_attribute": {
|
||||
"color": "#ansidarkgreen"
|
||||
},
|
||||
"name_class": {
|
||||
"color": "#ansiteal"
|
||||
},
|
||||
"name_constant": {
|
||||
"color": "#ansidarkblue"
|
||||
},
|
||||
"name_decorator": {
|
||||
"color": "#ansidarkgreen"
|
||||
},
|
||||
"name_exception": {},
|
||||
"name_function": {
|
||||
"color": "#ansidarkgreen"
|
||||
},
|
||||
"name_other": {},
|
||||
"literal": {},
|
||||
"literal_number": {
|
||||
"color": "#ansiturquoise"
|
||||
},
|
||||
"literal_date": {},
|
||||
"literal_string": {
|
||||
"color": "#ansibrown"
|
||||
},
|
||||
"literal_string_escape": {
|
||||
"color": "#ansipurple"
|
||||
},
|
||||
"generic_deleted": {
|
||||
"color": "#ansidarkred"
|
||||
},
|
||||
"generic_emph": {
|
||||
"color": "#ansibrown",
|
||||
"italic": true
|
||||
},
|
||||
"generic_inserted": {
|
||||
"color": "#ansidarkgreen"
|
||||
},
|
||||
"generic_strong": {
|
||||
"color": "#ansiyellow",
|
||||
"bold": true
|
||||
},
|
||||
"generic_subheading": {
|
||||
"color": "#ansidarkblue"
|
||||
},
|
||||
"background": {
|
||||
"background_color": "#44475"
|
||||
}
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"center_separator": "┼",
|
||||
"column_separator": "│",
|
||||
"row_separator": "─"
|
||||
},
|
||||
"definition_list": {},
|
||||
"definition_term": {},
|
||||
"definition_description": {
|
||||
"block_prefix": "\n🠶 "
|
||||
},
|
||||
"html_block": {},
|
||||
"html_span": {}
|
||||
}
|
||||
15
office/.config/imapfilter/accounts.lua
Normal file
15
office/.config/imapfilter/accounts.lua
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
local accounts = {}
|
||||
|
||||
local status, gmailuser = pipe_from(
|
||||
'gpg2 --decrypt --no-tty --quiet --no-verbose --for-your-eyes-only --pinentry-mode ask ~/.local/share/pass/misc/aerc-gmail-app-password.gpg | grep username | cut -d: -f2')
|
||||
local status, gmailpass = pipe_from(
|
||||
'gpg2 --decrypt --no-tty --quiet --no-verbose --for-your-eyes-only --pinentry-mode ask ~/.local/share/pass/misc/aerc-gmail-app-password.gpg | head -n1')
|
||||
-- Setup an imap account called gmail
|
||||
accounts.gmail = IMAP {
|
||||
server = "imap.gmail.com",
|
||||
username = gmailuser,
|
||||
password = gmailpass,
|
||||
ssl = "auto"
|
||||
}
|
||||
|
||||
return accounts
|
||||
86
office/.config/imapfilter/config.lua
Normal file
86
office/.config/imapfilter/config.lua
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
-- According to the IMAP specification, when trying to write a message
|
||||
-- to a non-existent mailbox, the server must send a hint to the client,
|
||||
-- whether it should create the mailbox and try again or not. However
|
||||
-- some IMAP servers don't follow the specification and don't send the
|
||||
-- correct response code to the client. By enabling this option the
|
||||
-- client tries to create the mailbox, despite of the server's response.
|
||||
-- This variable takes a boolean as a value. Default is “false”.
|
||||
options.create = true
|
||||
-- By enabling this option new mailboxes that were automatically created,
|
||||
-- get auto subscribed
|
||||
options.subscribe = true
|
||||
-- How long to wait for servers response.
|
||||
options.timeout = 120
|
||||
|
||||
-- whether to enter IDLE mode and conintuously check
|
||||
-- for new incoming mail to filter
|
||||
CONTINUOUS = false
|
||||
-- time to wait for next synchronization
|
||||
-- only used in case server does not support IDLE mode
|
||||
UPDATE_TIME = 120
|
||||
|
||||
-- implement simple wait function in case server does not support IDLE mode
|
||||
function sleep(n) os.execute("sleep " .. tonumber(n)) end
|
||||
|
||||
-- will set filters to be grabbed from XDG-compliant filter directory
|
||||
-- can be overridden with env var IMAPFILTER_FILTERDIR
|
||||
function getConfigDir()
|
||||
-- -- set directory for imapfilter files
|
||||
local configdir
|
||||
if os.getenv("IMAPFILTER_CONFIGDIR") then
|
||||
configdir = os.getenv("IMAPFILTER_CONFIGDIR")
|
||||
elseif os.getenv("XDG_CONFIG_HOME") then
|
||||
configdir = os.getenv("XDG_CONFIG_HOME") .. "/imapfilter"
|
||||
else
|
||||
configdir = os.getenv("HOME") .. "/.config/imapfilter"
|
||||
end
|
||||
return configdir
|
||||
end
|
||||
|
||||
-- will set filters to be grabbed from XDG-compliant filter directory
|
||||
-- can be overridden with env var IMAPFILTER_FILTERDIR
|
||||
function getFilterDir()
|
||||
-- -- set directory for imapfilter files
|
||||
local imapfilterdir
|
||||
if os.getenv("IMAPFILTER_FILTERDIR") then
|
||||
imapfilterdir = os.getenv("IMAPFILTER_FILTERDIR")
|
||||
else
|
||||
imapfilterdir = configDir .. "/filters"
|
||||
end
|
||||
return imapfilterdir
|
||||
end
|
||||
|
||||
-- dirlist, from https://stackoverflow.com/a/25266573
|
||||
function applyFilters(dir)
|
||||
local p = io.popen('find "' .. dir .. '" -type f -name "*.lua"') -- Open directory look for files, save data in p. By giving '-type f' as parameter, it returns all files.
|
||||
for file in p:lines() do -- Loop through all files
|
||||
loadfile(file)()
|
||||
end
|
||||
end
|
||||
|
||||
-- create global variable containing the configuration files
|
||||
configDir = getConfigDir()
|
||||
assert(configDir,
|
||||
"No configuration directory found. Ensure " .. os.getenv("HOME") ..
|
||||
"/.config/imapfilter exists.")
|
||||
|
||||
-- create global variable containing account access
|
||||
accounts = loadfile(configDir .. "/accounts.lua")()
|
||||
assert(accounts,
|
||||
"No accounts configured. Ensure accounts.lua exists and returns a table of accounts.")
|
||||
|
||||
-- immediately act on the filters once
|
||||
applyFilters(getFilterDir())
|
||||
|
||||
-- continuously watch for mail if needed
|
||||
while CONTINUOUS == true do
|
||||
local has_idle = accounts.gmail['Inbox']:enter_idle()
|
||||
applyFilters(getFilterDir())
|
||||
|
||||
if has_idle == false then
|
||||
print(
|
||||
"Server does not support idle, application will be polling again in " ..
|
||||
UPDATE_TIME .. "minutes.")
|
||||
sleep(UPDATE_TIME)
|
||||
end
|
||||
end
|
||||
40
office/.config/imapfilter/filters/rollup-dump.lua
Normal file
40
office/.config/imapfilter/filters/rollup-dump.lua
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
function sendToFolder(folderFrom, folderTo, senders)
|
||||
local messages = folderFrom:select_all()
|
||||
for _, sender in pairs(senders) do
|
||||
local filtered = messages:contain_from(sender)
|
||||
filtered:mark_seen()
|
||||
filtered:move_messages(folderTo)
|
||||
end
|
||||
end
|
||||
|
||||
-- will set filters to be grabbed from XDG-compliant filter directory
|
||||
-- can be overridden with env var IMAPFILTER_ROLLUPFILE
|
||||
function getRollupFile(fname)
|
||||
local f
|
||||
local fname = fname or "rollup.txt"
|
||||
if os.getenv("IMAPFILTER_ROLLUPFILE") then
|
||||
f = os.getenv("IMAPFILTER_ROLLUPFILE")
|
||||
elseif os.getenv("XDG_DATA_HOME") then
|
||||
f = os.getenv("XDG_DATA_HOME") .. "/imapfilter/" .. fname
|
||||
else
|
||||
f = os.getenv("HOME") .. "/.local/share/imapfilter/" .. fname
|
||||
end
|
||||
return f
|
||||
end
|
||||
|
||||
function getSenderList(rollupfile)
|
||||
local rollupSenders = {}
|
||||
|
||||
local file = io.open(rollupfile)
|
||||
if file then
|
||||
for line in file:lines() do table.insert(rollupSenders, line) end
|
||||
else
|
||||
print(
|
||||
"ERROR: rollup did not find rollup.txt file containing mail addresses at " ..
|
||||
rollupfile or "")
|
||||
end
|
||||
return rollupSenders
|
||||
end
|
||||
|
||||
sendToFolder(accounts.gmail["Inbox"], accounts.gmail["Dump"],
|
||||
getSenderList(getRollupFile()))
|
||||
68
office/.config/isync/mbsyncrc
Normal file
68
office/.config/isync/mbsyncrc
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# documentation: https://wiki.archlinux.org/index.php/isync
|
||||
|
||||
IMAPAccount gmail
|
||||
# Address to connect to
|
||||
Host imap.gmail.com
|
||||
UserCmd "pass show misc/gmail-app-password | grep username | cut -d: -f2"
|
||||
PassCmd "pass show misc/gmail-app-password | head -n1"
|
||||
# To store the password in an encrypted file use PassCmd instead of Pass
|
||||
# PassCmd "gpg2 -q --for-your-eyes-only --no-tty -d ~/.mailpass.gpg"
|
||||
#
|
||||
# Use SSL
|
||||
TLSType IMAPS
|
||||
CertificateFile /etc/ssl/certs/ca-certificates.crt
|
||||
# Throttle simultaneous access to make google happy
|
||||
PipelineDepth 60
|
||||
|
||||
IMAPStore gmail-remote
|
||||
Account gmail
|
||||
|
||||
MaildirStore mail-local
|
||||
Subfolders Verbatim
|
||||
# The trailing "/" is important
|
||||
Path ~/documents/mail/
|
||||
Inbox ~/documents/mail/Inbox
|
||||
# define generous maximum size to store locally
|
||||
MaxSize 50M
|
||||
|
||||
Channel gmail-inbox
|
||||
Far :gmail-remote:INBOX
|
||||
Near :mail-local:inbox
|
||||
# Exclude everything under the internal [Gmail] folder, except the interesting folders
|
||||
# Automatically create missing mailboxes, both locally and on the server
|
||||
Create Near
|
||||
# Save the synchronization state files in the relevant directory
|
||||
SyncState *
|
||||
|
||||
Channel gmail-sent
|
||||
Far :gmail-remote:"[Google Mail]/Sent Mail"
|
||||
Near :mail-local:sent
|
||||
Create Near
|
||||
|
||||
Channel gmail-trash
|
||||
Far :gmail-remote:"[Google Mail]/Trash"
|
||||
Near :mail-local:trash
|
||||
Create Near
|
||||
|
||||
Channel gmail-important
|
||||
Far :gmail-remote:"[Google Mail]/Starred"
|
||||
Near :mail-local:important
|
||||
Create Near
|
||||
|
||||
Channel gmail-drafts
|
||||
Far :gmail-remote:"[Google Mail]/Drafts"
|
||||
Near :mail-local:drafts
|
||||
Create Near
|
||||
|
||||
Channel gmail-all
|
||||
Far :gmail-remote:"[Google Mail]/All Mail"
|
||||
Near :mail-local:archive
|
||||
Create Near
|
||||
|
||||
# Put all the channels into one group
|
||||
Group googlemail
|
||||
Channel gmail-inbox
|
||||
Channel gmail-important
|
||||
Channel gmail-sent
|
||||
Channel gmail-trash
|
||||
Channel gmail-all
|
||||
16
office/.config/khal/config
Normal file
16
office/.config/khal/config
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
[calendars]
|
||||
|
||||
[[calendar_local]]
|
||||
path = ~/documents/calendars/*
|
||||
type = discover
|
||||
color = auto
|
||||
|
||||
[locale]
|
||||
timeformat = %H:%M
|
||||
dateformat = %Y-%m-%d
|
||||
longdateformat = %Y-%m-%d
|
||||
datetimeformat = %Y-%m-%d %H:%M
|
||||
longdatetimeformat = %Y-%m-%d %H:%M
|
||||
|
||||
[default]
|
||||
default_calendar = Activities
|
||||
18
office/.config/msmtp/config
Normal file
18
office/.config/msmtp/config
Normal 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 "pass show misc/gmail-app-password | head -n1"
|
||||
|
||||
# Set a default account
|
||||
account default : personal-gmail
|
||||
16
office/.config/neomutt/account
Normal file
16
office/.config/neomutt/account
Normal 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"
|
||||
|
||||
233
office/.config/neomutt/colors
Normal file
233
office/.config/neomutt/colors
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
# # 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
|
||||
# Nerd icons idea based on https://github.com/sheoak/neomutt-powerline-nerdfonts/
|
||||
# Dracula colors based on Dracula Theme by Paul Townsend <paul@caprica.org>
|
||||
|
||||
|
||||
# Formatting ----------------------------------------------------------------------
|
||||
set date_format = "%a %d %h %H:%M"
|
||||
set index_format=" %zc %zs %zt | %-35.35L %@attachment_info@ %?M10?~(%1M) ?%-30.100s %> %?Y?%Y ? %(!%a %d %h %H:%M) "
|
||||
set pager_format="%n %T %s%* %{!%d %b · %H:%M} %?X? %X?%P"
|
||||
set status_format = " %D %?u? %u ?%?R? %R ?%?d? %d ?%?t? %t ?%?F? %F ?%?p? %p? \n \n"
|
||||
set compose_format="-- NeoMutt: Compose [Approx. msg size: %l Atts: %a]%>-"
|
||||
# set vfolder_format = "%N %?n?%3n& ? %8m · %f"
|
||||
set attach_format = "%u%D %T%-75.75d %?T?%& ? %5s · %m/%M"
|
||||
set sidebar_format = '%D%?Z? [%Z]?%* %?S?%S?'
|
||||
index-format-hook attachment_info '=B text/calendar ~X 1' ' '
|
||||
index-format-hook attachment_info '=B text/calendar' " "
|
||||
index-format-hook attachment_info '~X 1' " "
|
||||
index-format-hook attachment_info '~A' " "
|
||||
|
||||
|
||||
# General Colors ------------------------------------------------------------------
|
||||
color normal default default # general text
|
||||
color error color231 color212 # error messages
|
||||
color message default default # messages at the bottom
|
||||
color prompt default default # prompt text
|
||||
color search black color10 # search highlight
|
||||
|
||||
|
||||
# Statusbar Colors ----------------------------------------------------------------
|
||||
color status color141 default
|
||||
color status color7 color8 '([a-zA-Z0-9\.,]|\[|\])(\s)' # bubble content 1
|
||||
color status color7 color8 '(\s)([a-zA-Z0-9\.,]|\[|\])' # bubble content 2
|
||||
color status color7 color8 '(\% )' # % symbol
|
||||
color status color7 color8 '(\S)' # empty spaces
|
||||
color status color8 default '(|)' # statusline "bubbles"
|
||||
color status color69 black '(\` )' # bubble account variation
|
||||
color status white color69 '([a-zA-Z0-9\.]+)( )' # account text
|
||||
color status green color8 '' # Unread messages count
|
||||
color status blue color8 '' # Read messages count icon
|
||||
color status yellow color8 '' # Flagged icon
|
||||
color status red color8 '' # Pending delete icon
|
||||
|
||||
|
||||
# Index Colors --------------------------------------------------------------------
|
||||
color index color15 default '~N' # new messages
|
||||
color index color8 default '~R' # read messages
|
||||
color index color8 default '~Q' # messages which have been replied to
|
||||
color index_collapsed color4 default # collapsed thread (message count text)
|
||||
color index color5 default '!~Q^~p' # sent only to me and haven't been replied to
|
||||
color index color22 default '~h X-Label..' # messages with a complete label
|
||||
color index color6 default '~F' # flagged messages
|
||||
color index color6 default '~F~N' # flagged messages (new)
|
||||
color index color14 default '~F~R' # flagged messages (read)
|
||||
color index color1 default '~D' # deleted messages
|
||||
color index color1 default '~D~N' # deleted messages (new)
|
||||
color index color9 default '~D~R' # deleted messages (read)
|
||||
color index color3 default '~T' # tagged messages
|
||||
color index color3 default '~T~N' # tagged messages (new)
|
||||
color index color11 default '~T~R' # tagged messages (read)
|
||||
color tree color8 color8 # thread tree lines/arrow
|
||||
color indicator default color8 # selection indicator
|
||||
color index_date color8 default # date is always the same colour
|
||||
color index_label color6 default # label is always the same colour
|
||||
|
||||
|
||||
# Sidebar Colors ------------------------------------------------------------------
|
||||
color sidebar_indicator color14 black # currently selected mailbox
|
||||
color sidebar_highlight white color8 # highlighted, but not open, mailbox.
|
||||
color sidebar_ordinary color8 default # Color to give mailboxes by default
|
||||
color sidebar_divider color8 black # divider between sidebar & content
|
||||
color sidebar_flagged red black # mailboxes containing flagged mail
|
||||
color sidebar_new green black # mailboxes containing new mail
|
||||
color sidebar_unread color7 default # mailboxes containing unread mail
|
||||
color sidebar_unread color7 default # mailboxes containing unread mail
|
||||
|
||||
|
||||
# Message Headers -----------------------------------------------------------------
|
||||
color hdrdefault color8 default
|
||||
|
||||
|
||||
# Message Body --------------------------------------------------------------------
|
||||
|
||||
# Attachments
|
||||
color attachment color8 default
|
||||
|
||||
# Signature
|
||||
color signature color8 default
|
||||
|
||||
# emails
|
||||
# color body color14 default '[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+'
|
||||
|
||||
# hide "mailto"
|
||||
color body color0 color0 '<mailto:[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+>'
|
||||
|
||||
# URLs
|
||||
color body color3 default '(https?|ftp)://[-\.,/%~_:?&=\#a-zA-Z0-9\+]+'
|
||||
|
||||
# Dividers
|
||||
color body color8 default '(^[-_]*$)'
|
||||
|
||||
# Important info in calendar invites
|
||||
color body color6 default '^(Date\/Time|Location|Organiser|Invitees|Teams Meeting)(:| \~\~)'
|
||||
|
||||
# Quotes
|
||||
color quoted color61 default
|
||||
color quoted1 color117 default
|
||||
color quoted2 color84 default
|
||||
color quoted3 color215 default
|
||||
color quoted4 color212 default
|
||||
|
||||
# Forward/reply headers
|
||||
color body color8 default '(^(To|From|Sent|Subject):.*)'
|
||||
|
||||
# Patch syntax highlighting
|
||||
# color body brightwhite default '^[[:space:]].*'
|
||||
# color body yellow default ^(diff).*
|
||||
# color body white default ^[\-\-\-].*
|
||||
# color body white default ^[\+\+\+].*
|
||||
# color body green default ^[\+].*
|
||||
# color body red default ^[\-].*
|
||||
# color body brightblue default [@@].*
|
||||
# color body cyan default ^(Signed-off-by).*
|
||||
# color body brightwhite default ^(Cc)
|
||||
# color body yellow default "^diff \-.*"
|
||||
# color body brightwhite default "^index [a-f0-9].*"
|
||||
# color body brightblue default "^---$"
|
||||
# color body white default "^\-\-\- .*"
|
||||
# color body white default "^[\+]{3} .*"
|
||||
# color body green default "^[\+][^\+]+.*"
|
||||
# color body red default "^\-[^\-]+.*"
|
||||
# color body brightblue default "^@@ .*"
|
||||
# color body green default "LGTM"
|
||||
# color body brightmagenta default "-- Commit Summary --"
|
||||
# color body brightmagenta default "-- File Changes --"
|
||||
# color body brightmagenta default "-- Patch Links --"
|
||||
# color body green default "^Merged #.*"
|
||||
# color body red default "^Closed #.*"
|
||||
# color body brightblue default "^Reply to this email.*"
|
||||
|
||||
|
||||
# Misc -----------------------------------------------------------------------------
|
||||
|
||||
# no addressed to me, to me, group, cc, sent by me, mailing list
|
||||
set to_chars=" "
|
||||
|
||||
# unchanged mailbox, changed, read only, attach mode
|
||||
set status_chars = " "
|
||||
ifdef crypt_chars set crypt_chars = " "
|
||||
set flag_chars = " "
|
||||
|
||||
# hide some tags
|
||||
set hidden_tags = "unread,draft,flagged,passed,replied,attachment,signed,encrypted"
|
||||
tag-transforms "replied" "↻ " \
|
||||
"encrytpted" "" \
|
||||
"signed" "" \
|
||||
"attachment" "" \
|
||||
|
||||
# The formats must start with 'G' and the entire sequence is case sensitive.
|
||||
tag-formats "replied" "GR" \
|
||||
"encrypted" "GE" \
|
||||
"signed" "GS" \
|
||||
"attachment" "GA" \
|
||||
|
||||
# don't put '+' at the beginning of wrapped lines
|
||||
set markers=no
|
||||
28
office/.config/neomutt/mailcap
Normal file
28
office/.config/neomutt/mailcap
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# open html emails in browser (or whatever GUI program is used to render HTML)
|
||||
text/html; xdg-open %s ; nametemplate=%s.html
|
||||
# render html emails inline using magic (uncomment the line below to use lynx instead)
|
||||
# text/html; lynx -assume_charset=%{charset} -display_charset=utf-8 -collapse_br_tags -dump %s; nametemplate=%s.html; copiousoutput
|
||||
text/html; render-prettyhtml %s; nametemplate=%s.html; copiousoutput;
|
||||
text/plain; $EDITOR %s ;
|
||||
|
||||
# show calendar invites
|
||||
text/calendar; mutt-ics; copiousoutput
|
||||
application/ics; mutt-ics; copiousoutput
|
||||
|
||||
# open images externally
|
||||
image/*; nsxiv %s ;
|
||||
|
||||
# open videos in mpv
|
||||
video/*; mpv --autofit-larger=90\%x90\% %s; needsterminal;
|
||||
video/*; setsid mpv --quiet %s &; copiousoutput
|
||||
|
||||
# open spreadsheets in sc-im
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; sc-im %s; needsterminal
|
||||
|
||||
# open anything else externally
|
||||
application/pdf; xdg-open %s;
|
||||
|
||||
application/*; mkdir -p /tmp/mutt \; cp %s /tmp/mutt \; xdg-open /tmp/mutt/$(basename %s) &
|
||||
application/pgp-encrypted; gpg -d '%s'; copiousoutput;
|
||||
application/pgp-keys; gpg --import '%s'; copiousoutput;
|
||||
|
||||
61
office/.config/neomutt/maps
Normal file
61
office/.config/neomutt/maps
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# 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
|
||||
# markdown to html for composition
|
||||
macro compose M "F pandoc -s -f markdown -t html \ny^T^Utext/html; charset=UTF-8\n" "Convert from MD to HTML"
|
||||
|
||||
# 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; sync-mail<enter><sync-mailbox>" "refresh all e-mail"
|
||||
macro index o "<sync-mailbox><shell-escape>export MBSYNC_PRE=true; sync-mail 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"
|
||||
6
office/.config/neomutt/neomuttrc
Normal file
6
office/.config/neomutt/neomuttrc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
source colors
|
||||
source settings
|
||||
source maps
|
||||
|
||||
source account
|
||||
|
||||
105
office/.config/neomutt/settings
Normal file
105
office/.config/neomutt/settings
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# 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
|
||||
|
||||
set quit # at least for rapid prototyping
|
||||
set sleep_time = 0 # no pause for info messages
|
||||
set mark_old = no # things should only be new/unread or I actually looked at them
|
||||
set pager_read_delay = 3 # mark read after 3 sec
|
||||
set pipe_decode # get rid of headers when passing messages along
|
||||
set auto_tag # apply commands to all tagged messages automatically
|
||||
set wait_key = no # don't wait for user input after shell cmds, auto-view, piping, etc
|
||||
set thorough_search = no # don't pre-process mail for ~b/~B searches
|
||||
set flag_safe # make it impossible to delete flagged mails
|
||||
# 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
|
||||
# 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 application/ics
|
||||
auto_view text/calendar
|
||||
auto_view text/plain
|
||||
auto_view text/html
|
||||
alternative_order text/calendar application/ics text/plain text/enriched text/html text/* multipart/mixed multipart/related text/plain
|
||||
set count_alternatives = yes # look for attachments also in multipart/alternatives
|
||||
# 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 forward_format = "FW: %s" # subject for forwarding
|
||||
set mime_forward = no # forward attachments with mail
|
||||
set fcc_attach # attachments saved with body
|
||||
# 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 allow_ansi # allow escape codes for color etc
|
||||
set sort = threads
|
||||
set sort_re # thread based on regex below
|
||||
set reply_regex = "^(([Rr][Ee]?(\[[0-9]+\])?: *)?(\[[^]]+\] *)?)*"
|
||||
set quote_regex = "^( {0,4}[>|:#%]| {0,4}[A-Za-z0-9]+[>|]+)+"
|
||||
set sort_aux = last-date-received
|
||||
#### Thread ordering
|
||||
set use_threads=reverse
|
||||
set sort='last-date'
|
||||
set collapse_all = yes
|
||||
set uncollapse_new = no
|
||||
set thread_received = yes
|
||||
set narrow_tree=no
|
||||
# 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 = 24
|
||||
# set sidebar_format = "%B%?F? [%F]?%* %?N?%N/?%S"
|
||||
set sidebar_divider_char = ' ░'
|
||||
set sidebar_folder_indent = yes
|
||||
set sidebar_indent_string = ' - '
|
||||
set sidebar_visible = no
|
||||
set sidebar_next_new_wrap = yes
|
||||
set sidebar_short_path = yes
|
||||
set sidebar_component_depth = 0
|
||||
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 = 10
|
||||
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
|
||||
set wrap = 90
|
||||
# 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
|
||||
88
office/.config/notmuch/config
Normal file
88
office/.config/notmuch/config
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# .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=documents/mail
|
||||
|
||||
# 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=Marty Oehme
|
||||
primary_email=marty.oehme@gmail.com
|
||||
other_email=mo82rimu@studserv.uni-leipzig.de;moehme@ruc.dk;
|
||||
|
||||
# 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]
|
||||
tags=
|
||||
ignore=
|
||||
|
||||
# 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]
|
||||
exclude_tags=deleted;spam;
|
||||
|
||||
# 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
|
||||
27
office/.config/sh/alias.d/calcurse-vdir.sh
Normal file
27
office/.config/sh/alias.d/calcurse-vdir.sh
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env sh
|
||||
#
|
||||
# Wraps around the calcurse invocation and syncs calendar data
|
||||
# to local vdir - given by default below.
|
||||
#
|
||||
# For now ONLY PROVIDES ONE-WAY Synchronization, see below.
|
||||
|
||||
# The path in which *the calendars* reside (i.e. toplevel with access to all paths)
|
||||
CAL_PATH="$HOME/documents/calendars"
|
||||
|
||||
calcurse() {
|
||||
find "$CAL_PATH" -maxdepth 1 -type d -exec calcurse-vdir import {} \;
|
||||
}
|
||||
|
||||
# Enable two-way sync. One issue is that calcurse would sync everything
|
||||
# into the top-level path (or the selected calendar path) since it makes
|
||||
# not the same differentiation as the vdir between calendars.
|
||||
# FIXME Not sure how to resolve currently.
|
||||
#
|
||||
# The below works as a simple two-way synchronization on exiting calcurse.
|
||||
# To function the invocation has to be turned from a function above to an
|
||||
# executable shell-script file instead.
|
||||
# trap 'calcurse_export' 0
|
||||
#
|
||||
# calcurse_export() {
|
||||
# calcurse-vdir export "$CAL_PATH"
|
||||
# }
|
||||
79
office/.config/sh/alias.d/fzfmail.sh
Normal file
79
office/.config/sh/alias.d/fzfmail.sh
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/env sh
|
||||
# Fzf searching notmuch email database
|
||||
|
||||
# Search with notmuch queries
|
||||
# You can either invoke:
|
||||
# `fzfmail` -> and then interactively create a notmuch query (not fuzzy searching)
|
||||
# or:
|
||||
# `fzfmail [notmuchquery]` -> pre-craft a query and then use fzf to filter it further, e.g.
|
||||
# fzfmail tag:archived and subject:Important and not tag:flagged
|
||||
#
|
||||
# select as many mails as you wish (ctrl-a for all current results)
|
||||
# preview mails with ?
|
||||
#
|
||||
# read with <enter>
|
||||
# re-tag with <ctrl-t>
|
||||
|
||||
if exist fzf; then
|
||||
# Allow fuzzy search filtering of a notmuch search query
|
||||
fzfmail() {
|
||||
# shellcheck disable=2016 # we only want the expression to expand when fzf preview is actually called not by the shell
|
||||
if [ -z "$1" ]; then
|
||||
# interactive query
|
||||
fzfmail_mails=$(
|
||||
printf "
|
||||
\nStart a notmuch search query:\n" |
|
||||
fzf --multi \
|
||||
--header "tag: | from: | to: | subject: | folder: | date: || and | not | or | near | adj || <enter> read | <ctrl-t> tag" \
|
||||
--bind "change:reload:notmuch search {q} || true" \
|
||||
--bind "ctrl-a:toggle-all" \
|
||||
--bind '?:toggle-preview' \
|
||||
--expect 'ctrl-t,esc' \
|
||||
--preview='notmuch show --part=1 $(echo {} | cut -d" " -f1)' \
|
||||
--preview-window hidden \
|
||||
--phony |
|
||||
cut -d" " -f1
|
||||
)
|
||||
else
|
||||
# pre-queried fuzzy search
|
||||
fzfmail_mails=$(
|
||||
notmuch search "$*" |
|
||||
fzf --multi \
|
||||
--header "<enter> read | <ctrl-t> tag" \
|
||||
--bind "ctrl-a:toggle-all" \
|
||||
--bind '?:toggle-preview' \
|
||||
--expect 'ctrl-t,esc' \
|
||||
--preview='notmuch show --part=1 $(echo {} | cut -d" " -f1)' \
|
||||
--preview-window hidden |
|
||||
cut -d" " -f1
|
||||
)
|
||||
fi
|
||||
|
||||
# find out expected action
|
||||
fzfmail_action=$(echo "$fzfmail_mails" | head -n1)
|
||||
# quit on esc pressed -- do not do anything with selected results
|
||||
if echo "$fzfmail_action" | grep -qe 'esc'; then return 0; fi
|
||||
|
||||
# get the selected mails
|
||||
fzfmail_mails=$(echo "$fzfmail_mails" | tail -n+2)
|
||||
|
||||
# tag mails
|
||||
if echo "$fzfmail_action" | grep -qe 'ctrl-t'; then
|
||||
printf "current tags: %s\n" "$(notmuch search --output=tags "$fzfmail_mails" | tr '\n' ' ')"
|
||||
printf "add tags with +tag; remove with -tag\n"
|
||||
printf "apply tags: "
|
||||
read -r fzfmail_tags
|
||||
notmuch tag "$fzfmail_tags" -- "$fzfmail_mails"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# display the mails, in semi-readable format
|
||||
# highlight subject line in color
|
||||
# allow moving through results with n/p
|
||||
notmuch show "$fzfmail_mails" | sed -e 's/^\fmessage{.*$/MESSAGE:/' -e '/^\f[a-z]/d' -e 's/^Subject:/\o033[41mSubject:\o033[0m/' | less --pattern '^MESSAGE:$' -R
|
||||
|
||||
unset fzfmail_mails
|
||||
unset fzfmail_action
|
||||
unset fzfmail_tags
|
||||
}
|
||||
fi
|
||||
3
office/.config/sh/alias.d/imapfilter-xdg.sh
Normal file
3
office/.config/sh/alias.d/imapfilter-xdg.sh
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
alias imapfilter='imapfilter -c "${XDG_CONFIG_HOME:-$HOME/.config}/imapfilter/config.lua"'
|
||||
3
office/.config/sh/alias.d/mbsync-xdg.sh
Normal file
3
office/.config/sh/alias.d/mbsync-xdg.sh
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
alias mbsync='mbsync -c ${XDG_CONFIG_HOME:-$HOME/.config}/isync/mbsyncrc'
|
||||
4
office/.config/sh/env.d/neomutt-create-cache-dir.sh
Normal file
4
office/.config/sh/env.d/neomutt-create-cache-dir.sh
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
# Ensure the neomutt cache directories exist
|
||||
|
||||
[ -d "${XDG_CACHE_HOME:-~/.cache}/neomutt" ] || mkdir -p "${XDG_CACHE_HOME:-~/.cache}/neomutt/hcache"
|
||||
4
office/.config/sh/env.d/notmuch-xdg.sh
Normal file
4
office/.config/sh/env.d/notmuch-xdg.sh
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
# Make notmuch config comply with xdg base dir specification
|
||||
|
||||
export NOTMUCH_CONFIG="${XDG_CONFIG_HOME:-~/.config}/notmuch/config"
|
||||
39
office/.config/vdirsyncer/config
Normal file
39
office/.config/vdirsyncer/config
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
[general]
|
||||
status_path = "~/.local/vdirsyncer/status/"
|
||||
|
||||
[pair calendar]
|
||||
a = "calendar_local"
|
||||
b = "calendar_nextcloud"
|
||||
collections = ["from a", "from b"]
|
||||
metadata = ["displayname", "color"]
|
||||
conflict_resolution = "b wins"
|
||||
|
||||
[storage calendar_local]
|
||||
type = "filesystem"
|
||||
path = "~/documents/calendars/"
|
||||
fileext = ".ics"
|
||||
|
||||
[storage calendar_nextcloud]
|
||||
type = "caldav"
|
||||
url = "https://files.martyoeh.me/remote.php/dav/"
|
||||
username.fetch = ["shell", "pass personal/files.martyoeh.me/me | awk -F': ' '{print $2}'"]
|
||||
password.fetch = ["shell", "pass personal/files.martyoeh.me/me | head -n1"]
|
||||
|
||||
[pair contacts]
|
||||
a = "contacts_local"
|
||||
b = "contacts_nextcloud"
|
||||
collections = ["from a", "from b"]
|
||||
metadata = ["displayname", "description"]
|
||||
conflict_resolution = "b wins"
|
||||
|
||||
[storage contacts_local]
|
||||
type = "filesystem"
|
||||
path = "~/documents/contacts/"
|
||||
fileext = ".vcf"
|
||||
|
||||
[storage contacts_nextcloud]
|
||||
type = "carddav"
|
||||
url = "https://files.martyoeh.me/remote.php/dav/"
|
||||
username.fetch = ["shell", "pass personal/files.martyoeh.me/me | awk -F': ' '{print $2}'"]
|
||||
password.fetch = ["shell", "pass personal/files.martyoeh.me/me | head -n1"]
|
||||
|
||||
34
office/.local/bin/mail-searchcontacts
Executable file
34
office/.local/bin/mail-searchcontacts
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env sh
|
||||
# gets known e-mail adresses out of the current notmuch database
|
||||
#
|
||||
# called like `mail-searchcontacts [myadress]`
|
||||
#
|
||||
# where myaddress can be anything that connects mails to their adresses:
|
||||
# if directly found in the 'from': field, it will return those adresses
|
||||
# if no results are returned, it will switch to a more fuzzy search mode
|
||||
# looking through subjects, mail text, and so on for the keywords
|
||||
#
|
||||
# this can be somewhat slow for large mailboxes, in which case you probably
|
||||
# want to turn off fuzzy matching
|
||||
|
||||
searchterm="$1"
|
||||
|
||||
# make search fuzzy if 'fuzzy' is the second arg
|
||||
searchcmd() {
|
||||
if [ -n "$1" ] && [ "$2" = "fuzzy" ]; then
|
||||
term="and $1"
|
||||
elif [ -n "$1" ]; then
|
||||
term="and from:$1"
|
||||
else
|
||||
term=""
|
||||
fi
|
||||
notmuch address --deduplicate=address --output=count not from:marty.oehme@gmail.com "$term" | sort --numeric-sort -r | cut -f2- | sed -e 's/\(^.*\)\(<.*$\)/\2\t\1/'
|
||||
}
|
||||
|
||||
results=$(searchcmd "$searchterm")
|
||||
|
||||
if [ -z "$results" ]; then
|
||||
results=$(searchcmd "$searchterm" "fuzzy")
|
||||
fi
|
||||
|
||||
echo "$results"
|
||||
6
office/.local/bin/render-prettyhtml
Executable file
6
office/.local/bin/render-prettyhtml
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
# render html as markdown and display in glow, supports syntax highlighting
|
||||
# requires: html2text, glow
|
||||
# author: CEUK
|
||||
perl -0777pe 's/(<code class="sourceCode\s?)(\w+?)(">)(.*?)(<\/code>)/\1\2\3\n```\2\n\4\n```\n\5/gs' "$1" | html2text | sed -re 's/^\s+(```(\w+)?)/\1/gm' >/tmp/mutt.md
|
||||
glow -s ~/.config/glow/email.json /tmp/mutt.md | sed 's/\x1b\[[6-9;]*m//g'
|
||||
166
office/.local/bin/sync-mail
Executable file
166
office/.local/bin/sync-mail
Executable file
|
|
@ -0,0 +1,166 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Runs mbsync, with pre-hooks and post-hooks
|
||||
# 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,
|
||||
# run `checkmail raw`.
|
||||
# this will simply invoke a single isync run on all
|
||||
# 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
|
||||
# https://sourceforge.net/p/isync/feature-requests/8/
|
||||
|
||||
# available env vars:
|
||||
# MBSYNC_MAX_TRIES=3
|
||||
# MBSYNC_PRE="/bin/usr/cmd-to-run"
|
||||
# MBSYNC_POST="/bin/usr/cmd-to-run"
|
||||
# MBSYNC_NOTIFY=1
|
||||
# MBSYNC_PASSWORD_FILE="/path/to/gpg/file.gpg"
|
||||
|
||||
# What to run before and after decrypting the password file.
|
||||
PASSWORD_CMD="pass open -t 1min"
|
||||
# POST_PASSWORD_CMD=""
|
||||
|
||||
prehook() {
|
||||
if [ -n "$MBSYNC_PRE" ]; then
|
||||
eval "$MBSYNC_PRE"
|
||||
return 0
|
||||
fi
|
||||
imapfilter -c "${XDG_CONFIG_HOME:-$HOME/.config}/imapfilter/config.lua"
|
||||
}
|
||||
|
||||
posthook() {
|
||||
if [ -n "$MBSYNC_POST" ]; then
|
||||
eval "$MBSYNC_POST"
|
||||
return 0
|
||||
fi
|
||||
|
||||
notmuch new 2>/dev/null
|
||||
countnew
|
||||
}
|
||||
|
||||
# use notmuch to index incoming mail and set the
|
||||
# correct number of mails if new ones arrived for notifications
|
||||
countnew() {
|
||||
num=$(notmuch count tag:unread and tag:inbox)
|
||||
HASMAIL="${num:-0}"
|
||||
}
|
||||
|
||||
# fail the routine and optionally send a message why
|
||||
fail() {
|
||||
[ -n "$1" ] && echo "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
checkmail() {
|
||||
mbsync -c "${XDG_CONFIG_HOME:-$HOME/.config}/isync/mbsyncrc" "${1:--a}"
|
||||
}
|
||||
|
||||
checkonline() {
|
||||
# Ping 1.1.1.1 to confirm that we are on the internet
|
||||
ping -c 1 "1.1.1.1" >/dev/null 2>/dev/null || fail "checkmail can not access the internet."
|
||||
}
|
||||
|
||||
# warn user that he has to enter his password in a moment
|
||||
# to stop catching him offguard or entering something by accident
|
||||
checkwarnuser() {
|
||||
enablegpgagent
|
||||
if echo "$agt" | grep -qE 'No secret key'; then
|
||||
notify "Mail" "Password phrase needed!"
|
||||
sleep 2.5
|
||||
fi
|
||||
}
|
||||
|
||||
enablegpgagent() {
|
||||
[ -n "$agt" ] && return
|
||||
|
||||
if [ -n "$PASSWORD_CMD" ]; then
|
||||
IFS=" " read -r -a PASSWORD_CMD <<<"$PASSWORD_CMD"
|
||||
# shellcheck disable=SC2068
|
||||
agt=$(${PASSWORD_CMD[@]})
|
||||
fi
|
||||
|
||||
if [ -n "$POST_PASSWORD_CMD" ]; then
|
||||
IFS=" " read -r -a POST_PASSWORD_CMD <<<"$POST_PASSWORD_CMD"
|
||||
"${POST_PASSWORD_CMD[@]}"
|
||||
fi
|
||||
|
||||
## exit program after first failed attempt
|
||||
if echo "$agt" | grep -qE 'decryption failed' ||
|
||||
echo "$agt" | grep -qE 'No such file'; then
|
||||
notify "Mail" "Process aborted."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# send out a notification on new mail, to libnotify and stdout
|
||||
notify_on_new_mail() {
|
||||
[ "${MBSYNC_NOTIFY:-1}" -eq 0 ] && return
|
||||
|
||||
if [ "${HASMAIL:-0}" -gt 0 ]; then
|
||||
notify "Mail" "New Mail ($HASMAIL)"
|
||||
fi
|
||||
}
|
||||
|
||||
notify() {
|
||||
command -v notify-send >/dev/null && notify-send "$@"
|
||||
echo "$@"
|
||||
}
|
||||
|
||||
# Routine start
|
||||
|
||||
# check
|
||||
|
||||
# skip any retries and pre/post hooks, just run mbsync
|
||||
if [ "$1" = "raw" ]; then
|
||||
checkmail
|
||||
exit
|
||||
# any other argument passed through selects mbsync targets
|
||||
elif [ -n "$1" ]; then
|
||||
selected_mailbox="$1"
|
||||
fi
|
||||
|
||||
main() {
|
||||
checkwarnuser
|
||||
enablegpgagent
|
||||
prehook
|
||||
|
||||
tries=0
|
||||
while true; do
|
||||
if checkmail "$selected_mailbox"; then
|
||||
break
|
||||
fi
|
||||
|
||||
tries=$((tries + 1))
|
||||
if [ $tries -gt "${MBSYNC_MAX_TRIES:-3}" ]; then
|
||||
fail "maximum retries reached without success."
|
||||
fi
|
||||
done
|
||||
unset tries
|
||||
|
||||
posthook
|
||||
notify_on_new_mail
|
||||
}
|
||||
|
||||
main
|
||||
27
office/README.md
Normal file
27
office/README.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# office module
|
||||
|
||||
neomutt - terminal mail client
|
||||
[mbsync](https://isync.sourceforge.io/mbsync.html) - mirror your Imapped mail directory locally with two-way synchronization
|
||||
[notmuch](https://notmuchmail.org/) - index and search your mail
|
||||
msmtp - send mail through shell commands
|
||||
imapfilter - rule-based filtering engine for your incoming mail
|
||||
vdirsyncer - mirror your contacts and calendars locally with two-way synchronization
|
||||
khal - terminal vdir-compatible calendar client
|
||||
calcurse - a pretty terminal calendar client, but not very vdir compatible
|
||||
|
||||
Most of the credential/account setup of course is highly specific to my setup and should be changed as required.
|
||||
|
||||
The current mail setup uses `mbsync` (from the isync project) to locally mirror the GMail imap folder.
|
||||
It is run through a `sync-mail` script which can invoke pre- and post-sync hooks
|
||||
(e.g. run your incoming mail through filters as soon as they arrive or ingest them into full-text search engines).[^1]
|
||||
The sync script also automatically unlocks any pass directory so that credentials can be put into their respective applications and the directory closes again after use.
|
||||
`msmtp` is used for mail sending by neomutt (and git if using git send-email).
|
||||
`neomutt` then picks up the mail directory filled by `mbsync` and lets you browse it, respond to mail or create new ones.
|
||||
|
||||
[^1]: That being said, the script is a little dusty and could probably use a little overhaul. It *works* but could be more fantastic I feel.
|
||||
|
||||
For calendars and contacts, the wonderful `vdirsyncer` is used to sync everything from a remote Dav client (hard-coded to my server currently) to the local directories in documents.
|
||||
This is then picked up by `khal` to allow you to browse and edit your events, and create new ones - all of which in turn ends up remotely.
|
||||
|
||||
You can also browse your events locally with `calcurse` which will import them on each startup, but will not sync back yet;
|
||||
meaning, any changes you do through the application will not reflect themselves back on any of your other connected devices unfortunately.
|
||||
Loading…
Add table
Add a link
Reference in a new issue