Skip to content

@btravstack/mailer


@btravstack/mailer / index

index

Classes

Mailer

Defined in: packages/mailer/src/mailer.ts:61

The port an application depends on. send answers when the transport has ACCEPTED the message, which is not the same as delivered — a caller needing delivery semantics asks its provider's webhooks.

Retries are not here. A failed send is a modeled MailNotSent, and what to do about it belongs to the caller's transport, whose own retry budget owns redelivery rather than a policy this package invented.

Extends

Constructors

Constructor
ts
new Mailer(): Mailer;

Defined in: packages/di/dist/index.d.mts:16

Returns

Mailer

Inherited from
ts
Port("Mailer")<MailerService>.constructor

Properties

PropertyModifierTypeInherited fromDefined in
[ID]readonly"Mailer"Port("Mailer").[ID]packages/di/dist/index.d.mts:12
[SERVICE]readonlyMailerServicePort("Mailer").[SERVICE]packages/di/dist/index.d.mts:13
portIdreadonly"Mailer"Port("Mailer").portIdpackages/di/dist/index.d.mts:17

MailerBackend

Defined in: packages/mailer/src/mailer.ts:70

The port every adapter provides, and the one an application never depends on.

di allows one provider per port per graph, so the instrumented composition cannot be a layer over the plain one: an adapter targets this, and mailer() turns it into Mailer. A spec overrides THIS port.

Extends

Constructors

Constructor
ts
new MailerBackend(): MailerBackend;

Defined in: packages/di/dist/index.d.mts:16

Returns

MailerBackend

Inherited from
ts
Port("MailerBackend")<MailerService>.constructor

Properties

PropertyModifierTypeInherited fromDefined in
[ID]readonly"MailerBackend"Port("MailerBackend").[ID]packages/di/dist/index.d.mts:12
[SERVICE]readonlyMailerServicePort("MailerBackend").[SERVICE]packages/di/dist/index.d.mts:13
portIdreadonly"MailerBackend"Port("MailerBackend").portIdpackages/di/dist/index.d.mts:17

MailNotSent

Defined in: packages/mailer/src/mailer.ts:42

The send did not happen. It carries to and subject and never the body: a failure is logged, and a body is the one part of a message that is reliably somebody's personal data.

Extends

  • TaggedErrorInstance<"MailNotSent", { reason: string; subject: string; to: readonly string[]; }>

Constructors

Constructor
ts
new MailNotSent(args): MailNotSent;

Defined in: node_modules/.pnpm/unthrown@5.8.0/node_modules/unthrown/dist/index.d.mts:2034

Parameters
ParameterType
argsobject & object
Returns

MailNotSent

Inherited from
ts
TaggedError("MailNotSent")<{
  readonly to: readonly string[];
  readonly subject: string;
  readonly reason: string;
}>.constructor

Properties

PropertyModifierTypeInherited fromDefined in
_tagreadonly"MailNotSent"TaggedError("MailNotSent")._tagnode_modules/.pnpm/unthrown@5.8.0/node_modules/unthrown/dist/index.d.mts:2011
cause?publicunknownTaggedError("MailNotSent").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstringTaggedError("MailNotSent").messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstringTaggedError("MailNotSent").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
reasonreadonlystringTaggedError("MailNotSent").reasonpackages/mailer/src/mailer.ts:45
stack?publicstringTaggedError("MailNotSent").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076
subjectreadonlystringTaggedError("MailNotSent").subjectpackages/mailer/src/mailer.ts:44
toreadonlyreadonly string[]TaggedError("MailNotSent").topackages/mailer/src/mailer.ts:43

Type Aliases

Mail

ts
type Mail = object;

Defined in: packages/mailer/src/mailer.ts:23

One message: the envelope, a subject and a body. No templating — that is an application's decision with a library of its own — but everything an envelope carries, because an invoice mail with an attachment is roughly the second one a service sends, and a port that cannot carry it gets bypassed rather than extended, losing the recorder and the instrumentation with it.

Properties

PropertyModifierTypeDescriptionDefined in
attachments?readonlyreadonly MailAttachment[]-packages/mailer/src/mailer.ts:32
bcc?readonlyreadonly string[]-packages/mailer/src/mailer.ts:27
cc?readonlyreadonly string[]-packages/mailer/src/mailer.ts:26
fromreadonlystring-packages/mailer/src/mailer.ts:24
headers?readonlyReadonly<Record<string, string>>Extra headers, verbatim. What an adapter already sets it sets — this does not replace an envelope field.packages/mailer/src/mailer.ts:34
html?readonlystring-packages/mailer/src/mailer.ts:31
subjectreadonlystring-packages/mailer/src/mailer.ts:28
textreadonlystringThe plain-text body. Required: a mail with only HTML is a mail some clients cannot read.packages/mailer/src/mailer.ts:30
toreadonlyreadonly string[]-packages/mailer/src/mailer.ts:25

