Python
Official Unsent Python SDK for sending emails and managing contacts.
This guide shows how to install and use the official unsent Python SDK.
Initialize
Import the unsent class and initialize the client with your API key.
from unsent import unsent
# Initialize with raise_on_error=False to return errors as tuples
client = unsent("un_xxx", raise_on_error=False)Send an email
Now you can send an email. The SDK uses TypedDict definitions (like EmailCreate) to provide type hinting in your editor, but at runtime, you simply pass a standard Python dictionary.
Here is an example of sending a simple HTML email:
from unsent import unsent, types
client = unsent("un_xxx")
# Define the email payload
payload: types.EmailCreate = {
"to": "user@example.com",
"from": "no-reply@yourdomain.com",
"subject": "Welcome",
"html": "<strong>Hello!</strong>",
"headers": {"X-Campaign": "welcome"},
}
# Send the email
data, err = client.emails.send(payload)
if err:
print("Error:", err)
else:
print("Email sent:", data)Note
Unsent forwards your custom headers to SES. Only the X-Unsent-Email-ID and References headers are managed automatically by Unsent.
Attachments and scheduling
You can also send emails with attachments and schedule them for later delivery.
- Attachments: Provide a list of attachments, where each attachment has a
filenameandcontent(Base64 encoded string). - Scheduling: Use the
scheduledAtfield with adatetimeobject.
from datetime import datetime, timedelta
from unsent import types
payload: types.EmailCreate = {
"to": ["user1@example.com", "user2@example.com"],
"from": "no-reply@yourdomain.com",
"subject": "Report",
"text": "See attached.",
"attachments": [
{"filename": "report.txt", "content": "SGVsbG8gd29ybGQ="}, # Content must be Base64 encoded
],
"scheduledAt": datetime.utcnow() + timedelta(minutes=10), # Schedule for 10 minutes from now
}
data, err = client.emails.create(payload)Batch send
To send multiple emails efficiently in a single request, use the batch method.
items: list[types.EmailBatchItem] = [
{"to": "a@example.com", "from": "no-reply@yourdomain.com", "subject": "A", "html": "<p>A</p>"},
{"to": "b@example.com", "from": "no-reply@yourdomain.com", "subject": "B", "html": "<p>B</p>"},
]
data, err = client.emails.batch(items)Retrieve and manage emails
You can retrieve details of sent emails, update scheduled emails, or cancel them.
Get an email
Fetch the status and details of a specific email using its ID:
email, err = client.emails.get("email_123")Update schedule time
Change the scheduled delivery time for a pending email:
from datetime import datetime, timedelta
update: types.EmailUpdate = {"scheduledAt": datetime.utcnow() + timedelta(hours=1)}
data, err = client.emails.update("email_123", update)Cancel a scheduled email
Cancel a scheduled email so it won't be sent:
data, err = client.emails.cancel("email_123")Contacts
Manage your contacts and organize them into contact books. All contact operations require a contact book ID (book_id).
Create a contact
Add a new contact to a specific contact book. You can include custom properties.
create: types.ContactCreate = {
"email": "user@example.com",
"firstName": "Jane",
"properties": {"plan": "pro"},
}
data, err = client.contacts.create("book_123", create)Get a contact
Retrieve a contact's details:
contact, err = client.contacts.get("book_123", "contact_456")Update a contact
Update a contact's information:
update: types.ContactUpdate = {"subscribed": False}
data, err = client.contacts.update("book_123", "contact_456", update)Upsert a contact
Use upsert to create a contact if they don't exist, or update them if they do.
upsert: types.ContactUpsert = {
"email": "user@example.com",
"firstName": "Jane",
}
data, err = client.contacts.upsert("book_123", "contact_456", upsert)Delete a contact
Remove a contact from a book:
data, err = client.contacts.delete(book_id="book_123", contact_id="contact_456")Campaigns
Campaigns allow you to send emails to all contacts in a specific contact book.
Create a campaign
Create a new campaign by defining its content and the target contact book.
campaign: types.CampaignCreate = {
"name": "Welcome Series",
"subject": "Welcome!",
"html": "<p>Thanks for joining us!</p>",
"from": "welcome@yourdomain.com",
"contactBookId": "book_123",
}
data, err = client.campaigns.create(campaign)Schedule a campaign
Schedule the campaign to be sent at a specific time.
schedule: types.CampaignSchedule = {
"scheduledAt": "2024-12-01T10:00:00Z"
}
data, err = client.campaigns.schedule("campaign_123", schedule)Pause and Resume
Control the delivery of your campaign.
# Pause
data, err = client.campaigns.pause("campaign_123")
# Resume
data, err = client.campaigns.resume("campaign_123")Domains
Manage your sending domains.
List domains
Get a list of all domains and their statuses.
data, err = client.domains.list()Create a domain
Register a new domain for sending.
domain: types.DomainCreate = {
"domain": "yourdomain.com",
"region": "us-east-1",
}
data, err = client.domains.create(domain)Verify a domain
Check the verification status of a domain.
data, err = client.domains.verify(123)Error handling
The SDK supports two modes of error handling.
Raising Exceptions (Default)
By default, the client raises unsentHTTPError for non-2xx responses. This is useful for standard exception handling.
from unsent import unsent, unsentHTTPError
# Raises exceptions on errors (default)
client = unsent("un_xxx")
try:
data, _ = client.emails.get("email_123")
except unsentHTTPError as e:
print("Request failed:", e)Returning Error Tuples
If you prefer to check for errors in the return value instead of using try-except blocks, pass raise_on_error=False when initializing the client.
# Returns (None, error) instead of raising
client = unsent("un_xxx", raise_on_error=False)
data, err = client.emails.get("email_123")
if err:
print("Error:", err)
else:
print("Success:", data)