问题
I have a custom user model. and I use Django rest auth to handle authentication of users. the problem is that after sign up when the email is sent. if the user doesn't verify the email before it expires, it seems that it remains stuck like that indefinitely. I was expecting the verification email to be sent again since ACCOUNT_EMAIL_VERIFICATION = "mandatory"
in my settings, from the documentation, it is supposed to resend the verification message by default, but this isnt happening. I am lost as to what else to do and I can't seem to find any resource that helps.
below is my model
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']
in my settings.py the user has an expiry date of 2 days
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"
回答1:
First of all, you have mentioned you are using django-rest-auth
which is not the case, and you are probably using django-allauth
.
According to django-allauth
's documentation:
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.
So there is nothing mentioned about re-sending the verification email if the first one expires. To accomplish what you want, you should have a job
script running and checking for expired
verification tokens and re-send the verification emails manually.
You should create a script that looks something like this:
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)
And keep this script running using any scheduler you like (supervisor
, pm2
, cronjob
, etc).
Bottom line, django-allauth
does not/can not have the functionality you want. This job needs to be done manually.
回答2:
Eventually, I was able to solve this differently, I created a view and URL that requests the user email and then send a link to them if they are unverified.
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'),
来源:https://stackoverflow.com/questions/60218433/allauth-unverified-email-remains-unverified-once-email-expires