mutt-wizard

fork of Luke Smith's mutt-wizard
Log | Files | Refs | README | LICENSE

mailsync (4752B)


      1 #!/bin/sh
      2 
      3 # - Syncs mail for all accounts, or a single account given as an argument.
      4 # - Displays a notification showing the number of new mails.
      5 # - Displays a notification for each new mail with its subject displayed.
      6 # - Runs notmuch to index new mail.
      7 # - This script can be set up as a cron job for automated mail syncing.
      8 
      9 # There are many arbitrary and ugly features in this script because it is
     10 # inherently difficult to pass environmental variables to cronjobs and other
     11 # issues. It also should at least be compatible with Linux (and maybe BSD) with
     12 # Xorg and MacOS as well.
     13 
     14 # Run only if not already running in other instance
     15 pgrep mbsync >/dev/null && { echo "mbsync is already running."; exit ;}
     16 
     17 # First, we have to get the right variables for the mbsync file, the pass
     18 # archive, notmuch and the GPG home.  This is done by searching common profile
     19 # files for variable assignments. This is ugly, but there are few options that
     20 # will work on the maximum number of machines.
     21 eval "$(grep -h -- \
     22 	"^\s*\(export \)\?\(MBSYNCRC\|MPOPRC\|PASSWORD_STORE_DIR\|PASSWORD_STORE_GPG_OPTS\|NOTMUCH_CONFIG\|GNUPGHOME\|MAILSYNC_MUTE\|XDG_CONFIG_HOME\|XDG_DATA_HOME\)=" \
     23 	"$HOME/.profile" "$HOME/.bash_profile" "$HOME/.zprofile"  "$HOME/.config/zsh/.zprofile" "$HOME/.zshenv" \
     24 	"$HOME/.config/zsh/.zshenv" "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.config/zsh/.zshrc" \
     25 	"$HOME/.pam_environment" 2>/dev/null)"
     26 
     27 # For non-interactive shell (e.g. cron job) run only when the GPG key (in $GNUPGHOME or pass --homedir) is unlocked
     28 tty -s || (echo "dummy" | gpg --sign --batch --pinentry-mode error -o /dev/null > /dev/null 2>&1) || exit
     29 
     30 export GPG_TTY="$(tty)"
     31 
     32 [ -n "$MBSYNCRC" ] && alias mbsync="mbsync -c $MBSYNCRC" || MBSYNCRC="$HOME/.mbsyncrc"
     33 [ -n "$MPOPRC" ] || MPOPRC="$HOME/.config/mpop/config"
     34 
     35 lastrun="${XDG_CONFIG_HOME:-$HOME/.config}/mutt/.mailsynclastrun"
     36 
     37 # Settings are different for MacOS (Darwin) systems.
     38 case "$(uname)" in
     39 	Darwin) notify() { osascript -e "display notification \"$2\" with title \"$1\"" ;} ;;
     40 	*)
     41 	case "$(readlink -f /sbin/init)" in
     42 		*systemd*|*openrc*) export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus ;;
     43 		*dinit*) export DBUS_SESSION_BUS_ADDRESS=$(grep -E -z "DBUS_SESSION_BUS_ADDRESS" "/proc/$(pgrep -x swaybar)/environ" | sed 's/DBUS_SESSION_BUS_ADDRESS=//') ;;
     44 	esac
     45 	# remember if a display server is running since `ps` doesn't always contain a display
     46 	pgrepoutput="$(pgrep -ax X\(\|org\|wayland\))"
     47 	displays="$(echo "$pgrepoutput" | grep -wo "[0-9]*:[0-9]\+" | sort -u)"
     48 	[ -z "$displays" ] && [ -d /tmp/.X11-unix ] && displays=$(cd /tmp/.X11-unix && for x in X*; do echo ":${x#X}"; done)
     49 
     50 	notify() { [ -n "$pgrepoutput" ] && for x in ${displays:-:0}; do
     51 			export DISPLAY=":0"
     52 			notify-send --app-name="mutt-wizard" -- "$1" "$2"
     53 		done ;}
     54 	;;
     55 esac
     56 
     57 # Check account for new mail. Notify if there is new content.
     58 syncandnotify() {
     59 	case "$1" in
     60 		imap) mbsync -q "$2" ;;
     61 		pop) mpop -q "$2" ;;
     62 	esac
     63 	new=$(find\
     64 		"$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/new/ \
     65 		"$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/cur/ \
     66 		-type f -newer "$lastrun" 2> /dev/null)
     67 	newcount=$(echo "$new" | sed '/^\s*$/d' | wc -l)
     68 	case 1 in
     69 		$((newcount > 5)) )
     70 			echo "$newcount new mails for $2."
     71 			[ -z "$MAILSYNC_MUTE" ] && notify "New Mail!" "📬 $newcount new mails in \`$2\` account."
     72 			;;
     73 		$((newcount > 0)) )
     74 			echo "$newcount new mail(s) for $2."
     75 			[ -z "$MAILSYNC_MUTE" ] &&
     76 			for file in $new; do
     77 				# Extract and decode subject and sender from mail.
     78 				subject=$(awk '/^Subject: / && ++n == 1,/^.*: / && ++i == 2' "$file" | head -n-1 |
     79 					perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' |
     80 					sed 's/^Subject: //' | tr -d '\n\t')
     81 				from="$(sed -n "/^From:/ s|From: *|| p" "$file" |
     82 					perl -CS -MEncode -ne 'print decode("MIME-Header", $_)')"
     83 				from="${from% *}" ; from="${from%\"}" ; from="${from#\"}"
     84 				notify "📧$from:" "$subject"
     85 			done
     86 			;;
     87 		*) echo "No new mail for $2." ;;
     88 esac
     89 }
     90 
     91 allaccounts="$(grep -hs "^\(Channel\|account\)" "$MBSYNCRC" "$MPOPRC")"
     92 
     93 # Get accounts to sync. All if no argument. Prefix with `error` if non-existent.
     94 IFS='
     95 '
     96 if [ -z "$1" ]; then
     97 	tosync="$allaccounts"
     98 else
     99 	tosync="$(for arg in "$@"; do for availacc in $allaccounts; do
    100 		[ "$arg" = "${availacc##* }" ] && echo "$availacc" && break
    101 	done || echo "error $arg"; done)"
    102 fi
    103 
    104 for account in $tosync; do
    105 	case $account in
    106 		Channel*) syncandnotify imap "${account##* }" & ;;
    107 		account*) syncandnotify pop "${account##* }" & ;;
    108 		error*) echo "ERROR: Account ${account##* } not found." ;;
    109 	esac
    110 done
    111 
    112 wait
    113 
    114 notmuch new --quiet
    115 
    116 pkill -RTMIN+12 "${STATUSBAR:-i3blocks}"
    117 #Create a touch file that indicates the time of the last run of mailsync
    118 touch "$lastrun"