How to make Django Password Reset Email Beautiful HTML?

My Django app is currently set up to use its own registration package to handle authentication and user management.

I created several files in myApp/templates/registration , which are used to send a password reset token, as described in these documents .

Works fine. Except that password reset email is a hideous text freak. I would like it to match the look of all the other emails that my application sends. IE: I want it to be HTML and contain images, styles and links. How can i do this?

I followed the detailed instructions here . However, there is an error in this code with which I do not know what to do: 'CustomPasswordResetForm' object has no attribute 'users_cache'

Can someone show me a detailed working example on how to do this? I would like it to be not so difficult.

+9
source share
11 answers

[dragged from Does Django password_reset support html HTML templates? ]

After some trial and error, I discovered a much simpler way to provide my own reset password pattern in the latest version of Django (1.8).

In project/urls.py add the following imports:

 from django.contrib.auth import views as auth_views from django.core.urlresolvers import reverse_lazy 

And add the following route to your urls before the usual inclusion of the django contrib url route:

 url(r'^accounts/password/reset/$', auth_views.password_reset, { 'post_reset_redirect': reverse_lazy('auth_password_reset_done'), 'html_email_template_name': 'registration/password_reset_html_email.html' }, name='auth_password_reset'), url('^', include('django.contrib.auth.urls')), 

And then in the application’s templates/registration folder, create password_reset_html_email.html with whatever HTML template you want.

The reason this seemed necessary is because of the source for django/contrib/auth/views.py , which has a view function for which the original URL is mapped to:

 147 def password_reset(request, is_admin_site=False, 148 template_name='registration/password_reset_form.html', 149 email_template_name='registration/password_reset_email.html', 150 subject_template_name='registration/password_reset_subject.txt', 151 password_reset_form=PasswordResetForm, 152 token_generator=default_token_generator, 153 post_reset_redirect=None, 154 from_email=None, 155 current_app=None, 156 extra_context=None, 157 html_email_template_name=None): 158 

The html_email_template_name value html_email_template_name set to None by default, and there seemed to be no way to assign its value other than rewriting this particular route for this case, as I mentioned above.

Hope this helps without having to copy-paste a bunch of almost identical code, for example, some of the other suggested answers - feedback is welcome, of course!

+9
source

The django authentication helper default views cannot send multicast (HTML) emails because the basic send_mail method send_mail not support HTML emails yet.

This will be fixed in the next version by adding the html_message flag.

The easiest way to fix this is to create your own reset password and use EmailMultiAlternatives to send your message, which allows your HTML to display correctly in the mail client.

You can use the existing form and make your changes:

 class HTMLPasswordResetForm(forms.Form): email = forms.EmailField(label=_("Email"), max_length=254) def save(self, domain_override=None, subject_template_name='registration/password_reset_subject.txt', email_template_name='registration/password_reset_email.html', use_https=False, token_generator=default_token_generator, from_email=None, request=None): """ Generates a one-use only link for resetting password and sends to the user. """ # from django.core.mail import send_mail from django.core.mail import EmailMultiAlternatives UserModel = get_user_model() email = self.cleaned_data["email"] active_users = UserModel._default_manager.filter( email__iexact=email, is_active=True) for user in active_users: # Make sure that no email is sent to a user that actually has # a password marked as unusable if not user.has_usable_password(): continue if not domain_override: current_site = get_current_site(request) site_name = current_site.name domain = current_site.domain else: site_name = domain = domain_override c = { 'email': user.email, 'domain': domain, 'site_name': site_name, 'uid': urlsafe_base64_encode(force_bytes(user.pk)), 'user': user, 'token': token_generator.make_token(user), 'protocol': 'https' if use_https else 'http', } subject = loader.render_to_string(subject_template_name, c) # Email subject *must not* contain newlines subject = ''.join(subject.splitlines()) email = loader.render_to_string(email_template_name, c) msg = EmailMessage(subject, email, from_email, [user.email]) msg.content_subtype = "html" # Main content is now text/html msg.send() #send_mail(subject, email, from_email, [user.email]) 

Once you do this, change the call to password_reset and go to the new form class:

 password_reset(request, password_reset_form=HTMLPasswordResetForm) 
+7
source

Adding my results for django version 2.0 as I found that the rest of the answers to this question are out of date.

Since 2.0, the correct way to add a URL to your urls.py file is with path() :

 from django.urls import path from django.contrib.auth import views as auth_views path('accounts/password_reset/', auth_views.PasswordResetView.as_view( html_email_template_name='registration/password_reset_html_email.html' )), 

The next piece of code to highlight here is the .as_view() function. Django 2.0 implements auth views as classes. For more information, see Authentication Documentation.

