@bumail/queue 0.13.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 +44 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +442 -26
- package/dist/index.js.map +21 -13
- package/dist/queue/deliver.d.ts +2 -0
- package/dist/queue/deliver.d.ts.map +1 -1
- package/dist/queue/events.d.ts +3 -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 +10 -0
- package/dist/queue/options.d.ts.map +1 -1
- package/dist/queue/outcome.d.ts.map +1 -1
- package/dist/queue/session.d.ts +4 -0
- package/dist/queue/session.d.ts.map +1 -1
- package/dist/queue/settings/index.d.ts +3 -0
- package/dist/queue/settings/index.d.ts.map +1 -1
- 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 +63 -1
- package/docs/roadmap.md +6 -4
- package/docs/troubleshooting.md +49 -0
- package/package.json +5 -3
package/docs/roadmap.md
CHANGED
|
@@ -6,13 +6,15 @@ only number on it.
|
|
|
6
6
|
|
|
7
7
|
## Now
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- **MTA-STS (RFC 8461) and TLS-RPT (RFC 8460)** ([#292](https://github.com/softistx/bumail/issues/292)) — a recipient
|
|
10
|
+
domain's policy fetched with `@bumail/mta-sts`, cached and enforced on MX
|
|
11
|
+
delivery: the certificate is checked against the policy's MX names. Opt-in
|
|
12
|
+
in the library, on in `@bumail/server`. An enforce failure defers the
|
|
13
|
+
message (`4.7.5`) and bounces it only at `giveUpAfter`. TLS reports are
|
|
14
|
+
recorded and sent opt-in.
|
|
10
15
|
|
|
11
16
|
## Next
|
|
12
17
|
|
|
13
|
-
- **MTA-STS (RFC 8461) and TLS-RPT (RFC 8460)** — a recipient domain's
|
|
14
|
-
policy fetched, cached and enforced, `mxTls: 'required'` with the
|
|
15
|
-
certificate checked against the policy's MX names, and the reports.
|
|
16
18
|
- **DANE (RFC 7672)** — TLSA records checked for MX hosts, once a
|
|
17
19
|
resolver that validates DNSSEC can be given to the queue.
|
|
18
20
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -99,6 +99,12 @@ parts shown as … vary.
|
|
|
99
99
|
|
|
100
100
|
**Delivery**
|
|
101
101
|
|
|
102
|
+
- [A recipient is deferred with `4.7.5`, or fails with `5.7.5`, `MTA-STS policy of … (enforce)`](#a-recipient-is-deferred-with-475-or-fails-with-575-mta-sts-policy-of--enforce)
|
|
103
|
+
- [`MTA-STS discovery took more than N ms`](#mta-sts-discovery-took-more-than-n-ms-a-tls-event-with-tlsresult-sts-policy-fetch-error)
|
|
104
|
+
- [`QueueError: mtaSts must be an object of options…`, `mtaSts.cache must be a PolicyCache with get and set`, `mtaSts.fetch must be a function`](#queueerror-mtasts-must-be-an-object-of-options-mtastscache-must-be-a-policycache-with-get-and-set-mtastsfetch-must-be-a-function)
|
|
105
|
+
- [`QueueError: mtaSts.fetchTimeoutMs must be a number of milliseconds…`, `mtaSts.maxAgeCap must be a whole number of seconds…`, `mtaSts.skip must be a function`](#queueerror-mtastsfetchtimeoutms-must-be-a-number-of-milliseconds-mtastsmaxagecap-must-be-a-whole-number-of-seconds-mtastsskip-must-be-a-function)
|
|
106
|
+
- [`QueueError: mtaSts needs a resolver with txt(name)`](#queueerror-mtasts-needs-a-resolver-with-txtname)
|
|
107
|
+
- [A `tls` event with `sts-policy-fetch-error` and the mail goes out unprotected](#a-tls-event-with-sts-policy-fetch-error-and-the-mail-goes-out-unprotected)
|
|
102
108
|
- [A recipient stays `deferred` with `4.4.1` or `4.4.2`](#a-recipient-stays-deferred-with-441-or-442)
|
|
103
109
|
- [Every delivery fails at once with `5.7.1`, or with a reply naming your IP or EHLO name](#every-delivery-fails-at-once-with-571-or-with-a-reply-naming-your-ip-or-ehlo-name)
|
|
104
110
|
- [A recipient fails with `5.1.3`, `The address is not one SMTP can carry`](#a-recipient-fails-with-513-the-address-is-not-one-smtp-can-carry)
|
|
@@ -896,6 +902,49 @@ const clean = text.replaceAll('\0', '').toWellFormed();
|
|
|
896
902
|
|
|
897
903
|
## Delivery
|
|
898
904
|
|
|
905
|
+
### A recipient is deferred with `4.7.5`, or fails with `5.7.5`, `MTA-STS policy of … (enforce)`
|
|
906
|
+
|
|
907
|
+
**When:** `mtaSts` is set, the recipient domain publishes a policy in mode `enforce`, and the `deferred` event's `reply.status` is `4.7.5` (or the `failed` one's `5.7.5`) with a text such as `MTA-STS policy of example.com (enforce): No mail host of example.com (mx.other.net) is allowed by the policy's MX names (mail.example.com)`.
|
|
908
|
+
**Why:** a session broke the policy: no MX host of the domain matches the policy's `mx` list (`MX_NOT_ALLOWED`), the MX does not offer STARTTLS, or its certificate does not check out for the MX name. The message is not sent anywhere else, `fallback` included (and under an `enforce` policy a plain connection failure of every MX is deferred too, never sent through the `fallback`). It is deferred with the usual back-off and bounced as `5.7.5` only at `retry.giveUpAfter`, after the policy is fetched once more.
|
|
909
|
+
**Fix:** the `tls` events name the host and the `tlsResult` (`validation-failure` for a name outside the policy, `certificate-host-mismatch`, `certificate-expired`, `certificate-not-trusted`, `starttls-not-supported`). It is the receiving domain's to fix; if its policy is wrong, the message is delivered once the policy is. To send meanwhile, `retryNow(id)` after the domain changed its policy to `testing` or `none` and its record `id`.
|
|
910
|
+
|
|
911
|
+
### `MTA-STS discovery took more than N ms` (a `tls` event with `tlsResult: 'sts-policy-fetch-error'`)
|
|
912
|
+
|
|
913
|
+
**When:** `mtaSts` is set and the cache, the `_mta-sts` lookup and the policy fetch together used the whole `fetchTimeoutMs`.
|
|
914
|
+
**Why:** the discovery has one deadline, not one per step, so a slow resolver or cache leaves the fetch less time. The message is sent without the policy (a cached one that has not expired stays in force). A policy fetch that failed is remembered for 5 minutes per domain and record `id`: a remote policy fixed under the same `id` is not fetched again for up to 5 minutes, and each session in between tells the same event. A timeout caused only by a budget the earlier steps had already used is not remembered.
|
|
915
|
+
**Fix:** raise `fetchTimeoutMs`, or fix the slow resolver or cache; the domain's owner publishes a new `id` to have the policy fetched at once, or waits the 5 minutes.
|
|
916
|
+
|
|
917
|
+
### `QueueError: mtaSts must be an object of options…`, `mtaSts.cache must be a PolicyCache with get and set`, `mtaSts.fetch must be a function`
|
|
918
|
+
|
|
919
|
+
**Code:** `INVALID`. `mtaSts` is the options object, `cache` an object with `get` and `set` (`createMemoryPolicyCache()` fits), `fetch` a function.
|
|
920
|
+
|
|
921
|
+
```ts
|
|
922
|
+
mtaSts: { cache: createMemoryPolicyCache(), fetch: globalThis.fetch }
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
### `QueueError: mtaSts.fetchTimeoutMs must be a number of milliseconds…`, `mtaSts.maxAgeCap must be a whole number of seconds…`, `mtaSts.skip must be a function`
|
|
926
|
+
|
|
927
|
+
**Code:** `INVALID`. `fetchTimeoutMs` is above 0 and at most 2147483647; `maxAgeCap` is a whole number of seconds from 0 to 31557600 (`MAX_AGE_LIMIT` of `@bumail/mta-sts`); `skip` is a function.
|
|
928
|
+
|
|
929
|
+
```ts
|
|
930
|
+
mtaSts: { fetchTimeoutMs: 30_000, maxAgeCap: 7 * 86_400 }
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
### `QueueError: mtaSts needs a resolver with txt(name)`
|
|
934
|
+
|
|
935
|
+
**Code:** `INVALID`. `mtaSts` reads the `_mta-sts` TXT record, and neither `mtaSts.resolver` nor the queue's `resolver` has `txt`.
|
|
936
|
+
|
|
937
|
+
```ts
|
|
938
|
+
createQueue({ store, hostname, resolver: nodeResolver(), mtaSts: {} }); // nodeResolver() has txt
|
|
939
|
+
createQueue({ store, hostname, resolver, mtaSts: { resolver: nodeResolver() } });
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
### A `tls` event with `sts-policy-fetch-error` and the mail goes out unprotected
|
|
943
|
+
|
|
944
|
+
**When:** `mtaSts` is set, and the `tls` event has no `mxHost` and a `tlsResult` of `sts-policy-fetch-error`, `sts-policy-invalid` or `sts-webpki-invalid`.
|
|
945
|
+
**Why:** the domain has an `_mta-sts` record, but `https://mta-sts.<domain>/.well-known/mta-sts.txt` could not be had (a timeout, a redirect, a status other than 200, a wrong content type, an invalid policy, a certificate the system does not trust). RFC 8461 §5.1 then applies a cached policy that has not expired, and with none sends without a policy: that session is not protected.
|
|
946
|
+
**Fix:** the domain's to fix. Check the policy URL yourself, and that the `fetch` you gave (`mtaSts.fetch`) can reach it.
|
|
947
|
+
|
|
899
948
|
### A recipient stays `deferred` with `4.4.1` or `4.4.2`
|
|
900
949
|
|
|
901
950
|
**When:** the `deferred` event's `reply` has no `code`, a `status` of
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bumail/queue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "The outbound mail queue of a mail server: every recipient's state, retries with back-off, delivery status notifications (RFC 3464), leases for several workers, and a memory, a bun:sqlite, a PostgreSQL (Bun.sql) and a Redis (Bun.redis) store, delivering through @bumail/smtp/client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -73,12 +73,14 @@
|
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@bumail/dns": "^0.2.2",
|
|
75
75
|
"@bumail/mime": "^0.2.0",
|
|
76
|
-
"@bumail/
|
|
76
|
+
"@bumail/mta-sts": "^0.1.0",
|
|
77
|
+
"@bumail/smtp": "^0.13.0",
|
|
77
78
|
"@types/bun": "^1.4.2"
|
|
78
79
|
},
|
|
79
80
|
"peerDependencies": {
|
|
80
81
|
"@bumail/mime": "^0.2.0",
|
|
81
|
-
"@bumail/
|
|
82
|
+
"@bumail/mta-sts": "^0.1.0",
|
|
83
|
+
"@bumail/smtp": "^0.13.0",
|
|
82
84
|
"typescript": "^6.0.3 || ^7.0.0"
|
|
83
85
|
},
|
|
84
86
|
"peerDependenciesMeta": {
|