|
|
@@ -0,0 +1,150 @@ |
|
|
#!/bin/zsh |
|
|
# |
|
|
# Trigger a command when new mail arrives on the server, using IMAP IDLE. Cf. |
|
|
# <http://dwm.suckless.org/scripts/email_notifier_script>. |
|
|
# |
|
|
# Note that, theoretically, fetchmail can take a comma-separated list of |
|
|
# multiple folders, but IDLE will only poll the first one, so if you need to |
|
|
# monitor multiple mailboxes, you need to run multiple monitor instances. |
|
|
# |
|
|
# Passwords are read from the password store keyring by default. |
|
|
# |
|
|
# Requirements: |
|
|
# |
|
|
# - fetchmail |
|
|
# - docopts |
|
|
# - zsh |
|
|
# |
|
|
# |
|
|
# Copyright © 2018 Sebastian Reuße |
|
|
# |
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
|
|
# of this software and associated documentation files (the "Software"), to deal |
|
|
# in the Software without restriction, including without limitation the rights |
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
|
# copies of the Software, and to permit persons to whom the Software is |
|
|
# furnished to do so, subject to the following conditions: |
|
|
# |
|
|
# The above copyright notice and this permission notice shall be included in all |
|
|
# copies or substantial portions of the Software. |
|
|
# |
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
|
# SOFTWARE. |
|
|
|
|
|
############################## |
|
|
## Tweakables ## |
|
|
############################## |
|
|
|
|
|
get_password() { |
|
|
local account=$1 |
|
|
pass show mail/$account |
|
|
} |
|
|
|
|
|
notify() { |
|
|
local account=$1 |
|
|
local mail_info=$2 |
|
|
local mailbox=$3 |
|
|
|
|
|
local message="$account: new mail ($mail_info)" |
|
|
notify-send $message |
|
|
xset led named "Scroll Lock" |
|
|
mbsync -V $account:$mailbox |
|
|
} |
|
|
|
|
|
|
|
|
############################## |
|
|
## Program ## |
|
|
############################## |
|
|
|
|
|
setopt \ |
|
|
nounset \ |
|
|
pipefail \ |
|
|
warncreateglobal |
|
|
|
|
|
program_name=$(basename $0) |
|
|
usage_text="$program_name |
|
|
|
|
|
Usage: |
|
|
$program_name -a ACCOUNT -r HOSTNAME -l USERNAME [options] |
|
|
|
|
|
Options: |
|
|
-h, --help Show this help. |
|
|
-a, --account ACCOUNT Read password from password store entry mail/ACCOUNT |
|
|
-b, --mailbox MAILBOX Monitor this mailbox [default: INBOX] |
|
|
-r, --host HOSTNAME Connect to HOST |
|
|
-l, --login USERNAME Login as USERNAME |
|
|
-p, --port PORT Connect to this port |
|
|
-x, --debug Enable debug output |
|
|
--caroot PATH Load TLS root certificates from here [default: /etc/ssl/cert.pem] |
|
|
--imaps Connect using IMAPS instead of STARTTLS" |
|
|
|
|
|
cleanup() { |
|
|
local statuscode=$? |
|
|
kill -- -$$ |
|
|
rm -vr $FETCHMAILHOME |
|
|
exit $statuscode |
|
|
} |
|
|
|
|
|
main() { |
|
|
unsetopt warncreateglobal |
|
|
eval "$(docopts -h $usage_text : $*)" |
|
|
setopt warncreateglobal |
|
|
|
|
|
if [[ $debug == true ]]; then |
|
|
setopt xtrace |
|
|
fi |
|
|
|
|
|
local port sslopts |
|
|
if [[ $imaps == true ]]; then |
|
|
port=${port:-993} |
|
|
sslopts="ssl sslproto TLS1" |
|
|
else |
|
|
port=${port:-143} |
|
|
sslopts="sslproto TLS1" |
|
|
fi |
|
|
|
|
|
local password |
|
|
get_password $account | read password |
|
|
|
|
|
# Generate a fetchmail-config on the fly. This avoids storing the password |
|
|
# in the clear, since fetchmail doesn’t offer something like msmtp’s |
|
|
# password_cmd. |
|
|
local fetchmail_config=" |
|
|
poll \"$host\" port $port proto IMAP \ |
|
|
user \"$login\" there with password \"$password\" \ |
|
|
keep idle $sslopts sslcertck sslcertfile \"$caroot\" |
|
|
folder \"$mailbox\"" |
|
|
|
|
|
# Since IDLE only polls one folder, we will probably want to run multiple |
|
|
# instances of this script. However, fetchmail only allows one process at |
|
|
# the same time. We can circumvent this by setting FETCHMAILHOME uniquely. |
|
|
# Hopefully, this is okay, since we’re using fetchmail in a way that doesn’t |
|
|
# touch the remote mail storage. Cf. |
|
|
# <http://fnxweb.com/blog/2012/07/14/using-multiple-fetchmail-instances-for-instant-gratification/> |
|
|
export FETCHMAILHOME=$(mktemp -d) |
|
|
local input mail_info |
|
|
fetchmail --check -f - <<<$fetchmail_config \ |
|
|
| while read input; do |
|
|
mail_info=$( |
|
|
sed 's/(//' <<<$input \ |
|
|
| awk '{print $1-$3}' |
|
|
) |
|
|
if [[ $mail_info != 0 ]]; then |
|
|
notify $account $mail_info $mailbox |
|
|
fi |
|
|
done & |
|
|
|
|
|
# Unset sensitive information once fetchmail is running. |
|
|
unset fetchmail_config |
|
|
unset password |
|
|
|
|
|
trap cleanup INT TERM QUIT |
|
|
wait |
|
|
} |
|
|
|
|
|
main $* |