#!/bin/bash set -e [ -n "$DEBUG" ] && set -x # check requirements for tool in mbsync notify-send python awk gdbus iconez; 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}/mailsync.lastrun accounts=(gnzler hu) 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 notifysend() { local summary=$1 local body=$2 local ico shift 2 if ! printf "%s" "$*" | grep -- "-i" >/dev/null; then ico="📨 " fi # -i /usr/share/icons/mdi/scalable/email-plus.svg \ notify-send $@ \ -a mailsync \ -c audible \ "${ico:-}${summary}" "${body}" } 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()))))))' } handle_msg() { local msg=$1 local from local subject local listid local ico from=$(sed ':a; N; $!b a; s/\n\s\{1,\}/ /g' "${msg}" | awk '/^From:/{print}' | cut -d: -f2 | decode) subject=$(sed ':a; N; $!b a; s/\n\s\{1,\}/ /g' "${msg}" | awk '/^Subject:/{print}' | cut -d: -f2 | decode) listid=$(sed ':a; N; $!b a; s/\n\s\{1,\}/ /g' "${msg}" | awk '/^List-ID:/{print}' | cut -d: -f2 | decode) if [ -n "${listid}" ]; then subject="${subject}\n~> $(echo "${listid}" | sed -e 's|<|\<|g' -e 's|>|\>|g')" ico="$(iconez -sn email-multiple-outline)" else ico="$(iconez -sn email-receive-outline)" fi notifysend "${from}" "${subject}" -i "${ico}" -t 2000 } 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 # local cur_or_new=${1:-new} # if [ "${cur_or_new}" = "new" ]; then # find "${maildir}"/"${acct}"/{INBOX,lists}/"${cur_or_new}"/ "${args[@]}" 2>/dev/null || true # else # find "${maildir}"/"${acct}"/*/"${cur_or_new}"/ "${args[@]}" 2>/dev/null || true # fi } run_notify() { local acct=$1 local new_mail new_mail=$(list_msg new "${acct}") if [ -n "${new_mail}" ]; then local num num="$(echo "${new_mail}" | grep -c INBOX)" # always print INBOX messages for msg in $(echo "${new_mail}" | grep INBOX); do handle_msg "$msg"; done # everything else, limit to 5, just print the count otherwise num="$(echo "${new_mail}" | grep -c -v INBOX)" notifysend "${acct}: new" "Found ${num} new mail" -i "$(iconez -sn email-receive-outline)" [ "${num}" -gt 5 ] && return for msg in $(echo "${new_mail}" | grep -v INBOX); do handle_msg "$msg"; done fi } run_sync() { local acct=$1 # exit if we're already running pgrep mbsync >/dev/null && { echo "mbsync is already running." notifysend "mailsync stopped" "mbsync is already running" -i "$(iconez -sn email-off-outline)" return } # persistent notification id=$(notifysend "${acct}: fetching new mail..." "running mbsync" -i "$(iconez -sn email-sync-outline)" --print-id --expire-time=0) mbsync_args= [ -n "${verbose}" ] && mbsync_args="--verbose" mbsync $mbsync_args --config="$HOME/.config/mbsyncrc" "$acct" clear-notification "$id" # create cachefile touch "${cachefile}.${acct}" # index new messages command notmuch >/dev/null 2>&1 && notmuch new } # 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