MailAttachment

ts
type MailAttachment = object;

Defined in: packages/mailer/src/mailer.ts:9

One file on a message. content is bytes or a string and never a path or a stream: a port that took either would be asking every adapter to own a filesystem and a lifetime, where a caller that has a file can read it.

Properties

PropertyModifierTypeDescriptionDefined in
contentreadonlyUint8Array | string-packages/mailer/src/mailer.ts:11
contentType?readonlystringDefaults to whatever the adapter infers from filename.packages/mailer/src/mailer.ts:13
filenamereadonlystring-packages/mailer/src/mailer.ts:10

MailerOptions

ts
type MailerOptions<E, N> = object;

Defined in: packages/mailer/src/module.ts:7

Type Parameters

Type Parameter
E
N

Properties

PropertyModifierTypeDescriptionDefined in
adapterreadonlyModule<MailerBackend, E, N>The adapter module: recordingMailer(recorder) from this entry point, smtpMailer() from @btravstack/mailer/smtp, or one an application wrote itself over MailerBackend.packages/mailer/src/module.ts:13

MailerService

ts
type MailerService = object;

Defined in: packages/mailer/src/mailer.ts:48

Properties

PropertyModifierTypeDefined in
sendreadonly(mail) => AsyncResult<void, MailNotSent>packages/mailer/src/mailer.ts:49

MailRecorder

ts
type MailRecorder = object;

Defined in: packages/mailer/src/recording.ts:12

What a spec asserts against: the mails that would have been sent. record is the adapter's half and sent/only the test's, on one object, so nothing reaches into an array somebody else owns. only() throws unless there is exactly one — a test that read it too early is a broken test.

Properties

PropertyModifierTypeDefined in
onlyreadonly() => Mailpackages/mailer/src/recording.ts:15
recordreadonly(mail) => voidpackages/mailer/src/recording.ts:13
sentreadonly() => readonly Mail[]packages/mailer/src/recording.ts:14

Functions

mailer()

ts
function mailer<E, N>(__namedParameters): Module<Mailer, E, N>;

Defined in: packages/mailer/src/module.ts:33

The mailer starter: an adapter, and Mailer provided from it.

ts
mailer({ adapter: smtpMailer() });

Two ports, because di allows one provider per port per graph: the port an application depends on must not be the one an adapter provides, which is what lets this function be the seam.

There is no instrumented flag. Every send is handed to whatever contributed to Observers; a graph that composed no observability has only this module's own no-op member, so it costs one call per send and nothing else. What rides the signals is the ENVELOPE — a recipient COUNT rather than the addresses, since a recipient list is personal data.

Type Parameters

Type Parameter
E
N

Parameters

ParameterType
__namedParametersMailerOptions<E, N>

Returns

Module<Mailer, E, N>


mailRecorder()

ts
function mailRecorder(): MailRecorder;

Defined in: packages/mailer/src/recording.ts:18

Returns

MailRecorder


recordingMailer()

ts
function recordingMailer(recorder): Module<MailerBackend, never, never>;

Defined in: packages/mailer/src/recording.ts:57

The adapter as a module, which is the shape mailer({ adapter }) takes.

Parameters

ParameterType
recorderMailRecorder

Returns

Module<MailerBackend, never, never>


recordingMailerBackend()

ts
function recordingMailerBackend(recorder): MailerService;

Defined in: packages/mailer/src/recording.ts:45

The testable-by-default adapter: it sends nothing and keeps everything, since the question in a suite is almost never "did SMTP work" but "would this code have sent the right message".

It cannot fail. A spec that needs the failure arm composes an adapter of its own; a configurable failure mode would put a policy in a fixture whose whole value is having none.

Parameters

ParameterType
recorderMailRecorder

Returns

MailerService


recordingMailerProvider()

ts
function recordingMailerProvider(recorder): Provider<MailerBackend, never, never> & object;

Defined in: packages/mailer/src/recording.ts:53

The adapter as a provider, which is the shape @btravstack/testing's overridden takes.

Parameters

ParameterType
recorderMailRecorder

Returns

Provider<MailerBackend, never, never> & object

Released under the MIT License.