0

I'm trying to override content for default password_reset_email.html with some html tag but it doesn't work. Here is my modification. For testing purpose, I'm just using p tag. But i doesn't work. I'm totally unaware what going wrong.

Here is my process.

urls.py

path('accounts/', include('django.contrib.auth.urls')),

and here is my html templates

{% load i18n %}
{% autoescape on %}
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at
{{ site_name }}.{% endblocktrans %}

{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
{% endblock %}
<p>Hello world</p>
{% trans 'Your username, in case you’ve forgotten:' %} {{ user.get_username }}

{% trans "Thanks for using our site!" %}

{% blocktrans %}The {{ site_name }} team{% endblocktrans %}

{% endautoescape %}

and here is the output

enter image description here

Sahil
  • 1,387
  • 14
  • 41

2 Answers2

1

The email_template_name is standard one that is send in raw text, not in HTML. Indeed, in the PasswordResetView we see:

class PasswordResetView(PasswordContextMixin, FormView):
    email_template_name = 'registration/password_reset_email.html'
    extra_email_context = None
    form_class = PasswordResetForm
    from_email = None
    html_email_template_name = None
    subject_template_name = 'registration/password_reset_subject.txt'
    success_url = reverse_lazy('password_reset_done')
    template_name = 'registration/password_reset_form.html'
    title = _('Password reset')
    token_generator = default_token_generator

    @method_decorator(csrf_protect)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)

    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': self.html_email_template_name,
            'extra_email_context': self.extra_email_context,
        }
        form.save(**opts)
        return super().form_valid(form)

In case you thus alter the registration/password_reset_email.html, it will still send the email as raw text, so an email client will render it as raw text.

What you can do is simply make a new path that takes precedence, and where you override the html_email_template_name:

# urls.py

urlpatterns = [
    path('accounts/password_reset/',
        views.PasswordResetView.as_view(
            html_email_template_name='registration/password_reset_email.html'
        ),
        name='password_reset'
    ),
    path('accounts/', include('django.contrib.auth.urls')),
    # …
]

It is important that this path appears before the path that includes the django.contrib.auth.urls, since otherwise it will still take the "old" path.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • this only render html but doesn't render internal css and static images, but its works for inline css – Sandeep Kushwaha May 31 '20 at 17:32
  • @SandeepKushwaha: that is pefectly normal, since the static css, etc. are not passed with the template, and `{% static ... %}`, will only render `/path/to/file.css`, not the hostname, so in that case you need to use `{{ protocol }}://{{ domain }}{% static ... %}`. Furthermore email clients will sometimes block fetching external resources, since this is a privacy issue. After all, one could use that to find out if a user has read the mail. – Willem Van Onsem May 31 '20 at 17:34
  • It is also not works for internal css, I mean css and html are in same page. and also i tried this one ```{{ protocol }}://{{ domain }}{% static ... %}``` but still i'm facing same problem for images. Here i'm using my own mail server to send email. – Sandeep Kushwaha May 31 '20 at 17:46
  • @SandeepKushwaha: the email *server* is not the problem. It is the client that needs to do the work. You just send an email that says that it is html and then the HTML page. But most email clients are quite restrictive in fetching external resources. For example I configure my email client to refuse all external resources, and not even render the email if there is no raw text part in the email. – Willem Van Onsem May 31 '20 at 17:48
  • tried to replace extrnal svg icon with inline svg, after that it render all the svg code instead of showing image – Sandeep Kushwaha May 31 '20 at 17:49
  • @SandeepKushwaha: as you can see here https://css-tricks.com/a-guide-on-svg-support-in-email/ and here https://stackoverflow.com/q/37753911/67579 very little clients will support that. – Willem Van Onsem May 31 '20 at 17:53
  • Thanks for your support, i think due to the localhost, image is unable to find. If I'm wrong please correct me. Happy coding – Sandeep Kushwaha May 31 '20 at 18:04
  • @SandeepKushwaha: that is possible, what if you use some url from somewhere else? If you later decide to deploy it, I think you better do some tests to check if the images are fetched properly. – Willem Van Onsem May 31 '20 at 18:07
0

This is just 5 letters to be added, and boom..!! you work will done.

change---

urls.py

patterns = [
path('accounts/password_reset/',
    views.PasswordResetView.as_view(
        email_template_name='registration/password_reset_email.html'
    ),
    name='password_reset'
),
path('accounts/', include('django.contrib.auth.urls')),
# …]

to--

patterns = [
path('accounts/password_reset/',
    views.PasswordResetView.as_view(
        html_email_template_name='registration/password_reset_email.html'
    ),
    name='password_reset'
),
path('accounts/', include('django.contrib.auth.urls')),
# …]