Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python logging: email entire log file as attachment when level >= ERROR

My logging system has a few handlers, log file (INFO), an email handler (>ERROR), and a stream handler for optional debugging. When an error/exception/critical message occurs, I want the email handler to attach the log file from the file handler to the error email.

import logging

def initialize_logging():
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    file_handler = createFileHandler()
    file_handler.setLevel(logging.INFO)
    logger.addHandler(file_handler)

    email_handler = createEmailHandler(file_handler.baseFilename)
    email_handler.setLevel(logging.ERROR)
    logger.addHandler(email_handler)

I found this example, but it's basically writing the handler from scratch. https://gist.github.com/LavinJ/238ccb229ac594a50b0a

I'd love if there was a simpler means of modifying the existing SMTPHandler

like image 779
Matthew Levine Avatar asked Sep 19 '25 12:09

Matthew Levine


1 Answers

Looking at the source, it appears this is the easiest way to do it. Attaching the log file alone works well with this handler and the above code

class SMTPAttachmentHandler(logging.handlers.SMTPHandler):
    def __init__(self, mailhost, fromaddr, toaddrs, subject, credentials=None,
                 secure=None, attachment=None):
        super(SMTPAttachmentHandler, self).__init__(mailhost, fromaddr, toaddrs, subject,
                                                    credentials, secure)
        self.attachment = attachment

    def emit(self, record):
        if self.attachment is None or not os.path.isfile(self.attachment):
            return super(SMTPAttachmentHandler, self).emit(record)
        try:
            import smtplib
            from email.utils import formatdate
            from email.mime.text import MIMEText
            from email.mime.multipart import MIMEMultipart

            port = self.mailport
            if not port:
                port = smtplib.SMTP_PORT
            smtp = smtplib.SMTP(self.mailhost, port, timeout=self._timeout)

            msg = MIMEMultipart()
            msg['From'] = self.fromaddr
            msg['To'] = ",".join(self.toaddrs)
            msg['Date'] = formatdate()
            msg['Subject'] = self.getSubject(record)
            msg.attach(MIMEText(self.format(record).encode('utf-8'), 'html', 'utf-8'))

            dispo = 'attachment; filename="%s"' % os.path.basename(self.attachment)
            with open(self.attachment, "rb") as fd:
                attachment = MIMEText(fd.read())
                attachment.add_header("Content-Disposition", "attachment",
                                      filename=os.path.basename(self.attachment))
                msg.attach(attachment)

            if self.username:
                if self.secure is not None:
                    smtp.ehlo()
                    smtp.starttls(*self.secure)
                    smtp.ehlo()
                smtp.login(self.username, self.password)
            smtp.sendmail(self.fromaddr, self.toaddrs, msg.as_string())
            smtp.quit()
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            self.handleError(record)
like image 78
Matthew Levine Avatar answered Sep 22 '25 03:09

Matthew Levine