Skip to main content

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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

seskit-0.1.0.tar.gz (13.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

seskit-0.1.0-py3-none-any.whl (19.0 kB view details)

Uploaded Python 3

File details

Details for the file seskit-0.1.0.tar.gz.

File metadata

  • Download URL: seskit-0.1.0.tar.gz
  • Upload date:
  • Size: 13.4 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for seskit-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fee0e5fef46e0babb3c40f46a6ca0673c9174de0c97593fd8c4366a6396b5be8
MD5 d52c0a9b1eb8edacade5b4efdc487a4f
BLAKE2b-256 2c3f3668b18211251070a7212aa3383183993d7bd73d0282e9328193078714d3

See more details on using hashes here.

File details

Details for the file seskit-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: seskit-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 19.0 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for seskit-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6a33997c0d6b02b229ec710d24c267fb9b7980c55dc9cfc11ab68ffffec57c62
MD5 0043c6a332d4356de5cd55ed06da8f1f
BLAKE2b-256 2e76ec3311d3145b7a46a1dd160e82e01ec9acbb072011707463df3d11ac13ab

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page