diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | README.md | 10 | ||||
| -rwxr-xr-x | bin/mailsync | 47 | ||||
| -rwxr-xr-x | bin/mw | 36 | ||||
| -rw-r--r-- | mw.1 | 4 | ||||
| -rw-r--r-- | share/domains.csv | 1 | ||||
| -rw-r--r-- | share/imapnotify-temp | 15 | ||||
| -rw-r--r-- | share/mbsync-temp | 2 | ||||
| -rw-r--r-- | share/mutt-temp | 2 | ||||
| -rw-r--r-- | share/mutt-wizard.muttrc | 2 |
10 files changed, 93 insertions, 28 deletions
@@ -1,6 +1,6 @@ .POSIX: -PREFIX = /usr/local +PREFIX ?= /usr/local MANPREFIX = $(PREFIX)/share/man install: @@ -4,7 +4,7 @@ https://muttwizard.com/ Get this great stuff without effort: -- A full-featured and autoconfigured email client on the terminal with neomutt +- A full-featured and autoconfigured email client on the terminal built with neomutt - Mail stored offline enabling the ability to: * view and write emails while you're away from the internet @@ -54,6 +54,8 @@ A user of Arch-based distros can also install the current mutt-wizard release fr ### Optional Dependencies +- `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). @@ -134,6 +136,12 @@ To give you an example of the interface, here's an idea: - <kbd>ctrl-b</kbd> - open a menu to select a URL you want to open in your browser. - <kbd>p</kbd> - encrypt/sign your message (in compose view, before sending the email). +## 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 +``` + ## Additional functionality - `pam-gnupg` - Automatically logs you into your GPG key on login, so you will diff --git a/bin/mailsync b/bin/mailsync index cbd36ff..7bca2d0 100755 --- a/bin/mailsync +++ b/bin/mailsync @@ -24,6 +24,9 @@ eval "$(grep -h -- \ "$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)" [ -n "$MBSYNCRC" ] && alias mbsync="mbsync -c $MBSYNCRC" || MBSYNCRC="$HOME/.mbsyncrc" @@ -45,7 +48,7 @@ case "$(uname)" in notify() { [ -n "$pgrepoutput" ] && for x in ${displays:-:0}; do export DISPLAY="$x" - notify-send --app-name="mutt-wizard" "$1" "$2" + notify-send --app-name="mutt-wizard" -- "$1" "$2" done ;} ;; esac @@ -55,7 +58,7 @@ syncandnotify() { case "$1" in imap) mbsync -q "$2" ;; pop) mpop -q "$2" ;; - esac + esac || return 1 new=$(find\ "$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/new/ \ "$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/cur/ \ @@ -63,16 +66,17 @@ syncandnotify() { 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." + 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 for $2." + 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="$(sed -n "/^Subject:/ s|Subject: *|| p" "$file" | - perl -CS -MEncode -ne 'print decode("MIME-Header", $_)')" + # Extract and decode subject and sender from mail. + subject=$(awk '/^Subject: / && ++n == 1,/^.*: / && ++i == 2' "$file" | sed '$d' | + 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#\"}" @@ -96,15 +100,34 @@ else done || echo "error $arg"; done)" fi +pids= # PIDs of backgrounded subshells +count=0 # number of accounts in $tosync +failed=0 # number of failed sync attempts for account in $tosync; do + count=$((count+1)) case $account in - Channel*) syncandnotify imap "${account##* }" & ;; - account*) syncandnotify pop "${account##* }" & ;; - error*) echo "ERROR: Account ${account##* } not found." ;; + Channel*) + syncandnotify imap "${account##* }" & + pids="$pids $!" + ;; + account*) + syncandnotify pop "${account##* }" & + pids="$pids $!" + ;; + error*) + echo "ERROR: Account ${account##* } not found." + failed=$((failed+1)) + ;; esac done -wait +IFS=' ' +for pid in $pids; do + wait $pid || failed=$((failed+1)) +done + +# Abort if no account sync succeeded +[ "$count" -gt "$failed" ] || exit 1 notmuch new --quiet @@ -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,19 @@ 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" \ @@ -63,7 +70,6 @@ list() { getaccounts && [ -n "$accounts" ] && echo "$accounts" || exit 1; } prepmsmtp() { mkdir -p "${msmtprc%/*}" "${msmtplog%/*}" - ln -s "$msmtprc" "$HOME/.msmtprc" 2>/dev/null envsubst <"$msmtptemp" >>"$msmtprc" } @@ -78,6 +84,10 @@ prepmpop() { envsubst <"$mpoptemp" >>"$mpoprc" } +prepimapnotify() { + mkdir -p "$imapnotify" ; envsubst < "$imapnotifytemp" >> "$imapnotify/$fulladdr.yaml" +} + prepmutt() { mkdir -p "${muttrc%/*}" "$accdir" envsubst <"$mutttemp" >"$accdir/$fulladdr.muttrc" @@ -85,6 +95,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() { @@ -106,6 +117,7 @@ getprofiles() { prepmsmtp prepmutt prepnotmuch + prepimapnotify } parsedomains() { @@ -181,7 +193,7 @@ askinfo() { } insertpass() { - printf "%s" "$password" | pass insert -fe "$PASSWORD_STORE_DIR/$passprefix$fulladdr" + printf "%s" "$password" | pass insert -fe "$passprefix$fulladdr" } errorexit() { @@ -208,7 +220,7 @@ getboxes() { if [ -n "${force+x}" ]; then mailboxes="$(printf "INBOX\\nDrafts\\nJunk\\nTrash\\nSent\\nArchive")" else - info="$(curl --location-trusted -s -m 5 --user "$login:$(pass "$passprefix$fulladdr")" --url "${protocol:-imaps}://$imap:${iport:-993}")" + info="$(curl --proxy "$proxy" --location-trusted -s -m 5 --user "$login:$(pass "$passprefix$fulladdr")" --url "${protocol:-imaps}://$imap:${iport:-993}")" [ -z "$info" ] && errorexit mailboxes="$(echo "$info" | grep -v HasChildren | sed "s/.*\" //;s/\"//g" | tr -d '\r')" fi @@ -288,6 +300,7 @@ Options allowed with -a: -X Delete an account's local email too when deleting. -o Configure address, but keep mail online. -f Assume typical English mailboxes without attempting log-on. + -R Use a proxy server for curl (useful for bypassing network restrictions) NOTE: Once at least one account is added, you can run \`mbsync -a\` to begin downloading mail. @@ -320,9 +333,10 @@ reorder() { ' "$tempfile" >>"$muttrc" } -while getopts "rfpXlhodTYD:y:i:I:s:S:u:a:n:P:x:m:t:" o; do case "${o}" in +while getopts "rfpXlhodTYD:y:i:I:s:S:u:a:n:P:x:m:t:R:" o; do case "${o}" in l) setact list ;; r) setact reorder ;; + R) proxy="$OPTARG" ;; d) setact delete ;; D) setact delete @@ -70,8 +70,12 @@ 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> +.TP +.B -R +Use a proxy server for curl (useful for bypassing network restrictions) .SH OTHER OPTIONS .TP .B -f diff --git a/share/domains.csv b/share/domains.csv index beb7a1e..374dce7 100644 --- a/share/domains.csv +++ b/share/domains.csv @@ -304,6 +304,7 @@ ukr.net,imap.ukr.net,993,smtp.ukr.net,465 umbc.edu,imap.gmail.com,993,smtp.gmail.com,587 uni-duesseldorf.de,mail.hhu.de,993,mail.hhu.de,465 uni-jena.de,imap.uni-jena.de,993,smtp.uni-jena.de,587 +uni-weimar.de,mailgate.uni-weimar.de,993,mailgate.uni-weimar.de,465 uni.edu.pe,imap.gmail.com,993,smtp.gmail.com,587 uni.strath.ac.uk,outlook.office365.com,993,smtp.office365.com,587 unilodz.eu,outlook.office365.com,993,smtp.office365.com,587 diff --git a/share/imapnotify-temp b/share/imapnotify-temp new file mode 100644 index 0000000..a81cba2 --- /dev/null +++ b/share/imapnotify-temp @@ -0,0 +1,15 @@ +{ + "host": "$imap", + "port": $iport, + "tls": true, + "tlsOptions": { + "rejectUnauthorized": false + }, + "username": "$login", + "password": "", + "passwordCmd": "pass $passprefix$fulladdr", + "onNewMail": "mailsync", + "onNewMailPost": "", + "boxes": [ "INBOX" ] +} + diff --git a/share/mbsync-temp b/share/mbsync-temp index 4e77b09..ead3920 100644 --- a/share/mbsync-temp +++ b/share/mbsync-temp @@ -4,7 +4,7 @@ Port $iport User $login PassCmd "pass $passprefix$fulladdr" AuthMechs LOGIN -SSLType $imapssl +TLSType $imapssl CertificateFile $sslcert MaildirStore $fulladdr-local diff --git a/share/mutt-temp b/share/mutt-temp index 63841ad..82e16ef 100644 --- a/share/mutt-temp +++ b/share/mutt-temp @@ -6,7 +6,7 @@ set sendmail = "msmtp -a $fulladdr" alias me $realname <$fulladdr> set folder = "$folder" set header_cache = "$cachedir/$safename/headers" -set message_cachedir = "$cachedir/$safename/bodies" +set message_cache_dir = "$cachedir/$safename/bodies" set mbox_type = Maildir set hostname = "$hostname" source $muttshare/switch.muttrc diff --git a/share/mutt-wizard.muttrc b/share/mutt-wizard.muttrc index 27ae216..f236bc4 100644 --- a/share/mutt-wizard.muttrc +++ b/share/mutt-wizard.muttrc @@ -101,7 +101,7 @@ macro index \eh "<pipe-message>$prefix/libexec/gpg-wks-client --receive | msmtp macro index,pager a "<enter-command>set my_pipe_decode=\$pipe_decode pipe_decode<return><pipe-message>abook --add-email<return><enter-command>set pipe_decode=\$my_pipe_decode; unset my_pipe_decode<return>" "add the sender address to abook" macro index \Cr "T~U<enter><tag-prefix><clear-flag>N<untag-pattern>.<enter>" "mark all messages as read" macro index O "<shell-escape>mailsync<enter>" "run mailsync to sync all mail" -macro index \Cf "<enter-command>unset wait_key<enter><shell-escape>printf 'Enter a search term to find with notmuch: '; read x; echo \$x >~/.cache/mutt_terms<enter><limit>~i \"\`notmuch search --output=messages \$(cat ~/.cache/mutt_terms) | head -n 600 | perl -le '@a=<>;s/\^id:// for@a;$,=\"|\";print@a' | perl -le '@a=<>; chomp@a; s/\\+/\\\\+/g for@a; s/\\$/\\\\\\$/g for@a;print@a' \`\"<enter>" "show only messages matching a notmuch pattern" +macro index \Cf "<enter-command>unset wait_key<enter><shell-escape>printf 'Enter a search term to find with notmuch: '; read x; echo \$x >\"\${XDG_CACHE_HOME:-\$HOME/.cache}/mutt_terms\"<enter><limit>~i \"\`notmuch search --output=messages \$(cat \"\${XDG_CACHE_HOME:-\$HOME/.cache}/mutt_terms\") | head -n 600 | perl -le '@a=<>;s/\^id:// for@a;$,=\"|\";print@a' | perl -le '@a=<>; chomp@a; s/\\+/\\\\+/g for@a; s/\\$/\\\\\\$/g for@a;print@a' \`\"<enter>" "show only messages matching a notmuch pattern" macro index A "<limit>all\n" "show all messages (undo limit)" # Sidebar mappings |
