diff options
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | README.md | 11 | ||||
| -rwxr-xr-x | bin/mailsync | 124 | ||||
| -rwxr-xr-x | bin/mw | 31 | ||||
| -rw-r--r-- | mw.1 | 1 | ||||
| -rw-r--r-- | share/imapnotify-temp | 14 |
6 files changed, 117 insertions, 68 deletions
@@ -7,10 +7,10 @@ install: mkdir -p $(DESTDIR)$(PREFIX)/bin mkdir -p $(DESTDIR)$(PREFIX)/lib/mutt-wizard mkdir -p $(DESTDIR)$(PREFIX)/share/mutt-wizard - cp -f bin/mailsync $(DESTDIR)$(PREFIX)/bin/mailsync + cp -f bin/mailsync $(DESTDIR)$(PREFIX)/bin cp -f bin/mutt.vcard.filter $(DESTDIR)$(PREFIX)/bin/mutt.vcard.filter cp -f bin/vcalendar-filter $(DESTDIR)$(PREFIX)/bin/vcalendar-filter - cp -f lib/openfile $(DESTDIR)$(PREFIX)/lib/mutt-wizard/openfile + cp -f lib/openfile $(DESTDIR)$(PREFIX)/lib/mutt-wizard chmod 755 $(DESTDIR)$(PREFIX)/share/mutt-wizard for shared in share/*; do \ cp -f $$shared $(DESTDIR)$(PREFIX)/share/mutt-wizard; \ @@ -65,12 +65,23 @@ A user of Arch-based distros can also install the current mutt-wizard release fr it that your mail is in `~/.local/share/mail/` (although `mw` will do this automatically if you haven't set notmuch up before). You can run it in mutt with <kbd>ctrl-f</kbd>. Run `notmuch new` to process new mail. + +- `goimapnotify` - required for push notifications. + [Check here for reference](https://wiki.archlinux.org/title/Isync#With_imapnotify). - `pam-gnupg` - Automatically logs you into your GPG key on login so you will never need to input your password once logged on to your system. Check the repo and directions out [here](https://github.com/cruegge/pam-gnupg). - `urlscan` - outputs urls in mail to browser. - `urlview` - outputs urls in mail to browser. +## Enable push notifications per mail + +**Note**: Replace the `fulladdrs` with your actual email address. You have to do this for each new mail you want to setup instant notifications. + +```bash +systemctl enable --user goimapnotify@fulladdrs.service +``` + ## Usage The mutt-wizard runs via the command `mw`. Once setup is complete, you'll use diff --git a/bin/mailsync b/bin/mailsync index cbd36ff..bb3feae 100755 --- a/bin/mailsync +++ b/bin/mailsync @@ -12,17 +12,23 @@ # Xorg and MacOS as well. # Run only if not already running in other instance -pgrep mbsync >/dev/null && { echo "mbsync is already running."; exit ;} +pgrep mbsync >/dev/null && { + echo "mbsync is already running." + exit +} # First, we have to get the right variables for the mbsync file, the pass # archive, notmuch and the GPG home. This is done by searching common profile # files for variable assignments. This is ugly, but there are few options that # will work on the maximum number of machines. eval "$(grep -h -- \ - "^\s*\(export \)\?\(MBSYNCRC\|MPOPRC\|PASSWORD_STORE_DIR\|PASSWORD_STORE_GPG_OPTS\|NOTMUCH_CONFIG\|GNUPGHOME\|MAILSYNC_MUTE\|XDG_CONFIG_HOME\|XDG_DATA_HOME\)=" \ - "$HOME/.profile" "$HOME/.bash_profile" "$HOME/.zprofile" "$HOME/.config/zsh/.zprofile" "$HOME/.zshenv" \ - "$HOME/.config/zsh/.zshenv" "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.config/zsh/.zshrc" \ - "$HOME/.pam_environment" 2>/dev/null)" + "^\s*\(export \)\?\(MBSYNCRC\|MPOPRC\|PASSWORD_STORE_DIR\|PASSWORD_STORE_GPG_OPTS\|NOTMUCH_CONFIG\|GNUPGHOME\|MAILSYNC_MUTE\|XDG_CONFIG_HOME\|XDG_DATA_HOME\)=" \ + "$HOME/.profile" "$HOME/.bash_profile" "$HOME/.zprofile" "$HOME/.config/zsh/.zprofile" "$HOME/.zshenv" \ + "$HOME/.config/zsh/.zshenv" "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.config/zsh/.zshrc" \ + "$HOME/.pam_environment" 2>/dev/null)" + +# For non-interactive shell (e.g. cron job) run only when the GPG key (in $GNUPGHOME or pass --homedir) is unlocked +tty -s || (echo "dummy" | gpg --sign --batch --pinentry-mode error -o /dev/null >/dev/null 2>&1) || exit export GPG_TTY="$(tty)" @@ -33,54 +39,56 @@ lastrun="${XDG_CONFIG_HOME:-$HOME/.config}/mutt/.mailsynclastrun" # Settings are different for MacOS (Darwin) systems. case "$(uname)" in - Darwin) notify() { osascript -e "display notification \"$2\" with title \"$1\"" ;} ;; - *) - case "$(readlink -f /sbin/init)" in - *systemd*|*openrc*) export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus ;; - esac - # remember if a display server is running since `ps` doesn't always contain a display - pgrepoutput="$(pgrep -ax X\(\|org\|wayland\))" - displays="$(echo "$pgrepoutput" | grep -wo "[0-9]*:[0-9]\+" | sort -u)" - [ -z "$displays" ] && [ -d /tmp/.X11-unix ] && displays=$(cd /tmp/.X11-unix && for x in X*; do echo ":${x#X}"; done) - - notify() { [ -n "$pgrepoutput" ] && for x in ${displays:-:0}; do - export DISPLAY="$x" - notify-send --app-name="mutt-wizard" "$1" "$2" - done ;} - ;; +Darwin) notify() { osascript -e "display notification \"$2\" with title \"$1\""; } ;; +*) + case "$(readlink -f /sbin/init)" in + *systemd* | *openrc*) export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus ;; + esac + # remember if a display server is running since `ps` doesn't always contain a display + pgrepoutput="$(pgrep -ax X\(\|org\|wayland\))" + displays="$(echo "$pgrepoutput" | grep -wo "[0-9]*:[0-9]\+" | sort -u)" + [ -z "$displays" ] && [ -d /tmp/.X11-unix ] && displays=$(cd /tmp/.X11-unix && for x in X*; do echo ":${x#X}"; done) + + notify() { [ -n "$pgrepoutput" ] && for x in ${displays:-:0}; do + export DISPLAY="$x" + notify-send --app-name="mutt-wizard" -- "$1" "$2" + done; } + ;; esac # Check account for new mail. Notify if there is new content. syncandnotify() { - case "$1" in - imap) mbsync -q "$2" ;; - pop) mpop -q "$2" ;; - esac - new=$(find\ - "$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/new/ \ - "$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/cur/ \ - -type f -newer "$lastrun" 2> /dev/null) - newcount=$(echo "$new" | sed '/^\s*$/d' | wc -l) - case 1 in - $((newcount > 5)) ) - echo "$newcount new mail for $2." - [ -z "$MAILSYNC_MUTE" ] && notify "New Mail!" "📬 $newcount new mail(s) in \`$2\` account." - ;; - $((newcount > 0)) ) - echo "$newcount new mail for $2." - [ -z "$MAILSYNC_MUTE" ] && - for file in $new; do - # Extract and decode subject and sender from mail. - subject="$(sed -n "/^Subject:/ s|Subject: *|| p" "$file" | - perl -CS -MEncode -ne 'print decode("MIME-Header", $_)')" - from="$(sed -n "/^From:/ s|From: *|| p" "$file" | - perl -CS -MEncode -ne 'print decode("MIME-Header", $_)')" - from="${from% *}" ; from="${from%\"}" ; from="${from#\"}" - notify "📧$from:" "$subject" - done - ;; - *) echo "No new mail for $2." ;; -esac + case "$1" in + imap) mbsync -q "$2" ;; + pop) mpop -q "$2" ;; + esac + new=$(find "$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/new/ \ + "$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/cur/ \ + -type f -newer "$lastrun" 2>/dev/null) + newcount=$(echo "$new" | sed '/^\s*$/d' | wc -l) + case 1 in + $((newcount > 5))) + echo "$newcount new mails for $2." >/dev/tty + [ -z "$MAILSYNC_MUTE" ] && notify "New Mail!" "📬 $newcount new mails in \`$2\` account." + ;; + $((newcount > 0))) + echo "$newcount new mail(s) for $2." >/dev/tty + [ -z "$MAILSYNC_MUTE" ] && + for file in $new; do + # Extract and decode subject and sender from mail. + subject=$(awk '/^Subject: / && ++n == 1,/^.*: / && ++i == 2' "$file" | head -n-1 | + perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' | + sed 's/^Subject: //' | tr -d '\n\t') + from="$(sed -n "/^From:/ s|From: *|| p" "$file" | + perl -CS -MEncode -ne 'print decode("MIME-Header", $_)')" + from="${from% *}" + from="${from%\"}" + from="${from#\"}" + notify "📧$from:" "$subject" + done + ;; + *) echo "No new mail for $2." ;; + esac } allaccounts="$(grep -hs "^\(Channel\|account\)" "$MBSYNCRC" "$MPOPRC")" @@ -89,19 +97,19 @@ allaccounts="$(grep -hs "^\(Channel\|account\)" "$MBSYNCRC" "$MPOPRC")" IFS=' ' if [ -z "$1" ]; then - tosync="$allaccounts" + tosync="$allaccounts" else - tosync="$(for arg in "$@"; do for availacc in $allaccounts; do - [ "$arg" = "${availacc##* }" ] && echo "$availacc" && break - done || echo "error $arg"; done)" + tosync="$(for arg in "$@"; do for availacc in $allaccounts; do + [ "$arg" = "${availacc##* }" ] && echo "$availacc" && break + done || echo "error $arg"; done)" fi for account in $tosync; do - case $account in - Channel*) syncandnotify imap "${account##* }" & ;; - account*) syncandnotify pop "${account##* }" & ;; - error*) echo "ERROR: Account ${account##* } not found." ;; - esac + case $account in + Channel*) syncandnotify imap "${account##* }" & ;; + account*) syncandnotify pop "${account##* }" & ;; + error*) echo "ERROR: Account ${account##* } not found." ;; + esac done wait @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -a @@ -12,12 +12,14 @@ msmtprc="${XDG_CONFIG_HOME:-$HOME/.config}/msmtp/config" msmtplog="${XDG_STATE_HOME:-$HOME/.local/state}/msmtp/msmtp.log" mbsyncrc="${MBSYNCRC:-$HOME/.mbsyncrc}" mpoprc="${XDG_CONFIG_HOME:-$HOME/.config}/mpop/config" +imapnotify="${XDG_CONFIG_HOME:-$HOME/.config}/imapnotify" mpoptemp="$muttshare/mpop-temp" mbsynctemp="$muttshare/mbsync-temp" mutttemp="$muttshare/mutt-temp" msmtptemp="$muttshare/msmtp-temp" onlinetemp="$muttshare/online-temp" notmuchtemp="$muttshare/notmuch-temp" +imapnotifytemp="$muttshare/imapnotify-temp" # With the use of templates, it's impossible to use parameter substitution. # Therefore, some default variables that might be otherwise overwritten are set # here. @@ -29,14 +31,20 @@ maxmes="0" alias mbsync='mbsync -c "$mbsyncrc"' -# mbsync now requires "Far/Near" rather than "Master/Slave", but Ubuntu/Debian -# have the older version. -if command -V apt-get >/dev/null 2>&1; then - master="Master" - slave="Slave" -else +# mbsync >=1.4.0 requires "Far/Near" rather than "Master/Slave." +mbver="$(mbsync -v)" +mbver="${mbver#* }" +mbver="${mbver%.*}" +# Comparing two float numbers in bash is a pain in the butt, so we get rid of +# dots and turn them into nice integers +mbver="${mbver/\./}" + +if [ "${mbver}" -gt 14 ]; then master="Far" slave="Near" +else + master="Master" + slave="Slave" fi for x in "/etc/ssl/certs/ca-certificates.crt" \ @@ -90,6 +98,11 @@ prepmpop() { envsubst <"$mpoptemp" >>"$mpoprc" } +prepimapnotify() { + mkdir -p "$imapnotify" + envsubst <"$imapnotifytemp" >>"$imapnotify/$fulladdr.conf" +} + prepmutt() { mkdir -p "${muttrc%/*}" "$accdir" envsubst <"$mutttemp" >"$accdir/$fulladdr.muttrc" @@ -97,6 +110,7 @@ prepmutt() { ! grep -q "^source.*mutt-wizard.muttrc" "$muttrc" && echo "source $muttshare/mutt-wizard.muttrc" >>"$muttrc" ! grep "^source.*.muttrc" "$muttrc" | grep -qv "$muttshare/mutt-wizard.muttrc" && echo "source $accdir/$fulladdr.muttrc" >>"$muttrc" echo "macro index,pager i$idnum '<sync-mailbox><enter-command>source $accdir/$fulladdr.muttrc<enter><change-folder>!<enter>;<check-stats>' \"switch to $fulladdr\"" >>"$muttrc" + neomutt -v | grep -q lmdb && ! grep -q "^set header_cache_backend.*lmdb" "$muttrc" && echo "set header_cache_backend = \"lmdb\"" >>"$muttrc" } getprofiles() { @@ -118,6 +132,7 @@ getprofiles() { prepmsmtp prepmutt prepnotmuch + prepimapnotify } parsedomains() { @@ -217,7 +232,7 @@ askinfo() { } insertpass() { - printf "%s" "$password" | pass insert -fe "$PASSWORD_STORE_DIR/mail/$passprefix$fulladdr" + printf "%s" "$password" | pass insert -fe "$passprefix$fulladdr" } errorexit() { @@ -79,6 +79,7 @@ SMTP server port (assumed to be 465 if not specified) .TP .B -x Account password. You will be prompted for the password interactively if this option is not given. +.TP .B -P Pass Prefix. The password will be stored using pass at <passprefix><email> .SH OTHER OPTIONS diff --git a/share/imapnotify-temp b/share/imapnotify-temp new file mode 100644 index 0000000..3cdd360 --- /dev/null +++ b/share/imapnotify-temp @@ -0,0 +1,14 @@ +{ + "host": "$imap", + "port": $iport, + "tls": true, + "tlsOptions": { + "rejectUnauthorized": false + }, + "username": "$login", + "password": "", + "passwordCmd": "pass $passprefix$fulladdr", + "onNewMail": "mailsync", + "onNewMailPost": "", + "boxes": [ "INBOX" ] +} |
