This is an old question but I'm leaving an answer here in case anyone shows up like me.
The answer is given here and I modified it for TLS usage.
import logging
import logging.handlers as handlers
#mail sender informations
mail_host = 'smtp-legacy.office365.com'
mail_port = 587
mail_from = 'email_address@g.com'
mail_password = 'password'
mail_to = ['receiver_1','receiver_2'] #seperate it with comma for other addresses
mail_subject = 'Test Logging email from Python logging module (buffering)'
#Setting up a buffered email logger class to send emails as bulk. capacity variable defines the bulk size
class BufferingSMTPHandler(logging.handlers.BufferingHandler):
def __init__(self, mailhost, mailport, fromaddr, mailpwd, toaddrs, subject, capacity):
logging.handlers.BufferingHandler.__init__(self, capacity)
self.mailhost = mailhost
self.mailport = mailport
self.fromaddr = fromaddr
self.toaddrs = toaddrs
self.subject = subject
self.password = mailpwd
self.setFormatter(formatter)
#this is called by the smtphandler of the logging itself, below is just the setup of the mail and sending it
def flush(self):
if len(self.buffer) > 0:
try:
import smtplib, ssl
port = self.mailport
if not port:
port = smtplib.SMTP_PORT
context = ssl.create_default_context()
smtp = smtplib.SMTP(self.mailhost, port)
smtp.starttls(context=context)
msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (self.fromaddr, ','.join(self.toaddrs), self.subject)
for record in self.buffer:
s = self.format(record)
print (s)
msg = msg + s + "\r\n"
smtp.login(self.fromaddr, self.password)
smtp.sendmail(self.fromaddr, self.toaddrs, msg)
smtp.quit()
except:
self.handleError(None) # no particular record
self.buffer = []
Usage is like below
#logging obj creation and set a level to keep in the server main log file.
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logMailHandler = BufferingSMTPHandler(mail_host, mail_port, mail_from, mail_password, mail_to, mail_subject, 2)
logger.addHandler(logMailHandler)
logger.critical('My critical error')
logger.critical('My critical error2') # in the second call it'll send the email