Official Python SDK for the Emailit Email API
Project description
Emailit Python
The official Python SDK for the Emailit Email API.
Requirements
- Python 3.7+
- Requests 2.20+
Installation
pip install emailit
Getting Started
from emailit import EmailitClient
client = EmailitClient("your_api_key")
email = client.emails.send({
"from": "hello@yourdomain.com",
"to": ["user@example.com"],
"subject": "Hello from Emailit",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
})
print(email.id) # em_abc123...
print(email.status) # pending
All service methods return typed resource objects (Email, Domain, Contact, etc.) with direct attribute access -- just like the Stripe SDK.
Available Services
| Service | Property | Description |
|---|---|---|
| Emails | client.emails |
Send, list, get, cancel, retry emails |
| Domains | client.domains |
Create, verify, list, manage sending domains |
| API Keys | client.api_keys |
Create, list, manage API keys |
| Audiences | client.audiences |
Create, list, manage audiences |
| Subscribers | client.subscribers |
Add, list, manage subscribers in audiences |
| Templates | client.templates |
Create, list, publish email templates |
| Suppressions | client.suppressions |
Create, list, manage suppressed addresses |
| Email Verifications | client.email_verifications |
Verify email addresses |
| Email Verification Lists | client.email_verification_lists |
Create, list, get results, export |
| Webhooks | client.webhooks |
Create, list, manage webhooks |
| Contacts | client.contacts |
Create, list, manage contacts |
| Events | client.events |
List and retrieve events |
Usage
Emails
Send an email
email = client.emails.send({
"from": "hello@yourdomain.com",
"to": ["user@example.com"],
"subject": "Hello from Emailit",
"html": "<h1>Welcome!</h1>",
})
print(email.id)
print(email.status)
Send with a template
email = client.emails.send({
"from": "hello@yourdomain.com",
"to": "user@example.com",
"template": "welcome_email",
"variables": {
"name": "John Doe",
"company": "Acme Inc",
},
})
Send with attachments
import base64
email = client.emails.send({
"from": "invoices@yourdomain.com",
"to": "customer@example.com",
"subject": "Your Invoice #12345",
"html": "<p>Please find your invoice attached.</p>",
"attachments": [
{
"filename": "invoice.pdf",
"content": base64.b64encode(open("invoice.pdf", "rb").read()).decode(),
"content_type": "application/pdf",
},
],
})
Schedule an email
email = client.emails.send({
"from": "reminders@yourdomain.com",
"to": "user@example.com",
"subject": "Appointment Reminder",
"html": "<p>Your appointment is tomorrow at 2 PM.</p>",
"scheduled_at": "2026-01-10T09:00:00Z",
})
print(email.status) # scheduled
print(email.scheduled_at) # 2026-01-10T09:00:00Z
List emails
emails = client.emails.list({"page": 1, "limit": 10})
for email in emails:
print(f"{email.id} — {email.status}")
if emails.has_more():
# fetch next page
pass
Cancel / Retry
client.emails.cancel("em_abc123")
client.emails.retry("em_abc123")
Domains
# Create a domain
domain = client.domains.create({
"name": "example.com",
"track_loads": True,
"track_clicks": True,
})
print(domain.id)
# Verify DNS
domain = client.domains.verify("sd_123")
# List all domains
domains = client.domains.list()
# Get a domain
domain = client.domains.get("sd_123")
# Update a domain
domain = client.domains.update("sd_123", {"track_clicks": False})
# Delete a domain
client.domains.delete("sd_123")
API Keys
# Create an API key
key = client.api_keys.create({
"name": "Production Key",
"scope": "full",
})
print(key.key) # only available on create
# List all API keys
keys = client.api_keys.list()
# Get an API key
key = client.api_keys.get("ak_123")
# Update an API key
client.api_keys.update("ak_123", {"name": "Renamed Key"})
# Delete an API key
client.api_keys.delete("ak_123")
Audiences
# Create an audience
audience = client.audiences.create({"name": "Newsletter"})
print(audience.id)
print(audience.token)
# List audiences
audiences = client.audiences.list()
# Get an audience
audience = client.audiences.get("aud_123")
# Update an audience
client.audiences.update("aud_123", {"name": "Updated Newsletter"})
# Delete an audience
client.audiences.delete("aud_123")
Subscribers
Subscribers belong to an audience, so the audience ID is always the first argument.
# Add a subscriber
subscriber = client.subscribers.create("aud_123", {
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
})
# List subscribers in an audience
subscribers = client.subscribers.list("aud_123")
# Get a subscriber
subscriber = client.subscribers.get("aud_123", "sub_456")
# Update a subscriber
client.subscribers.update("aud_123", "sub_456", {
"first_name": "Jane",
})
# Delete a subscriber
client.subscribers.delete("aud_123", "sub_456")
Templates
# Create a template
result = client.templates.create({
"name": "Welcome",
"subject": "Welcome!",
"html": "<h1>Hi {{name}}</h1>",
})
# List templates
templates = client.templates.list()
# Get a template
template = client.templates.get("tem_123")
# Update a template
client.templates.update("tem_123", {"subject": "New Subject"})
# Publish a template
client.templates.publish("tem_123")
# Delete a template
client.templates.delete("tem_123")
Suppressions
# Create a suppression
suppression = client.suppressions.create({
"email": "spam@example.com",
"type": "hard_bounce",
"reason": "Manual suppression",
})
# List suppressions
suppressions = client.suppressions.list()
# Get a suppression
suppression = client.suppressions.get("sup_123")
# Update a suppression
client.suppressions.update("sup_123", {"reason": "Updated"})
# Delete a suppression
client.suppressions.delete("sup_123")
Email Verifications
result = client.email_verifications.verify({
"email": "test@example.com",
})
print(result.status) # valid
print(result.score) # 0.95
print(result.risk) # low
Email Verification Lists
# Create a verification list
vlist = client.email_verification_lists.create({
"name": "Marketing List Q1",
"emails": [
"user1@example.com",
"user2@example.com",
"user3@example.com",
],
})
print(vlist.id) # evl_abc123...
print(vlist.status) # pending
# List all verification lists
vlists = client.email_verification_lists.list()
# Get a verification list
vlist = client.email_verification_lists.get("evl_abc123")
print(vlist.stats["successful_verifications"])
# Get verification results
results = client.email_verification_lists.results("evl_abc123", {"page": 1, "limit": 50})
for result in results:
print(f"{result.email} — {result.result}")
# Export results as XLSX
response = client.email_verification_lists.export("evl_abc123")
with open("results.xlsx", "wb") as f:
f.write(response.body.encode())
Webhooks
# Create a webhook
webhook = client.webhooks.create({
"name": "My Webhook",
"url": "https://example.com/hook",
"all_events": True,
"enabled": True,
})
print(webhook.id)
# List webhooks
webhooks = client.webhooks.list()
# Get a webhook
webhook = client.webhooks.get("wh_123")
# Update a webhook
client.webhooks.update("wh_123", {"enabled": False})
# Delete a webhook
client.webhooks.delete("wh_123")
Contacts
# Create a contact
contact = client.contacts.create({
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
})
print(contact.id)
# List contacts
contacts = client.contacts.list()
# Get a contact
contact = client.contacts.get("con_123")
# Update a contact
client.contacts.update("con_123", {"first_name": "Jane"})
# Delete a contact
client.contacts.delete("con_123")
Events
# List events
events = client.events.list({"type": "email.delivered"})
for event in events:
print(event.type)
# Get an event
event = client.events.get("evt_123")
print(event.type)
print(event.data["email_id"])
Webhook Events
The SDK provides typed event classes for all Emailit webhook event types under the emailit.events module, plus a WebhookSignature class for verifying webhook request signatures.
Verifying Webhook Signatures
from emailit import WebhookSignature, ApiErrorException
from emailit.events import EmailDelivered
raw_body = request.body # raw request body string
signature = request.headers["x-emailit-signature"]
timestamp = request.headers["x-emailit-timestamp"]
secret = "your_webhook_signing_secret"
try:
event = WebhookSignature.verify(raw_body, signature, timestamp, secret)
# event is automatically typed based on the event type
print(event.type) # e.g. "email.delivered"
print(event.event_id) # e.g. "evt_abc123"
# Access the event data
data = event.get_event_data()
if isinstance(event, EmailDelivered):
# Handle delivered email
pass
except ApiErrorException as e:
return Response(e.args[0], status=401)
You can disable replay protection by passing tolerance=None, or set a custom tolerance in seconds:
# Skip replay check
event = WebhookSignature.verify(raw_body, signature, timestamp, secret, tolerance=None)
# Custom 10-minute tolerance
event = WebhookSignature.verify(raw_body, signature, timestamp, secret, tolerance=600)
Available Event Types
Emails: email.accepted, email.scheduled, email.delivered, email.bounced, email.attempted, email.failed, email.rejected, email.suppressed, email.received, email.complained, email.clicked, email.loaded
Domains: domain.created, domain.updated, domain.deleted
Audiences: audience.created, audience.updated, audience.deleted
Subscribers: subscriber.created, subscriber.updated, subscriber.deleted
Contacts: contact.created, contact.updated, contact.deleted
Templates: template.created, template.updated, template.deleted
Suppressions: suppression.created, suppression.updated, suppression.deleted
Email Verifications: email_verification.created, email_verification.updated, email_verification.deleted
Email Verification Lists: email_verification_list.created, email_verification_list.updated, email_verification_list.deleted
Each event type has a corresponding class under emailit.events (e.g. EmailDelivered, DomainCreated). You can use isinstance checks or the EVENT_TYPE constant for routing:
from emailit.events import EmailDelivered, EmailBounced, ContactCreated
if isinstance(event, EmailDelivered):
handle_delivered(event)
elif isinstance(event, EmailBounced):
handle_bounce(event)
elif isinstance(event, ContactCreated):
handle_new_contact(event)
else:
print(f"Unhandled: {event.type}")
Error Handling
The SDK raises typed exceptions for API errors:
from emailit import (
ApiErrorException,
AuthenticationException,
InvalidRequestException,
RateLimitException,
UnprocessableEntityException,
ApiConnectionException,
)
try:
client.emails.send({...})
except AuthenticationException:
# Invalid API key (401)
pass
except InvalidRequestException:
# Bad request or not found (400, 404)
pass
except RateLimitException:
# Too many requests (429)
pass
except UnprocessableEntityException:
# Validation failed (422)
pass
except ApiConnectionException:
# Network error
pass
except ApiErrorException as e:
# Any other API error
print(e.http_status)
print(e.http_body)
print(e.json_body)
License
MIT -- see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file emailit-2.0.1.tar.gz.
File metadata
- Download URL: emailit-2.0.1.tar.gz
- Upload date:
- Size: 31.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cde7214d0abce49e06b1bb89961214c5ab2db5beee07d49bffed3ca96f7ce588
|
|
| MD5 |
3ef6983f26f70147e1f31cbf31af2970
|
|
| BLAKE2b-256 |
ed7667afe230eab15fbcdf06c131f18438ec2e9af7a8edeec5dcee04dd6d08ab
|
File details
Details for the file emailit-2.0.1-py3-none-any.whl.
File metadata
- Download URL: emailit-2.0.1-py3-none-any.whl
- Upload date:
- Size: 38.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
95c3aadb224e89031f3ee210bfb155411794916b4e956e58721fdc54cafbba7d
|
|
| MD5 |
5840e9e7ffa92f130987fa77dbba06d0
|
|
| BLAKE2b-256 |
379fc39607c0d267a79cbc1b40cb14504c03556763ca108ecde5cde06baa1b5b
|