Plugins
Built-in plugins and extension points for Email SDK.
Plugins are add-ons for an email client. They can register adapters, change a message before validation, record send activity, or expose a small typed helper on the client.
Plugins are how repeated send-pipeline behavior becomes reusable: defaults before validation, observability after attempts, capture in tests, and adapter registration for community routes. For a full production path, see Production send pipeline.
Most apps should start with the built-in plugins. If a behavior should be reused across apps, move it into a plugin.
Built-in plugins
| Plugin | Import | Use it when |
|---|---|---|
| Defaults | @opencoredev/email-sdk/plugins/defaults | Every send needs shared headers, tags, metadata, reply-to, or idempotency defaults. |
| Observability | @opencoredev/email-sdk/plugins/observability | You want logs, metrics, or traces without leaking recipients or email body content. |
| Capture | @opencoredev/email-sdk/plugins/capture | Tests need to inspect attempted sends, retries, responses, and errors. |
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";
const email = createEmailClient({
adapters: [resend({ apiKey: process.env.RESEND_API_KEY! })],
plugins: [
defaultsPlugin({
headers: { "X-App": "billing" },
sendMetadata: { service: "billing" },
}),
observabilityPlugin({
log(event) {
console.log(event.type, event.provider);
},
}),
],
});What plugins can do
| Capability | Example |
|---|---|
| Register adapters | A community provider package can add its own EmailProvider. |
| Change a message | Defaults can add headers before provider validation. |
| Observe sends | Observability can emit redacted success, retry, and error events. |
| Capture tests | Capture can expose email.capture.events. |
| Add helpers | A plugin can add a small typed property to the returned client. |
What plugins cannot do
Email SDK plugins do not add databases, migrations, HTTP endpoints, route middleware, rate limits, or server/client plugin pairs. Those are framework-level features. Email SDK plugins stay focused on sending email.
Common plugin shapes
| Shape | Where to start |
|---|---|
| Shared defaults | Use the defaults plugin. |
| Redacted logging | Use the observability plugin. |
| Test capture | Use the capture plugin. |
| Custom provider | Follow Create an adapter. |
| Reusable behavior | Follow Create your first plugin. |
| Community adapter | Follow Publish a community adapter. |
| Community behavior package | Follow Publish a community plugin. |
Order
Plugin order is deterministic.
- Direct
adaptersregister first. - Plugins run in array order.
- Plugin adapters register in plugin order.
- Duplicate plugin IDs throw.
- Duplicate adapter names throw.
beforeSendmiddleware runs before message validation.- Plugin hooks run before user
hooks.
Use a custom id when mounting more than one instance of the same plugin type. If the plugin extends the client, also give each instance a distinct extension key, such as capturePlugin({ id: "capture:audit", clientKey: "auditCapture" }).
Next
Defaults plugin
Apply shared message and send-option defaults.
Observability plugin
Emit redacted log, metric, and trace events.
Capture plugin
Record email behavior in tests.
Community plugins and adapters
Browse third-party package listings and verification labels.
Writing plugins
Build a reusable policy plugin step by step.
Create an adapter
Write a custom provider adapter and wrap it as a plugin.
