Python Quickstart

Send your first email from a Python project. Works with any Python 3.8+ runtime — Django, Flask, FastAPI, scripts, Lambda. The SDK is pure-Python, no compiled deps.

1. Install

terminal
pip install mailstorm
# or with uv: uv pip install mailstorm
# or in pyproject.toml: dependencies = ["mailstorm"]

2. Get an API key

Sign up at mailstorm.dev. Generate a key at /api-keys.

3. Send your first email

send.py
import os
from mailstorm import Mailstorm

ms = Mailstorm(os.environ["MAILSTORM_API_KEY"])

resp = ms.emails.send(
    from_="onboarding@yourdomain.com",
    to="user@example.com",
    subject="Hello",
    html="<p>It works.</p>",
)
print("sent:", resp["id"])

Note on from_: Python reserves from as a keyword. The SDK accepts from_ as the parameter name and serializes it to the wire as from.

4. Verify your sending domain

Live sends require ownership of the FROM domain. Add your domain at /domains; paste the DKIM, SPF, DMARC records into your DNS host. Verification typically completes in 5 minutes after propagation.

5. Send to multiple recipients

python
ms.emails.send(
    from_="alerts@yourdomain.com",
    to=["a@example.com", "b@example.com"],
    cc=["c@example.com"],
    reply_to="support@yourdomain.com",
    subject="System update",
    html="<p>...</p>",
)

6. Send a batch

python
ms.batch.send([
    {"from": "alerts@yourdomain.com", "to": "a@example.com", "subject": "x", "html": "<p>1</p>"},
    {"from": "alerts@yourdomain.com", "to": "b@example.com", "subject": "y", "html": "<p>2</p>"},
])

7. Idempotency

python
ms.emails.send(
    from_="...",
    to="...",
    subject="Order confirmation",
    html="<p>...</p>",
    idempotency_key="order-12345",
)

8. Common patterns

Django

settings.py
MAILSTORM_API_KEY = os.environ["MAILSTORM_API_KEY"]
signals.py
from django.dispatch import receiver
from django.contrib.auth.signals import user_logged_in
from mailstorm import Mailstorm

@receiver(user_logged_in)
def welcome(sender, user, request, **kwargs):
    Mailstorm(settings.MAILSTORM_API_KEY).emails.send(
        from_="hi@yourdomain.com",
        to=user.email,
        subject="Welcome",
        html=render_to_string("emails/welcome.html", {"user": user}),
    )

FastAPI

main.py
from fastapi import BackgroundTasks, FastAPI
from mailstorm import Mailstorm
ms = Mailstorm(os.environ["MAILSTORM_API_KEY"])

app = FastAPI()

def _send_welcome(email: str):
    ms.emails.send(from_="hi@yourdomain.com", to=email, subject="Welcome", html="...")

@app.post("/signup")
def signup(email: str, bg: BackgroundTasks):
    bg.add_task(_send_welcome, email)
    return {"ok": True}

What's next