@marianmeres/send-email
v1.0.0
Published
[](https://www.npmjs.com/package/@marianmeres/send-email) [](https://jsr.io/@marianmeres/send-email) [.
- Provider-agnostic transport interface (the adapter seam).
- Nodemailer SMTP transport (the one real adapter in v1) — with attachments
and a real connect+auth
verify(). - Mock transport for tests and dry runs.
- One-shot
send()convenience. - First-class CLI with
sendandverify,.envsupport, and stdin bodies.
Installation
# Deno (JSR)
deno add jsr:@marianmeres/send-email
# npm
npx jsr add @marianmeres/send-emailOr run the CLI with no install at all:
deno run -A jsr:@marianmeres/send-email --helpThe npm package ships the library (
send, the transports). The bundled CLI is a Deno/JSR feature — run it viadeno run -A jsr:…as above.
Library usage
The library never reads the environment — all configuration is explicit.
import { send } from "@marianmeres/send-email";
// One-shot: pass SMTP options and a transport is built for this single send.
const { externalId } = await send(
{
to: "[email protected]",
from: "[email protected]",
subject: "Hello",
text: "Hi there",
html: "<p>Hi there</p>",
},
{ smtp: { host: "smtp.example.com", port: 587, auth: { user: "u", pass: "p" } } },
);Reuse one transport (and its connection) across many sends:
import { createNodemailerTransport, send } from "@marianmeres/send-email";
const transport = createNodemailerTransport({
host: "smtp.example.com",
port: 587,
auth: { user: "u", pass: "p" },
defaultReplyTo: "[email protected]",
});
await transport.verify(); // optional preflight: connect + auth, no message sent
await send(msg1, { transport });
await send(msg2, { transport });Tests and dry runs use the mock transport:
import { createMockTransport, send } from "@marianmeres/send-email";
const transport = createMockTransport();
await send(msg, { transport });
transport.getLastEmail()?.subject;Errors are thrown, never returned. A successful result only carries
{ externalId }.
CLI usage
The bare module is the CLI entrypoint. Credentials come only from the environment — never from flags (flags leak into the process table and shell history).
# Send
deno run -A jsr:@marianmeres/send-email send \
--to [email protected] --subject "Hi" --text "Hello"
# Verify SMTP config without sending (connect + auth handshake only)
deno run -A jsr:@marianmeres/send-email verify
# Pipe a body in
report | deno run -A jsr:@marianmeres/send-email send --to [email protected] -s Report
# Machine-readable, and a dry run that sends nothing
deno run -A jsr:@marianmeres/send-email send --to [email protected] --text hi --dry-run --jsonInstall it as a command:
deno install -A -n send-email jsr:@marianmeres/send-emailCommands
| Command | Purpose |
| --------- | ----------------------------------------------------------------------------------------------------- |
| send | Send one message (SMTP transport resolved from env). |
| verify | Connect + auth handshake only; ✅ summary on success, Error: on stderr on failure. No message sent. |
| help | Usage. Also --help / -h. |
| version | Print the package version. Also --version. |
Exit codes: 0 success, 1 runtime failure, 2 usage error.
See API.md for the full flag reference.
Environment
The CLI builds the SMTP transport from these variables (loaded from ./.env,
or --env-file <path>). Process env takes precedence over the .env file.
| Variable | Required | Notes |
| ------------------------------ | -------- | ---------------------------------------------- |
| SMTP_HOST | yes | SMTP server hostname. |
| SMTP_PORT | no | Default 587. |
| SMTP_SECURE | no | Implicit TLS; defaults to port === 465. |
| SMTP_USER / SMTP_PASS | no | SMTP AUTH credentials. Never via CLI flags. |
| SMTP_FROM | no | Default sender when --from is omitted. |
| SMTP_REPLY_TO | no | Default Reply-To when --reply-to is omitted. |
| SMTP_SERVERNAME | no | TLS SNI / cert hostname override. |
| SMTP_TLS_REJECT_UNAUTHORIZED | no | Set false only as an insecure last resort. |
| SMTP_CONNECTION_TIMEOUT_MS | no | Connection timeout (ms). |
| SMTP_SOCKET_TIMEOUT_MS | no | Socket timeout (ms). |
See .env.example.
Consumers
This package is the bottom layer. Higher-level email systems (service,
queue, DB-backed collections, templating) are intended to consume it: such a
consumer's SMTP transport shrinks to a thin adapter that maps its own (often
DB-shaped, snake_case) payload onto this package's send(), dropping its direct
npm:nodemailer dependency in favor of this one. Message types stay parallel on
purpose — this package is clean camelCase; a consumer's payload can be whatever
its storage needs.
API
See API.md for the complete library and CLI reference.
