Skip to content

fix(user): password change silently lost when notification email fails to send#1808

Open
miaulalala wants to merge 3 commits into
masterfrom
fix/password-change-notification-failure
Open

fix(user): password change silently lost when notification email fails to send#1808
miaulalala wants to merge 3 commits into
masterfrom
fix/password-change-notification-failure

Conversation

@miaulalala

Copy link
Copy Markdown
Contributor

Summary

  • password_changed_signal (nextcloudappstore/user/signals.py) is a pre_save hook on User that regenerates the API token and emails the user whenever their password changes. It called update_token() before send_mail(), with no error handling. If send_mail() raised (e.g. a mail outage), the exception propagated out of the pre_save signal and aborted the .save() entirely — so the password change was silently lost, even though the token had already been regenerated as a side effect.
  • This affected both the logged-in /account/password/ change form and the forgot-password /password/reset/key/... flow, since both ultimately call user.save().
  • Reordered so the token is only regenerated once the notification email is confirmed sent, and wrapped send_mail() so a failure raises a clear ValidationError instead of a raw SMTP/socket exception. The save is still aborted on failure by design — a password should never change without the user being notified.
  • Added PasswordView.form_valid() handling and a new PasswordResetFromKeyView (wired ahead of allauth's own URL for account_reset_password_from_key) so this failure now shows a friendly warning banner instead of an unhandled error page.

Test plan

  • New tests in nextcloudappstore/user/tests.py covering: password persists when mail succeeds, is rejected when mail fails, token isn't regenerated on failure, no mail sent for unrelated field changes, and both password-change views show a warning (not a crash) on failure while leaving the old password intact
  • poetry run python manage.py test nextcloudappstore.user nextcloudappstore.core nextcloudappstore.api.v1 --settings nextcloudappstore.settings.development --exclude-tag=e2e — 184 tests pass

🤖 Generated with Claude Code

miaulalala and others added 3 commits July 2, 2026 16:35
…med sent

password_changed_signal is a pre_save hook on User, so previously it
called update_token() before send_mail() with no error handling. If
send_mail() raised (e.g. a mail outage), the exception propagated out
of the signal, aborting the save entirely -- so the password change
was silently lost, but the API token had already been regenerated as
a side effect.

Reorder so the token is only regenerated once the notification email
has actually been sent, and wrap send_mail() so a mail failure raises
a clear ValidationError instead of a raw SMTP/socket exception. The
save is still aborted on failure by design: users should not have
their password changed without being notified.

Signed-off-by: Anna Larch <anna@nextcloud.com>
…e failure

password_changed_signal can now raise ValidationError (previous
commit) when it can't notify the user by email, aborting the
password save. Both places that call user.save() as part of a
password change -- the logged-in /account/password/ form and the
forgot-password /password/reset/key/... flow -- left that exception
unhandled, so users hit a raw error page instead of a clear message.

Override PasswordView.form_valid() and add a
PasswordResetFromKeyView (wired ahead of allauth's own URL) that
catch the ValidationError and re-render the form with a
messages.error() warning instead.

Signed-off-by: Anna Larch <anna@nextcloud.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant