Mailgun’s SMTP endpoint doesn’t actually send email itself; it’s a gateway that forwards your mail to one of their actual sending servers, which are themselves just sophisticated wrappers around standard SMTP servers.
Let’s get this email sending. We’ll use Mailgun’s SMTP service, which is a fantastic way to reliably send transactional emails from your application without managing your own mail server.
Here’s a typical setup for sending email via Mailgun’s SMTP from a Python application using the smtplib library.
import smtplib
from email.mime.text import MIMEText
# Mailgun SMTP server details
mailgun_smtp_server = "smtp.mailgun.org"
mailgun_smtp_port = 587 # Use 587 for STARTTLS, 465 for SSL
mailgun_smtp_login = "postmaster@your-domain.mailgun.org" # Replace with your Mailgun login
mailgun_smtp_password = "YOUR_API_KEY" # Replace with your Mailgun API key (SMTP password)
# Email details
sender_email = "sender@your-domain.com" # Must be a verified sender in Mailgun
recipient_email = "recipient@example.com"
subject = "Test Email from Mailgun SMTP"
body = "This is a test email sent using Mailgun's SMTP service."
# Create the email message
message = MIMEText(body)
message['Subject'] = subject
message['From'] = sender_email
message['To'] = recipient_email
try:
# Connect to the Mailgun SMTP server
with smtplib.SMTP(mailgun_smtp_server, mailgun_smtp_port) as server:
server.set_debuglevel(1) # Uncomment for verbose debugging
# Start TLS encryption
server.starttls()
# Login to Mailgun
server.login(mailgun_smtp_login, mailgun_smtp_password)
# Send the email
server.sendmail(sender_email, recipient_email, message.as_string())
print("Email sent successfully!")
except Exception as e:
print(f"Error sending email: {e}")
This code snippet demonstrates the core mechanics. You instantiate an smtplib.SMTP object, establish a secure connection using starttls(), authenticate with your Mailgun credentials, and then use sendmail() to dispatch the message. The email.mime.text.MIMEText part is just standard Python for constructing an email message.
What’s Happening Under the Hood?
When your application makes that smtplib.SMTP connection, it’s not talking directly to the Mailgun servers that will eventually deliver the email to the recipient’s inbox. Instead, it’s connecting to a specific Mailgun SMTP relay server. This relay server’s job is to receive your email, authenticate your application, and then pass the email along to Mailgun’s internal routing system. From there, Mailgun’s actual sending infrastructure takes over, handling DNS lookups, IP reputation, retries, and all the nitty-gritty of getting the email to its final destination.
The postmaster@your-domain.mailgun.org address is a convention. Mailgun uses this as the username for SMTP authentication. The password for this login is your Mailgun API key, specifically the one labeled as "SMTP Password" in your Mailgun control panel.
The port 587 is the standard for SMTP with STARTTLS. This means the connection starts unencrypted, and then starttls() negotiates an encrypted TLS tunnel. If you prefer, you can use port 465 with smtplib.SMTP_SSL to establish an SSL/TLS encrypted connection from the very beginning.
Key Configuration Points
-
Domain Verification: Before you can send email from a domain through Mailgun, that domain must be verified in your Mailgun account. This involves adding specific DNS records (like MX, TXT, and CNAME) to your domain’s DNS zone. Mailgun provides these records in your account dashboard. Without this, Mailgun won’t accept mail from your domain, and your SMTP connection will likely fail authentication or the emails will be rejected.
-
Sender Authorization: The
sender_emailyou use insendmail()(e.g.,sender@your-domain.com) must be an authorized sender within your Mailgun account. For new domains, Mailgun automatically authorizespostmaster@your-domain.mailgun.org. For other addresses, you need to explicitly add them as "Authorized Recipients" or "Verified Senders" in your Mailgun domain settings. This prevents spoofing. -
API Key (SMTP Password): The
mailgun_smtp_passwordis your Mailgun API key. You can find this in your Mailgun Control Panel under "Account Settings" -> "API Keys". It’s crucial to use the correct API key, as this is how Mailgun authenticates your application’s requests. Treat this like a password; don’t commit it directly into your code. Use environment variables or a secrets management system. -
SMTP Server and Port: While
smtp.mailgun.organd port587(STARTTLS) are the most common, Mailgun also supportssmtp.eu.mailgun.orgfor their EU region. Always use the server and port appropriate for your Mailgun region. Port465is also available for SSL-only connections.
Common Pitfalls and Debugging
- Authentication Errors: If you get an authentication error (e.g., "535 Authentication failed"), double-check your
mailgun_smtp_loginandmailgun_smtp_password. Ensure you are using the correct API key and that the login format ispostmaster@your-domain.mailgun.org(or your custom subdomain if you’ve configured one). - Invalid Sender: If emails are bounced back with an "unauthorized sender" error, ensure the
sender_emailis verified in your Mailgun domain settings. - Domain Not Verified: If you get a general connection or authentication failure, and your domain isn’t verified, this is often the culprit. Verify your domain’s DNS records with Mailgun.
- Network/Firewall Issues: Ensure your server or local machine can reach
smtp.mailgun.orgon port587or465. Firewalls can sometimes block outbound SMTP traffic. - Incorrect Port: Using port 25 is generally discouraged and often blocked by ISPs. Stick to 587 or 465.
The most common next issue you’ll encounter is dealing with email deliverability, specifically how Mailgun handles bounces, complaints, and suppressed email addresses, which requires setting up webhooks.