See why hundreds of Python projects chose Postmark API to send their transactional emails
pip install postmark-python
ServerClient and send your first email. The SDK is fully async — all API calls must be awaited.import asyncio
import os
import postmark
async def main():
async with postmark.ServerClient(os.environ["POSTMARK_SERVER_TOKEN"]) as client:
response = await client.outbound.send({
"sender": "sender@example.com",
"to": "recipient@example.com",
"subject": "Postmark test",
"html_body": "<p>HTML body goes here</p>",
})
print(f"Sent: {response.message_id}")
asyncio.run(main())
# settings.py — use Postmark as Django's email backend via SMTP
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.postmarkapp.com"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ["POSTMARK_SERVER_TOKEN"]
EMAIL_HOST_PASSWORD = os.environ["POSTMARK_SERVER_TOKEN"]
DEFAULT_FROM_EMAIL = "sender@example.com"
# Then send from anywhere in Django:
# from django.core.mail import send_mail
# send_mail("Subject", "Body", None, ["recipient@example.com"])
import asyncio
import os
import postmark
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/send", methods=["POST"])
def send_email():
async def _send():
async with postmark.ServerClient(os.environ["POSTMARK_SERVER_TOKEN"]) as client:
return await client.outbound.send({
"sender": "sender@example.com",
"to": "recipient@example.com",
"subject": "Postmark test",
"html_body": "<p>HTML body goes here</p>",
})
result = asyncio.run(_send())
return jsonify({"message_id": result.message_id})
import os
import postmark
from fastapi import FastAPI
app = FastAPI()
@app.post("/send")
async def send_email():
async with postmark.ServerClient(os.environ["POSTMARK_SERVER_TOKEN"]) as client:
response = await client.outbound.send({
"sender": "sender@example.com",
"to": "recipient@example.com",
"subject": "Postmark test",
"html_body": "<p>HTML body goes here</p>",
})
return {"message_id": response.message_id}
import os
import smtplib
from email.message import EmailMessage
# No extra dependencies needed — smtplib ships with Python.
token = os.environ["POSTMARK_SERVER_TOKEN"]
msg = EmailMessage()
msg["From"] = "sender@example.com"
msg["To"] = "recipient@example.com"
msg["Subject"] = "Postmark test"
msg.set_content("Plain text body goes here.")
with smtplib.SMTP("smtp.postmarkapp.com", 587) as smtp:
smtp.starttls()
smtp.login(token, token)
smtp.send_message(msg)
Want to test our APIs and activity logging? Send emails to test@blackhole.postmarkapp.com
Install with pip install postmark-python. Python 3.10+, fully async, MIT licensed.
Tutorials, client references, and usage examples on the GitHub Wiki.
Programmatically check up on any message you sent from Python using its unique ID.
Full API reference, SMTP setup, Templates, Inbound, webhooks, and more.
A comprehensive suite of tools to help you integrate email with your Python application.
Responsive templates for sending transactional emails, including welcome messages, password resets, and more.
SPF, DKIM, and DMARC support included, with clear guides to help you get set up.
45 days worth of full content history by default to help you troubleshoot (customizable from 7 to 365 days if needed).
Keep track of bounced emails through the web dashboard, or use web hooks to notify your app of any issues.
Increased visibility with detailed open and delivery tracking for every email.
We share our delivery statistics to the major inbox providers right on our status page.
We’re really happy we decided to use Postmark for ITV’s British Soap Awards. We only count votes from verified email addresses and Postmark’s excellent delivery has lead to our highest verification percentage ever. We'll definitely use Postmark again!
Made the switch to @postmarkapp today. The customer service and delivery rates are awesome, but the thing I love is EVERYTHING IS YELLOW!
Trying out @postmarkapp for my next react app blog and wow they have much better dev. experience than @SendGrid. Very clear & step-by-step.
Password reset emails delivered by @postmarkapp arrive in gmail in 1 second (vs 64 seconds for SendGrid)
We’ve got you covered. We process transactional email for companies of all sizes:
Not necessarily. Python's built-in smtplib library works with Postmark's SMTP server without extra dependencies. If you prefer a cleaner API experience, install the official Postmark Python library with pip install postmark.
The Postmark team has built and maintains the official Postmark library, with full API coverage and async support. Community libraries like postmarker and python-postmark were valuable early contributions, but may not reflect the latest Postmark API features or support modern Python versions.
The official Postmark library supports Python 1.0 and above.
Never hardcode your server token directly in your code. Instead, store it as an environment variable and read it at runtime. For local development, a .env file with a library like python-dotenv keeps things simple. Just make sure .env is in your .gitignore.
Postmark provides a test server token that accepts API calls without delivering any email. Swap it in during development and testing: POSTMARK_API_TEST.
You can also send to test@blackhole.postmarkapp.com, which accepts any email without delivering it.
Postmark works with any Python framework. You can use Postmark as a drop-in replacement for Django's default email setup by setting the SMTP server to smtp.postmarkapp.com. For Flask and FastAPI, the library integrates naturally: Wire up a route, create a client, and send.
Yes. The official postmark library supports async automatically, so it's a natural fit for FastAPI, Starlette, or any async Python application.
Your customers expect transactional emails to arrive immediately—not eventually.
We constantly monitor our delivery speeds and share the data publicly.