ToSend Python SDK
Official Python SDK for the ToSend email API.
Installation
pip install tosend
Examples
See 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.py
Quick Start
from 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)
Usage
Send an Email
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
)
With CC, BCC, and Reply-To
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>",
)
With Attachments
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,
}
],
)
Batch Sending
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}")
Get Account Info
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}")
Admin API
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.
Configuration
With Options
client = ToSend(
api_key="tsend_your_api_key",
base_url="https://api.tosend.com", # optional
timeout=60, # optional, in seconds
)
Error Handling
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)
pass
Type Hints
The 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>",
)
Requirements
- Python 3.8 or higher
- No external dependencies (uses only standard library)
License
MIT
Metadata
Release files for tosend 1.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tosend-1.1.1.tar.gz | 15.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tosend-1.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.2 kB
Release files / tosend-1.1.1.tar.gz
| Download URL | tosend-1.1.1.tar.gz |
|---|---|
| Size | 15.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7ead4f4e299dc37a733613abe0a5ab275cc5f6f30d178560a8556aca6567c4a8
|
|
BLAKE2b-256 checksum How to use checksums |
639e24d6e6d909f3d65349931817014479393e8e245e84b33c02b7ed49ce73b2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / tosend-1.1.1-py3-none-any.whl
| Download URL | tosend-1.1.1-py3-none-any.whl |
|---|---|
| Size | 13.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9f78445124d56a479ae7673a5642d4da2a5afc8f42d8be7bcbe7297227a01ab9
|
|
BLAKE2b-256 checksum How to use checksums |
26e7f41be58e6bdfc4592d5d34e0c3a438b6d995f4d80eba736b56a7168c7e42
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Security for tosend 1.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.