From 45bffb073f32b2011df8d7c7c44b65a5a56ae505 Mon Sep 17 00:00:00 2001 From: bobbyonmagic Date: Sun, 11 Oct 2026 07:28:24 +0300 Subject: [PATCH] Label the quick start receipt transactional Unlabelled mail is marketing now: it gets a one-click unsubscribe header and skips people who unsubscribed. Claude-Session: https://claude.ai/code/session_01FRYkaYp9vFJjWBjAQdjnQ4 --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 5eee90c..e6f9720 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,13 @@ email = client.emails.send({ "to": ["customer@example.org"], "subject": "Your receipt", "html": "

Thanks for your order.

", + "category": "transactional", }) print(email["id"]) ``` +Email is marketing unless you set `category` to `transactional`. Marketing email gets a one-click unsubscribe header and is not sent to people who unsubscribed. Set `transactional` on receipts, password resets and account alerts so a marketing opt-out does not block them. + Requests and responses are plain dicts, typed with `TypedDict`s from `smtpfast.types`, so your editor and type checker know every field. A new field or value from the API never breaks your code, because the SDK does not validate responses at runtime. Every API operation is a method, named after its path: `client.domains.verify(id)`, `client.contacts.segments.add(contact_id, segment_id)`, `client.inboxes.threads.emails.reply(inbox_id, thread_id, email_id, params)`. Path parameters come first, then the request body, and query parameters are keyword arguments: `client.emails.list(limit=20, status="bounced")`.