Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resend Activation Email #44

Open
quank123wip opened this issue Apr 16, 2020 · 19 comments
Open

Resend Activation Email #44

quank123wip opened this issue Apr 16, 2020 · 19 comments
Labels
enhancement New feature or request

Comments

@quank123wip
Copy link

Just like the title.

@opeodedeyi
Copy link

opeodedeyi commented Apr 17, 2020

I had issues with this not too long ago. the problem is I thought Django-rest-auth or Dj-rest-auth handles it for users, but that is not the case. in my case, I had to set up a view for this.

this is what my view looked like for requesting new verification email

from rest_framework.permissions import AllowAny
from django.contrib.auth import get_user_model
from rest_framework.generics import get_object_or_404
from allauth.account.admin import EmailAddress
from allauth.account.utils import send_email_confirmation
from rest_framework.response import Response
from rest_framework import status
from rest_framework.exceptions import APIException

User = get_user_model()

class NewEmailConfirmation(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)

my url.py

path('resend-verification-email/', NewEmailConfirmation.as_view(), name='resend-email-confirmation'),

and when making the request to the API, you just pass the email as shown below, and if the email is already verified, it will not send new verification email, but if not verified, it will send the confirmation email


{
    "email": ""
}

@fsboehme
Copy link

If we're trying to play nice with allauth, this should happen automatically when trying to log in with an unverified email.

From docstring for allauth.account.send_email_confirmation:

    E-mail verification mails are sent:
    a) Explicitly: when a user signs up
    b) Implicitly: when a user attempts to log in using an unverified
    e-mail while EMAIL_VERIFICATION is mandatory.

@opeodedeyi
Copy link

In my case, the EMAIL_VERIFICATION was mandatory and the email didn't send automatically. I also posted this issue on different platforms wasting months with no reply till today. that is how I got to my conclusion. How did you solve yours? did yours send automatically?

@fsboehme
Copy link

No no, I was tracking down why it wasn't sending and landed here. Just added that as a note in case anyone is looking at fixing this. Would be a little more seamless without an extra view. I'll probably use your solution as a starting point for now. Thanks for posting that!

@quank123wip
Copy link
Author

I had issues with this not too long ago. the problem is I thought Django-rest-auth or Dj-rest-auth handles it for users, but that is not the case. in my case, I had to set up a view for this.

this is what my view looked like for requesting new verification email

from rest_framework.permissions import AllowAny
from django.contrib.auth import get_user_model
from rest_framework.generics import get_object_or_404
from allauth.account.admin import EmailAddress
from allauth.account.utils import send_email_confirmation
from rest_framework.response import Response
from rest_framework import status
from rest_framework.exceptions import APIException

User = get_user_model()

class NewEmailConfirmation(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)

my url.py

path('resend-verification-email/', NewEmailConfirmation.as_view(), name='resend-email-confirmation'),

and when making the request to the API, you just pass the email as shown below, and if the email is already verified, it will not send new verification email, but if not verified, it will send the confirmation email


{
    "email": ""
}

It's a good workaround, I think we need to write a view inside dj-rest-auth, Maybe I will make a pull request soon.

@iMerica
Copy link
Owner

iMerica commented Apr 18, 2020

Pull requests are welcome 👍 . Don't forget tests.

@iMerica iMerica added the enhancement New feature or request label Apr 18, 2020
@sijandh35
Copy link

sijandh35 commented Jun 15, 2021

from allauth.account.utils import complete_signup

