How to customize django rest auth password reset email content/template

McLosys Creative picture McLosys Creative · Jan 20, 2016 · Viewed 17.6k times · Source

In django rest_auth password reset, default email content look like following:-

You're receiving this email because you requested a password reset for your user account at localhost:8000.

Please go to the following page and choose a new password:

http://localhost:8000/api/reset/Kih/89a-23809182347689312b123/

Your username, in case you've forgotten: test

Thanks for using our site!

The localhost:8000 team

How to customize content of this email ?

Answer

Brian K. picture Brian K. · Aug 31, 2018

I recently needed to implement the same thing in one of my projects and could not find a thorough answer anywhere.

So I'm leaving my solution here for anyone who needs it in the future.

Expanding on mariodev's suggestion:

1. Create your own PasswordResetSerializer with customized save method.

Base PasswordResetSerializer copied from here: (https://github.com/Tivix/django-rest-auth/blob/v0.6.0/rest_auth/serializers.py#L102)

yourproject_app/serializers.py

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 ExampleUserModel

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 ExampleUserModel.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': 'example_message.txt',

            'request': request,
        }
        self.reset_form.save(**opts)

2. Connect custom PasswordResetSerializer to override default

yourproject_app/settings.py

REST_AUTH_SERIALIZERS = {
    'PASSWORD_RESET_SERIALIZER': 
        'yourproject_app.serializers.PasswordResetSerializer',
}

3. Add the path to the directory where your custom email message text file is located to TEMPLATES

yourproject/settings.py

TEMPLATES = [
    {
        ...
        'DIRS': [os.path.join(BASE_DIR, 'yourproject/templates')],
        ...
    }
]

4. Write custom email message (default copied from Django)

yourproject/templates/example_message.txt

{% load i18n %}{% autoescape off %}
{% 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 %}
{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }}

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

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

{% endautoescape %}

UPDATE: This solution was written for an older version of django-rest-auth (v0.6.0). As I can tell from the comments, it seems there have been some updates made to the source package that more readily handle custom email templates out-of-box. It is always better to use methods defined in a package rather than overriding them like in my solution. Though once a necessity, it may not be so any longer.