当 Django 生成 500 错误时,是否可以向管理员发送的电子邮件中添加标题?

5
我正在使用第三方发送电子邮件,他们允许我通过添加邮件头将我的电子邮件分类。
在发送异常电子邮件之前是否可以添加一个邮件头?或者至少,我将通过在中间件中捕获异常来管理发送电子邮件,但是如何生成Django在500时发送给我的漂亮电子邮件响应?
编辑:我知道如何添加电子邮件头,我知道如何通过中间件处理异常。我想知道如何生成与Django在出现异常时发送的相同的电子邮件,以便我可以添加一个邮件头。
1个回答

8
  1. 子类化 AdminEmailHandler(定义在django.utils.log中)。
  2. 相应地配置日志记录

这是AdminEmailHandler的工作原理:

class AdminEmailHandler(logging.Handler):
    """An exception log handler that emails log entries to site admins.

    If the request is passed as the first argument to the log record,
    request data will be provided in the email report.
    """

    def __init__(self, include_html=False):
        logging.Handler.__init__(self)
        self.include_html = include_html

    def emit(self, record):
        try:
            request = record.request
            subject = '%s (%s IP): %s' % (
                record.levelname,
                (request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'),
                record.msg
            )
            filter = get_exception_reporter_filter(request)
            request_repr = filter.get_request_repr(request)
        except:
            subject = '%s: %s' % (
                record.levelname,
                record.getMessage()
            )
            request = None
            request_repr = "Request repr() unavailable."

        if record.exc_info:
            exc_info = record.exc_info
            stack_trace = '\n'.join(traceback.format_exception(*record.exc_info))
        else:
            exc_info = (None, record.getMessage(), None)
            stack_trace = 'No stack trace available'

        message = "%s\n\n%s" % (stack_trace, request_repr)
        reporter = ExceptionReporter(request, is_email=True, *exc_info)
        html_message = self.include_html and reporter.get_traceback_html() or None
        mail.mail_admins(subject, message, fail_silently=True, html_message=html_message)

仅供参考:我的先前回答。

  1. 创建一个自定义中间件:可以从CommonMiddleware中获取灵感,该中间件位于https://code.djangoproject.com/browser/django/trunk/django/middleware/common.py(查看process_response
  2. 基于https://code.djangoproject.com/browser/django/trunk/django/core/mail/message.py创建一个名为send_mail_with_exception_header的函数

这是一个示例:

# Custom middleware

class MyErrorMiddleware(object):
    def process_response(self, request, response):
        if response.status_code == 404:
            domain = request.get_host()
            referer = request.META.get('HTTP_REFERER', None)
            is_internal = _is_internal_request(domain, referer)
            path = request.get_full_path()
                if referer and not _is_ignorable_404(path) and (is_internal or '?' not in referer):
                    ua = request.META.get('HTTP_USER_AGENT', '<none>')
                    ip = request.META.get('REMOTE_ADDR', '<none>')
                    mail_error("Broken %slink on %s" % ((is_internal and 'INTERNAL ' or ''), domain),
                        "Referrer: %s\nRequested URL: %s\nUser agent: %s\nIP address: %s\n" \
                                  % (referer, request.get_full_path(), ua, ip),
                                  fail_silently=True)
                return response

# Custom mail_error function

def mail_error(subject, message, fail_silently=False, connection=None,
                  html_message=None):
    """Sends a message to the managers, as defined by the MANAGERS setting."""
    if not settings.MANAGERS:
        return

    # put your extra headers here
    mail = EmailMultiAlternatives(u'%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject),
                message, settings.SERVER_EMAIL, [a[1] for a in settings.MANAGERS],
                connection=connection, header={})
    mail
    if html_message:
        mail.attach_alternative(html_message, 'text/html')
    mail.send(fail_silently=fail_silently)

我理解这个问题,但是我该如何生成通常在管理员异常邮件中发送的漂亮数据呢? - MattoTodd
抱歉。我使用了 AdminEmailHandler 更新了我的答案,这展示了 Django 是如何做的。 - charlax
我目前正在运行django1.2,该版本没有django.utils.log模块,请问您知道在哪里可以找到该模块吗? - MattoTodd
它在django/core/handlers/base.py文件中。 - charlax
我认为我需要子类化BaseHandler来实现这个,那么我应该在哪里告诉Django使用我的子类? - MattoTodd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接