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

Django 3.1.1 auth模块:如何触发密码重置邮件生成并成功发送

解决密码重置邮件发送问题及调用生成邮件函数的方法

一、先配置Django邮件后端(必做)

要让Django能发送邮件,第一步得在settings.py里配置邮件服务。以常用的SMTP为例:

# settings.py
# 邮件后端配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# 替换为你的邮件服务商SMTP地址,比如QQ邮箱是smtp.qq.com,Gmail是smtp.gmail.com
EMAIL_HOST = 'smtp.example.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
# 你的邮箱账号
EMAIL_HOST_USER = 'your-email@example.com'
# 邮箱授权码(不是登录密码,比如QQ/163邮箱需要单独生成授权码)
EMAIL_HOST_PASSWORD = 'your-email-authorization-code'
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

如果只是测试用,也可以用文件后端,邮件会存在本地目录里:

EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = '/tmp/django-emails'  # 自定义存放邮件的目录

二、修复现有视图的问题(让邮件正常发送)

你现在的视图核心问题是:父类PasswordResetView的post方法依赖request.POST获取邮箱,但你的请求是JSON格式,导致后端拿不到邮箱参数,既没触发邮件发送,还返回了模板内容。修改post方法如下:

class ResetPasswordView(SuccessMessageMixin, PasswordResetView):
    template_name = 'users/password_reset.html'
    email_template_name = 'users/password_reset_email.html'
    subject_template_name = 'users/password_reset_subject'
    success_message = "We've emailed you instructions for setting your password, " \
                      "if an account exists with the email you entered. You should receive them shortly." \
                      " If you don't receive an email, " \
                      "please make sure you've entered the address you registered with, and check your spam folder."
    success_url = reverse_lazy('users-home')

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        request.csrf_processing_done = True
        return super().dispatch(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        # 解析JSON请求里的邮箱
        try:
            data = json.loads(request.body)
        except json.JSONDecodeError:
            return JsonResponse({'error': 'Invalid JSON'}, status=400)
        
        email = data.get('username')
        if not email:
            return JsonResponse({'error': 'Email is required'}, status=400)
        
        # 把邮箱参数放到request.POST里,让父类方法能正常获取
        request.POST = request.POST.copy()
        request.POST['email'] = email
        
        # 调用父类post方法,此时能正确触发邮件发送逻辑
        super().post(request, *args, **kwargs)
        
        # 给API请求返回JSON响应,而不是模板
        return JsonResponse({'message': self.success_message}, status=200)

注意:你原来写的reset_password_template_name不是PasswordResetView的属性,父类用的是template_name,所以这个配置可以删掉。

三、直接调用Django生成密码重置邮件的函数

如果不想依赖PasswordResetView,想手动控制邮件生成逻辑,有两种常用方式:

方式1:用PasswordResetForm的save方法(推荐)

这是Django封装好的逻辑,会自动生成重置链接、渲染邮件模板并发送:

from django.contrib.auth.forms import PasswordResetForm
from django.conf import settings

def send_password_reset_email(email):
    form = PasswordResetForm({'email': email})
    if form.is_valid():
        # 生成重置链接并发送邮件
        form.save(
            request=None,  # 不需要request的话传None,会用settings.SITE_DOMAIN生成链接
            use_https=settings.USE_HTTPS,
            email_template_name='users/password_reset_email.html',
            subject_template_name='users/password_reset_subject',
            from_email=settings.DEFAULT_FROM_EMAIL,
        )

直接调用这个函数就能发送重置邮件。

方式2:手动生成token并构建邮件

如果需要更灵活的自定义,可以手动生成重置token,自己构建邮件内容:

from django.contrib.auth.tokens import default_token_generator
from django.core.mail import send_mail
from django.contrib.auth.models import User
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes
from django.template.loader import render_to_string
from django.conf import settings

def send_custom_password_reset_email(email):
    try:
        user = User.objects.get(email=email, is_active=True)
    except User.DoesNotExist:
        return
    
    # 生成重置链接需要的uid和token
    uid = urlsafe_base64_encode(force_bytes(user.pk))
    token = default_token_generator.make_token(user)
    
    # 构建你的密码重置页面链接
    reset_url = f"{settings.SITE_DOMAIN}/reset/{uid}/{token}/"
    
    # 渲染邮件主题和内容
    email_subject = render_to_string('users/password_reset_subject').strip()
    email_body = render_to_string('users/password_reset_email.html', {
        'user': user,
        'reset_url': reset_url,
        'uid': uid,
        'token': token,
    })
    
    # 发送邮件
    send_mail(
        subject=email_subject,
        message=email_body,
        from_email=settings.DEFAULT_FROM_EMAIL,
        recipient_list=[email],
        fail_silently=False,
    )

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 07:45:38