#!/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 ` 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 checkwarnuser 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() { 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