Django 5 + Python 3.12.1 中使用send_mail报SSL证书验证错误(IP地址不匹配)的求助
我现在有一个基于Django 3.2.6和Python 3.9.6运行正常的应用,正在尝试升级到Django 5和Python 3.12.1。到目前为止,我已经排查并修复了很多由变更和弃用导致的问题,但这个问题已经困扰我好几天了。
在新环境中使用Django的send_mail()时,会抛出错误:
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for '40.99.213.34'. (_ssl.c:1000)
注意:我必须使用IPv4地址来建立连接,因为在我的Linux服务器上使用实际主机名时,会等待大约2分钟,直到默认的IPv6地址超时后才回退到IPv4。而在我的Win10开发环境中使用主机名字符串则完全正常。
以下是我的代码片段:
settings.py
import socket EMAIL_HOST = socket.gethostbyname('smtp.office365.com') # 解析为IPv4地址 EMAIL_PORT = 587 EMAIL_HOST_USER = 'name@company.co.uk' EMAIL_HOST_PASSWORD = 'password' EMAIL_USE_TLS = True
views.py
send_mail('Subject','Message Body','name@company.co.uk',['name@gmail.com'])
我在网上搜了好几个小时后,从Stack Overflow找到一个方法,在设置中添加了以下代码,但错误变成了更让人摸不着头脑的内容:[SSL] PEM Lib (_ssl.c:3917)
import certifi EMAIL_SSL_CERTFILE = certifi.where()
很明显,SSL连接的方式发生了一些变化,可能是Python 3.12.1在证书验证的要求上和3.9.6不一样了。我已经花了大量时间徒劳地寻找解决方案,甚至查看了Django的SMTP模块源码、Python的SSL模块源码,绝望之下还看了CPython的_ssl模块,但还是搞不清楚该怎么解决这个问题。如果有人能给我指个方向,我会非常感激。
备注:内容来源于stack exchange,提问作者yengip

