Michael Fox
Michael Fox

Reputation: 501

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!

Upvotes: 5

Views: 5128

Answers (2)

Jmills
Jmills

Reputation: 2422

I am not particularly familiar with sendmail (I use postfix) but I would suspect this is almost certainly related to something with sendmail and probably not Django. The second log entry has "SMTP+queueing@00:10:00". and this link would indicate that sendmail takes a flag on startup to determine how often to process the mail queue. You may want to look around your init or wherever your startup scripts are and see how sendmail is configured. Also, if you are using Gmail you really can't control any delays on their end, so along with determining the configuration of your mail server, you'll need to check logs for when actions are actually occurring such as the mail being queued/sent. Is the time that line shows in your log from when the view was executed? If so, it is in the hands of sendmail.

Upvotes: 0

Chirdeep Tomar
Chirdeep Tomar

Reputation: 4461

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.

Upvotes: 24

Related Questions