diff options
Diffstat (limited to 'bin/mailsync')
| -rwxr-xr-x | bin/mailsync | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/bin/mailsync b/bin/mailsync new file mode 100755 index 0000000..2100962 --- /dev/null +++ b/bin/mailsync @@ -0,0 +1,148 @@ +#!/bin/bash +set -eu +[ -n "${DEBUG:-}" ] && set -x + +# check requirements +for tool in mbsync fyi python awk; do + if ! command -v "$tool" >/dev/null; then + printf '%s: %s not installed but required\n' "$(basename "$0")" "$tool" >&2 + exit 1 + fi +done + +maildir="${HOME}/mail" +cachefile=${XDG_CACHE_HOME:-$HOME/.cache}/mailsync.lastrun + +accounts=(gnzler) +list= +verbose= +while getopts a:lvh opt; do + case "${opt}" in + a) accounts=("${OPTARG}") ;; + l) list=1 ;; + v) verbose=1 ;; + h | ?) + printf "usage: %s [-h] [ACCOUNT...]\n" "$(basename "$0")" + printf "\n" + printf " -a ACCOUNTS, accunts to sync (default: \"%s\")\n" "${accounts[*]}" + printf " -l list mail\n" + printf " -v be verbose" + printf "\n" + exit 2 + ;; + esac +done +shift $((OPTIND - 1)) + +if [ -n "${1:-}" ]; then + accounts=("$*") +fi + +notifyclose() { + fyi --close "$1" +} +notifysend() { + local summary="${1:?missing summary}" body="${2:?missing body}" + shift 2 + + fyi --print-id $@ -a mailsync \ + -i "${ico:-}" \ + "$summary" "<i>$body</i>" | cut -d= -f2 +} +try() { + [ "$1" = "--" ] && shift 1 + if ! { error=$( + set +x + eval $* 2>&3 + ); } 3>&1; then + notifysend "failed :(" "$error" -c error + return 1 + fi +} + + +decode() { + python -c 'import sys;import email.header;print(("".join(list(map(lambda s: s[0] if (type(s[0]) == str) else s[0].decode(s[1] or "utf-8"), email.header.decode_header(((sys.stdin.readlines() or [""])[0]).strip()))))))' +} + +list_msg() { + local acct=$2 + local args=(-type f -not -name '\.*') + local cachefile="${cachefile}.${acct}" + + find "${maildir}"/"${acct}"/{INBOX,lists}/new/ "${args[@]}" 2>/dev/null || true +} + +run_notify() { + local acct=$1 + local new_mail + local num + local nid + + new_mail=$(list_msg new "${acct}") + num=$(echo "$new_mail" | wc -l) + nid=$(notifysend "${acct}: new mail" "found ${num} new messages" --expire-time=6000) +} + +run_sync() { + local acct=$1 + local nid + local ret + + # exit if we're already running + pgrep mbsync >/dev/null && { + echo "mbsync is already running." + notifysend "${acct}: mailsync stopped" "mbsync is already running" + return + } + + # flush msmtp + nid=$(notifysend "${acct}: flushing queue" "running msmtp-queue" --expire-time=0) + try -- msmtp-queue -r || true + + # run sync + nid=$(notifysend "${acct}: syncing mail" "running mbsync" --expire-time=0 --replaces=$nid) + mbsync_args= + [ -n "${verbose}" ] && mbsync_args="--verbose" + try -- mbsync $mbsync_args --config="$HOME/.config/mbsyncrc" "$acct" + + # create cachefile + touch "${cachefile}.${acct}" + + # index new messages + if command -v notmuch >/dev/null 2>&1; then + nid=$(notifysend "${acct}: syncing mail" "running notmuch" --expire-time=0 --replaces=$nid) + try -- notmuch new + fi + + # update address book + if command -v maildir-rank-addr >/dev/null 2>&1; then + nid=$(notifysend "${acct}: syncing mail" "running maildir-rank-addr" --expire-time=0 --replaces=$nid) + maildir-rank-addr \ + --maildir=${maildir}/${acct} \ + --outputpath=${maildir}/addressbook \ + --addresses='(r|robert)@gnzler\.(de|io),robert(|\.)guenzler@gmail.com,therobotbase@gmail.com,robertg@balena.io,robert.gunzler@postman.com,robert@unikraft.io' \ + --filters='r\+.*@gnzler\.(de|io)' + fi + + notifyclose "$nid" +} + +# only list new mail, don't sync +if [ -z "${accounts[*]}" ]; then + echo "no account specified" >&2 + exit 1 +fi + +for acct in "${accounts[@]}"; do + ( + if [ -n "${list}" ]; then + list_msg "${list}" "${acct}" + exit 0 # exit ()& subshell + fi + run_sync "${acct}" + run_notify "${acct}" + ) & +done + +wait |