Connection timeout issue when sending emails through Mailgun SMTP in Django on Heroku

I’m having trouble with email delivery in my Django app deployed on Heroku. The emails work fine when I test locally, but I keep getting a connection timeout error on the production server.

My email configuration:

EMAIL_HOST = "smtp.mailgun.org"
EMAIL_PORT = 587
EMAIL_HOST_USER = os.environ["MAILGUN_USER"]
EMAIL_HOST_PASSWORD = os.environ["MAILGUN_PASS"]
EMAIL_USE_TLS = True
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

View function that handles registration:

import re
import os
from django.http import HttpResponse
from django.contrib.auth.hashers import make_password
import secrets
from .models import Account, VerificationToken
from django.core.mail import send_mail
from threading import Thread

sender_email = re.sub(".*@", "support@", os.environ["MAILGUN_USER"])

def send_email_async(title, content, sender, recipients):
    send_mail(
        subject=title,
        message=content,
        from_email=sender,
        recipient_list=recipients
    )

def register_user(request):
    if request.method == "POST":
        user_password = request.POST["password"]
        user_email = request.POST["email"]
        
        if not re.match(r"[^@]+@[^@]+\.[^@]+", user_email):
            return HttpResponse("Invalid email format")
        
        if Account.objects.filter(email=user_email).exists():
            return HttpResponse("User already registered")
        
        new_account = Account.objects.create(
            email=user_email, 
            password=make_password(user_password), 
            is_verified=False
        )
        
        token = secrets.token_hex(16)
        VerificationToken.objects.create(user=new_account, token=token)
        confirm_url = request.get_host() + "/verify/" + str(token)
        
        Thread(target=send_email_async, args=(
            "Account Verification", 
            confirm_url, 
            sender_email, 
            [user_email]
        )).start()
        
        return HttpResponse("Registration successful")

The error I’m getting:

TimeoutError: [Errno 110] Connection timed out

The weird thing is this works perfectly on my local machine but fails on Heroku. The form submission works and returns the success message, but the email sending fails in the background thread after about a minute. Has anyone encountered this before?

This timeout thing usually happens because Heroku’s filesystem and networking can be wonky with SMTP connections. I hit this exact problem last year - adding connection timeouts to your email settings helps a ton. Try EMAIL_TIMEOUT = 30 in your Django settings to stop connections from hanging forever. Your background threading approach might be causing trouble too since Heroku can kill dynos without warning. I’d use Celery with Redis for email queuing instead, or at least wrap your send_mail call in try-except to handle failures. Also check if your Mailgun credentials are set right in Heroku’s environment variables - sometimes it’s just a misconfigured env var that works locally but breaks in production.

Had the same problem a few months ago. Heroku blocks port 587 on free/hobby tiers for security. Switch to port 465 with SSL instead - set EMAIL_PORT = 465 and EMAIL_USE_SSL = True (ditch the TLS setting). Double-check your Mailgun domain is set up right in your Heroku config vars. If you’re using Mailgun’s EU region, use smtp.eu.mailgun.org instead of the regular SMTP server. Your threading setup should work fine once you fix the connection.

Check your Heroku logs first - heroku logs --tail shows the exact error. Mailgun has rate limits that hit production but not local dev. Heroku’s ephemeral filesystem also screws with SMTP connections. Add EMAIL_USE_LOCALTIME = False to settings and verify your Mailgun domain in their dashboard. Threading gets killed when Heroku restarts dynos too.