Home/Email Notification in Django

Email Notification in Django

Published On: 29 December 2020.By .
  • General

For sending email notification in django we use django’s send_mail function, with using some smtp sever.

we can get smtp server from free smtp service providers like SendGrid.

In our settings.py file we define some parameters for sending mails like:-

if os.getenv('DEV_ENV') == 'PRODUCTION':
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_USE_TLS = True
    EMAIL_PORT = 587
    EMAIL_HOST = "email-smtp.****com"
    EMAIL_HOST_USER = "AK*******GSPHDZ72SANP"
    EMAIL_HOST_PASSWORD = "*******"
    FROM_EMAIL = 'Interface <default server>'
else:
    EMAIL_BACKEND = "sgbackend.SendGridBackend"
    SENDGRID_API_KEY = os.getenv('SENDGRID_KEY')
    FROM_EMAIL = '<mail id registered on sendgrid>'

we define a function in our service file for sending mails like-

def send_email(subject="", html_content="", recipients=[], files=None, from_email=settings.FROM_EMAIL):
    try:
        from_email = settings.FROM_EMAIL if from_email is None else from_email
        if subject == "" or html_content == "" or len(recipients) == 0:
            return False
        msg = EmailMessage(subject=subject, body=html_content, from_email=from_email,to=recipients,reply_to=[settings.FROM_EMAIL])
        msg.content_subtype = "html"  # Main content is now text/html
        if files is not None:
           msg.attach_file(files)
        mail_status = msg.send()
        if mail_status:
            log_info.info("email send")
            return True, {}
        else:
            log.error("error in sending email.")
            return False, {'message': 'error in sending email.'}
    except Exception as e:
        log.error("Exception: " + str(e))
        return False, {'message': str(e)}

Now if we want to send mails asynchronously we define a decorator:

def execute_in_background(function):
    def start_thread(*args, **kwargs):
        thread = Thread(target=function,
                  args=args, kwargs=kwargs)
        thread.start()

    return start_thread

and define a async send_mail function which calls previously defined send_mail function,

@execute_in_background
def send_email_async(subject="", html_content="", recipients=[], files=None, from_email=settings.FROM_EMAIL):
    try:
        stat,msg = send_email(subject=subject, html_content=html_content, recipients=recipients, files=files, from_email=from_email)
    except Exception as e:
        log.error("Exception in send_email_async: " + str(e))

Now for sending template based email notifications we define some types of notifications in a constant file like:

EMAIL_NOTIFICATION_TYPES = {
    "VERIFICATION_EMAIL":"verification_email",
    "SIGNUP_SUCCESSFUL":"signup_successful",
    "PAYMENT_SUCCESSFUL":"payment_successful",
    "FAILURE_OF_PAYMENTS":"failure_of_payment",
    ...
}

and then a general function for sending those mails:

def send_email_notification(email_type, context_data, recipients=[],files = None):
    try:
        #2
        if email_type == EMAIL_NOTIFICATION_TYPES.get('SIGNUP_SUCCESSFUL',''):
            template = get_template("email_notifications/signup_successful.html")
            context_data['login_page_link'] = LOGIN_LINK
            html = template.render(context_data)
            mail_status, response = send_email(subject="Signup Successful", html_content=html, recipients=recipients, files=None, from_email=settings.FROM_EMAIL)
        #3
        if email_type == EMAIL_NOTIFICATION_TYPES.get('PAYMENT_SUCCESSFUL',''):
            template = get_template("email_notifications/payment_successful.html")
            context_data['login_page_link'] = LOGIN_LINK
            html = template.render(context_data)
            mail_status, response = send_email(subject="Payment Successful", html_content=html, recipients=recipients, files=None, from_email=settings.FROM_EMAIL)
        #4
        elif email_type == EMAIL_NOTIFICATION_TYPES.get('FAILURE_OF_PAYMENTS',''):

            template = get_template("email_notifications/payment_failure.html")
            context_data['login_page_link'] = LOGIN_LINK
            html = template.render(context_data)
            mail_status, response = send_email(subject="Failure of payment", html_content=html,recipients=recipients, files=None, from_email=settings.FROM_EMAIL)
        #5
....

and we are using edited templates(html templates) for rendering and we pass all related data in context_data which is a dict object.

Next for sending these asynchronously we define a new async function in which we call our send_email_notification function.

@execute_in_background
def send_email_notification_async(email_type, context_data, recipients=[],files = None):
    try:
        mail_status, response = send_email_notification(email_type=email_type, context_data=context_data, recipients=recipients,files=files)
        log_info.info(f"mail sent to {recipients }")
        
    except Exception as e:
        log.error("Exception in send_email_notification_async:" + str(e))
        responseData = {'message': str(e), 'status': False, "status_code": status.HTTP_300_MULTIPLE_CHOICES}
        return False, responseData

Now we can call it like-

send_email_notification_async(email_type=EMAIL_NOTIFICATION_TYPES.get("SIGNUP_SUCCESSFUL",None),context_data=context_data,recipients=recipients)

 

Related content

We Love Conversations

Say Hello
Go to Top