Search code examples
pythondjangoemailnginxsendmail

django send_mail() function taking several minutes


I'm trying to send emails in a function within my views.py file. I've set up the email in my settings file in the same manner as here.

Python Django Gmail SMTP setup

Email sending does work but it takes several minutes to occur which my users have been complaining about. I am receiving a gethostbyaddress error in my var/log/mail.log file which I'll post here. I used to get nginx timeout errors but put "proxy_read_timeout 150;" into my /etc/nginx/sites-enabled/django file.

http://www.nginxtips.com/upstream-timed-out-110-connection-timed-out-while-reading-response-header-from-upstream/

This solved the timeout errors when interacting with the website but the emails still take several minutes to load. I'm using a digitalocean django droplet and this slow speed has occured on all my droplets.

Here's my view function

@login_required
def AnnouncementPostView(request, leaguepk):
    league = League.objects.get(pk=leaguepk)
    lblog = league.blog

    if request.method == 'POST':
        form = AnnouncementPostForm(request.POST)
        if form.is_valid():
            posttext = request.POST['text']

            newAnnouncement = Announcement(text=posttext, poster=request.user)
            newAnnouncement.save()
            lblog.announce.add(newAnnouncement)

            titleText = "%s Announcement" % (league.name)

            send_mail(titleText, posttext, settings.EMAIL_HOST_USER, ['[email protected]'], fail_silently=False)

       return HttpResponseRedirect(reverse('league-view', args=[league.pk]))
else:
    form = AnnouncementPostForm()

return render(request, 'simposting/announcementpost.html', {'form': form, 'league': league})

This has worked, the announcement is posted to the desired page and is even emailed, it's just a time problem, people have come to expect nearly instant emailing processes which makes the 2-3 minutes unacceptable, especially when signing up also causes the 2-3 minute wait.

One issue may be the fact that while trying to solve this issue with the DigitalOcean support team I changed my droplet name and the hostname to be the domain that I set up.

My current hostname and droplet name is mydomain.com. I have it setup that way in my /etc/hostname file. My /etc/hosts file looks like this

127.0.0.1 localhost.localdomain localhost mydomain.com
127.0.1.1 mydomain.com

My var/log/mail.log file responds with this whenever I try to send mail

Oct 6 16:13:24 "oldDropletName" sm-mta[13660]: gethostbyaddr(10.xxx.xx.x) failed: 1
Oct 6 16:13:24 "oldDropletName" sm-mta[13662]: starting daemon (8.14.4): SMTP+queueing@00:10:00

I hope this is enough information to help, it's been troubling for several weeks and usually I can either solve my problems by looking up stuff here or working with the support team but it's got us stumped. Thank you for taking the time to help!


Solution

  • Sending an email is a network bound task and you don't know how long it will take to finish exactly like in your case. Although there might be a latency in your network but it's better to do such task in an async fashion so your main thread is free.

    I am using the following code in one my projects.

    utils.py

    import threading
    from django.core.mail import EmailMessage
    
    
    class EmailThread(threading.Thread):
        def __init__(self, subject, html_content, recipient_list, sender):
            self.subject = subject
            self.recipient_list = recipient_list
            self.html_content = html_content
            self.sender = sender
            threading.Thread.__init__(self)
    
        def run(self):
            msg = EmailMessage(self.subject, self.html_content, self.sender, self.recipient_list)
            msg.content_subtype = 'html'
            msg.send()
    
    
    def send_html_mail(subject, html_content, recipient_list, sender):
        EmailThread(subject, html_content, recipient_list, sender).start()
    

    just call send_html_mail from your view.