5

Good day, I am trying to override the password_reset_email of Django allauth. the issue is that it successfully overrides but I get the html code just sent to the user instead of the html representation.

I was expecting a styled email just like I got for my confirmation email, but this does not seem to be the case.

In my templates/registration/password_reset_email.html

{% load i18n %}
{% autoescape off %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Confirm Your E-mail</title>
    <style>
        .body {
            background-color: #f6f6f6;
            padding: 30px;
            display: flex;
            flex-direction: row;
            justify-content: center; 
            align-items: center;
        }
        
        .content {
            background-color: #FFFFFF;
            color: #4d4d4d;
            max-width: 400px;
            padding: 20px;
            margin: auto;
        }
        
        .title {
            font-size: 20px;
            font-weight: 600;
            margin: 10px 0;
            text-align: center
        }
        
        .intro {
            font-size: 15px;
            align-self: flex-start;
            color: #4d4d4d;
            margin-bottom: 15px;
        }
        
        .main-body {
            font-size: 15px;
            color: #4d4d4d;
            margin-bottom: 15px;
        }
        
        .alt-body {
            width: 100%;
            display: flex;
            flex-direction: row !important;
            justify-content: center !important;
        }

        .alt-body>a {
            font-size: 17px;
            font-weight: 500;
            text-decoration: none;
            color: #FFFFFF;
            margin: auto;
            margin-bottom: 15px;
        }
        
        .cta-button {
            background-color: #525659;
            padding: 9px 100px;
            border: 2px solid #525659;
            border-radius: 35px;
            align-self: center;
        }

        .cta-button:hover {
            background-color: #000000;
            border: 2px solid #000000;
        }
        
        .sub-body {
            font-size: 15px;
            color: #4d4d4d;
            margin-bottom: 15px;
            margin-top: 0;
            align-self: flex-start;
        }

        .sub-body a {
            text-decoration: none;
            color: #4d4d4d;
            font-size: 15px;
        }

        .sub-body a:hover {
            text-decoration: none;
            color: #4d4d4d;
        }

        .outro {
            margin: 20px 0;
        }

        .outro > p {
            font-size: 15px;
            margin-top: 3px;
            margin-bottom: 3px;
        }

        .outro a {
            text-decoration: none;
            color: #4d4d4d;
            font-size: 15px;
            margin-top: 3px;
            margin-bottom: 3px;
        }

        .outro a:hover {
            text-decoration: none;
            color: #4d4d4d;
        }
    </style>
</head>
<body class="body">
    <div class="content">
        {% blocktrans with site_name=current_site.name site_domain=current_site.domain %}

        <p class="title">Email Verification</p>

        <p class="intro">Hello there,</p>

        <p class="main-body">
            Simply click on the button to verify your cre8ive-mart email.
        </p>

        <div class="alt-body">
            <a href="{{ activate_url }}" class="cta-button">Verify Email</a>
        </div>
        
        <p class="sub-body">
            if you have any questions, please contact <a href="mailto:todoetester@gmail.com">todoetester@gmail.com</a>
        </p>

        <div class="outro">
            <p class="outro-greeting">Sincerely,</p>
            <p class="outro-main">cre8ive-mart</p>
            <a href="#" class="outro-website">cre8ivemart.com</a>
        </div>

        {% endblocktrans %}
    </div>
</body>
</html>
{% endautoescape %}

but the email I get is like this

but the email I get is just the html code back

it is just the html representation i get back. instead of a styled component.

Opeyemi Odedeyi
  • 766
  • 1
  • 10
  • 38

2 Answers2

3

I can't see the code you used but here is what works for me with django rest auth.

create a custom password reset serializer

from django.contrib.auth.forms import PasswordResetForm
from django.conf import settings
from django.utils.translation import gettext as _
from rest_framework import serializers

###### IMPORT YOUR USER MODEL ######
from .models import User


class PasswordResetSerializer(serializers.Serializer):
    email = serializers.EmailField()
    password_reset_form_class = PasswordResetForm

    def validate_email(self, value):
        self.reset_form = self.password_reset_form_class(data=self.initial_data)

        if not self.reset_form.is_valid():
            raise serializers.ValidationError(_('Error'))

        ###### FILTER YOUR USER MODEL ######
        if not User.objects.filter(email=value).exists():

            raise serializers.ValidationError(_('Invalid e-mail address'))
        return value

    def save(self):
        request = self.context.get('request')
        opts = {
            'use_https': request.is_secure(),
            'from_email': getattr(settings, 'DEFAULT_FROM_EMAIL'),

            ###### USE YOUR TEXT FILE ######
            'email_template_name': 'account/email/password_reset_key.html',
            'html_email_template_name': 'account/email/password_reset_key.html',
            'request': request,
        }
        self.reset_form.save(**opts)

Then have the password reset email template as account/email/password_reset_key.html

Then in the settings, update your password reset serializer to point to the custom password reset serializer.

REST_AUTH_SERIALIZERS = {
    'PASSWORD_RESET_SERIALIZER': '<path to >password_serializer.PasswordResetSerializer'
}

This should work, if it doesn't you will have to provide more context on how you setup this particular password reset flow so we can determine why it's sending it as text instead of the html representation

  • 1
    okay, it works as html representation, but the data is not sent with the email. I noticed that the data like the password reset link, site and domain name wasn't sent to the email with the form. – Opeyemi Odedeyi Feb 05 '20 at 10:51
  • please note that the 'email_template_name' should contain a .txt not a .html - you should not define the same template twice. – Xen_mar Feb 10 '20 at 14:48
3

With newer versions of django-rest-auth, we need less code to achieve what the OP wants:

Settings.py

REST_AUTH_SERIALIZERS = {
    'PASSWORD_RESET_SERIALIZER': 'users.serializer.PasswordResetSerializer'
}

Serializer.py

from rest_auth.serializers import PasswordResetSerializer

class PasswordResetSerializer(PasswordResetSerializer):

    def get_email_options(self):
        return {
            'subject_template_name': 'account/email/password_reset_key_subject.txt',
            'email_template_name': 'account/email/password_reset_key.txt',
            # 'html_email_template_name': 'account/password_reset_key.html',
        }
Xen_mar
  • 8,330
  • 11
  • 51
  • 74
  • 1
    bro, the html representation works now, but I noticed that the data wasn't passed through. I noticed that data like the password reset link, domain and site name wasn't sent with the email, which means the user cannot eventually reset his password. – Opeyemi Odedeyi Feb 10 '20 at 14:09
  • 1
    The template representation is the same as the one above. but here is a link to it too https://stackoverflow.com/questions/60078367/resetting-password-of-user-django-rest-auth – Opeyemi Odedeyi Feb 10 '20 at 14:11