Python

smtplib is in the standard library — nothing to install.

Before you start

  • Python 3.6 or later

1Send a test message

Your sandbox credentials
import smtplib
from email.message import EmailMessage

message = EmailMessage()
message['From'] = 'staging@example.com'
message['To'] = 'anyone@example.com'
message['Subject'] = 'Sandbox check'
message.set_content('Hello from Python.')

with smtplib.SMTP('smtp.mailclutch.com', 587) as smtp:
    smtp.starttls()
    smtp.login('mc_0000000000000000', 'pw_0000000000000000')
    smtp.send_message(message)

starttls() before login(): the credentials must not leave the process in the clear, and the server refuses AUTH before the upgrade.

2Or on port 465

Your sandbox credentials
with smtplib.SMTP_SSL('smtp.mailclutch.com', 465) as smtp:
    smtp.login('mc_0000000000000000', 'pw_0000000000000000')
    smtp.send_message(message)

Watch it land

Open the sandbox and the message is there — rendered HTML, plain text, raw source, attachments, and the SPF, DKIM and DMARC verdicts. It updates live, so you can leave it open next to your terminal.

Nothing is ever delivered onward, whatever address you send to; claim the inbox with an account and it stays.

Awaiting your email

Send from any address; it stops here rather than going onward. The inbox keeps what it catches for 24 hours.

What usually goes wrong

  • An HTML body

    message.add_alternative('<h1>Hello</h1>', subtype='html') adds the HTML part next to the text one, which is what a real application sends.

  • Flask, FastAPI, Celery

    Anything built on smtplib takes the same four values. In Flask-Mail they are MAIL_SERVER, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD, plus MAIL_USE_TLS = True.

Official documentationPython — smtplib (opens in a new tab)