我遇到了一个问题,需要将超过200个新用户加载到我的django应用程序中,并立即向他们发送密码重置电子邮件。这只需在后台由我完成一次,并安静地运行。在网上搜索只给我带来了一个或多或少正确的答案:在django中触发密码重置电子邮件而不使用浏览器?。唯一的问题是这篇文章大约四年前写的,当我尝试解决方案时,它并没有起作用...
我遇到了一个问题,需要将超过200个新用户加载到我的django应用程序中,并立即向他们发送密码重置电子邮件。这只需在后台由我完成一次,并安静地运行。在网上搜索只给我带来了一个或多或少正确的答案:在django中触发密码重置电子邮件而不使用浏览器?。唯一的问题是这篇文章大约四年前写的,当我尝试解决方案时,它并没有起作用...
我提到的链接中提到的两个最有价值的点:
form.is_valid()
save()
时完成的。以下是我查询所需用户并向每个用户发送密码重置链接的方法:
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
需要前端发起“请求”,但我没有。所以我简单地创建了一个。use_https=True
。我发现将@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')
,这最终是由于我的本地主机电子邮件服务器设置方式有问题,但一旦解决了这个问题,它就非常有效。将其放在管理命令中也很好,因为它不会堵塞您定期使用的代码(视图)。
from allauth.account.forms import ResetPasswordForm # note the different form import
form = ResetPasswordForm({"email": "some@mail.io"})
assert form.is_valid() # required because we need clean() executed
form.save(
request=None,
from_email="noreply@example.io",
)
django.contrib.sites
。
form.save()
中设置domain_override
,而不是创建一个请求,以便在重置电子邮件中显示您想要显示为域的内容(这将用于链接和电子邮件的默认主题)。 - Fasandnext(form.get_users(users_email_address))
来检查返回的生成器是否包含匹配项。顺便说一句,Fasand使用domain_override
的想法对我很有帮助!不错。 - Tristan