【问题标题】:Is there a way how to configure SMTPHandler in Python to do more advanced stuff?有没有办法在 Python 中配置 SMTPHandler 来做更高级的事情?
【发布时间】:2012-03-03 09:46:33
【问题描述】:

我正在使用标准 SMTPHandler 记录器来捕获我的 Python 异常。 有没有办法将异常名称放入邮件的主题中? 比使用静态主题要好得多,因为 Gmail(而不仅仅是 Gmail)可以根据主题对对话进行分组,所以它可以根据错误类型进行分组。

例如,如果出现 50 个完全相同的错误 + 1 个不同的错误,我会在收件箱中看到两个对话,而不是 1 个包含 51 封电子邮件的组,我可以很容易地忽略单个不同的一个。

另外,有没有办法防止发送仍然相同的错误? 例如。以某种方式定义我自己的函数来决定是否发送电子邮件。该函数将在参数中获取一些基本信息,以便它可以决定(例如缓存并查看是否已经发送了此类问题)。

我浏览了文档,但找不到类似的内容。这似乎很简单。 如果 SMTPHandler 不能做到这一点,那么最好且仍然简单的替代方案是什么?任何简洁的库?

谢谢!

【问题讨论】:

    标签: python exception-handling smtp logging


    【解决方案1】:

    简单灵活的方法是不仅格式化电子邮件内容,还格式化电子邮件主题。这需要子类化logging.handlers.SMTPHandler

    这样,如果您配置的主题中有任何变量引用,它将按需扩展。这是包含测试代码的实现:

        import logging, logging.handlers
        class TitledSMTPHandler(logging.handlers.SMTPHandler):
            def getSubject(self, record):
                formatter = logging.Formatter(fmt=self.subject)
                return formatter.format(record)
    
        # below is to test
        logging.getLogger().addHandler(TitledSMTPHandler(
            ('your.smtp.server',587), 
            'email@from.address', 'email@to.address', 
            '%(asctime)s Error: %(message)s', 
            ('SMTP login', 'SMTP password'), ()
        ))
    
        logging.error("TestError")
    

    用您的替换 SMTP 配置,运行代码,您应该会收到一封电子邮件,其中错误消息在主题中(也在电子邮件正文中)。

    如果您在日志配置文件中定义处理程序,请记住转义参数引用。例如%(asctime)s 应该变成 %%(asctime)s,以防止 configparser 的过早插值 - 但是在 python 3.1 和之前,%% 转义并没有受到影响。


    拜托,如果您一次只问一个问题,您将对其他 Google 员工有很大帮助。您应该开始两个主题,一个叫做“有没有办法将异常名称放入邮件主题?”另一个“有没有办法防止发送仍然相同的错误?”

    我只会回答您的第一个问题,以便专注于一个主题。也许您认为这两个问题可能相互依赖,因此必须一起提出,而它们只是一起出现在您的脑海中。我认为建议您更改问题的标题以强调一个问题而不是说“高级的东西”仍然是可行的。

    如果问题是一个开放主题和/或无法明确定义(例如“我想要高级的东西,其他人都用什么?”),我也建议访问 comp.lang.python

    【讨论】:

    • return formatter.format(record) 应该是 -> return formatter.formatMessage(record),否则你会得到:ValueError: Header values may not contain linefeed or car return characters
    【解决方案2】:

    您只需要创建自己的SMTPHandler 子类。

    对于您的第一个请求:您只需要覆盖 getSubject(record) 方法。至于主题里可以放什么,请在从 logging 导入 Formatter 后查看help(Formatter)

    对于您的第二个请求:您必须覆盖 emit(record) 方法。检查记录并自行决定是否应发送。如果是这样,那么只需调用super(SMTPHandler,self).emit(record) 方法。

    class MySMTPHandler(SMTPHandler):
    
        def getSubject(self, record):
            return "My Error Format from the record dict"
    
        def emit(self, record):
            #check for record in self.already_send or something
            if sendit:
               super(MySMTPHandler,self).emit(record)
    

    【讨论】:

      【解决方案3】:

      例如,您可以继承 SMTPHandler 类并增强或替换其功能

      class A(object):
          def __init__(self):
              self.email = "jjj@jjj.com"
      
          def send_error(self, error):
              send_mail(self.email, error)
      
      class B(A):
          def __init__(self):
              A.__init__(self)
      
          def send_error(self, error):
              if not error.sent:
                  A.send_mail(self, error)
              else:
                  #do nothing
                  pass
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-18
        • 1970-01-01
        • 2022-08-15
        • 2019-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多