Email SDK

Email SDK

One typed send() for 20 email providers — explicit routing, retries, fallbacks, and zero dependencies.

Email SDK is a zero-dependency TypeScript library for transactional email. You write one typed message; configured adapters decide how it reaches Resend, Postmark, SendGrid, AWS SES, Mailgun, SMTP, or any of 20 providers. Switching providers — or surviving an outage with a fallback route — never touches your application 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",
  text: "Your account is ready.",
});

Why Email SDK

  • One message shape, 20 providers. Import only the adapter you use — each one is a separate entry point, and the core has zero runtime dependencies.
  • No silent data loss. Providers differ: Resend has no metadata, SMTP has no tags. Adapters either map a field or throw before the request — never drop it. See field support.
  • Retries and fallback routes, made explicit. Exponential backoff inside an adapter, then explicit fallback adapters after it finally fails. How routing works.
  • Observable without leaking PII. Hooks and the observability plugin emit redacted events — counts and tag names, never bodies or recipients.
  • Testable for free. Memory and failing adapters plus the capture plugin assert send behavior without a real provider.
  • A CLI for the boring parts. email-sdk doctor checks your environment, --dry-run validates a message against an adapter, and send runs a real smoke test. CLI reference.

Start here

Beyond the core

What it is not

Email SDK is not a campaign tool, queue, template engine, or hosted analytics product. It is the layer apps keep rebuilding — adapter setup, one consistent send call, typed errors, compatibility checks, and fallback routes explicit enough to debug at 3 a.m.

Local checks are not deliverability

The SDK validates message shape and field support before every request, but live delivery still depends on your provider account: verified sender domains, API scopes, regions, and sandbox rules. Dry-run first, then run one real smoke send from your production environment.

On this page