Python SDK
The official Python SDK for Veil Mail with sync and async support.
- Sync and async clients via httpx
- Full type hint support (PEP 484)
- Typed error classes for error handling
- Webhook signature verification utility
- Python 3.9+ compatible
Installation
pip install veilmailQuick Start
send.py
import veilmail
client = veilmail.VeilMail("veil_live_xxxxx")
# Send an email
email = client.emails.send(
from_="hello@yourdomain.com",
to="user@example.com",
subject="Hello from Python!",
html="<h1>Welcome!</h1>",
)
print(email["id"]) # email_xxxxx
print(email["status"]) # queuedAsync Support
Use AsyncVeilMail for async/await support with asyncio.
async_send.py
import asyncio
import veilmail
async def main():
async with veilmail.AsyncVeilMail("veil_live_xxxxx") as client:
email = await client.emails.send(
from_="hello@yourdomain.com",
to="user@example.com",
subject="Hello from async Python!",
html="<h1>Welcome!</h1>",
)
print(email["id"])
asyncio.run(main())Resources
The client exposes the same resources as the Node.js SDK:
| Resource | Description |
|---|---|
client.emails | Send, list, get, cancel, update emails |
client.domains | Create, verify, list, delete domains |
client.templates | Create, update, list, delete templates |
client.audiences | Manage audiences and subscribers |
client.campaigns | Create, schedule, send, pause campaigns |
client.webhooks | Manage webhook endpoints |
client.topics | Manage subscription topics |
Subscriber Management
subscribers.py
# Get a subscribers helper for an audience
subs = client.audiences.subscribers("audience_xxxxx")
# Add a subscriber
subscriber = subs.add(
email="user@example.com",
first_name="Alice",
last_name="Smith",
metadata={"plan": "premium"},
)
# List subscribers
result = subs.list(status="active", limit=50)
for sub in result["data"]:
print(sub["email"])
# Import from CSV
result = subs.import_subscribers(
csv_data="email,firstName\nuser1@example.com,Bob\nuser2@example.com,Carol"
)
print(f"Created: {result['created']}, Skipped: {result['skipped']}")
# Export as CSV
csv_data = subs.export(status="active")
with open("subscribers.csv", "w") as f:
f.write(csv_data)Error Handling
errors.py
import veilmail
client = veilmail.VeilMail("veil_live_xxxxx")
try:
email = client.emails.send(
from_="hello@yourdomain.com",
to="user@example.com",
subject="Hello",
html="<p>Hi!</p>",
)
except veilmail.RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
except veilmail.PiiDetectedError as e:
print(f"PII detected: {e.pii_types}")
except veilmail.ValidationError as e:
print(f"Validation error: {e.message}")
except veilmail.AuthenticationError:
print("Invalid API key")
except veilmail.VeilMailError as e:
print(f"API error: {e.message} (code: {e.code})")Webhook Verification
Use the built-in utility to verify webhook signatures:
webhook_handler.py
import json
import veilmail
from flask import Flask, request
app = Flask(__name__)
WEBHOOK_SECRET = "whsec_xxxxx"
@app.post("/webhooks/veilmail")
def handle_webhook():
payload = request.get_data(as_text=True)
signature = request.headers.get("X-VeilMail-Signature", "")
if not veilmail.verify_webhook_signature(payload, signature, WEBHOOK_SECRET):
return "Invalid signature", 401
event = json.loads(payload)
if event["type"] == "email.delivered":
print(f"Delivered: {event['data']['emailId']}")
elif event["type"] == "email.bounced":
print(f"Bounced: {event['data']['emailId']}")
return "OK", 200Note on the from_ parameter
Since from is a reserved keyword in Python, the sender address parameter is named from_ (with a trailing underscore). The SDK automatically maps this to from in the API request.