Ecosystem
Mail with a clear boundary
Validated messages, HTTP delivery and a development mailbox.
Choose a transport
Mail validates every message, bounds concurrency and enforces a delivery deadline. Use the HTTP provider transport in an engine App, or capture for development.
pnpm add ajo-kit-mail@0.3.0Capture messages locally
configure() connects the transport to this package and Kit’s mail seam. The bounded in-memory capture transport is refused in production.
import { configure, send } from 'ajo-kit-mail'
import { capture } from 'ajo-kit-mail/capture'
const mailbox = capture()
configure({ transport: mailbox, from: 'hello@example.com' })
await send({
to: 'reader@example.com',
subject: 'Your first message',
text: 'Hello from Ajo.',
})Map an HTTP provider
The HTTP transport uses fetch and maps a validated envelope into your provider’s JSON schema. Keep credentials in a server-side environment accessor. The optional nodemailer SMTP transport is a Node-host integration; do not include it in the engine’s production graph.
import { http } from 'ajo-kit-mail/http'
const transport = http({
url: 'https://api.provider.example/send',
headers: () => ({ Authorization: readProviderAuthorization() }),
body: mail => ({
from: mail.from.address, to: mail.to.address,
subject: mail.subject, text: mail.text,
}),
})Handle delivery outcomes
Each delivery makes one attempt. send() throws a sanitized error; deliver() returns an outcome for code that decides whether to retry. An idempotency key is forwarded to providers that support one.