Search code examples
djangodjango-rest-frameworkdjango-allauthdjango-rest-auth

allauth unverified email remains unverified once email expires


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"

Solution

  • 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'),