90 lines
6.8 KiB
Markdown
90 lines
6.8 KiB
Markdown
# @suaveplan/emailer - Universal email service with plugin transports (Dummy / SMTP via injectable SmtpClientLike / Gmail REST via FetchLike), nine lifecycle hooks, retry, queue dispatch, Zod-validated boundaries, OpenTelemetry-instrumented hot paths, injectable Clock/Rng/Logger/FetchLike/TimersLike, stable defineCodes('EMAILER', [...]) error registry.
|
|
|
|
Universal email service with pluggable transports. Ships
|
|
`EmailService`, three transports (Dummy / SMTP via injectable
|
|
`SmtpClientLike` / Gmail REST via injectable `FetchLike`), nine lifecycle
|
|
hooks, deterministic retry, structural queue dispatch, Zod-validated option
|
|
boundaries, OpenTelemetry-instrumented hot paths, and a stable
|
|
`defineCodes("EMAILER", [...])` error registry.
|
|
|
|
<!-- begin:auto-docs -->
|
|
## Documentation tree
|
|
|
|
- [email-service](./src/core/email-service/email-service.md) — `EmailService<TTransport>` is the public entry point for `@suaveplan/emailer`. It orchestrates message validation, life…
|
|
- [base-email-transport](./src/core/email-service/base-email-transport.md) — `BaseEmailTransport` is the abstract helper that every concrete transport (`DummyTransport`, `SmtpTransport`, `GmailRes…
|
|
- [email-service](./src/core/email-service/email-service.md) — `EmailService<TTransport>` is the public entry point for `@suaveplan/emailer`. It orchestrates message validation, life…
|
|
- [retry](./src/core/retry/retry.md) — Deterministic retry helper used by `EmailService.send`. The helper takes a `RetryPolicy`, an injectable `TimersLike`, a…
|
|
- [retry](./src/core/retry/retry.md) — Deterministic retry helper used by `EmailService.send`. The helper takes a `RetryPolicy`, an injectable `TimersLike`, a…
|
|
- [validate](./src/core/validate/validate.md) — Shared address-formatting and message-validation helpers used by every concrete transport and by `EmailService` itself.…
|
|
- [validate](./src/core/validate/validate.md) — Shared address-formatting and message-validation helpers used by every concrete transport and by `EmailService` itself.…
|
|
- [error-codes](./src/error-codes/error-codes.md) — `@suaveplan/emailer` ships a single stable error-code registry that every failure path in the package routes through. T…
|
|
- [error-codes](./src/error-codes/error-codes.md) — `@suaveplan/emailer` ships a single stable error-code registry that every failure path in the package routes through. T…
|
|
- [fake-fetch](./src/fakes/fake-fetch.md) — Deterministic test double for `FetchLike`, used by `GmailRestTransport` tests. Queues scripted responses and captures e…
|
|
- [fake-smtp-client](./src/fakes/fake-smtp-client.md) — Deterministic test double for `SmtpClientLike`. Tests queue scripted responses, invoke the wrapped `SmtpTransport`, and…
|
|
- [otel](./src/otel/metrics.md) — Single source of truth for every OpenTelemetry instrument emitted by `@suaveplan/emailer`. Every production path that t…
|
|
- [metrics](./src/otel/metrics.md) — Single source of truth for every OpenTelemetry instrument emitted by `@suaveplan/emailer`. Every production path that t…
|
|
- [schemas](./src/schemas/schemas.md) — Centralised Zod schemas for every public option bundle and wire payload in `@suaveplan/emailer`. The schemas exist to e…
|
|
- [schemas](./src/schemas/schemas.md) — Centralised Zod schemas for every public option bundle and wire payload in `@suaveplan/emailer`. The schemas exist to e…
|
|
- [dummy](./src/transports/dummy/dummy-transport.md) — `DummyTransport` is a deterministic in-memory transport designed for tests, fixtures, and local development. It records…
|
|
- [dummy-transport](./src/transports/dummy/dummy-transport.md) — `DummyTransport` is a deterministic in-memory transport designed for tests, fixtures, and local development. It records…
|
|
- [gmail-rest](./src/transports/gmail-rest/gmail-rest-transport.md) — `GmailRestTransport` sends mail through Gmail's REST API directly, over an injectable `FetchLike`. The transport builds…
|
|
- [gmail-rest-transport](./src/transports/gmail-rest/gmail-rest-transport.md) — `GmailRestTransport` sends mail through Gmail's REST API directly, over an injectable `FetchLike`. The transport builds…
|
|
- [smtp](./src/transports/smtp/smtp-transport.md) — `SmtpTransport` is a structural SMTP transport: it accepts a caller-supplied `SmtpClientLike` adapter (the contract is…
|
|
- [smtp-transport](./src/transports/smtp/smtp-transport.md) — `SmtpTransport` is a structural SMTP transport: it accepts a caller-supplied `SmtpClientLike` adapter (the contract is…
|
|
<!-- end:auto-docs -->
|
|
|
|
## Why universal
|
|
|
|
The upstream `@suaveplan/emailer` was server-only because it imported
|
|
`nodemailer` and `googleapis` directly. The rewrite drops both hard
|
|
dependencies in favour of injectable contracts:
|
|
|
|
- **SMTP**: callers supply a thin `SmtpClientLike` adapter so nodemailer
|
|
(or any other library) lives in the consumer's app shell, not in this
|
|
package.
|
|
- **Gmail**: send is implemented directly against the Gmail REST API via
|
|
`FetchLike`, so token acquisition is the caller's concern and the
|
|
transport runs unchanged in Bun, Node, and the browser.
|
|
|
|
## Modules
|
|
|
|
- [`src/core/email-service/email-service.md`](src/core/email-service/email-service.md) — `EmailService<TTransport>` orchestrator
|
|
- [`src/core/email-service/base-email-transport.md`](src/core/email-service/base-email-transport.md) — abstract helper
|
|
- [`src/core/retry/retry.md`](src/core/retry/retry.md) — deterministic retry helper
|
|
- [`src/core/validate/validate.md`](src/core/validate/validate.md) — address-formatting helpers
|
|
- [`src/transports/dummy/dummy-transport.md`](src/transports/dummy/dummy-transport.md) — in-memory test transport
|
|
- [`src/transports/smtp/smtp-transport.md`](src/transports/smtp/smtp-transport.md) — SMTP via adapter
|
|
- [`src/transports/smtp/smtp-client-like.types.md`](src/transports/smtp/smtp-client-like.types.md) — adapter contract
|
|
- [`src/transports/gmail-rest/gmail-rest-transport.md`](src/transports/gmail-rest/gmail-rest-transport.md) — Gmail REST transport
|
|
- [`src/error-codes.md`](src/error-codes.md) — error registry
|
|
- [`src/schemas/schemas.md`](src/schemas/schemas.md) — Zod boundary schemas
|
|
- [`src/types/emailer.types.md`](src/types/emailer.types.md) — public types
|
|
- [`src/otel/metrics.md`](src/otel/metrics.md) — OTel instruments
|
|
- [`src/fakes/fake-smtp-client.md`](src/fakes/fake-smtp-client.md) — deterministic SMTP fake
|
|
- [`src/fakes/fake-fetch.md`](src/fakes/fake-fetch.md) — deterministic fetch fake
|
|
|
|
## Quick start
|
|
|
|
```ts
|
|
import { EmailService } from "@suaveplan/emailer";
|
|
import { createDummyTransport } from "@suaveplan/emailer/transports/dummy";
|
|
|
|
const transport = createDummyTransport();
|
|
const service = new EmailService({
|
|
transport,
|
|
transportOptions: {},
|
|
defaultFrom: "no-reply@example.com",
|
|
});
|
|
await service.initialize();
|
|
const result = await service.send({
|
|
to: "user@example.com",
|
|
subject: "hello",
|
|
html: "<p>hi</p>",
|
|
});
|
|
```
|
|
|
|
## License
|
|
|
|
MIT
|
|
|