Open quank123wip opened 4 years ago
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": ""
}
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.
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?
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!
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.
Pull requests are welcome ๐ . Don't forget tests.
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()
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
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.
@chymdyugah When you register, do get any error on your logs?
@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'
@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...
Why is this issue still open? I see there is ResendEmailVerificationView in dj_rest_auth.registration.views ...
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 theget_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)
@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 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__)
@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...
Seems to be fixed by #332
An endpoint already exists for this on version 5.0.2
http://localhost:8000/auth/registration/resend-email/
Just like the title.