iMerica / dj-rest-auth

Authentication for Django Rest Framework
https://dj-rest-auth.readthedocs.io/en/latest/index.html
MIT License
1.67k stars 311 forks source link

dj-rest-auth registration e-mail issues #437

Closed edmundsj closed 1 year ago

edmundsj commented 2 years ago

I am having an issue with user registration, and am not able to send registration e-mails successfully. I suspect I'm just not doing something pretty basic that django needs to send e-mails. If this is the case, then this issue request is actually a documentation request, as there are additional settings that need to be added other than the instructions in the "Installation" section to get user registration working.

I am able to get account registration to work on the database side - when I submit a POST request to the registration endpoint with the correct data, I can register a user and view them in the django admin console, but I am getting a server error when a websocket attempts to open, which looks like it has to do with my e-mail account.

Internal Server Error: /api/dj-rest-auth/registration/
Traceback (most recent call last):
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 472, in thread_handler
    raise exc_info[1]
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = await get_response(request)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 435, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "/usr/lib/python3.10/asyncio/tasks.py", line 408, in wait_for
    return await fut
  File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 476, in thread_handler
    return func(*args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/decorators/debug.py", line 92, in sensitive_post_parameters_wrapper
    return view(request, *args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/dj_rest_auth/registration/views.py", line 47, in dispatch
    return super().dispatch(*args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/rest_framework/generics.py", line 190, in post
    return self.create(request, *args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/dj_rest_auth/registration/views.py", line 69, in create
    user = self.perform_create(serializer)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/dj_rest_auth/registration/views.py", line 95, in perform_create
    complete_signup(
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/allauth/account/utils.py", line 186, in complete_signup
    return perform_login(
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/allauth/account/utils.py", line 168, in perform_login
    response = adapter.pre_login(request, user, **hook_kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/allauth/account/adapter.py", line 409, in pre_login
    send_email_confirmation(request, user, signup=signup, email=email)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/allauth/account/utils.py", line 319, in send_email_confirmation
    email_address.send_confirmation(request, signup=signup)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/allauth/account/models.py", line 59, in send_confirmation
    confirmation.send(request, signup=signup)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/allauth/account/models.py", line 166, in send
    get_adapter(request).send_confirmation_mail(request, self, signup)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/allauth/account/adapter.py", line 549, in send_confirmation_mail
    self.send_mail(email_template, emailconfirmation.email_address.email, ctx)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/allauth/account/adapter.py", line 140, in send_mail
    msg.send()
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/mail/message.py", line 298, in send
    return self.get_connection(fail_silently).send_messages([self])
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/mail/backends/smtp.py", line 124, in send_messages
    new_conn_created = self.open()
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/mail/backends/smtp.py", line 80, in open
    self.connection = self.connection_class(
  File "/usr/lib/python3.10/smtplib.py", line 255, in __init__
    (code, msg) = self.connect(host, port)
  File "/usr/lib/python3.10/smtplib.py", line 341, in connect
    self.sock = self._get_socket(host, port, self.timeout)
  File "/usr/lib/python3.10/smtplib.py", line 312, in _get_socket
    return socket.create_connection((host, port), timeout,
  File "/usr/lib/python3.10/socket.py", line 845, in create_connection
    raise err
  File "/usr/lib/python3.10/socket.py", line 833, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
HTTP POST /api/dj-rest-auth/registration/ 500 [0.28, 127.0.0.1:49584]

To fix this, I added the following to my settings.py:

from decouple import config

EMAIL_HOST = config('EMAIL_HOST')
EMAIL_HOST_USER = config('EMAIL_HOST_USERNAME')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD')

Where I am using environment variables for my username/password, and the host is smtp.gmail.com (it's my personal gmail account). Now, when I submit a request, I get the following error:

Application instance <Task pending name='Task-18' coro=<StaticFilesWrapper.__call__() running at /home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/channels/staticfiles.py:44> wait_for=<Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/lib/python3.10/asyncio/futures.py:384, Task.task_wakeup()]>> for connection <WebRequest at 0x7fe783f47df0 method=POST uri=/api/dj-rest-auth/registration/ clientproto=HTTP/1.0> took too long to shut down and was killed.

... and I'm stuck. Sounds like it's an authentication problem? But the error message isn't giving me much.

edmundsj commented 2 years ago

Adding the following lines to my settings.py appears to have "resolved" the issue:

EMAIL_PORT = 587
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = config('EMAIL_HOST_USERNAME')
SERVER_EMAIL = config('EMAIL_HOST_USERNAME')

I am still getting an error, but now it looks like it's a Gmail security error, as it doesn't look like they support username/password login via 3rd-party apps:

Internal Server Error: /api/account/send-email/
Traceback (most recent call last):
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 472, in thread_handler
    raise exc_info[1]
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = await get_response(request)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 435, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "/usr/lib/python3.10/asyncio/tasks.py", line 408, in wait_for
    return await fut
  File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 476, in thread_handler
    return func(*args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/home/jordan/axle_backend/users/views.py", line 132, in get
    send_mail('Subject',
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/mail/__init__.py", line 87, in send_mail
    return mail.send()
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/mail/message.py", line 298, in send
    return self.get_connection(fail_silently).send_messages([self])
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/mail/backends/smtp.py", line 124, in send_messages
    new_conn_created = self.open()
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/mail/backends/smtp.py", line 91, in open
    self.connection.login(self.username, self.password)
  File "/usr/lib/python3.10/smtplib.py", line 750, in login
    raise last_exception
  File "/usr/lib/python3.10/smtplib.py", line 739, in login
    (code, resp) = self.auth(
  File "/usr/lib/python3.10/smtplib.py", line 662, in auth
    raise SMTPAuthenticationError(code, resp)
smtplib.SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8  https://support.google.com/mail/?p=BadCredentials b9-20020a05622a020900b0035d430d4315sm6140818qtx.19 - gsmtp')
edmundsj commented 2 years ago

As a follow-up: which setting can I change to specify the registration "FROM" email address in the verification e-mails sent by dj-rest-auth? I have set EMAIL_HOST_USER but this is not the same thing as my "from" email address. I looked for it in the allauth docs but can't seem to find it.

edmundsj commented 2 years ago

It was staring me right in the face! The setting is from django, not django-allauth one, and adding the following line to my settings.py got the email to send successfully (where I have used an environment variable to define the email)!

DEFAULT_FROM_EMAIL = config('DEFAULT_FROM_EMAIL')

The e-mail sends successfully (sort of - it doesn't actually hit my inbox although it's labeled as being in my inbox in gmail), However, now when I try to click the confirmation link in the e-mail that was sent, django throws an error. It looks like it's trying to hit an endpoint /registration/account-confirm-email/ that doesn't exist. I have confirmed it dosen't exist by trying to hit it manually in my browser, and I get a 404 error. I have the registration endpoint in my urlpatterns, so why is it not adding an account-confirm-email? And how do I add it?

path('api/dj-rest-auth/registration/', include('dj_rest_auth.registration.urls'))

Stack trace:

HTTP POST /api/dj-rest-auth/registration/ 201 [0.90, 127.0.0.1:56902]
Internal Server Error: /api/dj-rest-auth/registration/account-confirm-email/MTM:1oeyyU:SkZ8UogQYxkunS-IJrrnXyFmHpvN0Oezj3fAdx992xY/
Traceback (most recent call last):
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 472, in thread_handler
    raise exc_info[1]
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = await get_response(request)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 435, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "/usr/lib/python3.10/asyncio/tasks.py", line 408, in wait_for
    return await fut
  File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 476, in thread_handler
    return func(*args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 142, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 217, in get
    return self.render_to_response(context)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 190, in render_to_response
    template=self.get_template_names(),
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 202, in get_template_names
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()'
HTTP GET /api/dj-rest-auth/registration/account-confirm-email/MTM:1oeyyU:SkZ8UogQYxkunS-IJrrnXyFmHpvN0Oezj3fAdx992xY/ 500 [0.07, 127.0.0.1:58742]
edmundsj commented 2 years ago

I found a hint in the API reference, and added the following lines to my urls.py:

from dj_rest_auth.registration.views import VerifyEmailView
...
path('api/dj-rest-auth/account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent'),

However, I'm still getting the same error. It looks like the endpoint the link is trying to hit is /api/dj-rest-auth/registration/account-confirm-email/, which is not the endpoint specified in the API. However, even when I change the url pattern to hit the endpoint /api/dj-rest-auth/registration/account-confirm-email/, I get exactly the same stack trace. I'm stumped.

I should also add that I'm currently running the django server on localhost using the django development server, and this API is not deployed. I am still expecting the registration links to work, but if this is not the case, advice for how to debug this before it gets deployed would be great, along with whatever settings still need to be used to get it to work.

Internal Server Error: /api/dj-rest-auth/registration/account-confirm-email/MTM:1oeyyU:SkZ8UogQYxkunS-IJrrnXyFmHpvN0Oezj3fAdx992xY/
Traceback (most recent call last):
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 472, in thread_handler
    raise exc_info[1]
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = await get_response(request)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 435, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "/usr/lib/python3.10/asyncio/tasks.py", line 408, in wait_for
    return await fut
  File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/asgiref/sync.py", line 476, in thread_handler
    return func(*args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 142, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 217, in get
    return self.render_to_response(context)
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 190, in render_to_response
    template=self.get_template_names(),
  File "/home/jordan/.local/share/virtualenvs/axle_backend-CFXWssDC/lib/python3.10/site-packages/django/views/generic/base.py", line 202, in get_template_names
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()'
HTTP GET /api/dj-rest-auth/registration/account-confirm-email/MTM:1oeyyU:SkZ8UogQYxkunS-IJrrnXyFmHpvN0Oezj3fAdx992xY/ 500 [0.05, 127.0.0.1:52410]
edmundsj commented 1 year ago

Closing, superseded by https://github.com/iMerica/dj-rest-auth/issues/445