From 83bf9fc57c804ca2f4962de116a261ee8e7ea822 Mon Sep 17 00:00:00 2001 From: Richard Connon Date: Sat, 18 Nov 2023 19:40:09 +0000 Subject: [PATCH] feat(accounts): Allow disabling email sending to unknown addresses Add a setting to the accounts app which disables sending emails to addresses which do not have an account. For many sites this behaviour will be undesirable since it sends potentially unsolicited email to someone who has not shared it with us. --- ChangeLog.rst | 3 +++ allauth/account/app_settings.py | 4 ++++ allauth/account/forms.py | 3 ++- allauth/account/tests/test_reset_password.py | 24 ++++++++++++++++++++ docs/account/configuration.rst | 4 ++++ 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ChangeLog.rst b/ChangeLog.rst index 6c7ec63250..aca18753ec 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -22,6 +22,9 @@ Note worthy changes - A configurable timeout (``SOCIALACCOUNT_REQUESTS_TIMEOUT``) is now applied to all upstream requests. +- Added a setting ``ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS`` to disable sending of + emails to unknown accounts. + Backwards incompatible changes ------------------------------ diff --git a/allauth/account/app_settings.py b/allauth/account/app_settings.py index 86eea74c3a..fe1c2a2156 100644 --- a/allauth/account/app_settings.py +++ b/allauth/account/app_settings.py @@ -386,6 +386,10 @@ def PASSWORD_RESET_TOKEN_GENERATOR(self): token_generator = EmailAwarePasswordResetTokenGenerator return token_generator + @property + def EMAIL_UNKNOWN_ACCOUNTS(self): + return self._setting("EMAIL_UNKNOWN_ACCOUNTS", True) + @property def REAUTHENTICATION_TIMEOUT(self): return self._setting("REAUTHENTICATION_TIMEOUT", 300) diff --git a/allauth/account/forms.py b/allauth/account/forms.py index 193d122667..c1c866cad6 100644 --- a/allauth/account/forms.py +++ b/allauth/account/forms.py @@ -588,7 +588,8 @@ def clean_email(self): def save(self, request, **kwargs): email = self.cleaned_data["email"] if not self.users: - self._send_unknown_account_mail(request, email) + if app_settings.EMAIL_UNKNOWN_ACCOUNTS: + self._send_unknown_account_mail(request, email) else: self._send_password_reset_mail(request, email, self.users, **kwargs) return email diff --git a/allauth/account/tests/test_reset_password.py b/allauth/account/tests/test_reset_password.py index 8e7c48450e..85652a5d15 100644 --- a/allauth/account/tests/test_reset_password.py +++ b/allauth/account/tests/test_reset_password.py @@ -6,12 +6,36 @@ from django.test.utils import override_settings from django.urls import reverse +import pytest + from allauth.account import app_settings from allauth.account.forms import ResetPasswordForm from allauth.account.models import EmailAddress from allauth.tests import TestCase +@pytest.mark.django_db +def test_reset_password_unknown_account(client, settings): + settings.ACCOUNT_PREVENT_ENUMERATION = True + client.post( + reverse("account_reset_password"), + data={"email": "unknown@example.org"}, + ) + assert len(mail.outbox) == 1 + assert mail.outbox[0].to == ["unknown@example.org"] + + +@pytest.mark.django_db +def test_reset_password_unknown_account_disabled(client, settings): + settings.ACCOUNT_PREVENT_ENUMERATION = True + settings.ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS = False + client.post( + reverse("account_reset_password"), + data={"email": "unknown@example.org"}, + ) + assert len(mail.outbox) == 0 + + @override_settings( ACCOUNT_PREVENT_ENUMERATION=False, ACCOUNT_DEFAULT_HTTP_PROTOCOL="https", diff --git a/docs/account/configuration.rst b/docs/account/configuration.rst index de4b515233..b45b57a6e0 100644 --- a/docs/account/configuration.rst +++ b/docs/account/configuration.rst @@ -72,6 +72,10 @@ Available settings: Subject-line prefix to use for email messages sent. By default, the name of the current ``Site`` (``django.contrib.sites``) is used. +``ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS`` (default: ``True``) + Configures whether password reset attempts for email addresses which do not + have an account result in sending an email. + ``ACCOUNT_DEFAULT_HTTP_PROTOCOL`` (default: ``"http"``) The default protocol used for when generating URLs, e.g. for the password forgotten procedure. Note that this is a default only --