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 --