部署到PythonAnywhere后Django密码重置功能出现ConnectionRefusedError
密码重置功能在开发环境可正常发送重置邮件,但部署到PythonAnywhere后,访问/reset_password时抛出ConnectionRefusedError,具体报错如下:
ConnectionRefusedError at /reset_password
[Errno 111] Connection refused
Request Method: POST
Django Version: 4.1
Exception Type: ConnectionRefusedError
Exception Value:
[Errno 111] Connection refused
Exception Location: /usr/local/lib/python3.10/socket.py, line 833, in create_connection
Raised during: django.contrib.auth.views.PasswordResetView
Python Executable: /usr/local/bin/uwsgi
Python Version: 3.10.5
Python Path:
['/var/www',
'.',
'',
'/var/www',
'/usr/local/lib/python310.zip',
'/usr/local/lib/python3.10',
'/usr/local/lib/python3.10/lib-dynload',
'/home/gridsquid/.virtualenvs/myvirtualenv/lib/python3.10/site-packages',
'/home/gridsquid/gridsquid']
Server time: Sat, 12 Nov 2022 16:45:30 +0000
已确认用户有效且邮箱可用,相关配置如下:
settings.py 邮件配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.sendgrid.net' EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = 'apikey' # Name for all the SenGrid accounts EMAIL_HOST_PASSWORD = os.getenv('SENDGRID_API_KEY')
urls.py 路由配置
path("reset_password", auth_views.PasswordResetView.as_view(template_name="gridsquid/reset-password.html"), name="password_reset"), path("reset_password_sent", auth_views.PasswordResetDoneView.as_view(template_name="gridsquid/reset-password-sent.html"), name="password_reset_done"), path("reset/<uidb64>/<token>", auth_views.PasswordResetConfirmView.as_view(template_name="gridsquid/reset.html"), name="password_reset_confirm"), path("reset_password_complete", auth_views.PasswordResetCompleteView.as_view(template_name="gridsquid/reset-password-complete.html"), name="password_reset_complete"),
开发环境一切正常,求排查方向。
PythonAnywhere端口限制:这是最常见原因,PythonAnywhere默认禁止直接访问外部SMTP端口(587/465)。有两种解决方式:
- 改用PythonAnywhere内部邮件中继服务,修改settings.py配置:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.pythonanywhere.com' EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = '你的PythonAnywhere用户名' EMAIL_HOST_PASSWORD = '你的PythonAnywhere账户密码' - 若坚持用SendGrid,需在PythonAnywhere后台提交外部服务白名单申请,解锁
smtp.sendgrid.net的587端口,但流程较慢,优先选第一种方案。
- 改用PythonAnywhere内部邮件中继服务,修改settings.py配置:
环境变量未加载:检查PythonAnywhere上的
SENDGRID_API_KEY环境变量是否配置正确。可在控制台执行echo $SENDGRID_API_KEY验证,或临时在settings.py硬编码API密钥测试(测试后务必删除),确认是否因变量未读取导致认证失败被拒。SendGrid账户问题:确认SendGrid的API密钥是否有邮件发送权限,后台是否完成发件人域名认证(DKIM/SPF),未完成认证可能导致SendGrid拒绝连接。同时检查账户是否存在额度耗尽或被封禁情况。
网络策略排查:虽概率较低,可确认SendGrid的IP是否被PythonAnywhere防火墙拦截,但优先排查前三点即可。
内容的提问来源于stack exchange,提问作者ragmats

