Python
Use the official Python SDK with Python 3.11 or later.
Before you start
You need a verified sending domain and an API key with the sending scope. Set EPOSTIX_API_KEY in your environment.
Install
python -m pip install epostix
Send an email
Replace the sender with an address at your verified domain and the recipient with your own address.
import os
from epostix import Epostix, EpostixAPIError, models
try:
with Epostix(api_key=os.environ["EPOSTIX_API_KEY"]) as client:
email = client.emails.send_email(
models.EmailCreate(
from_="hello@mail.yourdomain.com",
to=["you@yourdomain.com"],
subject="Your first email",
html="<p>Sent with Epostix.</p>",
text="Sent with Epostix.",
),
idempotency_key="first-email-001",
)
print(email.id)
except EpostixAPIError as error:
print(error.type, error.request_id)
raise
python send.py
from_ is the Python field name because from is a language keyword. The SDK sends it as from on the wire. The context manager closes the HTTP client when the block ends.
The ID confirms acceptance. Check Activity or subscribe to webhooks for delivery status.
Async applications
Use AsyncEpostix when your application uses asyncio:
import asyncio
import os
from epostix import AsyncEpostix, models
async def main():
async with AsyncEpostix(api_key=os.environ["EPOSTIX_API_KEY"]) as client:
email = await client.emails.send_email(
models.EmailCreate(
from_="hello@mail.yourdomain.com",
to=["you@yourdomain.com"],
subject="Your first async email",
text="Sent with Epostix.",
),
idempotency_key="first-async-email-001",
)
print(email.id)
asyncio.run(main())
Retries and background jobs
The SDK retries eligible transient failures within a bounded deadline. For a Celery task or another job that can run again, pass the same idempotency_key on every attempt. Use your stored order or event ID, not a fresh UUID inside the task.
Deduplication lasts 24 hours and is scoped to the API key, environment, method and path. A new key means a new send. See idempotency.
For a simulated send, use a test key or a sandbox recipient.
Django SMTP
Existing Django send_mail calls can use SMTP without adopting the API:
import os
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.epostix.com"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ["EPOSTIX_SMTP_USER"]
EMAIL_HOST_PASSWORD = os.environ["EPOSTIX_SMTP_PASSWORD"]
DEFAULT_FROM_EMAIL = "hello@mail.yourdomain.com"
SMTP credentials are separate from API keys. Use the SDK when you need API features such as scheduling, idempotency or reading message events.