27

This is my code:

class EmailThread(threading.Thread):
    def __init__(self, subject, html_content, recipient_list):
        self.subject = subject
        self.recipient_list = recipient_list
        self.html_content = html_content
        threading.Thread.__init__(self)

    def run (self):
        msg = EmailMultiAlternatives(self.subject, self.html_content, EMAIL_HOST_USER, self.recipient_list)
        #if self.html_content:
        msg.attach_alternative(True, "text/html")
        msg.send()

def send_mail(subject, html_content, recipient_list):
    EmailThread(subject, html_content, recipient_list).start()

It doesn't send email. What can I do?

Jeff LaFay
  • 12,882
  • 13
  • 71
  • 101
zjm1126
  • 34,604
  • 53
  • 121
  • 166

4 Answers4

41

it is ok now ;

import threading
from threading import Thread

class EmailThread(threading.Thread):
    def __init__(self, subject, html_content, recipient_list):
        self.subject = subject
        self.recipient_list = recipient_list
        self.html_content = html_content
        threading.Thread.__init__(self)

    def run (self):
        msg = EmailMessage(self.subject, self.html_content, EMAIL_HOST_USER, self.recipient_list)
        msg.content_subtype = "html"
        msg.send()

def send_html_mail(subject, html_content, recipient_list):
    EmailThread(subject, html_content, recipient_list).start()
Jayesh
  • 1,511
  • 1
  • 16
  • 37
zjm1126
  • 34,604
  • 53
  • 121
  • 166
  • Does anyone know for sure if threading works as one would expect with Django? This other related answer https://stackoverflow.com/questions/13567160/django-best-way-to-send-email-in-background seems to imply otherwise. Incase it helps, I used Mailgun to solve this problem. No SDK needed. Extremely simple API. Free tier available. I'm not affiliated with them. – Jonathan Berger Dec 11 '18 at 07:08
  • 3
    Mailgun is not actually solution to the question asked. He wants to send email asynchronously. Email will be sent using some smpt server which can be mailgun but sending it asynchronously, threads/celery or any solution have to be used. – Muhammad Hassan Mar 03 '20 at 06:04
  • Celery is definitely an Overkill for just sending emails. This is a much better way to handle email sending asynchronously. – Jayesh May 24 '20 at 15:52
  • any idea why EmailMultiAlternatives is not working ? – Sandeep Balagopal Jul 14 '20 at 05:36
  • 1
    This saved my day! Thanks a lot, I have been struggling with Celery to send Asynchronous emails but this is Awesome! – Mwibutsa Floribert Jul 18 '20 at 09:20
  • It may unblock the end user, but my question is are we increasing throuput of server by doing it using thread? see [this answer](https://stackoverflow.com/a/53327191/10268003]) comments for detail. – Aniket Singla Oct 05 '20 at 13:42
  • You may also use it as an app from pip: https://github.com/Jayesh-Mahato/DjangoAsyncMail – Jayesh Mar 16 '22 at 16:18
12

In the long run, it may prove to be a good decision to use a third-party Django application, such as django-mailer, to handle all sorts of asynchronous email sending/management requirements.

Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116
ayaz
  • 10,406
  • 6
  • 33
  • 48
  • I had a look at django-mailer, it doesn't seem to provide any feature to send an email 'right away', such as for email verification. – MrObjectOriented Jun 13 '21 at 15:04
3

After checking out more complex solutions based around celery, etc. I found django-post_office (https://github.com/ui/django-post_office) It's a very simple database + cron job plugin that took 5 mins to get up and running. Works perfectly on both my local dev machine and Heroku.

user2916527
  • 529
  • 4
  • 17
2

create new file named send_mail.py and add the function to send the mail

def send_html_mail (*args,**kwargs):
    
    subject = kwargs.get("subject")
    html_content = kwargs.get("html_content")
    recipient_list = kwargs.get("recipient_list")
    
  
    msg = EmailMultiAlternatives(subject, html_content, EMAIL_HOST_USER, recipient_list)
    msg.attach_alternative(True, "text/html")
    msg.send()

call a this function in the views.py

import threading
from send_mail import send_html_mail
def my_view (request):
   
    # .....

    threading.Thread (

        # call to send_html_mail
        target=send_html_mail,

        kwargs={

            "subject":"My super subject",
            "html_content":"My super html content",
            "recipient_list":["to@mail.com"]

            }).start()

    # .....