Django部署后调用Sendgrid SMTP发邮件报SMTPServerDisconnected错误
问题根因
shell环境能正常发信说明服务器本身的网络、邮件配置是正确的,仅API调用报错的核心原因是gunicorn进程的运行上下文和shell上下文存在差异,导致SMTP连接建立失败,常见的触发原因包括SELinux限制、环境变量差异、进程fork导致的连接句柄失效三类。
解决方案
按优先级依次排查:
- 先验证gunicorn进程的SMTP连通性,在API视图中加入以下测试代码,确认gunicorn进程能否正常连接Sendgrid SMTP服务器:
import socket # 把该函数返回值加入接口响应或日志输出 def check_smtp_conn(): try: sock = socket.create_connection(("smtp.sendgrid.net", 587), timeout=10) sock.close() return "SMTP端口连通正常" except Exception as e: return f"SMTP端口连通失败:{repr(e)}"
- 排查SELinux限制:如果是CentOS/RHEL系列服务器,先临时关闭SELinux验证:
setenforce 0 systemctl restart gunicorn # 替换成你实际的gunicorn服务名
如果测试接口恢复正常,执行以下命令永久放行Web进程的邮件发送权限:
setsebool -P httpd_can_sendmail 1 setsebool -P httpd_can_network_connect 1
- 替换SMTP连接方案,改用465端口SSL连接,避免TLS握手异常:
修改settings.py中的邮件配置:
#AUTO SEND EMAIL EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_USE_SSL = True EMAIL_HOST = 'smtp.sendgrid.net' EMAIL_HOST_USER = 'apikey' EMAIL_HOST_PASSWORD = 'the_sendgrid_key' EMAIL_PORT = 465
- 排查gunicorn进程fork导致的连接失效问题:修改gunicorn启动参数,添加
--preload参数,同时临时将worker数调整为1测试,确认是否是多worker fork继承了失效的连接句柄导致的问题。 - 校验运行时配置:在视图中打印Django运行时的邮件配置,确认gunicorn加载的配置和本地/shell环境一致,避免加载了错误的配置文件:
from django.conf import settings # 输出到日志或接口响应校验 email_config = { "backend": settings.EMAIL_BACKEND, "host": settings.EMAIL_HOST, "port": settings.EMAIL_PORT, "use_tls": settings.EMAIL_USE_TLS, "use_ssl": settings.EMAIL_USE_SSL, }
内容的提问来源于stack exchange,提问作者Linh Nguyen
相关产品推荐
相关产品推荐

