django-allauth change user email with/without verification

There are a few ways you could go about doing this.

Either listen to the email_confirmed signal handler, and have a function that checks whether user has two EmailAccount objects associated with his account, and if so, delete the other EmailAccount object.

The other would be set EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL and EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL in your settings and have related view delete the extra email address, if it exists.

Another way would be to just override the EmailView and/or AddEmailForm and have them do what you want.

For changing email without confirmation, you could just have your view call the EmailAddress.change method.


I think the new email address should be verified. If your application sends periodic emails, you don't want to fire off loads of emails to just any email address that a user enters.

What I did was allow multiple email addresses until the second email is verified. Then, listen for django-allauth's email_confirmed signal as elssar suggested. As soon as the address is verified, set the new email address as the primary email, then delete any previous EmailAddess. Here's a simplified example of what I ended up doing:

models:

from django.dispatch import receiver
from allauth.account.models import EmailAddress
from allauth.account.signals import email_confirmed

class CustomUser(models.Model):
    ...
    def add_email_address(self, request, new_email):
        # Add a new email address for the user, and send email confirmation.
        # Old email will remain the primary until the new one is confirmed.
        return EmailAddress.objects.add_email(request, self.user, new_email, confirm=True)

@receiver(email_confirmed)
def update_user_email(sender, request, email_address, **kwargs):
    # Once the email address is confirmed, make new email_address primary.
    # This also sets user.email to the new email address.
    # email_address is an instance of allauth.account.models.EmailAddress
    email_address.set_as_primary()
    # Get rid of old email addresses
    stale_addresses = EmailAddress.objects.filter(
        user=email_address.user).exclude(primary=True).delete()

views:

def update_user_details(request):
    user = request.user
    new_email = request.POST.get('new_email')
    user.custom_user.add_email_address(request, new_email)
    ...