Email SDK

Plugins

Package reusable send behavior (adapters, hooks, middleware, and typed client extensions) into one plugins array.

A plugin bundles send-pipeline behavior into one reusable unit you mount with plugins: [...]. One plugin can register adapters, transform messages before validation, observe every attempt, and add typed helpers to the client. Shared policy lives in one place instead of being copied around every createEmailClient call.

lib/email.ts
import { createEmailClient } from "@opencoredev/email-sdk";
import { defaultsPlugin } from "@opencoredev/email-sdk/plugins/defaults";
import { observabilityPlugin } from "@opencoredev/email-sdk/plugins/observability";
import { resend } from "@opencoredev/email-sdk/resend";

export const email = createEmailClient({
  adapters: [resend({ apiKey: process.env.RESEND_API_KEY! })],
  plugins: [
    defaultsPlugin({ headers: { "X-App": "acme" }, replyTo: "support@acme.com" }),
    observabilityPlugin({ log: (event) => console.log(event.type, event.provider) }),
  ],
});

What a plugin can do

A plugin is a plain object with an id and any combination of four capabilities:

CapabilityFieldWhat it does
Add routesadaptersRegisters providers into the client, same as the adapters option. This is how community provider packages ship one-call setup.
TransformmiddlewarebeforeSend runs once per send, before validation, and can replace the message or options. afterSend / onError observe outcomes.
ObservehooksThe same hooks as the client option: per-attempt, observe-only, failures swallowed.
ExtendextendClientAdds typed properties to the returned client, like email.capture from the capture plugin.

Middleware is the capability only plugins have: client-level hooks can watch a send, but only plugin middleware can change it.

Built-in plugins

Three plugins ship with the SDK, each from its own entry point:

PluginImportUse it when
Defaults@opencoredev/email-sdk/plugins/defaultsEvery send needs the same headers, tags, reply-to, or idempotency prefix.
Observability@opencoredev/email-sdk/plugins/observabilityYou want logs, metrics, or traces without leaking recipients or bodies.
Capture@opencoredev/email-sdk/plugins/captureTests need to assert attempted sends, retries, responses, and errors.

Registration rules

Plugins register in array order, and the order is deterministic:

  1. Direct adapters register first, then each plugin's adapters in plugin order.
  2. Middleware and hooks run in plugin order; plugin hooks run before client hooks.
  3. Duplicate plugin ids and duplicate adapter names throw an EmailValidationError. Mount two instances of the same plugin with distinct ids and distinct extension keys, e.g. capturePlugin({ id: "capture:audit", clientKey: "auditCapture" }).

The full rules, event shapes, and error cases are in the plugin API reference.

Explore

On this page