|
|
|
The official (Beta) Python SDK for Postmark — send emails, manage bounces, templates, webhooks, and more.
For tutorials and detailed usage, check out the wiki.
For details about the Postmark API in general, see the Postmark developer docs.
- Python 3.10+
Security: the Brotli decoder is affected by CVE-2026-111497.
httpxrequests and decodes Brotli only when the optionalbrotliorbrotlicffipackage is installed. If you have either, usebrotli>= 1.2.1 orbrotlicffi>= 1.2.1.0.
Install from PyPI as postmark-python (the Python package you import is still postmark):
pip install postmark-python
The SDK is async-first — all API calls return awaitables. As of v0.3.0, a synchronous wrapper is also available for use in non-async contexts.
Async:
import asyncio import os import postmark # Tokens are read from the environment here. Optionally: pip install python-dotenv, # then use load_dotenv() to populate os.environ from a .env file. async def main(): async with postmark.ServerClient(os.environ["POSTMARK_SERVER_TOKEN"]) as client: response = await client.outbound.send( { "sender": "[email protected]", "to": "[email protected]", "subject": "Hello from Postmark", "text_body": "Sent with the Postmark Python SDK.", } ) print(f"Sent: {response.message_id}") asyncio.run(main())
Sync (v0.3.0+):
import os import postmark.sync with postmark.sync.ServerClient(os.environ["POSTMARK_SERVER_TOKEN"]) as client: response = client.outbound.send( { "sender": "[email protected]", "to": "[email protected]", "subject": "Hello from Postmark", "text_body": "Sent with the Postmark Python SDK.", } ) print(f"Sent: {response.message_id}")
Why
sender, notfrom?fromis a reserved keyword in Python, so the SDK usessenderfor the sending address. Everything else matches the Postmark API field names directly.
| Client | Token | Use for |
|---|---|---|
ServerClient |
Server API token | Sending email, bounces, templates, stats, webhooks, streams |
AccountClient |
Account API token | Domains, sender signatures, managing servers, data removals |
import postmark # Use as async context managers to ensure connections are closed async with postmark.ServerClient(os.environ["POSTMARK_SERVER_TOKEN"]) as client: ... async with postmark.AccountClient(os.environ["POSTMARK_ACCOUNT_TOKEN"]) as account: ... # Or call close() explicitly when done client = postmark.ServerClient(os.environ["POSTMARK_SERVER_TOKEN"]) await client.close()
postmark.django.EmailBackend is a drop-in EMAIL_BACKEND for Django's django.core.mail, supporting Django 4.2 LTS through 6.1. Requires the django extra:
pip install postmark-python[django]
# settings.py EMAIL_BACKEND = "postmark.django.EmailBackend" POSTMARK_SERVER_TOKEN = "your-server-token"
See the Django Backend wiki page and examples/django/ for tags, metadata, attachments, and signals.
git clone https://github.com/ActiveCampaign/postmark-python.git
cd postmark-python
poetry install
poetry run pre-commit install# Run tests poetry run pytest # Lint and type-check poetry run pre-commit run --all-files
See CONTRIBUTING.md for setup, testing, and PR guidelines.
- Issues: GitHub Issues
- Postmark Support: [email protected]
MIT — see LICENSE.
