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

Django密码重置邮件仅本地生效,部署后无法发送求助

问题解决:跨环境密码重置邮件发送失败

问题原因分析

核心问题是邮件中的重置链接触发了邮件服务商的反垃圾机制,或动态生成的链接不符合邮件服务器安全规则:

  • request.build_absolute_uri依赖请求的Host头,通过Nginx/VPS访问时,可能生成内网IP或未备案域名的链接,被判定为恶意内容拦截。
  • 你传递了空的纯文本邮件内容,部分严格的邮件服务器会拒收仅含HTML格式的邮件。

修复方案

1. 替换动态链接生成方式,使用固定公网地址

不依赖请求对象生成链接,直接从配置文件读取公网访问地址,避免生成不可访问的内网链接:

首先在settings.py添加配置:

# settings.py
BASE_URL = "https://your-public-domain.com"  # 替换为你的公网域名或VPS公网IP

修改视图中的链接生成代码:

def password_reset_request(request):
    if request.method == "POST":
        form = PasswordResetRequestForm(request.POST)
        if form.is_valid():
            cpf = form.cleaned_data['cpf']
            user = CustomUser.objects.get(cpf=cpf)
            
            token = default_token_generator.make_token(user)
            uid = urlsafe_base64_encode(force_bytes(user.pk))
            
            # 手动构建重置链接,替代request.build_absolute_uri
            reset_path = reverse('password_reset_confirm', kwargs={'uidb64': uid, 'token': token})
            reset_link = f"{settings.BASE_URL}{reset_path}"  # 使用配置的公网地址
            
            # 其余代码保持不变...

2. 补充纯文本版本的邮件内容

空纯文本内容会被部分邮件服务器判定为异常,添加纯文本版本:

try:
    # 编写纯文本邮件内容
    plain_text_content = f"""Hello {user.username},
    
We received a request to reset your account password. Use the link below to set a new password:
{reset_link}

This link is valid for 24 hours.

If you didn't request this, you can safely ignore this email.

Best regards,
CIGMA Team"""

    send_mail(
        theme,
        plain_text_content,  # 替换原空字符串位置
        settings.DEFAULT_FROM_EMAIL,
        [user.email],
        html_message=email_content,
        fail_silently=False,
    )
    print("Email sent successfully!")
except Exception as e:
    print(f"Email sending failed: {e}")

3. 配置Nginx正确传递请求头(若使用反向代理)

如果用Nginx部署,需确保传递正确的Host头和协议信息,避免生成错误链接:

server {
    # 其他配置...
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;  # 传递http/https协议
    }
}

同时在settings.py添加:

USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')  # 启用HTTPS时添加

验证步骤

  1. 用公网IP/域名访问系统,发起密码重置请求
  2. 查看控制台输出的reset_link是否为正确的公网地址
  3. 检查收件箱(含垃圾邮件文件夹)是否收到邮件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 09:06:17