Email SDK

Plugin API

Type reference for EmailPlugin and EmailSendMiddleware.

This page is the type reference. For examples, start with Writing plugins.

EmailPlugin

type EmailPlugin<TExtension extends object = object> = {
  id: string;
  adapters?: EmailProvider[] | ((ctx: EmailPluginContext) => EmailProvider[]);
  hooks?: EmailHooks;
  middleware?: EmailSendMiddleware[];
  extendClient?: (ctx: EmailPluginContext) => TExtension;
};
FieldNotes
idRequired stable plugin ID. Duplicate IDs throw.
adaptersProviders to register. Duplicate adapter names throw.
hooksObservability callbacks that run before user hooks.
middlewareSend-pipeline middleware.
extendClientAdds non-conflicting helper properties to the client.

createEmailClient is synchronous, so plugin adapter factories must return adapters synchronously.

EmailPluginContext

type EmailPluginContext = {
  adapters: ReadonlyMap<string, EmailProvider>;
  defaultAdapter: string;
  addAdapter(adapter: EmailProvider): void;
};

EmailSendMiddleware

type EmailSendMiddleware = {
  beforeSend?: (event: EmailBeforeSendEvent) => MaybePromise<EmailBeforeSendResult | void>;
  afterSend?: (event: EmailAfterSendEvent) => MaybePromise<void>;
  onError?: (event: EmailErrorEvent) => MaybePromise<void>;
};

beforeSend

Runs once per send call before message validation and before any adapter is called.

beforeSend(event) {
  return {
    message: {
      ...event.message,
      headers: { "X-App": "billing" },
    },
    options: {
      metadata: { template: "receipt" },
    },
  };
}

Thrown errors stop the send.

afterSend

Runs after a provider returns a normalized response.

afterSend(event) {
  console.log(event.provider, event.response.id);
}

Thrown errors are swallowed.

onError

Runs after a provider attempt fails.

onError(event) {
  console.error(event.provider, event.error);
}

Fallback adapters can still run after this callback. Thrown errors are swallowed.

On this page