django-allauth: Cleanup expired email confirmation

Is there a way to clean up expired email confirmations?

Say we have two users Alice (alice@example.com) and Bob (bob@example.com). Now Alice creates an account and uses alice@example.com for her primary addresses. But she also adds bob@example.com as an additional email without confirming it (because she does not have Bob’s password for the mail account).

Now Bob wants to signup using bob@example.com which is not possible.

What about a management command which will delete non-verified emails older than timezone.now() - timedelta(days=app_settings.EMAIL_CONFIRMATION_EXPIRE_DAYS)?

About this issue

  • Original URL
  • State: closed
  • Created 11 years ago
  • Comments: 15 (9 by maintainers)

Most upvoted comments

@amin1998sh HTTP404 exception is catched here again. https://github.com/pennersr/django-allauth/blob/353386216b79f16709e97bb487c0bbbba2bc0c71/allauth/account/views.py#L297 And then return self.render_to_response(ctx). That’s why response status is 200.

@9mido The thing is, when the user clicks on a wrong activision link, recieves 200 OK, but according to what you said and according to raise Http404() in account/views.py line 385 it should send 404 status code.

        if recent_unverified_joined_users.count():
            deleted_count = recent_unverified_joined_users.delete()
            print('cleanupregistration completed. Deleted user count=%d' % deleted_count)
        else:
            print('cleanupregistration completed. There is no user has to be deleted.')

Not thing really different with yours. I just want to show logs. And this code will be run by cron.

Now we have ACCOUNT_MAX_EMAIL_ADDRESSES = 1 to prevent a user from adding another email address that is not their own.

It looks like EmailConfirmationManager in managers.py has delete_expired_confirmations which the links above are referring to. But the EmailConfirmationManager seems to be for the deprecated account_emailconfiguration database table. The hashtag line in the links are wrong now.

Here is a custom management command example:

#Command: python3 manage.py file

from django.core.management.base import BaseCommand

import datetime
from django.utils import timezone
import pytz

from allauth.account.models import EmailAddress
from django.contrib.auth.models import User

class Command(BaseCommand):
    help = 'Delete user accounts who have unverified email addresses that are between 1-2 days old'

    def handle(self, *args, **kwargs):
        recent_joined_users = User.objects.filter(date_joined__gt=timezone.now() - timezone.timedelta(days=2), date_joined__lt=timezone.now() - timezone.timedelta(days=1))
        for x in recent_joined_users:
            emails = EmailAddress.objects.filter(user=x, verified=False).values_list('user', flat=True)
            for y in emails:
                User.objects.get(id = y).delete()

The code above will delete unverified users who are created between 1-2 days ago. You can customize the days=number in the query to be whatever you want. However, this code is pretty strict and mostly applies for signed up users and not for users who have more than 1 email address. This code is good if you have ACCOUNT_MAX_EMAIL_ADDRESSES = 1 and you have /accounts/email/ blocked off via a 404.

If you have ACCOUNT_MAX_EMAIL_ADDRESSES > 1, you could delete unverified non-primary email addresses by EmailAddress.objects.filter(verified=False, primary=False).delete() if you want to make sure you delete only unverified email addresses associated with each account and not the whole account itself.

Related: #2011, #1522, #2731, #1196