如何在django 1.7.6中以编程方式触发密码重置电子邮件?

时间:2015-05-06 06:13:32

标签: python django passwords reset programmatically-created

我遇到了一个问题,我必须将超过200个新用户加载到我的django应用程序中,并立即向他们发送密码重置电子邮件。这必须只发生一次,只由我做,并在后端安静地运行。上网冲浪只给我一个或多或少的正确答案:Trigger password reset email in django without browser?。唯一的问题是这篇文章大约4年了,当然当我尝试解决方案时,它没有用......

2 个答案:

答案 0 :(得分:7)

我提到的链接中最有价值的两点:
1)在更新版本的Django中,我们需要调用form.is_valid()
2)在保存()时发送电子邮件。

以下是我如何查询我需要的用户并向他们发送密码重置链接:

    def find_users_and_send_email():
       from django.http import HttpRequest
       from django.contrib.auth.forms import PasswordResetForm
       from django.contrib.auth.models import User

       users = User.objects.filter(date_joined__gt = '2015-04-16')
       for user in users:
       try:

        if user.email:
            log.info("Sending email for to this email:", user.email)
            form = PasswordResetForm({'email': user.email})

            assert form.is_valid()
            request = HttpRequest()
            request.META['SERVER_NAME'] = 'help.mydomain.com'
            request.META['SERVER_PORT'] = '443'
            form.save(
                request= request,
                use_https=True,
                from_email="username@gmail.com", 
                    email_template_name='registration/password_reset_email.html')

       except Exception as e:
          log.info(e)
          continue

return 'done'

1)通常PasswordResetForm使用来自前端的“请求”,这是我没有的。所以我只创建了一个 2)当我跟踪链接中的示例时,它失败了..它在请求中找不到服务器名称。 (这是有道理的,因为我无处不在实例化我的要求) 3)当我修复服务器名称时,它要求服务器端口。由于我使用https,我的端口是443,否则使用默认端口。 4)如果您使用https,请不要忘记在保存表单时指明它( use_https = True

答案 1 :(得分:1)

我发现将@chabislav的答案包装在自定义管理命令中很有用,然后可以根据需要重新使用它。请注意,我取消了用户对象过滤器,因为我知道我想向所有用户发送密码重置指令。

# myproject/myapp/management/commands/send_password_reset_emails.py
from django.core.management.base import BaseCommand, CommandError
# I use a custom user model, so importing that rather than the standard django.contrib.auth.models
from users.models import User
from django.http import HttpRequest
from django.contrib.auth.forms import PasswordResetForm


class Command(BaseCommand):
    help = 'Emails password reset instructions to all users'

    def handle(self, *args, **kwargs):
        users = User.objects.all()
        for user in users:
            try:
                if user.email:
                    print("Sending email for to this email:", user.email)
                    form = PasswordResetForm({'email': user.email})
                    assert form.is_valid()
                    request = HttpRequest()
                    request.META['SERVER_NAME'] = 'www.example.com'
                    request.META['SERVER_PORT'] = 443
                    form.save(
                        request= request,
                        use_https=True,
                        from_email="admin@mysite.com", 
                        email_template_name='registration/password_reset_email.html'
                        )
            except Exception as e:
                print(e)
                continue

        return 'done'

然后可以使用python manage.py send_password_reset_emails轻松地运行它。

请注意,我收到一条错误消息(550, b'5.7.1 Relaying denied'),最终导致设置我的本地主机电子邮件服务器的方式出现问题,但是一旦清除,它就可以很好地工作了。将其包含在管理命令中也很好,因为它不会阻塞您经常使用的代码(视图)。