Skip to main content

Official SDK for mailbuttons — email for AI agents with policy enforcement.

Project description

mailbuttons

Official SDK for mailbuttons — email for AI agents with policy enforcement.

v0.1.x is pre-stable. Breaking changes will be flagged in the CHANGELOG.

Install

pip install mailbuttons
# or
uv add mailbuttons

Requires Python 3.11 or later.

Quick start

import asyncio
import os

from aiohttp import web
from mailbuttons import (
    Mailbuttons,
    MailPolicy,
    parse_webhook,
    verify_webhook,
)

MAILBOX_ID = 42
SECRET = os.environ["MAILBUTTONS_WEBHOOK_SECRET"]
client = Mailbuttons(api_key=os.environ["MAILBUTTONS_API_KEY"])

policy = MailPolicy.model_validate({
    "defaultAction": "bounce",
    "senders": [{
        "match": {"domain": "your-company.com", "requireDkim": True},
        "capabilities": ["read_calendar", "propose_meeting"],
        "rateLimit": {"perHour": 30},
    }],
    "contentGuards": [{"reject": "(?i)wire transfer", "reason": "phishing"}],
    "auditLog": {"retentionDays": 30, "includeBodyHash": True},
})

async def main() -> None:
    await client.set_policy(MAILBOX_ID, policy)

async def webhook(request: web.Request) -> web.Response:
    raw = await request.read()
    sig = request.headers.get("X-Mailbuttons-Signature")
    if not verify_webhook(raw, sig, SECRET):
        return web.Response(status=401)
    event = parse_webhook(raw)
    if event.type == "inbound_message":
        await client.reply(MAILBOX_ID, event.data, "Got it — replying soon.")
    return web.Response(status=204)

app = web.Application()
app.router.add_post("/webhook", webhook)
asyncio.run(main())

Policy schema

A MailPolicy declares which senders can talk to your mailbox, what they're allowed to do, and how the platform enforces it. See mailbuttons.com/docs/policy for the full reference.

from mailbuttons import (
    AuditConfig, ContentGuard, MailPolicy, RateLimit, SenderMatch, SenderRule,
)

policy = MailPolicy(
    default_action="bounce",
    senders=[
        SenderRule(
            match=SenderMatch(address="boss@acme.com"),
            capabilities=["read_calendar", "confirm_meeting"],
        ),
        SenderRule(
            match=SenderMatch(domain="acme.com", require_dkim=True),
            capabilities=["read_calendar"],
            rate_limit=RateLimit(per_hour=30),
        ),
    ],
    content_guards=[ContentGuard(reject=r"(?i)\bsecret\b", reason="data exfil")],
    audit_log=AuditConfig(retention_days=90, include_body_hash=True),
)

Webhook handling

verify_webhook checks the HMAC-SHA-256 signature in X-Mailbuttons-Signature (format sha256=<hex>) against your shared secret. parse_webhook validates the JSON shape and returns a discriminated WebhookEvent.

ok = verify_webhook(raw_body, headers.get("X-Mailbuttons-Signature"), secret)
if not ok:
    return reject()
event = parse_webhook(raw_body)
if event.type == "inbound_message":
    await handle(event.data)

The signature is computed over the raw body bytes; do not parse JSON before verifying.

Errors

Every method raises one of:

  • AuthError (401/403) — missing or revoked API key.
  • NotFoundError (404) — mailbox or message not found.
  • ValidationError (400/422) — request body rejected; .field_errors lists the failures.
  • RateLimitError (429) — too many requests; .retry_after_seconds if the server hinted.
  • ServerError (5xx) — backend or upstream failure.
  • NetworkError — transport-level failure (DNS, TCP, timeout); .__cause__ carries the original.
  • WebhookSignatureErrorverify_webhook got malformed input.
  • WebhookPayloadErrorparse_webhook got a body that didn't match the expected schema.

Every error has a stable .code string for programmatic dispatch ("auth", "rate_limited", etc.).

Reference integration

A working agent built on top of this SDK lives at mailbuttons/claude-scheduling-agent-py. Five end-to-end scenarios; same harness as the TypeScript version.

Status & versioning

Pre-1.0. Breaking changes will be called out in CHANGELOG.md. Once the public surface settles, this package will move to 1.0 and adopt strict semver.

Licence

MIT.

Project details


Download files

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

Source Distribution

mailbuttons-0.1.0.tar.gz (9.7 kB view details)

Uploaded Source

Built Distribution

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

mailbuttons-0.1.0-py3-none-any.whl (12.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mailbuttons-0.1.0.tar.gz
  • Upload date:
  • Size: 9.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mailbuttons-0.1.0.tar.gz
Algorithm Hash digest
SHA256 aa69eca5641c4971811030faba282f83e5c19121fa5cfe099b0e9d38e8f5d4b1
MD5 cceba3fd37ec32f804d40735b86c011a
BLAKE2b-256 38eefb246433ff3d91b92e10e53d0837ab14553f3e770f39782719f5272a77b6

See more details on using hashes here.

Provenance

The following attestation bundles were made for mailbuttons-0.1.0.tar.gz:

Publisher: publish.yml on mailbuttons/sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: mailbuttons-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mailbuttons-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 36efa6a15a88cc269b766141ad1aae53fb0f1d170bfd021b660bf1ac8bcdebe6
MD5 bd112498c07f00531a3a66f234e98cc0
BLAKE2b-256 d6c020e6c9df4a604978e34f0d767578884929dfe398f4901e38a1eaa033ed1d

See more details on using hashes here.

Provenance

The following attestation bundles were made for mailbuttons-0.1.0-py3-none-any.whl:

Publisher: publish.yml on mailbuttons/sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page