Skip to content

@btravstack/mailer


@btravstack/mailer / index

index ​

Classes ​

Mailer ​

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

The port an application depends on. send answers when the transport has ACCEPTED the message for every recipient, 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:15

Returns ​

Mailer

Inherited from ​

Port("Mailer")<MailerService>.constructor

Properties ​

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

MailerBackend ​

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

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:15

Returns ​

MailerBackend

Inherited from ​

Port("MailerBackend")<MailerService>.constructor

Properties ​

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

MailNotSent ​

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

The message was not accepted for every recipient. 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. On partial SMTP acceptance, to names only rejected recipients; the others may already have been accepted, so retry only these recipients.

Extends ​

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

Constructors ​

Constructor ​
ts
new MailNotSent(args): MailNotSent;

Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386

Parameters ​
ParameterType
argsobject & object
Returns ​

MailNotSent

Inherited from ​

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.12.1/node_modules/unthrown/dist/index.d.mts:2363
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:47
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:46
toreadonlyreadonly string[]TaggedError("MailNotSent").topackages/mailer/src/mailer.ts:45

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:50

Properties ​

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

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>


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.