@samveys/mail

Mailables, SMTP over node:net/tls, log and fake transports

Version
1.0.3Nov 5, 2026
Install
pnpm add @samveys/mail

This list was read from version 1.0.2; run pnpm sync to refresh it.

Import
import { composeMail, createMailer, defineMail, dotStuff, encodeHeaderWord, encodeQuotedPrintable, … } from '@samveys/mail'

Function (11)

composeMail Function

Builds the RFC 5322 / MIME message and the SMTP envelope. Throws SVS_E103 on an invalid message.

function composeMail(message: MailMessage, options?: ComposeOptions): ComposedMail;

Exported from packages/mail/src/compose.ts

createMailer Function

A mailer over one transport. Every failure surfaces as SVS_E103.

function createMailer(options: MailerOptions): Mailer;

Exported from packages/mail/src/mailer.ts

defineMail Function

Defines a mailable: a function from data to a message.

function defineMail<D = void>(build: (data: D) => MailMessage): Mailable<D>;

Exported from packages/mail/src/mailer.ts

dotStuff Function

Escapes lines starting with "." (RFC 5321 §4.5.2) and ends the data with CRLF.CRLF.

function dotStuff(raw: string): string;

Exported from packages/mail/src/smtp.ts

encodeHeaderWord Function

RFC 2047 encoded-word(s) for a header value; ASCII text is returned untouched.

function encodeHeaderWord(text: string): string;

Exported from packages/mail/src/compose.ts

encodeQuotedPrintable Function

Quoted-printable (RFC 2045) of UTF-8 text, CRLF line breaks, lines at most 76 chars.

function encodeQuotedPrintable(text: string): string;

Exported from packages/mail/src/compose.ts

fake Function

Records messages in memory. No network. `assertSent(predicate)` throws when none matches.

function fake(): FakeMailTransport;

Exported from packages/mail/src/transports.ts

formatDate Function

RFC 5322 date-time in UTC, e.g. `Wed, 04 Nov 2026 07:34:16 +0000`.

function formatDate(instant: Temporal.Instant): string;

Exported from packages/mail/src/compose.ts

log Function

Writes each message to `write` (default `console.log`) instead of sending it. For local development.

function log(write?: (text: string) => void): MailTransport;

Exported from packages/mail/src/transports.ts

mail Function

The `@samveys/mail` plugin: binds `'mail'` (the {@link Mailer}).

function mail(config: MailConfig): import("@samveys/core").Plugin<MailConfig>;

Exported from packages/mail/src/plugin.ts

smtp Function

SMTP over `node:net` / `node:tls`: EHLO, STARTTLS, AUTH PLAIN/LOGIN, MAIL FROM, RCPT TO, DATA. One connection per message.

function smtp(options: SmtpOptions): MailTransport;

Exported from packages/mail/src/smtp.ts

Interface (11)

ComposedMail Interface

A message ready for a transport: wire format plus envelope.

interface ComposedMail {
    readonly messageId: string;
    /** Envelope sender (`MAIL FROM`). */
    readonly from: string;
    /** Envelope recipients (`RCPT TO`): to, cc and bcc. */
    readonly recipients: readonly string[];
    /** RFC 5322 message with CRLF line endings. */
    readonly raw: string;
    /** The message it was composed from. */
    readonly message: MailMessage;
}

Exported from packages/mail/src/contracts.ts

ComposeOptions Interface

No documentation comment.