Then you “convert” the class into a view using `.as_view (), and you can pass the class attributes defined in the source code as named parameters.

Passing to html_email_template_name (default is None) automatically sends the html email address.

You can access the source code for PasswordResetView by following this python path: django.contrib.auth.views

Here you can see other class attributes that you can pass to PasswordResetView and other auth views. This is very useful for passing extra_context to your django templates.

+3
source

Have you tried to edit this template? registration / password _reset_email.html

You can add the password_reset_email.html file to your templates / registration folder in your project, and then add the appropriate / HTML sections to get a good template. The default template is empty.

+1
source

For django2.2 use this thing to add your own email template to your password reset email template

In urls.py file add these lines

 urlpatterns = [ path('password-reset', auth_views.PasswordResetView.as_view( template_name='accounts/password_reset.html', html_email_template_name="accounts/email_reset_template.html", email_template_name='accounts/password_reset_email.html', subject_template_name="accounts/password_reset_subject.txt", ), name="password_reset"), path('password-reset/done', auth_views.PasswordResetDoneView.as_view( template_name='accounts/password_reset_done.html'), name="password_reset_done"), path('password-reset-complete/', auth_views.PasswordResetCompleteView.as_view( template_name='accounts/password_reset_complete.html'), name="password_reset_complete"), path('password-reset-confirm/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view( template_name='accounts/password_reset_confirm.html'), name="password_reset_confirm"), #Add more urls you want ] 

After adding the above lines, you can omit the email_template name from 'password_reset' if you provide the html template name, but to use the template in the email you need the html template, now select your own html template from another website, which you want and post it. file inside the same folders where there are all the files for resetting the password.

Now the important part is adding a link to your own HTML template, to add this, you need to add the following lines to your own HTML template, for example:

 <a href="{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}" style=".."> Reset Password </a> 

and you can add the line below anywhere in the HTML template to suit your needs

  {% load i18n %} {% autoescape off %} You're receiving this e-mail because you requested a password reset for your Xandar account. {% trans "Thanks for using our site!" %} {% blocktrans %}The {{ site_name }} team{% endblocktrans %} {% endautoescape %} 

If you still have doubts, let me know

This definitely works, and I used it in my project.

+1
source

Django 2

 # add this import from django.contrib.auth import views as auth_view ... # add this path path('accounts/password_reset/', auth_views.PasswordResetView.as_view( html_email_template_name='registration/password_reset_email.html' )), # just before path('accounts/', include('django.contrib.auth.urls')), 
+1
source

You need to override the default html. To do this, go to the tt2 folder and copy password_reset_email.html from django templates and paste it into [templates]/registration/password_reset_email.html . Then define your CSS and edit the html by default, and if your HTML code appears in the body, disable django template manager autostart, but it will not be recommended.

0
source

You can do the following.

Add both password_reset parameters:

 html_email_template_name='YOUR TEMPLATE PATH', email_template_name='YOUR TEMPLATE PATH' 

This worked for me (Django 1.11)

0
source

The easiest (and honestly the only way) to get email to be sent as HTML is to override the form_valid method.

views.py:

 class MyPasswordResetView(PasswordResetView): # forcing to use HTML email template (param: html_email_template_name) def form_valid(self, form): opts = { 'use_https': self.request.is_secure(), 'token_generator': self.token_generator, 'from_email': self.from_email, 'email_template_name': self.email_template_name, 'subject_template_name': self.subject_template_name, 'request': self.request, 'html_email_template_name': 'registration/password_reset_email.html', 'extra_email_context': self.extra_email_context, } form.save(**opts) return HttpResponseRedirect(self.get_success_url()) 

urls.py

 path('password_reset/', myapp.MyPasswordResetView.as_view(), name='password_reset'), 
0
source

1) Add the password_reset_email.html file to the Templates / Registration folder in your myApp project.
2) Move "django.contrib.admin" below "myApp" in your INSTALLED_APPS.
https://github.com/macropin/django-registration/issues/50#issuecomment-142637807

Not the best solution, but it worked for me!

0
source

I solved this problem by changing the password_reset function parameter in the django.contrib.auth file. By default, html_email_template_name is set to None. If you forward it to the file 'registration / password_reset_email.html', it will send emails with the correct html.

 def password_reset(request, template_name='registration/password_reset_form.html', email_template_name='registration/password_reset_email.html', subject_template_name='registration/password_reset_subject.txt', password_reset_form=PasswordResetForm, token_generator=default_token_generator, post_reset_redirect=None, from_email=None, extra_context=None, html_email_template_name='registration/password_reset_email.html', extra_email_context=None): 
0
source

All Articles