Celery异步发送注册邮件时出现DNS解析错误求助
问题:Celery异步邮件注册功能DNS解析错误排查
更换电脑后,使用Celery实现的异步邮件注册功能触发请求时出现DNS解析错误,Celery控制台可正常识别任务,但执行时抛出如下异常:
Traceback (most recent call last): File "d:\python3\lib\site-packages\dns\resolver.py", line 982, in nameservers raise NotImplementedError NotImplementedError During handling of the above exception, another exception occurred: Traceback (most recent call last): File "d:\python3\lib\site-packages\celery\app\trace.py", line 451, in trace_task R = retval = fun(*args, **kwargs) File "d:\python3\lib\site-packages\celery\app\trace.py", line 734, in __protected_call__ return self.run(*args, **kwargs) File "E:\Exploit_blog\blog_index_html\tasks.py", line 9, in send_email send_mail( File "d:\python3\lib\site-packages\django\core\mail\__init__.py", line 61, in send_mail return mail.send() File "d:\python3\lib\site-packages\django\core\mail\message.py", line 284, in send return self.get_connection(fail_silently).send_messages([self]) File "d:\python3\lib\site-packages\django\core\mail\backends\smtp.py", line 102, in send_messages new_conn_created = self.open() File "d:\python3\lib\site-packages\django\core\mail\backends\smtp.py", line 62, in open self.connection = self.connection_class(self.host, self.port, **connection_params) File "d:\python3\lib\smtplib.py", line 1034, in __init__ SMTP.__init__(self, host, port, local_hostname, timeout, File "d:\python3\lib\smtplib.py", line 253, in __init__ (code, msg) = self.connect(host, port) File "d:\python3\lib\smtplib.py", line 339, in connect self.sock = self._get_socket(host, port, self.timeout) File "d:\python3\lib\smtplib.py", line 1040, in _get_socket new_socket = super()._get_socket(host, port, timeout) File "d:\python3\lib\smtplib.py", line 310, in _get_socket return socket.create_connection((host, port), timeout, File "d:\python3\lib\site-packages\eventlet\green\socket.py", line 44, in create_connection for res in getaddrinfo(host, port, 0, SOCK_STREAM): File "d:\python3\lib\site-packages\eventlet\support\greendns.py", line 543, in getaddrinfo qname, addrs = _getaddrinfo_lookup(host, family, flags) File "d:\python3\lib\site-packages\eventlet\support\greendns.py", line 505, in _getaddrinfo_lookup answer = resolve(host, qfamily, False, use_network=use_network) File "d:\python3\lib\site-packages\eventlet\support\greendns.py", line 450, in resolve return _proxy.query(name, rdtype, raise_on_no_answer=raises, File "d:\python3\lib\site-packages\eventlet\support\greendns.py", line 394, in query step(self._resolver.query, qname, rdtype, rdclass, tcp, source, raise_on_no_answer=False) File "d:\python3\lib\site-packages\eventlet\support\greendns.py", line 334, in _resolver self.clear() File "d:\python3\lib\site-packages\eventlet\support\greendns.py", line 342, in clear self._resolver = dns.resolver.Resolver(filename=self._filename) File "d:\python3\lib\site-packages\dns\resolver.py", line 756, in __init__ self.read_registry() File "d:\python3\lib\site-packages\dns\resolver.py", line 858, in read_registry self.nameservers = info.nameservers File "d:\python3\lib\site-packages\dns\resolver.py", line 984, in nameservers raise ValueError(f'nameserver {nameserver} is not an ' ValueError: nameserver ; is not an IP address or valid https URL
任务代码
from django.core.mail import send_mail from celery import shared_task # 发送邮件验证码,使用task进行异步处理,获取从视图层获取来的值,然后发送到用户邮箱中 @shared_task def send_email(request, rand_str): send_mail( subject='验证码', message='你的验证码为:' + rand_str + '请不要将你的验证码告诉其他人', from_email='TEXT', recipient_list=[request], fail_silently=False ) return (request, rand_str)
Django邮件配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_USE_TLS = False EMAIL_USE_SSL = True EMAIL_HOST = 'smtp.gmail.com' EMAIL_PORT = 587 EMAIL_HOST_USER = 'xxx' EMAIL_HOST_PASSWORD = 'xxx'
错误原因分析
核心报错ValueError: nameserver ; is not an IP address or valid https URL表明:系统在读取DNS服务器配置时,错误将分号;识别为DNS地址,导致无法解析SMTP服务器域名smtp.gmail.com。
更换电脑后出现该问题,根源在于新电脑的DNS配置存在格式错误:
- Windows系统的DNS注册表或网络配置中存在多余的分号符号
- Eventlet的
greendns模块读取系统DNS配置时,误将分号解析为有效DNS服务器地址
此外,邮件配置中EMAIL_USE_SSL = True与EMAIL_PORT = 587不匹配,Gmail的SSL对应端口为465,TLS对应587,该配置可能加剧连接失败问题。
解决办法
1. 修复系统DNS配置
检查并修正Windows网络DNS设置:
- 打开「网络和共享中心」→ 更改适配器设置 → 右键当前网络连接 → 属性 → 双击「Internet协议版本4 (TCP/IPv4)」
- 确保DNS服务器地址为有效IP(如
8.8.8.8、114.114.114.114),无多余符号(如分号) - 若使用自动获取DNS,可临时切换为手动指定公共DNS测试
2. 强制指定DNS给Eventlet
在Celery启动前,手动设置DNS服务器,避免读取系统错误配置:
import eventlet eventlet.support.greendns.set_default_resolver('8.8.8.8')
3. 修正邮件加密方式与端口匹配
调整Gmail邮件配置,确保加密方式与端口对应:
# 方案1:使用TLS EMAIL_USE_TLS = True EMAIL_USE_SSL = False EMAIL_PORT = 587 # 方案2:使用SSL EMAIL_USE_TLS = False EMAIL_USE_SSL = True EMAIL_PORT = 465
4. 绕过Eventlet的DNS解析
若上述方法无效,禁用Eventlet的greendns,改用系统原生DNS解析:
import eventlet eventlet.monkey_patch(dns=False)
内容的提问来源于stack exchange,提问作者Exploit
相关产品推荐
相关产品推荐