interface ComposeOptions {
    readonly from?: MailAddress;
    readonly encoding?: MailEncoding;
    /** Domain of the generated Message-ID. Default: the sender's domain. */
    readonly messageIdDomain?: string;
    readonly now?: () => Temporal.Instant;

Exported from packages/mail/src/contracts.ts

FakeMailTransport Interface

No documentation comment.

interface FakeMailTransport extends MailTransport {
    readonly sent: readonly ComposedMail[];
    assertSent(predicate?: (message: MailMessage) => boolean): void;

Exported from packages/mail/src/contracts.ts

Mailable Interface

A reusable message built from data.

interface Mailable<D = void> {
    readonly kind: 'mailable';
    build(data: D): MailMessage;
}

Exported from packages/mail/src/contracts.ts

MailConfig Interface

Configuration of `mail()`.

interface MailConfig extends ComposeOptions {
    /** `smtp(...)`, `log()` or `fake()`. */
    readonly transport: MailTransport;
}

Exported from packages/mail/src/plugin.ts

Mailer Interface

No documentation comment.

interface Mailer {
    send(message: MailMessage): Promise<SentMail>;
    send<D>(mailable: Mailable<D>, data: D): Promise<SentMail>;
}

Exported from packages/mail/src/contracts.ts

MailerOptions Interface

No documentation comment.

interface MailerOptions extends ComposeOptions {
    readonly transport: MailTransport;
}

Exported from packages/mail/src/mailer.ts

MailMessage Interface

A message to send. At least one of `text` and `html` is required.

interface MailMessage {
    /** Falls back to the mailer's default `from`. */
    readonly from?: MailAddress;
    readonly to: MailAddress | readonly MailAddress[];
    readonly cc?: MailAddress | readonly MailAddress[];
    /** Receives the message but is never written to the headers. */
    readonly bcc?: MailAddress | readonly MailAddress[];
    readonly replyTo?: MailAddress;
    readonly subject: string;
    readonly text?: string;
  …
Show the whole declaration (14 lines)
interface MailMessage {
    /** Falls back to the mailer's default `from`. */
    readonly from?: MailAddress;
    readonly to: MailAddress | readonly MailAddress[];
    readonly cc?: MailAddress | readonly MailAddress[];
    /** Receives the message but is never written to the headers. */
    readonly bcc?: MailAddress | readonly MailAddress[];
    readonly replyTo?: MailAddress;
    readonly subject: string;
    readonly text?: string;
    readonly html?: string;
    /** Extra headers. Names and values must not contain line breaks. */
    readonly headers?: Readonly<Record<string, string>>;
}

Exported from packages/mail/src/contracts.ts

MailTransport Interface

No documentation comment.

interface MailTransport {
    readonly name: string;
    send(mail: ComposedMail): Promise<SentMail>;
    close?(): Promise<void>;
}

Exported from packages/mail/src/contracts.ts

SentMail Interface

No documentation comment.

interface SentMail {
    readonly messageId: string;
    readonly accepted: readonly string[];
    /** Server reply to the end of DATA, or a transport note. */
    readonly response: string;
}

Exported from packages/mail/src/contracts.ts

SmtpOptions Interface

No documentation comment.

interface SmtpOptions {
    readonly host: string;
    readonly port: number;
    /** Implicit TLS (port 465). With `false`, STARTTLS is used when the server offers it. */
    readonly secure?: boolean;
    /** Fail instead of sending in clear text when STARTTLS is unavailable. */
    readonly requireTLS?: boolean;
    readonly auth?: {
        readonly user: string;
        readonly pass: string;
  …
Show the whole declaration (24 lines)
interface SmtpOptions {
    readonly host: string;
    readonly port: number;
    /** Implicit TLS (port 465). With `false`, STARTTLS is used when the server offers it. */
    readonly secure?: boolean;
    /** Fail instead of sending in clear text when STARTTLS is unavailable. */
    readonly requireTLS?: boolean;
    readonly auth?: {
        readonly user: string;
        readonly pass: string;
    };
    /** Permit AUTH over an unencrypted connection. Default false: credentials are never sent in clear text. */
    readonly allowInsecureAuth?: boolean;
    /** Name sent in EHLO. Default: the machine's hostname. */
    readonly clientName?: string;
    /** Connection and per-command timeout in ms. Default 30 000. */
    readonly timeoutMs?: number;
    /** Passed to `tls.connect` (e.g. `ca`, `rejectUnauthorized`). */
    readonly tls?: {
        readonly ca?: string | Buffer;
        readonly rejectUnauthorized?: boolean;
        readonly servername?: string;
    };
}

Exported from packages/mail/src/contracts.ts

Type (2)

MailAddress Type

`"ada@example.com"` or `{ name: 'Ada', address: 'ada@example.com' }`.

type MailAddress = string | {
    readonly name?: string;
    readonly address: string;
};

Exported from packages/mail/src/contracts.ts

MailEncoding Type

No documentation comment.

type MailEncoding = 'base64' | 'quoted-printable';

Exported from packages/mail/src/contracts.ts