allauth 未验证的电子邮件在电子邮件过期后仍未验证
allauth unverified email remains unverified once email expires
我有一个自定义用户模型。我使用 Django rest auth 来处理用户身份验证。 问题 是在发送电子邮件时注册后。如果用户在电子邮件过期之前没有验证电子邮件,它似乎会无限期地卡住。自从 ACCOUNT_EMAIL_VERIFICATION = "mandatory"
在我的设置中,我期待再次发送验证电子邮件,根据文档,它应该默认重新发送验证消息,但这并没有发生。我不知道还能做什么,而且我似乎找不到任何有帮助的资源。
下面是我的模型
models.py
class User(AbstractBaseUser, PermissionsMixin):
username = None
email = models.EmailField(max_length=254, unique=True)
name = models.CharField(max_length=250)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=255, unique=True, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
在我的 settings.py 中,用户的有效期为 2 天
ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS = True
ACCOUNT_AUTHENTICATION_METHOD = "email"
ACCOUNT_CONFIRM_EMAIL_ON_GET = True
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = None #or "api/authenticated/"
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
ACCOUNT_EMAIL_CONFIRMATION_HMAC = False
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
EMAIL_VERIFICATION = "mandatory"
ACCOUNT_DEFAULT_HTTP_PROTOCOL = "http"
ACCOUNT_EMAIL_CONFIRMATION_COOLDOWN = 3600
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 5
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 180
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = False
ACCOUNT_LOGOUT_ON_GET = True
ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE = True
ACCOUNT_LOGIN_ON_PASSWORD_RESET = False
ACCOUNT_LOGOUT_REDIRECT_URL = "api/login/"
ACCOUNT_SESSION_REMEMBER = True
ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE = False
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_USER_MODEL_EMAIL_FIELD = "email"
首先,您提到您正在使用 django-rest-auth
,但事实并非如此,您可能正在使用 django-allauth
。
根据 django-allauth
的文档:
ACCOUNT_EMAIL_VERIFICATION:
When set to “mandatory” the user is blocked from logging in until the email address is verified. Choose “optional” or “none” to allow logins with an unverified e-mail address. In case of “optional”, the e-mail verification mail is still sent, whereas in case of “none” no e-mail verification mails are sent.
所以没有提到如果第一个过期重新发送验证邮件。要完成您想要的,您应该有一个 job
脚本 运行 并检查 expired
验证令牌并手动重新发送验证电子邮件。
您应该创建一个如下所示的脚本:
from time import sleep
from django.utils import timezone
from django_allauth.account.models import EmailConfirmation
while True:
def_expired = timezone.now() - datetime.timedelta(days=app_settings.EMAIL_CONFIRMATION_EXPIRE_DAYS)
expired_tokens = EmailConfirmation.objects.filter(sent__lte=def_expired)
for token in expired_tokens:
token.send()
sleep(2)
并使用您喜欢的任何调度程序(supervisor
、pm2
、cronjob
等)保留此脚本 运行。
最重要的是,django-allauth
not/can 没有您想要的功能。这项工作需要手动完成。
最终,我能够以不同的方式解决这个问题,我创建了一个视图并 URL 请求用户电子邮件,然后如果他们未经验证则向他们发送 link。
views.py
from allauth.account.utils import send_email_confirmation
from allauth.account.admin import EmailAddress
from rest_framework.exceptions import APIException
class EmailConfirmation(APIView):
permission_classes = [AllowAny]
def post(self, request):
user = get_object_or_404(User, email=request.data['email'])
emailAddress = EmailAddress.objects.filter(user=user, verified=True).exists()
if emailAddress:
return Response({'message': 'This email is already verified'}, status=status.HTTP_400_BAD_REQUEST)
else:
try:
send_email_confirmation(request, user=user)
return Response({'message': 'Email confirmation sent'}, status=status.HTTP_201_CREATED)
except APIException:
return Response({'message': 'This email does not exist, please create a new account'}, status=status.HTTP_403_FORBIDDEN)
urls.py
path('verify-email/again/', qv.EmailConfirmation.as_view(), name='resend-email-confirmation'),
我有一个自定义用户模型。我使用 Django rest auth 来处理用户身份验证。 问题 是在发送电子邮件时注册后。如果用户在电子邮件过期之前没有验证电子邮件,它似乎会无限期地卡住。自从 ACCOUNT_EMAIL_VERIFICATION = "mandatory"
在我的设置中,我期待再次发送验证电子邮件,根据文档,它应该默认重新发送验证消息,但这并没有发生。我不知道还能做什么,而且我似乎找不到任何有帮助的资源。
下面是我的模型
models.py
class User(AbstractBaseUser, PermissionsMixin):
username = None
email = models.EmailField(max_length=254, unique=True)
name = models.CharField(max_length=250)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=255, unique=True, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
在我的 settings.py 中,用户的有效期为 2 天
ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS = True
ACCOUNT_AUTHENTICATION_METHOD = "email"
ACCOUNT_CONFIRM_EMAIL_ON_GET = True
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = None #or "api/authenticated/"
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
ACCOUNT_EMAIL_CONFIRMATION_HMAC = False
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
EMAIL_VERIFICATION = "mandatory"
ACCOUNT_DEFAULT_HTTP_PROTOCOL = "http"
ACCOUNT_EMAIL_CONFIRMATION_COOLDOWN = 3600
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 5
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 180
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = False
ACCOUNT_LOGOUT_ON_GET = True
ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE = True
ACCOUNT_LOGIN_ON_PASSWORD_RESET = False
ACCOUNT_LOGOUT_REDIRECT_URL = "api/login/"
ACCOUNT_SESSION_REMEMBER = True
ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE = False
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_USER_MODEL_EMAIL_FIELD = "email"
首先,您提到您正在使用 django-rest-auth
,但事实并非如此,您可能正在使用 django-allauth
。
根据 django-allauth
的文档:
ACCOUNT_EMAIL_VERIFICATION:
When set to “mandatory” the user is blocked from logging in until the email address is verified. Choose “optional” or “none” to allow logins with an unverified e-mail address. In case of “optional”, the e-mail verification mail is still sent, whereas in case of “none” no e-mail verification mails are sent.
所以没有提到如果第一个过期重新发送验证邮件。要完成您想要的,您应该有一个 job
脚本 运行 并检查 expired
验证令牌并手动重新发送验证电子邮件。
您应该创建一个如下所示的脚本:
from time import sleep
from django.utils import timezone
from django_allauth.account.models import EmailConfirmation
while True:
def_expired = timezone.now() - datetime.timedelta(days=app_settings.EMAIL_CONFIRMATION_EXPIRE_DAYS)
expired_tokens = EmailConfirmation.objects.filter(sent__lte=def_expired)
for token in expired_tokens:
token.send()
sleep(2)
并使用您喜欢的任何调度程序(supervisor
、pm2
、cronjob
等)保留此脚本 运行。
最重要的是,django-allauth
not/can 没有您想要的功能。这项工作需要手动完成。
最终,我能够以不同的方式解决这个问题,我创建了一个视图并 URL 请求用户电子邮件,然后如果他们未经验证则向他们发送 link。
views.py
from allauth.account.utils import send_email_confirmation
from allauth.account.admin import EmailAddress
from rest_framework.exceptions import APIException
class EmailConfirmation(APIView):
permission_classes = [AllowAny]
def post(self, request):
user = get_object_or_404(User, email=request.data['email'])
emailAddress = EmailAddress.objects.filter(user=user, verified=True).exists()
if emailAddress:
return Response({'message': 'This email is already verified'}, status=status.HTTP_400_BAD_REQUEST)
else:
try:
send_email_confirmation(request, user=user)
return Response({'message': 'Email confirmation sent'}, status=status.HTTP_201_CREATED)
except APIException:
return Response({'message': 'This email does not exist, please create a new account'}, status=status.HTTP_403_FORBIDDEN)
urls.py
path('verify-email/again/', qv.EmailConfirmation.as_view(), name='resend-email-confirmation'),