You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django招聘者注册接口发验证邮件遇WinError 10060超时错误求助

解决Django发送Gmail邮件时的TimeoutError [WinError 10060]

排查修复步骤

  • 网络连通性验证
    先确认本地能否连接Gmail的SMTP服务器:
    打开PowerShell执行命令:

    Test-NetConnection smtp.gmail.com -Port 587
    

    如果显示tcp测试失败,说明网络层面被拦截,尝试:

    • 临时关闭Windows防火墙或第三方杀毒软件,重试发送邮件。
    • 切换到手机热点网络,排除本地ISP屏蔽端口的问题。
    • 清理本地DNS缓存:执行ipconfig /flushdns后重新尝试连接。
  • Gmail配置检查

    • 重新生成应用密码:登录Google账号进入「安全」-「应用密码」,生成新密码替换EMAIL_HOST_PASSWORD,旧密码可能因账号风控规则失效。
    • 切换SMTP端口协议:把TLS端口587换成SSL端口465,修改settings配置:
      EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
      EMAIL_USE_SSL = True  # 替换原EMAIL_USE_TLS配置
      EMAIL_HOST = 'smtp.gmail.com'
      EMAIL_PORT = 465
      EMAIL_HOST_USER = '你的完整Gmail账号'
      EMAIL_HOST_PASSWORD = '新生成的应用密码'
      
  • Django环境调整

    • 增加超时时间:在settings里添加EMAIL_TIMEOUT = 30,延长SMTP连接的超时阈值,避免网络波动导致超时。
    • 优化错误捕获:在邮件工具类中补充网络异常捕获,方便定位问题:
      import socket
      from django.core.mail import EmailMessage
      from smtplib import SMTPException
      
      class RecruiterUtil:
          @staticmethod
          def send_email(data):
              try:
                  email = EmailMessage(subject=data['email_subject'], body=data['email_body'], to=[data['to_email']])
                  email.send()
              except SMTPException as e:
                  print(f"SMTP发送失败: {e}")
              except socket.error as e:
                  print(f"网络连接错误: {e}")
      

问题详情

开发支持邮箱验证的招聘者注册接口时,突然出现超时错误,此前接口可正常发送验证邮件,未修改任何代码,关闭VPN后问题依旧:

报错回溯

Internal Server Error: /users/register/recruiter/
Traceback (most recent call last):
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\django\views\decorators\csrf.py", line 56, in wrapper_view
    return view_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\django\views\generic\base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\rest_framework\views.py", line 509, in dispatch
    response = self.handle_exception(exc)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\rest_framework\views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\rest_framework\views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\users\views.py", line 184, in post
    RecruiterUtil.send_email(data)
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\users\utils.py", line 21, in send_email
    email.send()
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\django\core\mail\message.py", line 298, in send
    return self.get_connection(fail_silently).send_messages([self])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\django\core\mail\backends\smtp.py", line 127, in send_messages
    new_conn_created = self.open()
                       ^^^^^^^^^^^
  File "C:\Users\hp\Desktop\CS50\afritechjobsite\venv\Lib\site-packages\django\core\mail\backends\smtp.py", line 85, in open
    self.connection = self.connection_class(
                      ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\smtplib.py", line 255, in __init__
    (code, msg) = self.connect(host, port)
                  ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\smtplib.py", line 341, in connect
    self.sock = self._get_socket(host, port, self.timeout)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\smtplib.py", line 312, in _get_socket
    return socket.create_connection((host, port), timeout,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\socket.py", line 851, in create_connection
    raise exceptions[0]
  File "C:\Program Files\Python311\Lib\socket.py", line 836, in create_connection
    sock.connect(sa)
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
[26/Jul/2023 08:12:39] "POST /users/register/recruiter/ HTTP/1.1" 500 20320

相关代码

Views
class RecruiterRegisterView(GenericAPIView):

    serializer_class = RecruiterRegisterSerializer

    def post(self, request):
        user=request.data
        serializer = self.serializer_class(data=user)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        user_data = serializer.data
        # 获取当前用户邮箱
        user = Recruiter.objects.get(email = user_data['email'])
        # 生成用户验证token
        token = RefreshToken.for_user(user).access_token
        # 获取当前站点域名
        current_site = get_current_site(request).domain
        # 反向解析验证邮件URL
        relativeLink = reverse('users:verify_recruiter_email')
        # 拼接完整验证链接
        absoluteurl = 'http://'+ current_site + relativeLink + "?token=" + str(token)
        email_body = 'Hi, ' + user.username + ' 使用下方链接验证你的邮箱 \n' + absoluteurl
        data={'email_body': email_body, 'email_subject': 'Verify your email', 'to_email': user.email,}
        RecruiterUtil.send_email(data)

        return Response(data=user_data, status=status.HTTP_201_CREATED)
Serializer
class RecruiterRegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(max_length=68, min_length=6, write_only=True)

    class Meta:
        model = Recruiter
        fields = ('email', 'username', 'password')

    def validate(self, attrs):
        if not attrs['username'].isalnum():
            raise serializers.ValidationError('用户名只能包含字母和数字')
        return attrs
    
    def create(self, validated_data):
        return Recruiter.objects.create_user(**validated_data)
Util
class RecruiterUtil:
    @staticmethod
    def send_email(data):
        try:
            email = EmailMessage(subject=data['email_subject'], body=data['email_body'], to=[data['to_email']])
            email.send()
        except SMTPException as e:
            print("Email sending failed:", e)
Settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = '@gmail.com'
EMAIL_HOST_PASSWORD = 'cbp'
URL
path("register/recruiter/", RecruiterRegisterView.as_view(), name="recruiter_register"),

注:已使用Gmail自定义应用密码,问题仍存在。


内容的提问来源于stack exchange,提问作者Chuks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 11:23:08