Django集成Mailgun API返回401 Forbidden问题排查求助
问题描述
已安装Django Anymail并将其加入INSTALLED_APPS,尝试通过Mailgun实现密码重置功能,但API和SMTP两种方式均返回401 Forbidden错误。
API方式配置
EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend" ANYMAIL_MAILGUN_API_KEY = config("MAIL_GUN_DOMAIN_API")
已尝试使用账户私钥和域发送密钥作为MAIL_GUN_DOMAIN_API的值,结果一致报错。
SMTP方式配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.mailgun.org' EMAIL_PORT = 465 EMAIL_HOST_USER = config('MAIL_GUN_USERNAME') EMAIL_HOST_PASSWORD = config('MAIL_GUN_SMTP_PASSWORD') EMAIL_USE_TLS = True
使用域登录名作为MAIL_GUN_USERNAME,域密码作为MAIL_GUN_SMTP_PASSWORD,尝试过Mailgun所有端口并切换TLS/SSL,问题未解决。
排查方向与解决方案
一、API方式的常见问题
缺少验证域配置
Anymail需要明确指定Mailgun验证过的域名,否则可能默认使用受限的测试域。补充以下配置:ANYMAIL_MAILGUN_SENDER_DOMAIN = "mg.yourdomain.com" # 替换为你的实际验证域密钥读取或权限问题
- 检查
MAIL_GUN_DOMAIN_API环境变量名是否拼写正确,在Django Shell中执行from django.conf import settings; print(settings.ANYMAIL_MAILGUN_API_KEY)确认值是否正确读取; - 账户私钥(
key-开头)是全局权限密钥,域发送密钥(pubkey-开头)仅对应单个域,确保发送邮箱属于该密钥关联的域; - 确认密钥无多余空格、换行,复制完整。
- 检查
API访问限制
登录Mailgun后台,检查账户安全设置:- 服务器IP是否被加入黑名单;
- 是否开启IP白名单但未添加当前服务器IP。
二、SMTP方式的常见问题
用户名密码错误
Mailgun的SMTP用户名不是域登录名,而是固定格式的postmaster@你的验证域(比如postmaster@mg.yourdomain.com);SMTP密码是在Mailgun域设置的「SMTP Credentials」中生成的专用密码,不是域的登录密码。端口与加密方式不匹配
- 端口465对应
EMAIL_USE_SSL = True,而非EMAIL_USE_TLS = True; - 端口587对应
EMAIL_USE_TLS = True; - 端口25需配合
EMAIL_USE_TLS = True,但多数服务器会封禁该端口。
修正465端口的配置示例:
EMAIL_PORT = 465 EMAIL_USE_SSL = True # 替换原有的EMAIL_USE_TLS- 端口465对应
域名未完成验证
确认你的域名在Mailgun后台完成了DNS验证(MX、TXT记录配置正确),未验证的域只能发送到Mailgun测试收件箱,无法正常对外发送邮件。
三、通用排查步骤
最小化测试邮件发送
在Django Shell中执行以下代码,排除密码重置视图的干扰,查看具体错误详情:from django.core.mail import send_mail send_mail( 'Test Subject', 'Test message', 'sender@yourdomain.com', ['recipient@example.com'], fail_silently=False, )401错误通常会返回更具体的原因(比如"Invalid credentials"或"Domain not verified")。
检查Mailgun后台日志
登录Mailgun后台查看「Logs」板块,里面会记录每一次请求的详细错误信息,帮助定位问题。
内容的提问来源于stack exchange,提问作者badhabit16

