How to send Email using Celery in Django application

silver and black laptop computer
Reading Time: 6 minutes

Hello Readers! In this blog we will see how to send email using celery in the django application. We will use celery_flower for the monitoring of the tasks done by the celery. As you all know celery is use for the tasks for doing asynchronously. A task can be anything like any python functions which have something to execute. 

Prerequisites:

Before starting we have some prerequisites that we need to follow:

  1. Celery must be installed. You can install the celery using pip:
        $ pip install celery
  1. We will use rabbitmq as a broker here. So, it must be running. Use the following command for running rabbitmq using docker:
        $ docker run -d -p 5672:5672 rabbitmq
  1. For sending mail using celery we need to turn on some settings in our email:
  • Firstly turn the Less secure app access on.
  • Next turn on the 2-step verification
  • Generate the app password and copy-paste it somewhere. We will use this password later.

So, let’s get started!

Step1: As we have successfully installed celery and RabbitMQ, now we have to create one django application.

First, create a Django project using the below command:

$ django-admin startproject <poject_name>

Under this project create a Django app:

$ python3 manage.py startapp <app_name>

So, for me the django project name is django_with_celery and the app name is sending_email_app. It will create a predefined directory structure. 

Step2: Create a file named celery.py inside your django project. Inside this file we will define an instance of the celery library. Paste the following code inside your file:

from __future__ import absolute_import
import os
from celery import Celery


os.environ.setdefault('DJANGO_SETTING_MODULE' , 'django_with_celery.settings')

app = Celery ('django_with_celery')

app.config_from_object('django.conf:settings' , namespace='CELERY')

app.autodiscover_tasks()

We are defining our django settings file using the environment variable.

os.environ.setdefault('DJANGO_SETTING_MODULE' , 'django_with_celery.settings')

With the below line Celery will automatically discover tasks from all of my django apps.

app.autodiscover_tasks()

Step3: We need to import this app in your project/__init__.py module. This ensures that the app is loaded when Django starts. 

from .celery import app as celery_app
__all__ = ('celery_app',)

Step4: Now we have to define our settings in the project/settings.py file. Inside installed apps lists we have to add our app name there.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'sending_email_app',
]

After this we will define our celery settings in this file by adding following lines:

CELERY_BROKER_URL = 'amqp://guest@localhost:5672//'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Kolkata'

My celery broker i.e Rabbitmq is running. Mention there the url of your celery broker. Rest will be the same as above.

Now, as we are using celery here for sending the email to the user asynchronously. So, for this we have to define all the email settings here. For this paste the following settings in settings.py file:

EMAIL_BACKEND ='django.core.mail.backends.smtp.EmailBackend'
#add your host of the email here in this case its Gmail so we are going to use Gmail host
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
#add the port number of the email server
EMAIL_PORT = 587
#add your gamil here
EMAIL_HOST_USER = 'naincygupta100@gmail.com'
#add your password here
EMAIL_HOST_PASSWORD = '<your_app_password>'
DEFAULT_FROM_EMAIL='Celery <naincygupta100@gmail.com>'

Change the above settings according to your needs.

Step5: Celery performs the tasks that we define inside our application. So, let’s create a file inside our app named tasks.py. Inside this file I will write a python function for sending email. We will use a for loop here this loop will send mail to all the users defined in django admin. Mention your mail_subject and mail_message as per your wish inside this function:

from django.contrib.auth import get_user_model
from celery import shared_task
from django.core.mail import send_mail
from django_with_celery import settings
@shared_task(bind=True)
def send_mail_func(self):
    #operations
    users = get_user_model().objects.all()
    for user in users:
        mail_subject="Hye from celery"
        message="Yaaaa....I have completed this task by celery!!"
        to_email=user.email
        send_mail(
            subject= mail_subject,
            message=message,
            from_email=settings.EMAIL_HOST_USER,
            recipient_list=[to_email],
            fail_silently=True,
        )
    return "Done"

Step6: Now, we will define our views inside the app/views.py file. Django views are python functions that take http requests and return http response, like HTML documents. Paste the following code inside your file:


from django.http import HttpResponse
from django.shortcuts import render
from sending_email_app.tasks import send_mail_func
# Create your views here.

def send_mail_to_all(request): 
    send_mail_func.delay()  
    return HttpResponse("Sent Email Successfully...Check your mail please")

This line “Sent Email Successfully…Check your mail please” can be change as your wish. 

Step7: It’s time to add urls for sending email in our project/urls.py file. Urls.py file is used for defining routing in a web application. When a web request is made to a Django application, it is the job of the urls.py file to determine what to do with that request. Let’s add url for sendmail in this file:

from django.contrib import admin
from django.urls import path
from sending_email_app import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('sendmail/', views.send_mail_to_all, name="sendmail"),

]

Step8: Finally everything is done.Now, it’s time to run our application and execute the tasks using celery. Firstly run the following command where is your manage.py:

$ python3 manage.py runserver
django application

Run your django server using this command:

$ python3 manage.py runserver
django runserver

Celery is my worker here. Run your worker using the following command:

$ celery -A django_with_celery worker --loglevel=info 
celery worker

When you will open the django admin page using this url http://127.0.0.1:8000/admin you will find the list of users. You can also add or delete the users from here. So, the mail will be send to all the users mentioned in this list. I have given here only my email id. So, the mail would only be sent to me.

django-admin

Let’s send the mail by hitting this url http://127.0.0.1:8000/sendmail/  as we have given this url in our project/urls.py file. As you will hit this url the mail will be sent to you.

Django application

I have found my email successfully.

Email using Celery in Django application

And in the celery you can see this the Task sending_email_app.tasks.send_mail_func[148f9eed-3461-47b2-8126-ebf0728d021c] succeeded in 4.3880218180001975s: ‘Done’

celery

Yaa….We have successfully 👏 sent the mail by using the celery in django application. 

Monitoring tasks and workers using celery_flower:

The Celery Flower is a tool for monitoring your celery tasks and workers. It’s web based and allows you to see task progress, details, and worker status. So, for this we have to install the celery_flower by using the following command:

$ pip install flower

After this for running celery_flower with your django application use the following command:

$ celery -A django_with_celery flower  --address=127.0.0.6 --port=5566 --persistent=True --db=flower.db
install celery_flower

Open the url here you will find the celery_flower running. And –persistent= True is given for the data to not be lost if I stop my celery_flower. You can see my worker status here.

celery_flower

You can find the list of all the tasks that we have performed here by using my celery in the django application.

celery_flower

We can also see my broker here i.e rabbitmq.

celery_flower

This is how we can monitor the celery tasks and workers using celery_flower.

We are all done now!!!!

Conclusion:

Thank you for sticking to the end. In this blog we can have sent the email using celery in our django application. And finally we monitor tasks and workers using celery_flower. If you like this blog, please do show your appreciation by giving thumbs ups and share this blog and give me suggestions on how I can improve my future posts to suit your needs.

HAPPY LEARNING!

Written by 

Naincy Kumari is a DevOps Consultant at Knoldus Inc. She is always ready to learn new technologies and tools. She loves painting and dancing.

Leave a Reply