@xlambda-tech/email
v0.2.0
Published
xlambda managed email SDK: Resend-compatible sending, domain/DKIM setup, and a ready-made inbound-mail webhook handler.
Readme
@xlambda-tech/email
Send email from your own domain, and — the reason this package exists — turn on receiving with almost no glue code.
Receiving inbound mail
import { createInboundHandler } from '@xlambda-tech/email';
export const { POST } = createInboundHandler({
secret: process.env.XLAMBDA_WEBHOOK_SECRET!,
onReceived: async (msg) => {
// msg is fully typed: domain, from, to, subject, textBody, htmlBody, headers, sizeBytes, truncated
await db.inboundEmails.create({ data: msg });
},
}).toNextRouteHandler();That's the whole integration for a Next.js App Router route handler. Point
your project's webhookUrl (dashboard → Settings → Webhooks) at this
endpoint and inbound mail on your managed domain starts landing in your own
database.
This is the only place a message's body ever exists. The platform
stores no message content server-side by design — only metadata (from, to,
subject, size) shows up in client.domains.messages(). If your handler
doesn't persist what it needs on receipt, it's gone (deliveries do retry 3×
with exponential backoff if your endpoint errors, so a transient failure
isn't fatal — a onReceived that never runs at all is).
Other frameworks:
import { toExpressHandler } from '@xlambda-tech/core/webhooks/adapters/express';
import { toFastifyPlugin } from '@xlambda-tech/core/webhooks/adapters/fastify';
// Express - MUST be mounted behind express.raw(), not express.json()
app.post('/webhooks/email', express.raw({ type: 'application/json' }), toExpressHandler(handler));
// Fastify - registers its own route + raw-body content-type parser, scoped to this plugin only
fastify.register(toFastifyPlugin(handler), { prefix: '/webhooks/email' });
// Raw Node http
const server = http.createServer(handler.toNodeHandler());onSent/onDelivered/onBounced are also available on
createInboundHandler for the outbound-side events, if you want one
endpoint handling everything.
Sending
import { EmailClient } from '@xlambda-tech/email';
const client = new EmailClient({ apiKey: process.env.XLAMBDA_API_KEY! });
await client.emails.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Hello',
html: '<p>Hi there</p>',
});Resend-compatible shape (from/to/cc/bcc/replyTo/subject/text/html).
from's domain must belong to a domain your project owns and has verified.
Setting up a domain
const domain = await client.domains.create({ projectId, domain: 'yourdomain.com' });
// domain.dkimRecords -> publish these at your DNS registrar
await client.domains.verify(domain.id); // re-checks MX/SPF/DKIM/DMARC once publishedChecking message history
const { messages } = await client.domains.messages(domain.id, { direction: 'received', limit: 50 });Metadata only (from/to/subject/status/size) — for the full body of a
received message, you must have captured it via createInboundHandler at
receipt time (see above).
