[Fixed]-Inform user that email is invalid using Django's Password Reset

23👍

So I finally figured it out myself. Here’s my implementation:

class EmailValidationOnForgotPassword(PasswordResetForm):
    def clean_email(self):
        email = self.cleaned_data['email']
        if not User.objects.filter(email__iexact=email, is_active=True).exists():
            raise ValidationError("There is no user registered with the specified email address!")

        return email

You also need to add {'password_reset_form': EmailValidationOnForgotPassword} to urls.py. Here’s an example:

url(r'^user/password/reset/$',
    'django.contrib.auth.views.password_reset',
    {'post_reset_redirect': '/user/password/reset/done/',
     'html_email_template_name': 'registration/password_reset_email.html',
     'password_reset_form': EmailValidationOnForgotPassword},
    name="password_reset"),

5👍

For later versions of Django such as Django 2.1 there is a similar question with slightly modified code.

#forms.py
from django.contrib.auth.forms import PasswordResetForm

class EmailValidationOnForgotPassword(PasswordResetForm):

    def clean_email(self):
        email = self.cleaned_data['email']
        if not User.objects.filter(email__iexact=email, is_active=True).exists():
            msg = _("There is no user registered with the specified E-Mail address.")
            self.add_error('email', msg)
        return email

And

#urls.py
from accounts.forms import EmailValidationOnForgotPassword

path('accounts/password_reset/', auth_views.PasswordResetView.as_view(form_class=EmailValidationOnForgotPassword), name='password_reset'),

Please be aware that this can be used to obtain usernames/e-mails. One way to reduce this issue is to respond with a 429 Too Many Requests as soon an user tries 3 different E-Mails. This can be achived using for example django-ratelimit

👤ohlr

1👍

forms.py

from django.contrib.auth.forms import PasswordResetForm
class EmailValidationOnForgotPassword(PasswordResetForm):
    def clean_email(self):
        email = self.cleaned_data['email']
        if not NewUser.objects.filter(email__iexact=email, is_active=True).exists():
            raise forms.ValidationError("There is no user registered with the specified email address!")
        return email

urls.py

from users.forms import EmailValidationOnForgotPassword
from django.contrib.auth import views as auth_views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('users.urls',namespace='users')),
 
    path('reset_password', auth_views.PasswordResetView.as_view(form_class=EmailValidationOnForgotPassword), name='reset_password'),
    path('reset_password_sent',auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
    path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
    path('reset_password_complete/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]

password_reset_form.html

 <form method="post">{% csrf_token %}

   {% if form.errors %}
   {% for field in form %}
   {% for error in field.errors %} 
   <div class="alert alert-danger">
      <strong>{{ error|escape }}</strong>
   </div>
   {% endfor %}
   {% endfor %}
   {% endif %} 

   <div class="form-group">
      <label><strong>Email</strong></label>
      {{ form.email|attr:"type:email"|attr:"class:form-control"|attr:"placeholder:Email" }}
   </div>
   <div class="text-center">
      <button type="submit" class="btn btn-primary btn-block">SUBMIT</button>
   </div>
</form>

Leave a comment