summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.config/mbsyncrc73
-rwxr-xr-xbin/hibiki/mailsync119
2 files changed, 158 insertions, 34 deletions
diff --git a/.config/mbsyncrc b/.config/mbsyncrc
index 30c5c0b..9e8725a 100644
--- a/.config/mbsyncrc
+++ b/.config/mbsyncrc
@@ -1,20 +1,85 @@
+## gnzler
+
 IMAPAccount gnzler
 Host mail.gandi.net
 User robert@gnzler.io
 PassCmd "pass email/gnzler.io | head -n1"
 SSLType IMAPS
 
+IMAPStore gnzler
+Account gnzler
+
 MaildirStore local
 Path ~/Mail/gnzler/
 INBOX ~/Mail/gnzler/INBOX
 SubFolders Verbatim
 
-IMAPStore gnzler
-Account gnzler
-
-Channel primary
+Channel gnzler
 Far :gnzler:
 Near :local:
 Patterns INBOX Archive/2022 Drafts Sent lists
 Create Near
+SyncState *
+# WATCH OUT WHAT YOU'RE DOING
+Expunge both
+
+## selfhosted
+
+IMAPAccount selfhosted
+Host localhost:1430
+User postmaster@gnzler.de
+PassCmd "pass email/postmaster@gnzler.io | head -n1"
+SSLType None
+
+IMAPStore selfhosted
+Account selfhosted
+
+## backup
+
+MaildirStore backup
+Path ~/Mail/server.bak/
+INBOX ~/Mail/server.bak/INBOX
+SubFolders Verbatim
+
+Channel backup
+Far :gnzler:
+Near :backup:
+Patterns *
+Create Both
+SyncState *
+Sync Pull
+
+## restore
+
+Channel restore
+Far :selfhosted:
+Near :backup:
+Patterns *
+Create Both
+SyncState *
+Sync Push
+
+## hu
+
+IMAPAccount hu
+Host mailbox.informatik.hu-berlin.de
+User guenzler
+PassCmd "pass email/hu-berlin.de | head -n1"
+SSLType IMAPS
+
+MaildirStore local-hu
+Path ~/Mail/hu/
+INBOX ~/Mail/hu/INBOX
+SubFolders Verbatim
+
+IMAPStore hu
+Account hu
+
+Channel hu
+Far :hu:
+Near :local-hu:
+Patterns INBOX
+Create Near
+SyncState *
+# WATCH OUT WHAT YOU'RE DOING
 Expunge both
diff --git a/bin/hibiki/mailsync b/bin/hibiki/mailsync
index ae96bd0..3fc940f 100755
--- a/bin/hibiki/mailsync
+++ b/bin/hibiki/mailsync
@@ -3,52 +3,111 @@
 set -e
 [ -n "$DEBUG" ] && set -x
 
-#
-# mbsync call here:
-#
-mbsync -c "$HOME/.config/mbsyncrc" primary
+maildir="${HOME}/Mail"
+cachefile=${XDG_CACHE_HOME}/mailsync.lastrun
 
-#
-# notifications-related only from here:
-#
+accounts=(gnzler hu)
+list=
+verbose=
+while getopts a:l:vh opt; do
+	case "${opt}" in
+	a) accounts=("${OPTARG}") ;;
+	l) list="${OPTARG}" ;;
+	v) verbose=1 ;;
+	h | ?)
+		printf "usage: %s [-h]\n" "$(basename "$0")"
+		printf "\n"
+		printf "  -a ACCOUNTS, accunts to sync (default: \"%s\")\n" "$(echo "${accounts[@]}")"
+		printf "  -l CUR_OR_NEW, list new or current mails (default: \"%s\")\n" "${list}"
+		printf "  -v be verbose"
+		printf "\n"
+		exit 2
+		;;
+	esac
+done
+shift $((OPTIND - 1))
 
-MAILDIR_PATTERN=$HOME/Mail/*
-new_mail=$(find ${MAILDIR_PATTERN}/*/new/ -type f | wc -l)
-old_mail=$(find ${MAILDIR_PATTERN}/*/cur/ -type f | wc -l)
+notifysend() {
+	local summary=$1
+	local body=$2
 
-notify() {
 	notify-send \
 		-i /usr/share/icons/mdi/scalable/email-plus.svg \
 		-a mailsync \
 		-c audible \
-		"$1" "$2"
+		"${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()[0])))))'
+	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()[0]).strip()))))))'
 }
 
-handle_new_msg() {
-	msg=$1
+handle_msg() {
+	local msg=$1
+	local from
+	local subject
+	local listid
 
-	from=$(awk '/^From:/{print $2}' "$msg" | decode)
-	subject=$(awk '/^Subject:/{print}' "$msg" | cut -d' ' -f2- | decode)
-	to=$(awk '/^To:/{print $2}' "$msg" | decode)
+	from=$(awk '/^From:/{print}' "${msg}" | cut -d':' -f2- | decode)
+	subject=$(awk '/^Subject:/{print}' "${msg}" | cut -d':' -f2- | decode)
+	listid=$(awk '/^List-ID:/{print}' "${msg}" | cut -d':' -f2- | decode)
+	if [ -n "${listid}" ]; then
+		subject="${subject}\n<span alpha='90%' size='small'>~> $(echo "${listid}" | sed -e 's|<|\&lt;|g' -e 's|>|\&gt;|g')</span>"
+	fi
+	notifysend "${from}" "${subject}"
+}
 
-	if [[ "$to" =~ (lists.sr.ht|noreply.github.com) ]]; then
-		subject="$to\n$subject"
+notify() {
+	local acct=$1
+	local new_mail
+
+	new_mail=$(list_msg new "${acct}")
+	if [ -n "$new_mail" ]; then
+		printf "found %d new mail\n" "$(echo "${new_mail}" | wc -l)"
+		for msg in ${new_mail}; do handle_msg "$msg"; done
 	fi
+}
+
+list_msg() {
+	local cur_or_new=${1:-new}
+	local acct=$2
+	local args=(-type f)
+	local cachefile="${cachefile}.${acct}"
 
-	notify "new mail from: $from" "$subject"
+	[ "${cur_or_new}" = "new" ] && [ -f "${cachefile}" ] && args+=(-newer "${cachefile}")
+	find "${maildir}"/"${acct}"/*/"${cur_or_new}"/ "${args[@]}" 2>/dev/null
 }
 
-if [ "$new_mail" -gt 0 ]; then
-	new_inbox=$(find ${MAILDIR_PATTERN}/INBOX/new/ -type f)
-	if [ -n "$new_inbox" ]; then
-		for msg in "${new_inbox[@]}"; do
-			handle_new_msg "$msg"
-		done
-	else
-		notify "new mail" "new: $new_mail / old: $old_mail"
-	fi
+sync() {
+	local acct=$1
+
+	# exit if we're already running
+	pgrep mbsync >/dev/null && {
+		echo "mbsync is already running."
+		return
+	}
+	mbsync_args=
+	[ -n "${verbose}" ] && mbsync_args="--verbose"
+	mbsync $mbsync_args --config="$HOME/.config/mbsyncrc" "$acct"
+	# create cachefile
+	touch "${cachefile}.${acct}"
+}
+
+# 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
+		sync "${acct}"
+		notify "${acct}"
+	) &
+done
+
+wait