Skip to content

Instantly share code, notes, and snippets.



Last active Apr 2, 2017
What would you like to do?
Originally written for Mandrill (screw them), this script can send an email alert, for example, when a remote job fails or some other unexpected event happens: I'm using it on my QNAP TS-212 NAS to alert me about backup jobs failures and other abnormal events.
# Failure reporter, logs to a well-known log file failure messages
# Created 2014-04-30, M. Massenzio (
declare -r LOGFILE="/var/log/fail.log"
declare -r ALERT_ICON="/usr/share/icons/ubudao-style/actions/dialog-warning.png"
declare -r ERROR_ICON="/usr/share/icons/ubudao-style/actions/stock_dialog-error.png"
echo "[ERROR] `date` -- $1" >> ${LOGFILE}
notify-send -i ${ALERT_ICON} "Failure Alert" "$1" -f ${HOME}/.yagmail -m "$1" -s "Failure Alert from `hostname`" \
-d >> ${LOGFILE} 2>&1
if [ $? != 0 ]; then
echo "[ERROR] `date` -- Failed to send email alert" >> ${LOGFILE}
notify-send -i ${ERROR_ICON} "Cannot Send Email" "Failed to send email alert, see log at ${LOGFILE}"
#!/usr/bin/env python
# Copyright (c) 2016. All rights reserved.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.
# Created by M. Massenzio (, 2016-05-14
import argparse
import logging
import socket
# See:
import yagmail
FORMAT = '%(asctime)-15s [%(levelname)s] %(message)s'
DATE_FMT = '%m/%d/%Y %H:%M:%S'
def parse_args():
""" Parse command line arguments and returns a configuration object
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--api-key-file', required=True,
help="The file containing the API key")
parser.add_argument('-m', dest='msg', required=True, help="The body of the message")
parser.add_argument('-d', dest='dest', help="The recipient of the email")
parser.add_argument('-s', dest='subject', help='The subject for the email',
default='Alert from {hostname}'.format(hostname=socket.gethostname()))
parser.add_argument('-v', dest='verbose', action='store_true', help='Enables debug logging')
return parser.parse_args()
def post_mail(to, subj, msg, **kwargs):
""" Sends the ``msg`` via email to the specified recipient.
@param to: the recipient for the message
@type to: str
@param subj: the subject for the email
@type subj: str
@param msg: the body of the message, in plain text
@type msg: str
contents = """<h3>Automated Alert</h3>
<h6>Sent via yagmail, using &copy; 2016 M. Massenzio, all rights reserved.<br>
with yagmail.SMTP(kwargs.get('username'), kwargs.get('api_key')) as yag:
yag.send(to, subj, contents)'Message "{subj}" sent to {to}'.format(to=to, subj=subj))
def read_api_key(filename):
with open(filename, 'r') as key_file:
username = key_file.readline().rstrip('\n')
api_key = key_file.readline().rstrip('\n')
return {'username': username, 'api_key': api_key}
def main():
config = parse_args()
loglevel = logging.DEBUG if config.verbose else logging.INFO
logging.basicConfig(format=FORMAT, datefmt=DATE_FMT, level=loglevel)'Mailer Auto Script starting...')
kwargs = read_api_key(config.api_key_file)
except Exception as ex:
logging.error("Could not read the API Key ({}), aborting", ex)
logging.debug('API key retrieved')
post_mail(to=config.dest, msg=config.msg, subj=config.subject, **kwargs)
if __name__ == "__main__":

Email Alerts via Yagmail API

Author: Marco Massenzio
Date: 2016-05-14
Version: 0.2


This script sends an email alert to the specified recipient.


[~] # ./ -f ./.secret -m "This is a test" -d -s "Test Test Test" -v

For a full explanation of the command-line options run with --help.

Note with the --verbose option specified, the API key will be logged to stdout (typically, console): don't do this unless you run this in a trusted environment.

For more details, please see my blog entry or the yagmail documentation

#!/usr/bin/env python
# Checks for remaining space in /boot and alerts if above a threshold.
# The threshold above which to alert can be passed in as the first CLI argument,
# or the default value will be used.
# Created by M. Massenzio, 2017-03-29
from sh import df, alert
import sys
threshold = 70
if len(sys.argv) > 1:
threshold = int(sys.argv[1])
alert("Program option should be a numeric value (threshold % above which to alert). "
"Was: {}".format(sys.argv[1]))
disk_space = df("-h")
for line in disk_space.split('\n'):
if line.endswith('/boot'):
items = line.split()
use_pct = items[-2]
assert use_pct.endswith('%')
used_space = int(use_pct[:-1])
if used_space > threshold:
alert("/boot is running out of space: {} used`({} bytes left)".format(use_pct, items[-3]))
# If we got here, we didn't find the /boot partition mount.
alert("Could not find the /boot partition, running `df`:\n{}".format(disk_space))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment