如何以编程方式在 django 1.7.6 中触发密码重置电子邮件?
How to programmatically trigger password reset email in django 1.7.6?
我遇到了一个问题,我不得不将 200 多个新用户加载到我的 django 应用程序中,并立即向他们发送密码重置电子邮件。这必须只发生一次,只能由我和 运行 在后端悄悄地完成。网上冲浪只让我找到一个或多或少正确的答案:Trigger password reset email in django without browser?。唯一的问题是这个 post 大约有 4 年历史,当然当我尝试解决方案时,它没有用...
我提到的 link 中最有价值的两点:
- 在最新版本的 Django 中,我们需要调用
form.is_valid()
- 电子邮件发送在
save()
时完成。
以下是我如何查询我需要的用户并向他们每个人发送密码重置 link:
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
import logging
logger = logging.getLogger(__name__)
users = User.objects.filter(date_joined__gt = '2015-04-16')
for user in users:
try:
if user.email:
logger.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:
logger.warning(str(e))
continue
return 'done'
- 通常
PasswordResetForm
使用来自前端的“请求”,但我没有。所以我简单地创建了一个。
- 当我按照 link 中的示例进行操作时,它失败了。它无法在请求中找到服务器名称。 (有道理,因为我凭空实例化了我的请求)
- 当我固定服务器名称时,它会询问服务器端口。由于我使用的是https,所以我的端口是443,否则使用默认端口。
- 如果您使用https,请不要忘记在保存表格时注明
use_https=True
我发现将@chabislav 的回答包含在自定义管理命令中很有用,然后可以根据需要重复使用。请注意,我删除了用户对象过滤器,因为我知道我想向 all 用户发送密码重置指令。
# 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')
,这最终成为我的本地主机电子邮件服务器设置方式的问题,但一旦清除该错误消息,它就运行良好。将它放在管理命令中也很好,因为它不会阻塞您定期使用的代码(视图)。
我遇到了一个问题,我不得不将 200 多个新用户加载到我的 django 应用程序中,并立即向他们发送密码重置电子邮件。这必须只发生一次,只能由我和 运行 在后端悄悄地完成。网上冲浪只让我找到一个或多或少正确的答案:Trigger password reset email in django without browser?。唯一的问题是这个 post 大约有 4 年历史,当然当我尝试解决方案时,它没有用...
我提到的 link 中最有价值的两点:
- 在最新版本的 Django 中,我们需要调用
form.is_valid()
- 电子邮件发送在
save()
时完成。
以下是我如何查询我需要的用户并向他们每个人发送密码重置 link:
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
import logging
logger = logging.getLogger(__name__)
users = User.objects.filter(date_joined__gt = '2015-04-16')
for user in users:
try:
if user.email:
logger.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:
logger.warning(str(e))
continue
return 'done'
- 通常
PasswordResetForm
使用来自前端的“请求”,但我没有。所以我简单地创建了一个。 - 当我按照 link 中的示例进行操作时,它失败了。它无法在请求中找到服务器名称。 (有道理,因为我凭空实例化了我的请求)
- 当我固定服务器名称时,它会询问服务器端口。由于我使用的是https,所以我的端口是443,否则使用默认端口。
- 如果您使用https,请不要忘记在保存表格时注明
use_https=True
我发现将@chabislav 的回答包含在自定义管理命令中很有用,然后可以根据需要重复使用。请注意,我删除了用户对象过滤器,因为我知道我想向 all 用户发送密码重置指令。
# 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')
,这最终成为我的本地主机电子邮件服务器设置方式的问题,但一旦清除该错误消息,它就运行良好。将它放在管理命令中也很好,因为它不会阻塞您定期使用的代码(视图)。