djangodjango-viewsdjango-formsdjango-authenticationdjango-email

django send mail on update password


I have a ChangePasswordView for my User:

class ChangePasswordView(PasswordChangeView):
    form_class = ChangePasswordForm
    success_url = reverse_lazy('password_success')

#success view
def password_success(request):
    return render(request, 'accounts/password_success.html')

I've been using the send_mail function to notify Users when they update their information, however, in this case, I'm having some trouble.

I added this to my ChangePasswordView:

    def form_valid(self, form):
        form.update_password_email()
        return redirect(self.success_url)

And this to my ChangePasswordForm:

def update_password_email(self):
        email = self.cleaned_data.get('email', None)
        if email and self.is_valid():
            send_mail(
                'Password changed',
                'Message',
                NOTIFICATION_EMAIL,
                [self.cleaned_data['email']],
                fail_silently=True
            )

But it doesn't work. I go to django's change password page, enter my old password, new password and confirm it, but the logic isn't running. Instead I get redirected to my success_url with no password change and no email notification.

Is the issue happening because of my view or my form? And what issue is happening.

Also do I need form_valid(): and if self.is_valid(): or is one of those extra? I assume they're doing the same thing.


Solution

  • form_valid is called after the form has been validated (https://github.com/django/django/blob/3b79dab19a2300a4884a3d81baa6c7c1f2dee059/django/views/generic/edit.py#L153).

    What I would do is to call send_mail from within form_valid:

    def form_valid(self, form):
        email = form.cleaned_data["email"]
        send_email(
            "Password changed",
            "Message",
            NOTIFICATION_EMAIL,
            [email],
            fail_silently=True,
        )
        return redirect(self.success_url)