class ResendEmailView(CreateAPIView):
    serializer_class = ResendEmailSerializer
    authentication_classes = [SessionAuthentication, JWTAuthentication, ]
    permission_classes = (IsAuthenticated,)

    def create(self, request, *args, **kwargs):
        serializer = ResendEmailSerializer(data=request.data)
        if serializer.is_valid():
            user = User.objects.get(username=request.data['username'])
            email_address = user.emailaddress_set.get(email=user.email)
            if not email_address.verified:
                complete_signup(self.request._request, user,
                                allauth_settings.EMAIL_VERIFICATION,
                                None)
                return Response("Verification Email Send", status=status.HTTP_201_CREATED)
            else:
                return Response("Email Already Verified", status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response({'Message': serializer.errors}, `status=status.HTTP_400_BAD_REQUEST)```
class ResendEmailSerializer(serializers.Serializer):
    username = serializers.CharField()

@escaper01
Copy link

In my case, the EMAIL_VERIFICATION was mandatory and the email didn't send automatically. I also posted this issue on different platforms wasting months with no reply till today. that is how I got to my conclusion. How did you solve yours? did yours send automatically?

If you set correctly, your email settings :
´´´
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'mail.privateemail.com'
EMAIL_USE_TLS = True
EMAIL_USE_SSl = False
EMAIL_PORT = 587
EMAIL_HOST_USER = getenv('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = getenv('EMAIL_HOST_PASSWORD')
´´´
and set
ACCOUNT_EMAIL_VERIFICATION = 'optional' or 'mandatory'
it should work automatically

@chymdyugah
Copy link

In my case, the EMAIL_VERIFICATION was mandatory and the email didn't send automatically. I also posted this issue on different platforms wasting months with no reply till today. that is how I got to my conclusion. How did you solve yours? did yours send automatically?

If you set correctly, your email settings :
´´´
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'mail.privateemail.com'
EMAIL_USE_TLS = True
EMAIL_USE_SSl = False
EMAIL_PORT = 587
EMAIL_HOST_USER = getenv('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = getenv('EMAIL_HOST_PASSWORD')
´´´
and set
ACCOUNT_EMAIL_VERIFICATION = 'optional' or 'mandatory'
it should work automatically

It doesn't work automatically for optional email verification, that I'm sure of. I think it's either you write a new view or update the login view for dj-rest-auth. I prefer the former to avoid too many unneccessary emails.

@escaper01
Copy link

escaper01 commented Aug 18, 2021

@chymdyugah When you register, do get any error on your logs?

@chymdyugah
Copy link

@escaper01 errors? No.

I get the email. I was saying when you login, you don't get the email again if you have it set to 'optional'

@mgoldenbe
Copy link

@escaper01 errors? No.

I get the email. I was saying when you login, you don't get the email again if you have it set to 'optional'

Neither is it re-sent with 'mandatory' (at least for me). I use console backend, it's for sure not because of some misconfiguration of email...

@mgoldenbe
Copy link

Why is this issue still open? I see there is ResendEmailVerificationView in dj_rest_auth.registration.views ...

@aladagemre
Copy link

aladagemre commented Sep 18, 2021

Are we sure this view really works? I get the following error when I POST email to http://127.0.0.1:8000/auth/registration/resend-email/

'ResendEmailVerificationView' should either include a queryset attribute, or override the get_queryset() method.

I see there's no such attribute or method in the view extending CreateAPIView. Maybe we should add that attribute. My temporary solution:

class CustomResendEmailVerificationView(CreateAPIView):
    permission_classes = (AllowAny,)
    serializer_class = ResendEmailVerificationSerializer
    queryset = EmailAddress.objects.all()

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        try:
            email = EmailAddress.objects.get(**serializer.validated_data)
        except allauth.account.models.EmailAddress.DoesNotExist as exc:
            logger.warning(exc)
            raise ValidationError("Account does not exist")
        if email.verified:
            raise ValidationError("Account is already verified")

        email.send_confirmation()
        return Response({"detail": _("ok")}, status=status.HTTP_200_OK)

@femiir
Copy link

femiir commented Jan 6, 2022

@aladagemre how were you able to by pass this error I am trying to use your code snippet but can't seem to import logger

@aladagemre
Copy link

@aladagemre how were you able to by pass this error I am trying to use your code snippet but can't seem to import logger

@femiir Put the following somewhere at the top:

import logging
logger = logging.getLogger(__name__)

@femiir
Copy link

femiir commented Jan 10, 2022

@aladagemre how were you able to by pass this error I am trying to use your code snippet but can't seem to import logger

@femiir Put the following somewhere at the top:

import logging
logger = logging.getLogger(__name__)

thank you so much
Apparently the updated version of dj-rest-auth has queryset added but returns ok status for almost every operation
I will suggest you make a pull request with your solution...

@aladagemre
Copy link

Seems to be fixed by #332

@chaulapatrice
Copy link

An endpoint already exists for this on version 5.0.2
http://localhost:8000/auth/registration/resend-email/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests