Python SDK for the Unsent API - Send transactional emails with ease
Project description
unsent Python SDK
Prerequisites
Installation
pip
pip install unsent
poetry
poetry add unsent
Usage
Basic Setup
from unsent import unsent
client = unsent("us_12345")
Environment Variables
You can also set your API key using environment variables:
# Set UNSENT_API_KEY or UNSENT_API_KEY in your environment
# Then initialize without passing the key
client = unsent()
Sending Emails
Simple Email
data, error = client.emails.send({
"to": "hello@acme.com",
"from": "hello@company.com",
"subject": "unsent email",
"html": "<p>unsent is the best open source product to send emails</p>",
"text": "unsent is the best open source product to send emails",
})
if error:
print(f"Error: {error}")
else:
print(f"Email sent! ID: {data['id']}")
Email with Attachments
data, error = client.emails.send({
"to": "hello@acme.com",
"from": "hello@company.com",
"subject": "Email with attachment",
"html": "<p>Please find the attachment below</p>",
"attachments": [
{
"filename": "document.pdf",
"content": "base64-encoded-content-here",
}
],
})
Scheduled Email
from datetime import datetime, timedelta
# Schedule email for 1 hour from now
scheduled_time = datetime.now() + timedelta(hours=1)
data, error = client.emails.send({
"to": "hello@acme.com",
"from": "hello@company.com",
"subject": "Scheduled email",
"html": "<p>This email was scheduled</p>",
"scheduledAt": scheduled_time,
})
Batch Emails
emails = [
{
"to": "user1@example.com",
"from": "hello@company.com",
"subject": "Hello User 1",
"html": "<p>Welcome User 1</p>",
},
{
"to": "user2@example.com",
"from": "hello@company.com",
"subject": "Hello User 2",
"html": "<p>Welcome User 2</p>",
},
]
data, error = client.emails.batch(emails)
if error:
print(f"Error: {error}")
else:
print(f"Sent {len(data['emails'])} emails")
Managing Emails
Get Email Details
data, error = client.emails.get("email_id")
if error:
print(f"Error: {error}")
else:
print(f"Email status: {data['status']}")
Update Email
data, error = client.emails.update("email_id", {
"subject": "Updated subject",
"html": "<p>Updated content</p>",
})
Cancel Scheduled Email
data, error = client.emails.cancel("email_id")
if error:
print(f"Error: {error}")
else:
print("Email cancelled successfully")
Managing Contacts
Create Contact
data, error = client.contacts.create("contact_book_id", {
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"metadata": {
"company": "Acme Inc",
"role": "Developer"
}
})
Get Contact
data, error = client.contacts.get("contact_book_id", "contact_id")
Update Contact
data, error = client.contacts.update("contact_book_id", "contact_id", {
"firstName": "Jane",
"metadata": {
"role": "Senior Developer"
}
})
Upsert Contact
# Creates if doesn't exist, updates if exists
data, error = client.contacts.upsert("contact_book_id", "contact_id", {
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
})
Delete Contact
data, error = client.contacts.delete(
book_id="contact_book_id",
contact_id="contact_id"
)
Managing Campaigns
Create Campaign
from unsent import types
campaign_payload: types.CampaignCreate = {
"name": "Welcome Series",
"subject": "Welcome to our service!",
"html": "<p>Thanks for joining us!</p>",
"from": "welcome@example.com",
"contactBookId": "cb_1234567890",
}
campaign_resp, error = client.campaigns.create(payload=campaign_payload)
if error:
print(f"Error: {error}")
else:
print(f"Campaign created! ID: {campaign_resp['id']}")
Schedule Campaign
from unsent import types
schedule_payload: types.CampaignSchedule = {
"scheduledAt": "2024-12-01T10:00:00Z",
}
schedule_resp, error = client.campaigns.schedule(
campaign_id=campaign_resp["id"],
payload=schedule_payload
)
if error:
print(f"Error: {error}")
else:
print("Campaign scheduled successfully!")
Pause/Resume Campaigns
# Pause a campaign
pause_resp, error = client.campaigns.pause(campaign_id="campaign_123")
if error:
print(f"Error: {error}")
else:
print("Campaign paused successfully!")
# Resume a campaign
resume_resp, error = client.campaigns.resume(campaign_id="campaign_123")
if error:
print(f"Error: {error}")
else:
print("Campaign resumed successfully!")
Get Campaign Details
data, error = client.campaigns.get("campaign_id")
if error:
print(f"Error: {error}")
else:
print(f"Campaign status: {data['status']}")
print(f"Recipients: {data['total']}")
print(f"Sent: {data['sent']}")
Managing Domains
List Domains
data, error = client.domains.list()
if error:
print(f"Error: {error}")
else:
for domain in data:
print(f"Domain: {domain['domain']}, Status: {domain['status']}")
Create Domain
data, error = client.domains.create({
"domain": "example.com"
})
Verify Domain
data, error = client.domains.verify(domain_id=123)
if error:
print(f"Error: {error}")
else:
print(f"Verification status: {data['status']}")
Get Domain
data, error = client.domains.get(domain_id=123)
Error Handling
By default, the SDK raises exceptions on HTTP errors:
from unsent import unsent, unsentHTTPError
client = unsent("us_12345")
try:
data, error = client.emails.send({
"to": "invalid-email",
"from": "hello@company.com",
"subject": "Test",
"html": "<p>Test</p>",
})
except unsentHTTPError as e:
print(f"HTTP {e.status_code}: {e.error['message']}")
To disable automatic error raising:
client = unsent("us_12345", raise_on_error=False)
data, error = client.emails.send({
"to": "hello@acme.com",
"from": "hello@company.com",
"subject": "Test",
"html": "<p>Test</p>",
})
if error:
print(f"Error: {error['message']}")
else:
print("Success!")
Custom Session
For advanced use cases, you can provide your own requests.Session:
import requests
from unsent import unsent
session = requests.Session()
session.verify = False # Not recommended for production!
client = unsent("us_12345", session=session)
API Reference
Client Methods
unsent(key, url, raise_on_error=True, session=None)- Initialize the client
Email Methods
client.emails.send(payload)- Send an email (alias forcreate)client.emails.create(payload)- Create and send an emailclient.emails.batch(emails)- Send multiple emails in batchclient.emails.get(email_id)- Get email detailsclient.emails.update(email_id, payload)- Update a scheduled emailclient.emails.cancel(email_id)- Cancel a scheduled email
Contact Methods
client.contacts.create(book_id, payload)- Create a contactclient.contacts.get(book_id, contact_id)- Get contact detailsclient.contacts.update(book_id, contact_id, payload)- Update a contactclient.contacts.upsert(book_id, contact_id, payload)- Upsert a contactclient.contacts.delete(book_id, contact_id)- Delete a contact
Campaign Methods
client.campaigns.create(payload)- Create a campaignclient.campaigns.get(campaign_id)- Get campaign detailsclient.campaigns.schedule(campaign_id, payload)- Schedule a campaignclient.campaigns.pause(campaign_id)- Pause a campaignclient.campaigns.resume(campaign_id)- Resume a campaign
Domain Methods
client.domains.list()- List all domainsclient.domains.create(payload)- Create a domainclient.domains.verify(domain_id)- Verify a domainclient.domains.get(domain_id)- Get domain details
Requirements
- Python 3.8+
- requests >= 2.32.0
- typing_extensions >= 4.7
License
MIT
Support
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
unsent-1.0.0.tar.gz
(10.1 kB
view details)
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
unsent-1.0.0-py3-none-any.whl
(11.1 kB
view details)
File details
Details for the file unsent-1.0.0.tar.gz.
File metadata
- Download URL: unsent-1.0.0.tar.gz
- Upload date:
- Size: 10.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.1 CPython/3.13.8 Darwin/25.0.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9cdd8789852b8df4efd5d4e97302f0181a6bd8881893c981ae4020468cfe01a0
|
|
| MD5 |
1932e5868cbf77f136c3193a41a05134
|
|
| BLAKE2b-256 |
4c0e16db4929747d411a820c0695b98581eb59401a1533c9bda5e67ff3bcff1c
|
File details
Details for the file unsent-1.0.0-py3-none-any.whl.
File metadata
- Download URL: unsent-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.1 CPython/3.13.8 Darwin/25.0.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e7073e52523a03cb777f6ec5029aa14aab24924232e934a44f619d9c843035c9
|
|
| MD5 |
6ff3f13476603a2174e1e7e4cfd08d10
|
|
| BLAKE2b-256 |
598606719638d937118c3e14fa09d971681f449ae67e80cfa17352c7820c980d
|