Created
August 16, 2018 08:44
-
-
Save eigengrau/5d03c2878e4e6f3bf9c5f95832358aa1 to your computer and use it in GitHub Desktop.
E-mail notifications using IMAP IDLE (no polling)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 $* |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment