mailauth 7.1.1 → 7.3.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/.c8rc.json +11 -0
- package/.prettierignore +3 -0
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +68 -0
- package/README.md +131 -31
- package/bin/mailauth.js +62 -0
- package/cli.md +150 -8
- package/docs/arc.md +62 -54
- package/docs/bimi.md +153 -54
- package/docs/dkim.md +37 -36
- package/docs/dkim2.md +154 -0
- package/docs/dmarc.md +4 -1
- package/docs/mta-sts.md +12 -9
- package/docs/spf.md +14 -13
- package/index.d.ts +583 -42
- package/lib/arc/index.d.ts +6 -2
- package/lib/arc/index.js +45 -15
- package/lib/bimi/index.js +362 -102
- package/lib/bimi/validate-svg.js +493 -60
- package/lib/commands/dkim2-hash.js +25 -0
- package/lib/commands/dkim2-sign.js +77 -0
- package/lib/commands/dkim2-verify.js +59 -0
- package/lib/commands/report.js +10 -35
- package/lib/commands/resolver.js +51 -0
- package/lib/commands/seal.js +10 -38
- package/lib/commands/spf.js +4 -35
- package/lib/dkim/dkim-signer.js +50 -30
- package/lib/dkim/dkim-verifier.js +79 -27
- package/lib/dkim/header/simple.js +2 -2
- package/lib/dkim/sign.js +7 -2
- package/lib/dkim/syntax.js +11 -0
- package/lib/dkim/verify.js +1 -0
- package/lib/dkim2/dkim2-parser.js +52 -0
- package/lib/dkim2/dkim2-signer.js +334 -0
- package/lib/dkim2/dkim2-verifier.js +572 -0
- package/lib/dkim2/fields.js +570 -0
- package/lib/dkim2/hash.d.ts +3 -0
- package/lib/dkim2/hash.js +51 -0
- package/lib/dkim2/key.js +203 -0
- package/lib/dkim2/message-state.js +181 -0
- package/lib/dkim2/recipe.js +134 -0
- package/lib/dkim2/sign.d.ts +3 -0
- package/lib/dkim2/sign.js +38 -0
- package/lib/dkim2/verify.d.ts +3 -0
- package/lib/dkim2/verify.js +19 -0
- package/lib/dmarc/author-domain.js +270 -5
- package/lib/dmarc/get-dmarc-record.js +24 -11
- package/lib/dmarc/verify.js +7 -3
- package/lib/mailauth.js +57 -14
- package/lib/mta-sts.js +37 -11
- package/lib/parse-received.js +214 -25
- package/lib/spf/index.js +21 -4
- package/lib/spf/macro.js +5 -3
- package/lib/spf/spf-verify.js +14 -5
- package/lib/spf/syntax.js +5 -0
- package/lib/tools.js +160 -21
- package/package.json +15 -6
- package/stryker.config.json +16 -0
package/docs/mta-sts.md
CHANGED
|
@@ -48,15 +48,17 @@ const { policy, status, warnings } = await getPolicy('example.com', knownPolicy,
|
|
|
48
48
|
|
|
49
49
|
### Policy Object Fields
|
|
50
50
|
|
|
51
|
-
| Field
|
|
52
|
-
|
|
|
53
|
-
| `id`
|
|
54
|
-
| `version`
|
|
55
|
-
| `mode`
|
|
56
|
-
| `mx`
|
|
57
|
-
| `maxAge`
|
|
58
|
-
| `expires`
|
|
59
|
-
| `error`
|
|
51
|
+
| Field | Type | Presence | Description |
|
|
52
|
+
| ------------ | --------------- | ---------------- | ------------------------------------------------------------------------- |
|
|
53
|
+
| `id` | `string\|false` | Always | Policy ID from DNS TXT record, or `false` if not found |
|
|
54
|
+
| `version` | `string` | Policy found | Always `"STSv1"` for valid policies |
|
|
55
|
+
| `mode` | `string` | Always | Policy mode (see below) |
|
|
56
|
+
| `mx` | `string[]` | Listed in policy | Array of allowed MX hostnames (may include wildcards) |
|
|
57
|
+
| `maxAge` | `number` | Policy found | Policy validity period in seconds |
|
|
58
|
+
| `expires` | `string` | Policy found | ISO 8601 expiration timestamp |
|
|
59
|
+
| `error` | `Error` | Status errored | Error object explaining why no live policy could be discovered or fetched |
|
|
60
|
+
| `retryId` | `string` | Fetch failed | New policy ID that could not be fetched while the cached policy is kept |
|
|
61
|
+
| `retryAfter` | `string` | Fetch failed | ISO 8601 timestamp before which `retryId` is not fetched again |
|
|
60
62
|
|
|
61
63
|
### Mode Values
|
|
62
64
|
|
|
@@ -79,6 +81,7 @@ await cache.set(domain, policy); // keep the entry at least until policy.expires
|
|
|
79
81
|
- **Valid cached policy, same ID in DNS:** the cached policy is returned as `renewed` without an HTTPS request. Its `expires` value is not extended, so the policy file is fetched again once it expires.
|
|
80
82
|
- **Valid cached policy, no live policy:** if the TXT lookup fails, the TXT record is missing, unusable or duplicated, the policy host has no address, or the new policy can not be fetched or is invalid, the cached policy is returned with `status: "errored"` and the reason in `policy.error`. A valid cached policy is never replaced by `mode: "none"` because of a discovery failure. An exception is a cached policy that already has mode `none`, which may be replaced by the retry placeholder described below.
|
|
81
83
|
- **Expired cached policy:** the policy file is fetched again. If the fetch fails, the default lax mode keeps returning the expired `enforce` or `testing` policy (with the `expired-cache` warning), while strict mode treats the domain as having no policy.
|
|
84
|
+
- **Cached policy kept after a failed fetch:** when the policy for a new ID can not be fetched and the cached policy is returned instead, it gets `retryId` (the new ID) and `retryAfter` (one hour ahead). Storing it makes the next calls return it as `errored` without HTTPS requests while the DNS record has the same ID, so the policy host is not retried for an hour (RFC 8461 3.3). A different policy ID is fetched right away, and the fields are dropped once a policy is fetched.
|
|
82
85
|
- **No usable cached policy and the fetch fails:** the result is a placeholder with the new policy ID, mode `none`, and `expires` set one hour ahead. Storing it makes the next calls return it as `renewed` without HTTPS requests, so the policy host is not retried for an hour. A changed policy ID is fetched right away.
|
|
83
86
|
|
|
84
87
|
## Strict Mode
|
package/docs/spf.md
CHANGED
|
@@ -19,17 +19,17 @@ const result = await spf({
|
|
|
19
19
|
|
|
20
20
|
## Options
|
|
21
21
|
|
|
22
|
-
| Option | Type | Default | Description
|
|
23
|
-
| ----------------- | ---------- | ----------------- |
|
|
24
|
-
| `sender` | `string` | `postmaster@helo` | MAIL FROM address. An empty value means a null reverse-path, so the HELO identity is checked
|
|
25
|
-
| `ip` | `string` | Required | SMTP client IP address. IPv4-mapped IPv6 addresses (`::ffff:192.0.2.1`, `::ffff:c000:201`) are checked as IPv4
|
|
26
|
-
| `helo` | `string` | | EHLO/HELO hostname
|
|
27
|
-
| `mta` | `string` | `os.hostname()` | Hostname of the MTA performing the check
|
|
28
|
-
| `resolver` | `function` | `dns.resolve` | Custom DNS resolver
|
|
29
|
-
| `maxResolveCount` | `number` | `10` | Maximum DNS lookups allowed
|
|
30
|
-
| `maxVoidCount` | `number` | `2` | Maximum void (empty) DNS lookups allowed
|
|
31
|
-
| `maxElapsedTime` | `number` | No limit | Maximum time in milliseconds for the whole evaluation. If exceeded, the result is `temperror` (RFC 7208 4.6.4)
|
|
32
|
-
| `strict` | `boolean` | `false` | Follow RFC 7208 exactly instead of the lenient default, see [Strict Mode](#strict-mode)
|
|
22
|
+
| Option | Type | Default | Description |
|
|
23
|
+
| ----------------- | ---------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
24
|
+
| `sender` | `string` | `postmaster@helo` | MAIL FROM address. An empty value means a null reverse-path, so the HELO identity is checked |
|
|
25
|
+
| `ip` | `string` | Required | SMTP client IP address. IPv4-mapped IPv6 addresses (`::ffff:192.0.2.1`, `::ffff:c000:201`) are checked as IPv4 |
|
|
26
|
+
| `helo` | `string` | | EHLO/HELO hostname |
|
|
27
|
+
| `mta` | `string` | `os.hostname()` | Hostname of the MTA performing the check |
|
|
28
|
+
| `resolver` | `function` | `dns.resolve` | Custom DNS resolver |
|
|
29
|
+
| `maxResolveCount` | `number` | `10` | Maximum DNS lookups allowed |
|
|
30
|
+
| `maxVoidCount` | `number` | `2` | Maximum void (empty) DNS lookups allowed. `0` is a valid limit, a value that is not a non-negative number uses the default |
|
|
31
|
+
| `maxElapsedTime` | `number` | No limit | Maximum time in milliseconds for the whole evaluation. If exceeded, the result is `temperror` (RFC 7208 4.6.4) |
|
|
32
|
+
| `strict` | `boolean` | `false` | Follow RFC 7208 exactly instead of the lenient default, see [Strict Mode](#strict-mode) |
|
|
33
33
|
|
|
34
34
|
A missing or invalid `ip` gives a `temperror` result with the comment `missing or invalid client IP address`.
|
|
35
35
|
|
|
@@ -68,7 +68,7 @@ In strict mode `status.smtp` holds only the identity that was checked (RFC 8601
|
|
|
68
68
|
|
|
69
69
|
## explanation
|
|
70
70
|
|
|
71
|
-
When the result is `fail` because of a mechanism match and the record has an `exp` modifier, the explanation string is fetched and expanded as described in RFC 7208 section 6.2. Any problem with it (DNS error, no or several TXT records, syntax error,
|
|
71
|
+
When the result is `fail` because of a mechanism match and the record has an `exp` modifier, the explanation string is fetched and expanded as described in RFC 7208 section 6.2. Any problem with it (DNS error, no or several TXT records, syntax error, text that is not printable US-ASCII before or after macro expansion) means that there is no explanation. The explanation lookup does not count toward the DNS lookup limits. The explanation of an included record is never used, and after a redirect only the explanation of the redirect target is used.
|
|
72
72
|
|
|
73
73
|
The explanation is text from the domain owner. It is not added to the generated headers. If you show it to an SMTP client, make clear that it comes from a third party, for example by prepending `"<domain> explains: "`.
|
|
74
74
|
|
|
@@ -144,7 +144,8 @@ These rules apply in both modes:
|
|
|
144
144
|
- `%{p}` expands to a validated PTR name or `unknown`.
|
|
145
145
|
- Trailing dots in domain-specs are accepted, names longer than 253 characters are truncated from the left, and uppercase macros are URL escaped.
|
|
146
146
|
- An internationalized MAIL FROM domain is converted to A-labels.
|
|
147
|
-
-
|
|
147
|
+
- A single trailing dot is removed from the MAIL FROM domain and the HELO name (RFC 7208 section 4.3). A zero-length label anywhere else gives `none`.
|
|
148
|
+
- Address lookups of MX hosts are not counted as void lookups. The PTR lookup of a `%{p}` expansion is not counted as a void lookup either, the query of the term itself decides if the term was void.
|
|
148
149
|
|
|
149
150
|
## Example Output
|
|
150
151
|
|