seskit
The Python SDK for SESKit — a Python-native, self-hosted developer email platform built on Amazon SES.
What SESKit is
SESKit makes Amazon SES feel as simple as Resend, without giving up ownership of your sending infrastructure. You run it yourself, on your own AWS account: an HTTP API for sending, a dashboard for looking at what happened, delivery event ingestion from SNS, and signed outbound webhooks.
This package is the client, not the server. You run the server; your application installs this. The same distinction as a database and its driver.
Install
pip install seskit
Send
from seskit import SesKit
client = SesKit(api_key="sk_live_...", base_url="https://seskit.example.com")
sent = client.emails.send(
from_="hello@example.com",
to=["user@example.com"],
subject="Welcome",
html="<h1>Welcome!</h1>",
)
base_url is the address of your own instance. There is no default, because
there is no hosted SESKit to point at.
Read
email = client.emails.get(sent.id)
email.status # queued, sending, sent, failed
email.delivered_at # None until a delivery event arrives
page = client.emails.list(status="failed")
for email in page:
print(email.id, email.last_error)
list returns one page, newest first. Pass page.last_id as starting_after
while page.has_more.
Errors
Every refusal is a class, so you branch on the type rather than on the message:
from seskit import SuppressedRecipient, DomainNotVerified, SESKitError
try:
client.emails.send(...)
except SuppressedRecipient:
... # the address hard-bounced or complained; it is on your list
except DomainNotVerified:
... # the sender is not verified in SES
except SESKitError as error:
... # anything else; error.type and error.message say what
Async
The same surface, awaited — because a blocking HTTP call inside an async handler stops the event loop for every other request on that worker:
from seskit import AsyncSesKit
client = AsyncSesKit(api_key="sk_live_...", base_url="https://seskit.example.com")
sent = await client.emails.send(
from_="hello@example.com",
to=["user@example.com"],
subject="Welcome",
html="<h1>Welcome!</h1>",
)
Retries
Rate limits, 5xx responses and connection failures are retried with backoff,
honouring Retry-After. Refusals are not — asking again produces the same
refusal.
Every send carries an Idempotency-Key, generated per call unless you pass
one, so a retry after a timeout cannot deliver a second copy. Pass your own
(an order id, say) when you have something that identifies the send across
process restarts.
It is optional
The SDK is deliberately a thin client over the HTTP API. Business logic lives in the API and is never duplicated here, so a Python call and a curl command cannot disagree about what SESKit does.
The consequence is worth stating: this client can never do anything a curl
command cannot. Reaching for it is a convenience, never a requirement.
Licence
MIT. See LICENSE.
Metadata
Release files for seskit 0.1.0
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 | |
|---|---|---|---|---|
| seskit-0.1.0.tar.gz | 13.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| seskit-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.3 kB
Release files / seskit-0.1.0.tar.gz
| Download URL | seskit-0.1.0.tar.gz |
|---|---|
| Size | 13.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fee0e5fef46e0babb3c40f46a6ca0673c9174de0c97593fd8c4366a6396b5be8
|
|
BLAKE2b-256 checksum How to use checksums |
2c3f3668b18211251070a7212aa3383183993d7bd73d0282e9328193078714d3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / seskit-0.1.0-py3-none-any.whl
| Download URL | seskit-0.1.0-py3-none-any.whl |
|---|---|
| Size | 19.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6a33997c0d6b02b229ec710d24c267fb9b7980c55dc9cfc11ab68ffffec57c62
|
|
BLAKE2b-256 checksum How to use checksums |
2e76ec3311d3145b7a46a1dd160e82e01ec9acbb072011707463df3d11ac13ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for seskit 0.1.0
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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.