Official Python SDK for the ToSend email API.
pip install tosendSee the examples folder for complete working examples:
- Send Email - Send a single email
- Batch Send - Send multiple emails in one request
- Account Info - Get account information and domains
export TOSEND_API_KEY=tsend_your_api_key
python examples/send_email.pyfrom tosend import ToSend
client = ToSend("tsend_your_api_key")
response = client.send(
from_address={"email": "hello@yourdomain.com", "name": "Your App"},
to=[{"email": "user@example.com"}],
subject="Welcome!",
html="<h1>Hello!</h1><p>Thanks for signing up.</p>",
)
print(response.message_id)response = client.send(
from_address={"email": "hello@yourdomain.com", "name": "Your App"},
to=[
{"email": "user@example.com"},
{"email": "another@example.com", "name": "John Doe"},
],
subject="Hello!",
html="<h1>Welcome</h1>",
text="Welcome", # optional
)response = client.send(
from_address={"email": "hello@yourdomain.com"},
to=[{"email": "user@example.com"}],
cc=[{"email": "cc@example.com"}],
bcc=[{"email": "bcc@example.com"}],
reply_to={"email": "support@yourdomain.com", "name": "Support"},
subject="Hello",
html="<p>Hello World</p>",
)import base64
with open("invoice.pdf", "rb") as f:
content = base64.b64encode(f.read()).decode()
response = client.send(
from_address={"email": "hello@yourdomain.com"},
to=[{"email": "user@example.com"}],
subject="Your Invoice",
html="<p>Please find your invoice attached.</p>",
attachments=[
{
"type": "application/pdf",
"name": "invoice.pdf",
"content": content,
}
],
)Send multiple emails in a single request:
response = client.batch([
{
"from": {"email": "hello@yourdomain.com"},
"to": [{"email": "user1@example.com"}],
"subject": "Hello User 1",
"html": "<p>Welcome!</p>",
},
{
"from": {"email": "hello@yourdomain.com"},
"to": [{"email": "user2@example.com"}],
"subject": "Hello User 2",
"html": "<p>Welcome!</p>",
},
])
for result in response.results:
if result.status == "success":
print(f"Sent: {result.message_id}")
else:
print(f"Failed: {result.message}")info = client.get_account_info()
print(info.account.status) # "active"
print(info.account.credit_balance) # None means the account does not consume credits
print(info.account.limit_per_second)
print(info.account.bounce_rate) # a fraction between 0 and 1
for domain in info.domains:
print(f"{domain.domain_name}: {domain.verification_status}")ToSendAdmin is a separate client for the Admin API. It takes an admin key (tsend_admin_...) and refuses a sending key at construction. Each call needs the matching scope on the key; a missing one raises ToSendError with status 403 and error.code == "insufficient_scope".
import os
from tosend import ToSendAdmin
admin = ToSendAdmin(os.environ["TOSEND_ADMIN_KEY"])
# Act on one of your client teams (sends X-Account-Id)
client = admin.for_account(4203)
domain = client.create_domain("client.example.com")
detail = client.get_domain(domain["id"])
print(detail["dns_records"]["dkim"]) # show these records to your client
# Needs api_keys:write and emails:send
key = client.create_sending_key("Client: Acme Corp")
print(key["api_key"]) # returned once, store it now
# Needs emails:send
client.send(
from_address={"email": "hello@client.example.com"},
to=[{"email": "user@example.com"}],
subject="Hi",
html="<p>Hello</p>",
)Also available: get_info, list_domains, delete_domain, list_emails, get_email, list_suppressions, delete_suppression, list_webhooks, create_webhook, update_webhook, delete_webhook, list_sending_keys, delete_sending_key, list_teams, create_team, update_team and batch. List methods take page and per_page and return a dict with data, total, page and per_page; single-resource methods return the resource as a dict.
client = ToSend(
api_key="tsend_your_api_key",
base_url="https://api.tosend.com", # optional
timeout=60, # optional, in seconds
)from tosend import ToSend, ToSendError
client = ToSend("tsend_your_api_key")
try:
response = client.send(
from_address={"email": "hello@yourdomain.com"},
to=[{"email": "user@example.com"}],
subject="Hello",
html="<p>Hello</p>",
)
except ToSendError as e:
print(f"Error: {e.message}")
print(f"Status: {e.status_code}")
print(f"Type: {e.error_type}")
print(f"Details: {e.errors}")
if e.is_validation_error:
# Handle validation error (422)
pass
if e.is_authentication_error:
# Handle auth error (401/403)
pass
if e.is_rate_limit_error:
# Handle rate limit (429)
passThe SDK includes full type hints. You can also use the provided dataclasses:
from tosend import ToSend, Address, SendEmailRequest
client = ToSend("tsend_your_api_key")
# Using Address dataclass
from_addr = Address(email="hello@yourdomain.com", name="Your App")
to_addr = Address(email="user@example.com")
response = client.send(
from_address=from_addr,
to=[to_addr],
subject="Hello!",
html="<h1>Welcome!</h1>",
)- Python 3.8 or higher
- No external dependencies (uses only standard library)
MIT