@ooneex/mailer component sends transactional emails. The built-in mailer renders a React node to HTML server-side so your email bodies are plain components. Every sender implements the same IMailer interface — a single send method — so callers stay identical no matter how mail is delivered. A MailerLayout component gives you a styled header/body/footer shell to build templates on.
Why this component
- One interface, container-managed. Every mailer implements
IMailer(send) and is registered with a decorator, so you resolve and inject it like any other service. - React templates. Email bodies are React nodes rendered to HTML with
renderToString— compose them like UI, not string concatenation. - Layout system.
MailerLayoutships withHeader,Body, andFootersubcomponents and sensible email-safe defaults. - Environment configuration. Credentials and the default sender are read from environment variables; per-send overrides are supported.
How it works
You resolve a mailer from the container and callsend. The mailer renders the content React node to HTML, resolves the sender (from the call or the environment), and delivers the message.
| Member | Purpose |
|---|---|
send(config) | Render content and send the email. Resolves to void. |
config object passed to send:
| Field | Type | Purpose |
|---|---|---|
to | string[] | Recipient email addresses. |
subject | string | Email subject line. |
content | React.ReactNode | Body rendered to HTML server-side. |
from | { name: string; address: string } | Optional sender override; falls back to the environment defaults. |
config.from wins, otherwise MAILER_SENDER_NAME and MAILER_SENDER_ADDRESS are used. If neither yields a name and address, send throws.
Environment variables
| Variable | Required | Purpose |
|---|---|---|
MAILER_SENDER_NAME | No | Default sender name. Required at send time unless from.name is provided. |
MAILER_SENDER_ADDRESS | No | Default sender address. Required at send time unless from.address is provided. |
Decorator and usage
@decorator.mailer()
Registers a mailer class with the container. It accepts an optional scope (defaults to singleton). The built-in mailer is already decorated under the mailer token; use the decorator on your own mailers so they can be resolved and injected.
Resolve the mailer from the container and send an email — the body is just a React node:
IMailer. Register it with the decorator and inject the underlying mailer under the mailer token:
Exceptions
The component throwsMailerException when it is misconfigured or a send cannot complete. It carries a machine-readable key, a human-readable message, and a data object.
| Key | When |
|---|---|
EMAIL_SEND_FAILED | send is called with no resolvable sender name (no from.name and no MAILER_SENDER_NAME). |
EMAIL_OPERATION_FAILED | send is called with no resolvable sender address (no from.address and no MAILER_SENDER_ADDRESS). |
Best practices
- Set the default sender in the environment. Configure
MAILER_SENDER_NAMEandMAILER_SENDER_ADDRESSonce so every send has a fallback, and overridefromonly when a message needs a different address. - Build bodies on
MailerLayout. Compose withHeader,Body, andFooterfor email-safe, consistent markup instead of raw HTML strings. - Keep templates as props-driven functions. Pass data in, return a React node — easy to render in tests without sending anything.
- Wrap a template per email type. A dedicated mailer (e.g.
WelcomeMailer) that delegates to the injectedIMailerkeeps subjects, templates, and props in one place. - Catch
MailerExceptionat send sites. Inspecterror.keyto distinguish configuration problems from delivery problems, and never leak credentials. - Resolve through the container. Inject mailers rather than constructing them so the credentials and defaults are wired consistently.
CLI command
Scaffold a mailer, its JSX template, and their tests with the generator. It writes the class undermodules/<module>/src/mailers/<Name>Mailer.ts, the template alongside it, and installs @ooneex/mailer if it is missing.
| Option | Description | Default |
|---|---|---|
--name | Mailer class name. The Mailer suffix is appended automatically. | Prompted if omitted |
--module | Target module the files are generated into. | shared |
--override | Overwrite an existing mailer without prompting. | false |
IMailer, ready for you to refine the subject and props:
MailerLayout:
Use with Claude and Codex
The generator ships a matchingmailer:create skill. It runs the scaffold and then guides your AI agent through completing the mailer — refining the send config, filling in the template props, and wiring up its tests. Initialize the skills once for your agent:
- Claude
- Codex
Prompt
mailer:create --name=Welcome, then builds the welcome template and completes the send method.