Skip to content

Commit

Permalink
feat(accounts): Allow disabling email sending to unknown addresses
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
riconnon committed Nov 18, 2023
1 parent c03fecb commit ad93496
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 1 deletion.
3 changes: 3 additions & 0 deletions ChangeLog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Note worthy changes
- Added MFA signals emitted when authenticators are added, removed or (in case
of recovery codes) reset.

- Added a setting ``ACCOUNT_SEND_TO_UNKNOWN_EMAILS`` to disable sending of
emails to unknown accounts.


0.58.2 (2023-11-06)
*******************
Expand Down
4 changes: 4 additions & 0 deletions allauth/account/app_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,10 @@ def PASSWORD_RESET_TOKEN_GENERATOR(self):
token_generator = EmailAwarePasswordResetTokenGenerator
return token_generator

@property
def SEND_TO_UNKNOWN_EMAILS(self):
return self._setting("SEND_TO_UNKNOWN_EMAILS", True)

@property
def REAUTHENTICATION_TIMEOUT(self):
return self._setting("REAUTHENTICATION_TIMEOUT", 300)
Expand Down
3 changes: 2 additions & 1 deletion allauth/account/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,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.SEND_TO_UNKNOWN_EMAILS:
self._send_unknown_account_mail(request, email)
else:
self._send_password_reset_mail(request, email, self.users, **kwargs)
return email
Expand Down
22 changes: 22 additions & 0 deletions allauth/account/tests/test_reset_password.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,28 @@ def test_password_forgotten_no_username_hint(self):
body = mail.outbox[0].body
assert user.username not in body

@override_settings(
ACCOUNT_PREVENT_ENUMERATION=True,
)
def test_reset_password_unknown_account(self):
self.client.post(
reverse("account_reset_password"),
data={"email": "[email protected]"},
)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].to, ["[email protected]"])

@override_settings(
ACCOUNT_PREVENT_ENUMERATION=True,
ACCOUNT_SEND_TO_UNKNOWN_EMAILS=False,
)
def test_reset_password_unknown_account_disabled(self):
self.client.post(
reverse("account_reset_password"),
data={"email": "[email protected]"},
)
self.assertEqual(len(mail.outbox), 0)

def _request_new_password(self):
user = get_user_model().objects.create(
username="john", email="[email protected]", is_active=True
Expand Down
11 changes: 11 additions & 0 deletions allauth/account/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,17 @@ class PasswordResetView(AjaxCapableProcessFormViewMixin, FormView):
def get_form_class(self):
return get_form_class(app_settings.FORMS, "reset_password", self.form_class)

def post(self, request, *args, **kwargs):
"""
Handle POST requests: instantiate a form instance with the passed
POST variables and then check if it's valid.
"""
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)

def form_valid(self, form):
r429 = ratelimit.consume_or_429(
self.request,
Expand Down

0 comments on commit ad93496

Please sign in to comment.