Search code examples
pythondjangodjango-formsrabbitmqcelery

How to send Django's password reset email using Celery (without third-party package)?


First of all I know this question has been answered previously here which use a third-party package django-celery-email, but I am trying to figure out how to do do such job without relaying on any third-party library.

So I need to send password reset email asynchronously with Celery.

My forms.py file look like this:

from django import forms
from accounts.tasks import send_mail
from django.contrib.auth.forms import PasswordResetForm as PasswordResetFormCore


class PasswordResetForm(PasswordResetFormCore):
    email = forms.EmailField(max_length=254, widget=forms.TextInput(
        attrs={
            'class': 'form-control',
            'id': 'email',
            'placeholder': 'Email'
        }
    ))

    def send_mail(self, subject_template_name, email_template_name,
                  context, from_email, to_email, html_email_template_name=None):
        """
        This method is inherating Django's core `send_mail` method from `PasswordResetForm` class
        """
        super().send_mail(subject_template_name, email_template_name,
                  context, from_email, to_email, html_email_template_name)

I am trying to send mail via Celery from send_mail method of PasswordResetForm class. I mean calling super().send_mail(...) with Celery. I also have a send_mail function in my Celery's tasks.py file, where I am trying to pass super().send_mail method as an argument to call it from there.

Right now my tasks.py file looks something like this:

from __future__ import absolute_import, unicode_literals


@shared_task
def send_mail():
    pass

I am using RabbitMQ as message broker alongside with Celery


Solution

  • Ok I have come across with a working solution for this. Here is my solution.

    I have changed forms.py like following

    from django import forms
    from accounts.tasks import send_mail
    from django.contrib.auth.forms import PasswordResetForm as PasswordResetFormCore
    
    
    class PasswordResetForm(PasswordResetFormCore):
        email = forms.EmailField(max_length=254, widget=forms.TextInput(
            attrs={
                'class': 'form-control',
                'id': 'email',
                'placeholder': 'Email'
            }
        ))
    
        def send_mail(self, subject_template_name, email_template_name, context, 
                      from_email, to_email, html_email_template_name=None):
            context['user'] = context['user'].id
    
            send_mail.delay(subject_template_name=subject_template_name, 
                            email_template_name=email_template_name,
                            context=context, from_email=from_email, to_email=to_email,
                            html_email_template_name=html_email_template_name)
    

    And the changed tasks.py is like following

    from __future__ import absolute_import, unicode_literals
    from accounts.models import User
    from django.contrib.auth.forms import PasswordResetForm
    
    
    @shared_task
    def send_mail(subject_template_name, email_template_name, context,
                  from_email, to_email, html_email_template_name):
        context['user'] = User.objects.get(pk=context['user'])
    
        PasswordResetForm.send_mail(
            None,
            subject_template_name,
            email_template_name,
            context,
            from_email,
            to_email,
            html_email_template_name
        )