Guides
Send email with Python
The stdlib is enough: urllib, one JSON POST, honest error handling.
Facts verified 2026-07-17 — corrections: hello@emailfast.dev
Python's standard library is enough — the Email Fast API is one JSON POST, so urllib.request does the job without adding requests to your dependencies. Wrap it in a small function and call it anywhere. If you'd rather have a typed client, the Python SDK quickstart covers that instead.
# send.py — Python 3.10+, stdlib only
import json
import os
import urllib.error
import urllib.request
API_KEY = os.environ["EMAILFAST_API_KEY"] # ef_sandbox_... while testing
def send_email(to: str, subject: str, html: str, data: dict, idempotency_key: str) -> dict:
req = urllib.request.Request(
"https://api.emailfast.dev/v1/emails",
data=json.dumps({
"to": to,
"subject": subject,
"html": html,
"data": data,
"idempotency_key": idempotency_key,
}).encode(),
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
)
try:
with urllib.request.urlopen(req, timeout=10) as res:
return json.load(res)
except urllib.error.HTTPError as e:
raise RuntimeError(f"send rejected ({e.code}): {e.read().decode()}") from e
result = send_email(
to="ada@example.com",
subject="Welcome",
html="<h1>Hi {{name}}</h1>",
data={"name": "Ada"},
idempotency_key="welcome-ada-1", # a retry replays, never re-sends
)
print(result["id"], result["status"]) # msg_... queueda 202 from the API means the send is committed to a durable, partitioned outbox before we answer — a crash can't lose it, and a retry with the same idempotency key can't double-send.
Gotchas
urllibraisesHTTPErroron any 4xx/5xx — catch it and reade.read(); the body names the exact rejection (invalid address, suppressed recipient, quota).- Always pass
timeout=— the default is to block forever on a stuck connection. - Read the key with
os.environ[...], not a literal: aKeyErrorat startup beats a silent auth failure at 2 a.m. - Sending many? Don't loop this function — POST up to 500 messages to
/v1/emails/batchin one call.
Next
- Python SDK quickstart — the typed client
- The email API — batch, scheduling, message timelines
- Sending from Django
- All docs