Commit d43b7578 authored by Jonathan Michalon's avatar Jonathan Michalon

Implement mail notifications of state changes

This implementation uses smtplib so that mails are sent via SMTP, even
when the mail daemon could be local, to be as flexible as possible.
parent e90341af
......@@ -5,11 +5,21 @@ from lib.checks import *
# Each check may then individually be configured to run every N * tick
base_tick = 60
# Email addresses to send to when an alert is triggered
emails = ['john@localhost']
mail = Host(ipv4='', ipv6='::1')
web = Host(ipv4='', ipv6='::42')
# Subject template for state change email notifications
# available substitutions:
# - state ("Problem" or "OK")
# - check (check's name, like "CheckDNSRec6")
# - dest (the target of the check ie. an IP or a Host's 'name' parameter)
subject_tpl = "[ARN] {state}: {check} on {dest}"
mail = Host(ipv4='', ipv6='::1', name='LXC mail')
web = Host(ipv4='', ipv6='::42', name='Bad IPs')
alsace = Host(ipv4='', ipv6='::1')
recursif = Host(ipv4='', ipv6='2a00:5881:8100:1000::3')
recursif = Host(ipv4='', ipv6='2a00:5881:8100:1000::31', name='DNS récursif')
checks = Checks()
checks.add(CheckDNSZone, ["", ""], ip_version=4)
from lib.subprocess_compat import TimeoutExpired, Popen, PIPE
import re
import lib.mails as mails
class Host(object):
......@@ -50,7 +51,10 @@ class Check(object):
self.retry_count = min(self.retry_count + 1, self.retry)
if self.retry_count == self.retry or immediate:
self.ok = False
if not self.ok:
self.ok = True
self.retry_count = 0
import socket
import smtplib
from email.mime.text import MIMEText
from collections import defaultdict
from sys import stderr
import email.charset
# Switch to quoted-printable so that we don't get something completely
# unreadable for non-ASCII chars if we have to look at raw email
email.charset.add_charset('utf-8', email.charset.QP, email.charset.QP, 'utf-8')
def send_email_for_check(check):
from config import emails, subject_tpl
addr_from = "Picomon <picomon@%s>" % socket.getfqdn()
# ensure we do not traceback with unknown substitutions
subject = subject_tpl.format_map(
defaultdict(lambda: "<no substitution>",
state='OK' if check.ok else 'Problem',
msg_text = ''
if check.ok:
msg_text = "FYI last error for this check was:\n"
msg_text += ("Check %s failed:\n%s" %
(str(check), check.errmsg.strip()))
# encode / decode is a fix that didn't make it into Debian Wheezy
msg = MIMEText(msg_text.encode('utf-8').decode('latin1'), 'plain', 'utf-8')
msg['Subject'] = subject
msg['From'] = addr_from
msg['To'] = ", ".join(emails)
server = smtplib.SMTP('localhost')
# server.set_debuglevel(1)
server.sendmail(addr_from, emails, msg.as_string())
except Exception as e:
print("Couldn't send email: %s" % str(e), file=stderr)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment