Django send_mail调用失败但smtplib正常的问题排查
问题:Django send_mail连接Gmail SMTP时触发SMTPServerDisconnected错误
使用Django的send_mail函数,通过开启双重验证的Gmail账户(使用应用专用密码)发送邮件时,出现smtplib.SMTPServerDisconnected: Connection unexpectedly closed错误,但直接用smtplib编写的脚本却能正常发送邮件。
排查过程与问题根源
- 编辑1:移除
django/core/mail/backends/smtp.py第81行中传递给self.connection_class的**connection_params参数后,send_mail可正常工作。 - 编辑2:将手动smtplib脚本中的
smtpObj = smtplib.SMTP('smtp-relay.gmail.com', 587)改为smtpObj = smtplib.SMTP('smtp-relay.gmail.com', 587, local_hostname='localhost')后,会触发相同的连接断开错误。 - 编辑3:问题核心在于
django/core/mail/backends/smtp.py第69行,代码硬编码将connection_params赋值为{"local_hostname": DNS_NAME.get_fqdn()},且未提供自定义或清空该参数的逻辑。而DNS_NAME.get_fqdn()调用socket.getfqdn()返回未完全限定的localhost,smtplib会将其替换为127.0.0.1,这属于Django的一处Bug。
相关代码片段
settings.py
... EMAIL_HOST = 'smtp-relay.gmail.com' EMAIL_HOST_USER = "myemail@costumgmail.com" EMAIL_HOST_PASSWORD = "mypass" EMAIL_PORT = 587 EMAIL_USE_TLS = True ...
djangotest.py
from django.core.mail import send_mail send_mail('Django mail', 'This e-mail was sent with Django.', "myemail@costumgmail.com" , ['some.other@mail.com'], fail_silently=False) # 触发错误:smtplib.SMTPServerDisconnected: Connection unexpectedly closed
smtplibtest.py
from email.message import EmailMessage import smtplib email_sender = "myemail@costumgmail.com" email_password="mypass" email_reciever ='some.other@mail.com' subject = "test" body = "test" em = EmailMessage() em['sender'] = email_sender em['to'] = email_reciever em['subject'] = subject em.set_content(body) smtpObj = smtplib.SMTP('smtp-relay.gmail.com', 587) smtpObj.ehlo() # 返回:(250, b'smtp-relay.gmail.com at your service, [188.26.233.149]\nSIZE 157286400\n8BITMIME\nSTARTTLS\nENHANCEDSTATUSCODES\nPIPELINING\nCHUNKING\nSMTPUTF8') smtpObj.starttls() # 返回:(220, b'2.0.0 Ready to start TLS') smtpObj.login(email_sender, email_password) # 返回:(235, b'2.7.0 Accepted') smtpObj.sendmail(email_sender, email_reciever, em.as_string()) # 发送成功
Django报错栈
Traceback (most recent call last): File "<console>", line 1, in <module> File "/root/.virtualenvs/myenv/lib/python3.10/site-packages/django/core/mail/__init__.py", line 87, in send_mail return mail.send() File "/root/.virtualenvs/myenv/lib/python3.10/site-packages/django/core/mail/message.py", line 298, in send return self.get_connection(fail_silently).send_messages([self]) File "/root/.virtualenvs/myenv/lib/python3.10/site-packages/django/core/mail/backends/smtp.py", line 124, in send_messages new_conn_created = self.open() File "/root/.virtualenvs/myenv/lib/python3.10/site-packages/django/core/mail/backends/smtp.py", line 87, in open self.connection.starttls( File "/usr/lib/python3.10/smtplib.py", line 769, in starttls self.ehlo_or_helo_if_needed() File "/usr/lib/python3.10/smtplib.py", line 612, in ehlo_or_helo_if_needed (code, resp) = self.helo() File "/usr/lib/python3.10/smtplib.py", line 441, in helo (code, msg) = self.getreply() File "/usr/lib/python3.10/smtplib.py", line 405, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") smtplib.SMTPServerDisconnected: Connection unexpectedly closed
内容的提问来源于stack exchange,提问作者Petru Tanas
相关产品推荐
相关产品推荐

