@bumail/queue 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +517 -32
- package/dist/index.js.map +23 -14
- package/dist/queue/attempt.d.ts.map +1 -1
- package/dist/queue/deliver.d.ts +2 -0
- package/dist/queue/deliver.d.ts.map +1 -1
- package/dist/queue/events.d.ts +10 -0
- package/dist/queue/events.d.ts.map +1 -1
- package/dist/queue/fallback-session.d.ts.map +1 -1
- package/dist/queue/fallback.d.ts.map +1 -1
- package/dist/queue/options.d.ts +25 -1
- package/dist/queue/options.d.ts.map +1 -1
- package/dist/queue/outcome.d.ts.map +1 -1
- package/dist/queue/session.d.ts +9 -1
- package/dist/queue/session.d.ts.map +1 -1
- package/dist/queue/settings/index.d.ts +8 -2
- package/dist/queue/settings/index.d.ts.map +1 -1
- package/dist/queue/settings/sender.d.ts +16 -0
- package/dist/queue/settings/sender.d.ts.map +1 -0
- package/dist/queue/settle.d.ts.map +1 -1
- package/dist/queue/worker.d.ts.map +1 -1
- package/dist/sts/attempt.d.ts +15 -0
- package/dist/sts/attempt.d.ts.map +1 -0
- package/dist/sts/bound.d.ts +15 -0
- package/dist/sts/bound.d.ts.map +1 -0
- package/dist/sts/cache.d.ts +27 -0
- package/dist/sts/cache.d.ts.map +1 -0
- package/dist/sts/discover.d.ts +52 -0
- package/dist/sts/discover.d.ts.map +1 -0
- package/dist/sts/options.d.ts +77 -0
- package/dist/sts/options.d.ts.map +1 -0
- package/dist/sts/refusal.d.ts +10 -0
- package/dist/sts/refusal.d.ts.map +1 -0
- package/dist/sts/run.d.ts +55 -0
- package/dist/sts/run.d.ts.map +1 -0
- package/dist/sts/settings.d.ts +5 -0
- package/dist/sts/settings.d.ts.map +1 -0
- package/dist/sts/tally.d.ts +20 -0
- package/dist/sts/tally.d.ts.map +1 -0
- package/docs/guide.md +98 -2
- package/docs/roadmap.md +15 -7
- package/docs/troubleshooting.md +75 -0
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -12,11 +12,12 @@ share one queue. No runtime dependency: only peers.
|
|
|
12
12
|
|
|
13
13
|
```sh
|
|
14
14
|
bun add @bumail/queue @bumail/smtp @bumail/mime
|
|
15
|
+
bun add @bumail/mta-sts # a required peer (its types are in the API), used when you set mtaSts
|
|
15
16
|
bun add @bumail/dns # for direct delivery by MX: the resolver
|
|
16
17
|
```
|
|
17
18
|
|
|
18
|
-
`@bumail/smtp` (its client)
|
|
19
|
-
peers. `@bumail/dns` is optional: any resolver of its shape will do, and a
|
|
19
|
+
`@bumail/smtp` (its client), `@bumail/mime` (for the DSNs) and
|
|
20
|
+
`@bumail/mta-sts` (for `mtaSts`) are required peers. `@bumail/dns` is optional: any resolver of its shape will do, and a
|
|
20
21
|
queue that only uses a smarthost needs none.
|
|
21
22
|
|
|
22
23
|
## Subpaths
|
|
@@ -153,6 +154,48 @@ With `fallback` (a smarthost), a recipient whose session by MX failed by a
|
|
|
153
154
|
connection failure, a timeout or a reputation refusal goes through that
|
|
154
155
|
smarthost at once (not after the final dot of `DATA`, where the MX may have taken the message: every recipient the MX did not refuse at `RCPT` is marked `mayHaveReachedMx` and never falls back on its own; a refused one may). If the smarthost's own session ends after the final dot, the recipient is marked `mayHaveReachedFallback` and later attempts go to the smarthost again, not to the MX; see [Falling back to a smarthost](docs/guide.md#falling-back-to-a-smarthost).
|
|
155
156
|
|
|
157
|
+
## MTA-STS
|
|
158
|
+
|
|
159
|
+
Opt in with `mtaSts` (off unless given; the smarthost routes and the `fallback` never use it). For each recipient domain on the MX route the queue reads `_mta-sts.<domain>` and fetches the policy (RFC 8461) through `@bumail/mta-sts`, keeping it in a `PolicyCache` until its `max_age` ends. With mode `enforce` it sends with `tls: 'required'` to the MX hosts the policy names only; with `testing` it sends as usual and only reports; a failure under `enforce` is deferred as `4.7.5` and bounced as `5.7.5` only at `retry.giveUpAfter`, after the policy is fetched once more. Under `enforce` nothing goes to the `fallback`: a connection failure defers. `mtaSts.skip(item, domain)` exempts a session (a mailed TLS-RPT report, a domain delivered in-process). Every try is told on the `tls` event, for RFC 8460 reports.
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import { nodeResolver } from '@bumail/dns';
|
|
163
|
+
import { createMemoryPolicyCache, createQueue } from '@bumail/queue';
|
|
164
|
+
import { MemoryQueueStore } from '@bumail/queue/memory';
|
|
165
|
+
|
|
166
|
+
const resolver = nodeResolver(); // has txt
|
|
167
|
+
const queue = createQueue({
|
|
168
|
+
store: new MemoryQueueStore(),
|
|
169
|
+
hostname: 'mail.example.net',
|
|
170
|
+
resolver,
|
|
171
|
+
mtaSts: { cache: createMemoryPolicyCache() }, // fetch: globalThis.fetch; resolver: the queue's
|
|
172
|
+
});
|
|
173
|
+
queue.on('tls', ({ domain, policy, mxHost, ok, tlsResult }) => {});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The `tls` event also carries `kind` (`'try'` or `'policy'`), `at` (the queue's clock, ms), `sendingAddress` and `reused`. A `send` of your own receives `mxNames`, `tls`, `onAttempt` and `onSkip` in its options and has to pass them to `sendMail`. See [MTA-STS](docs/guide.md#mta-sts).
|
|
177
|
+
|
|
178
|
+
## Reusing connections
|
|
179
|
+
|
|
180
|
+
Without a `send` of your own, the queue sends through a pool of SMTP
|
|
181
|
+
connections it owns: several messages to one server share a connection
|
|
182
|
+
(100 at most, idle 5 seconds), and `stop()` closes the pool. `reuse` tunes
|
|
183
|
+
it, `reuse: false` opens one connection per session, and a `send` you give
|
|
184
|
+
is never wrapped. Events carry `reused` when the sender says so. The
|
|
185
|
+
`bumail serve` queue of `@bumail/server` sends through the same pool, with
|
|
186
|
+
no setting. See `createSmtpPool` in the `@bumail/smtp` README.
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
createQueue({
|
|
190
|
+
store: new MemoryQueueStore(),
|
|
191
|
+
hostname: 'mail.example.net',
|
|
192
|
+
resolver: nodeResolver(),
|
|
193
|
+
reuse: { maxMessages: 50, idleSeconds: 10 }, // default { 100, 5 }; or false
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
See [Reusing connections](docs/guide.md#reusing-connections).
|
|
198
|
+
|
|
156
199
|
## Several workers
|
|
157
200
|
|
|
158
201
|
```ts
|
|
@@ -249,6 +292,7 @@ queue.on('delivered', ({ id, recipient, reply }) => console.info({ id, recipient
|
|
|
249
292
|
queue.on('deferred', ({ recipient, reply, nextAttemptAt }) => {});
|
|
250
293
|
queue.on('failed', ({ recipient, reply }) => {}); // reply: { code?, status?, text, host? }
|
|
251
294
|
queue.on('dsn', ({ kind, of, to }) => {});
|
|
295
|
+
queue.on('tls', ({ domain, policy, mxHost, address, ok, tlsResult }) => {}); // with mtaSts
|
|
252
296
|
queue.on('error', ({ error, id }) => console.error(id, error)); // the store, a lost lease, a bad route
|
|
253
297
|
|
|
254
298
|
const [next] = await queue.list({ limit: 50 }); // the next due first
|
|
@@ -363,17 +407,34 @@ control character in it.
|
|
|
363
407
|
}
|
|
364
408
|
```
|
|
365
409
|
|
|
410
|
+
## Upgrading
|
|
411
|
+
|
|
412
|
+
With MTA-STS (the release that adds `mtaSts`):
|
|
413
|
+
|
|
414
|
+
- **`@bumail/mta-sts` is a required peer.** Install it even when `mtaSts`
|
|
415
|
+
is unused: `bun add @bumail/mta-sts`.
|
|
416
|
+
- **`QueueEvents` has a new `tls` event kind**, for the TLS-RPT counts. A
|
|
417
|
+
listener that switches on the event kinds should handle it or ignore it.
|
|
418
|
+
- **`SmtpErrorCode` has `MX_NOT_ALLOWED`** (`X.7.5`, from `@bumail/smtp`), for
|
|
419
|
+
an MX host an `enforce` policy does not allow. A `switch` over the codes
|
|
420
|
+
needs the case.
|
|
421
|
+
- **A custom `send` must pass `mxNames`, `tls` and `onAttempt` to
|
|
422
|
+
`sendMail`**, or an `enforce` policy is not applied and the `tls` events
|
|
423
|
+
stay silent.
|
|
424
|
+
- `QueueStore` is unchanged.
|
|
425
|
+
|
|
366
426
|
## API
|
|
367
427
|
|
|
368
428
|
| export | |
|
|
369
429
|
| --- | --- |
|
|
370
430
|
| `createQueue(options)`, `Queue` | the queue: `enqueue`, `deliverDue`, `start`, `stop`, `on`, `list`, `get`, `retryNow`, `cancel`, `owner` |
|
|
371
|
-
| `QueueOptions` (`route`, `routes`, `fallback`), `Route`, `Smarthost`, `RetrySchedule`, `DsnOptions`, `QueueLimits`, `Clock`, `Sender` | what `createQueue` takes |
|
|
431
|
+
| `QueueOptions` (`route`, `routes`, `fallback`, `reuse`, `mtaSts`), `Route`, `Smarthost`, `RetrySchedule`, `DsnOptions`, `ReuseOptions`, `QueueLimits`, `Clock`, `Sender` | what `createQueue` takes |
|
|
372
432
|
| `MessageSource`, `QueueEnvelope` (`ret`, `envid`, `recipients`), `RecipientDsn`, `RecipientNotify`, `NotifyEvent`, `OriginalRecipient`, `RetMode` | what `enqueue` takes, with the DSN parameters |
|
|
373
433
|
| `describeQueueStore`, `QueueStoreHarness`, `CreateQueueStore`, `ShareStore` | from `@bumail/queue/conformance`: `describeQueueStore(name, { create, share?, dispose? })`, run under `bun test`; without `share` the two several-workers tests are skipped |
|
|
374
434
|
| `deliveredDsn(input)`, `DeliveredDsnInput`, `DeliveredRecipient` | the `delivered` DSN for a local delivery: the bytes to enqueue, or `undefined` when no recipient asked for `SUCCESS` |
|
|
375
435
|
| `failedDsn(input)`, `FailedDsnInput`, `FailedRecipient`, `DEFAULT_MAX_RETURN` | the `failed` DSN for a recipient the application could not deliver locally: the bytes to enqueue, or `undefined` for a null reverse-path or when no recipient asked for failures; `DEFAULT_MAX_RETURN` is the 64 KiB a DSN returns of the original by default |
|
|
376
|
-
| `QueueEvents`, `QueueListener`, `RecipientEvent` (`route`, `fallback`, `mxReply`, `mayHaveReachedMx`, `mayHaveReachedFallback`), `DeferredEvent`, `DsnEvent`, `QueueErrorEvent` | the events |
|
|
436
|
+
| `QueueEvents`, `QueueListener`, `RecipientEvent` (`route`, `fallback`, `mxReply`, `mayHaveReachedMx`, `mayHaveReachedFallback`), `DeferredEvent`, `DsnEvent`, `TlsEvent`, `TlsPolicyReport`, `QueueErrorEvent` | the events |
|
|
437
|
+
| `MtaStsOptions`, `StsResolver`, `PolicyCache`, `PolicyCacheEntry`, `createMemoryPolicyCache()` | MTA-STS: the `mtaSts` option, its policy cache (`get`, `set`, `delete?`) and a cache in memory |
|
|
377
438
|
| `QueueStore` | the contract a store answers: `add`, `get`, `list`, `count`, `readMessage`, `claim`, `renew`, `complete(id, owner, result, dsns)`, `reschedule`, `cancel` |
|
|
378
439
|
| `Completed` (`item`, `dsns`) | what `complete` returns: the item as it now stands, and the DSN items it stored in the same step, in the order given; `undefined` when the lease was lost |
|
|
379
440
|
| `QueueItem`, `RecipientState`, `RecipientStatus`, `FinalStatus`, `Diagnostic`, `Lease` | an item, and where each recipient stands |
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export { DEFAULT_MAX_RETURN } from './dsn/policy';
|
|
|
6
6
|
export { QueueError, type QueueErrorCode } from './errors';
|
|
7
7
|
export type { MessageSource, QueueEnvelope } from './queue/envelope';
|
|
8
8
|
export type { DeferredEvent, DsnEvent, QueueErrorEvent, QueueEvents, QueueListener, RecipientEvent, } from './queue/events';
|
|
9
|
-
export type { Clock, DsnOptions, QueueLimits, QueueOptions, RetrySchedule, Route, Sender, Smarthost, } from './queue/options';
|
|
9
|
+
export type { Clock, DsnOptions, QueueLimits, QueueOptions, RetrySchedule, ReuseOptions, Route, Sender, Smarthost, } from './queue/options';
|
|
10
10
|
export { createQueue, type Queue } from './queue/queue';
|
|
11
|
+
export { createMemoryPolicyCache, type PolicyCache, type PolicyCacheEntry, } from './sts/cache';
|
|
12
|
+
export type { MtaStsOptions, StsResolver, TlsEvent, TlsPolicyReport, } from './sts/options';
|
|
11
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EACX,UAAU,EACV,aAAa,EACb,YAAY,EACZ,SAAS,EACT,UAAU,EACV,WAAW,EACX,KAAK,EACL,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,OAAO,GACP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,YAAY,GACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAC3D,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACrE,YAAY,EACX,aAAa,EACb,QAAQ,EACR,eAAe,EACf,WAAW,EACX,aAAa,EACb,cAAc,GACd,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACX,KAAK,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,KAAK,EACL,MAAM,EACN,SAAS,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EACX,UAAU,EACV,aAAa,EACb,YAAY,EACZ,SAAS,EACT,UAAU,EACV,WAAW,EACX,KAAK,EACL,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,OAAO,GACP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,YAAY,GACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,SAAS,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAC3D,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACrE,YAAY,EACX,aAAa,EACb,QAAQ,EACR,eAAe,EACf,WAAW,EACX,aAAa,EACb,cAAc,GACd,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACX,KAAK,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,KAAK,EACL,MAAM,EACN,SAAS,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EACN,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EACX,aAAa,EACb,WAAW,EACX,QAAQ,EACR,eAAe,GACf,MAAM,eAAe,CAAC"}
|