Django出现500错误时未向管理员发邮件但send_mail功能正常
问题原因与排查方案
最常见诱因:SERVER_EMAIL未完成SendGrid发件人认证
你手动调用send_mail时一般会显式指定已经过SendGrid验证的发件人地址,而Django错误告警邮件默认使用SERVER_EMAIL作为发件人。如果该地址对应的域名没有在SendGrid后台完成SPF、DKIM配置,或者单个发件人未通过验证,SendGrid会直接拒绝发信请求,且不会在活动日志中留下记录。你可以先核对SERVER_EMAIL的值和你send_mail调用时传入的发件人是否完全一致。错误邮件发送异常被默认静默吞服
Django内置的AdminEmailHandler在发送告警邮件失败时,默认不会抛出异常也不会输出日志,你看不到具体的失败原因。可以临时添加以下LOGGING配置暴露错误细节:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django.request': { 'handlers': ['console'], 'level': 'ERROR', 'propagate': True, }, 'django.core.mail': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': True, }, }, }
添加配置后再次触发500错误,即可在控制台看到发送告警邮件时的具体报错,比如发件人被拒、权限不足等。
SendGrid API Key权限范围不匹配
即使手动发信正常,也有可能你的API Key仅开放了send_mail场景下的权限,没有开放使用SERVER_EMAIL作为发件人的发信权限。可以去SendGrid后台核对API Key的权限配置,确认允许使用SERVER_EMAIL发信。异常被过滤或告警逻辑被接管
Django默认不会为Http404、PermissionDenied这类异常发送告警邮件,你测试时需要触发未捕获的500级别的异常。另外如果项目中接入了第三方异常监控组件,也可能会接管Django的默认错误告警逻辑,导致邮件未被发送。
内容的提问来源于stack exchange,提问作者Kevin Renskers

