可以为Django发送给管理员的500错误邮件添加头吗?
我正在使用一个第三方服务来发送电子邮件,他们允许我通过给发送的邮件添加一些头部信息来对邮件进行分类。
我想知道,是否可以在异常邮件发送之前添加一个头部信息?或者说,我可以通过在中间件中捕获异常来管理发送邮件,但我该如何生成Django在500错误时发送的那种漂亮的邮件回复呢?
补充说明:我知道如何给邮件添加头部信息,也知道如何通过中间件处理异常。我想了解的是,如何生成Django在发生异常时发送的那封邮件,这样我就可以添加头部信息了。
1 个回答
8
- 创建一个 AdminEmailHandler 的子类(这个类在 django.utils.log 中定义)。
- 相应地配置 日志记录。
下面是 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)
仅供参考:我之前的回答。
- 创建一个自定义中间件:可以参考 CommonMiddleware,具体在 这个链接 中查看(重点看
process_response
部分) - 基于 这个链接 创建一个函数 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)