Metadata-Version: 2.5
Name: seskit
Version: 0.1.0
Summary: Python SDK for SESKit, a self-hosted developer email platform built on Amazon SES
Project-URL: Homepage, https://github.com/Otitodev/seskit
Project-URL: Repository, https://github.com/Otitodev/seskit
Project-URL: Issues, https://github.com/Otitodev/seskit/issues
Author: SESKit Contributors
License: MIT License
        
        Copyright (c) 2026 SESKit Contributors
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: aws,email,ses,smtp,transactional-email
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Communications :: Email
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: httpx>=0.27
Description-Content-Type: text/markdown

# seskit

The Python SDK for [SESKit](https://github.com/Otitodev/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

```bash
pip install seskit
```

## Send

```python
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

```python
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:

```python
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:

```python
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](LICENSE).
