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 — so 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 — 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