A lightweight TypeScript SDK for transactional email send pipelines. Use one client in your app, pick the adapters you actually send through, validate provider compatibility before data is silently dropped, add retries and fallback routes, observe send behavior, and keep provider-specific field support visible in the docs.
Docs: https://email-sdk.dev/docs
packages/email-sdk- core SDK, adapters, plugins, CLI, tests, and package READMEapps/fumadocs- documentation siteskills/email-sdk- repo-local agent skill for Email SDK integrations
npm install @opencoredev/email-sdkpnpm add @opencoredev/email-sdkbun add @opencoredev/email-sdkThe public npm package is @opencoredev/email-sdk; the unscoped email-sdk package is unrelated.
The CLI binary installed by this package is still named email-sdk.
Use the SDK and CLI from server-side Node 20+ or Bun runtimes. Do not expose provider API keys in browser or client-side code.
import { createEmailClient } from "@opencoredev/email-sdk";
import { resend } from "@opencoredev/email-sdk/resend";
const email = createEmailClient({
adapters: [resend({ apiKey: process.env.RESEND_API_KEY! })],
});
await email.send({
from: "Acme <hello@acme.com>",
to: "user@example.com",
subject: "Welcome",
html: "<p>It works.</p>",
});- One normalized
EmailMessageshape. - Adapter routing through
defaultAdapter, per-sendadapter,fallback, andfallbackAdapters. - Fail-fast field support checks for fields a provider cannot represent.
- Retries inside one adapter and fallback routes after an adapter fails.
- Hooks and the
observabilityplugin for logs, metrics, traces, retry visibility, and errors. - Built-in
defaults,observability, andcaptureplugins. - Test capture and memory/failing adapters for app tests that should not call real providers.
- CLI dry-runs, adapter discovery, setup checks, and smoke-test sends.
- Built-in SMTP transport without Nodemailer.
See packages/email-sdk/README.md for SDK usage examples, read the public docs at https://email-sdk.dev/docs, or start with these pages:
resend, postmark, sendgrid, mailgun, mailersend, brevo, mailchimp, sparkpost, loops, plunk, mailtrap, cloudflare, scaleway, zeptomail, mailpace, smtp, and testing are exported from separate package entry points.
If you are choosing your first adapter, start with Resend for the shortest path to a first send. Use Postmark, SendGrid, AWS SES, Mailgun, Cloudflare, or Brevo when you need broader provider-specific controls. Use SMTP when you already have a trusted SMTP service and only need address fields, headers, and plain message delivery.
Plugin entry points:
@opencoredev/email-sdk/plugins/defaults@opencoredev/email-sdk/plugins/observability@opencoredev/email-sdk/plugins/capture
Run the CLI without installing anything globally:
npx --yes --package @opencoredev/email-sdk email-sdk adaptersAfter adding the package to a project, run the installed binary:
RESEND_API_KEY="re_..." npx email-sdk doctor --adapter resendInstall the Email SDK agent skill from skills.sh when you want an AI agent to add, review, or document an integration:
npx skills add opencoredev/email-sdk --skill email-sdkThe skill is stored in skills/email-sdk/SKILL.md. It tells agents to refresh the current README, Fumadocs pages, package exports, and TypeScript declarations before implementing, so the guidance stays useful as the SDK evolves without needing every new adapter or option copied into the skill.
bun install
bun test
bun run check-types
bun run buildUseful workspace scripts:
bun run build- build packages and apps through Turbobun run check-types- run TypeScript checks across the workspacebun test- run package testsbun run check- run Oxlint and Oxfmt with write formattingbun run dev- start the docs dev server through Turbo
Releases use Changesets, Depot-backed GitHub Actions runners, npm, and the repo-local Homebrew formula. Release operator notes live in AGENTS.md.
Do not start the docs dev server unless you actually want a local preview.
The SDK validates messages locally and adapter tests verify payload mapping with injected fetch calls. Real provider sends still depend on live account setup: verified domains, sender identities, API scopes, sandbox settings, regions, rate limits, and provider-specific policy.
Before production use, configure one primary adapter, add a fallback adapter where delivery matters, and run a live smoke send from the target environment.