@bumail/queue 0.13.0 → 0.14.1

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.
Files changed (42) hide show
  1. package/README.md +44 -4
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +442 -26
  5. package/dist/index.js.map +21 -13
  6. package/dist/queue/deliver.d.ts +2 -0
  7. package/dist/queue/deliver.d.ts.map +1 -1
  8. package/dist/queue/events.d.ts +3 -0
  9. package/dist/queue/events.d.ts.map +1 -1
  10. package/dist/queue/fallback-session.d.ts.map +1 -1
  11. package/dist/queue/fallback.d.ts.map +1 -1
  12. package/dist/queue/options.d.ts +10 -0
  13. package/dist/queue/options.d.ts.map +1 -1
  14. package/dist/queue/outcome.d.ts.map +1 -1
  15. package/dist/queue/session.d.ts +4 -0
  16. package/dist/queue/session.d.ts.map +1 -1
  17. package/dist/queue/settings/index.d.ts +3 -0
  18. package/dist/queue/settings/index.d.ts.map +1 -1
  19. package/dist/queue/settle.d.ts.map +1 -1
  20. package/dist/queue/worker.d.ts.map +1 -1
  21. package/dist/sts/attempt.d.ts +15 -0
  22. package/dist/sts/attempt.d.ts.map +1 -0
  23. package/dist/sts/bound.d.ts +15 -0
  24. package/dist/sts/bound.d.ts.map +1 -0
  25. package/dist/sts/cache.d.ts +27 -0
  26. package/dist/sts/cache.d.ts.map +1 -0
  27. package/dist/sts/discover.d.ts +52 -0
  28. package/dist/sts/discover.d.ts.map +1 -0
  29. package/dist/sts/options.d.ts +77 -0
  30. package/dist/sts/options.d.ts.map +1 -0
  31. package/dist/sts/refusal.d.ts +10 -0
  32. package/dist/sts/refusal.d.ts.map +1 -0
  33. package/dist/sts/run.d.ts +55 -0
  34. package/dist/sts/run.d.ts.map +1 -0
  35. package/dist/sts/settings.d.ts +5 -0
  36. package/dist/sts/settings.d.ts.map +1 -0
  37. package/dist/sts/tally.d.ts +20 -0
  38. package/dist/sts/tally.d.ts.map +1 -0
  39. package/docs/guide.md +63 -1
  40. package/docs/roadmap.md +6 -4
  41. package/docs/troubleshooting.md +49 -0
  42. package/package.json +7 -5
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) and `@bumail/mime` (for the DSNs) are required
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,27 @@ 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
+
156
178
  ## Reusing connections
157
179
 
158
180
  Without a `send` of your own, the queue sends through a pool of SMTP
@@ -270,6 +292,7 @@ queue.on('delivered', ({ id, recipient, reply }) => console.info({ id, recipient
270
292
  queue.on('deferred', ({ recipient, reply, nextAttemptAt }) => {});
271
293
  queue.on('failed', ({ recipient, reply }) => {}); // reply: { code?, status?, text, host? }
272
294
  queue.on('dsn', ({ kind, of, to }) => {});
295
+ queue.on('tls', ({ domain, policy, mxHost, address, ok, tlsResult }) => {}); // with mtaSts
273
296
  queue.on('error', ({ error, id }) => console.error(id, error)); // the store, a lost lease, a bad route
274
297
 
275
298
  const [next] = await queue.list({ limit: 50 }); // the next due first
@@ -384,17 +407,34 @@ control character in it.
384
407
  }
385
408
  ```
386
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
+
387
426
  ## API
388
427
 
389
428
  | export | |
390
429
  | --- | --- |
391
430
  | `createQueue(options)`, `Queue` | the queue: `enqueue`, `deliverDue`, `start`, `stop`, `on`, `list`, `get`, `retryNow`, `cancel`, `owner` |
392
- | `QueueOptions` (`route`, `routes`, `fallback`, `reuse`), `Route`, `Smarthost`, `RetrySchedule`, `DsnOptions`, `ReuseOptions`, `QueueLimits`, `Clock`, `Sender` | what `createQueue` takes |
431
+ | `QueueOptions` (`route`, `routes`, `fallback`, `reuse`, `mtaSts`), `Route`, `Smarthost`, `RetrySchedule`, `DsnOptions`, `ReuseOptions`, `QueueLimits`, `Clock`, `Sender` | what `createQueue` takes |
393
432
  | `MessageSource`, `QueueEnvelope` (`ret`, `envid`, `recipients`), `RecipientDsn`, `RecipientNotify`, `NotifyEvent`, `OriginalRecipient`, `RetMode` | what `enqueue` takes, with the DSN parameters |
394
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 |
395
434
  | `deliveredDsn(input)`, `DeliveredDsnInput`, `DeliveredRecipient` | the `delivered` DSN for a local delivery: the bytes to enqueue, or `undefined` when no recipient asked for `SUCCESS` |
396
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 |
397
- | `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 |
398
438
  | `QueueStore` | the contract a store answers: `add`, `get`, `list`, `count`, `readMessage`, `claim`, `renew`, `complete(id, owner, result, dsns)`, `reschedule`, `cancel` |
399
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 |
400
440
  | `QueueItem`, `RecipientState`, `RecipientStatus`, `FinalStatus`, `Diagnostic`, `Lease` | an item, and where each recipient stands |
package/dist/index.d.ts CHANGED
@@ -8,4 +8,6 @@ export type { MessageSource, QueueEnvelope } from './queue/envelope';
8
8
  export type { DeferredEvent, DsnEvent, QueueErrorEvent, QueueEvents, QueueListener, RecipientEvent, } from './queue/events';
9
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
@@ -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,YAAY,EACZ,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"}