Sending HTML Emails
Note
Throughout the examples below, mail messages sent using
smtplib
are printed to the screen so we can see what’s going on:
>>> import smtplib
>>> server = smtplib.SMTP('localhost')
>>> server.sendmail('from@example.com', ['to@example.com'], 'The message')
sending to ['to@example.com'] from 'from@example.com' using ('localhost', 25)
The message
Love it or loath it, HTML email is now common and the formatting
opportunities it provides can be used to highlight important parts of
messages. mailinglogger
provides no pre-canned configuration of
this but below is an example of how to configure a
SummarisingLogger
such that important log rows stand out from
the summary.
To start with, we’ll need a template for the summary email that includes any headers or footers requires, along with setting up any CSS to be used in the mail message:
template = """<html><head><style>
tt {
padding: 0;
margin: 0;
color: #444444;
}
tt.WARNING {
color: #CC6600
}
tt.ERROR {
color: #990000
}
tt.CRITICAL {
color: #990000
}
</style></head>
<body><pre>%s</pre></body></html>
"""
To format each message logged as HTML, we need an appropriate formatter:
import logging
formatter = logging.Formatter(
'<tt class="%(levelname)s">%(asctime)s %(levelname)-8s %(message)s</tt>',
'%Y-%m-%d %H:%M:%S'
)
Be careful with the HTML and CSS used in both the template and the formatter. In particular, keep the CSS as simple as possible as CSS support varies across email clients. The above template and formatter are known to generate emails that work with both Thunderbird and Outlook and allow plain-text replies to those emails to be made without lots of annoying whitespace being inserted.
The SummarisingLogger
can now be configured as normal, but making
sure we use the template and formatter specified above, and setting
the content_type
of the email sent to text/html
:
from mailinglogger import SummarisingLogger
handler = SummarisingLogger('from@example.com',['to@example.com'],
template=template,
content_type='text/html')
handler.setFormatter(formatter)
One other thing that needs doing is the addition of a filter to the
handler to make sure that messages containing things that might be
interpretted as HTML are correctly quoted. HTMLFilter
is just such a filter:
from mailinglogger.common import HTMLFilter
handler.addFilter(HTMLFilter())
Now the handler can be added to a logger and used as normal:
>>> logger = logging.getLogger()
>>> logger.addHandler(handler)
>>> logger.setLevel(logging.INFO)
>>> logger.info('An info message')
>>> logger.warning('Malformed html: <a href=">foo &&')
>>> logger.error('An error')
>>> logging.critical('Something critical')
Now when the summary is sent, you can see that it is a correctly formatted HTML message:
>>> logging.shutdown()
sending to ['to@example.com'] from 'from@example.com' using ('localhost', 25)
Content-Transfer-Encoding: 7bit
Content-Type: text/html; charset="us-ascii"
Date: Mon, 01 Jan 2007 10:00:00 -0000
From: from@example.com
MIME-Version: 1.0
Message-ID: ...
Subject: Summary of Log Messages (CRITICAL)
To: to@example.com
X-Log-Level: CRITICAL
X-Mailer: MailingLogger ...
<html><head><style>
tt {
padding: 0;
margin: 0;
color: #444444;
}
tt.WARNING {
color: #CC6600
}
tt.ERROR {
color: #990000
}
tt.CRITICAL {
color: #990000
}
</style></head>
<body><pre><tt class="INFO">2007-01-01 10:00:00 INFO An info message</tt>
<tt class="WARNING">2007-01-01 10:00:00 WARNING Malformed html: <a href=">foo &&</tt>
<tt class="ERROR">2007-01-01 10:00:00 ERROR An error</tt>
<tt class="CRITICAL">2007-01-01 10:00:00 CRITICAL Something critical</tt>
</pre></body></html>