mailauth 4.13.1 → 4.13.3
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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +14 -0
- package/CLAUDE.md +66 -0
- package/docs/arc.md +89 -89
- package/docs/bimi.md +154 -153
- package/docs/dkim.md +137 -137
- package/docs/dmarc.md +128 -128
- package/docs/mta-sts.md +90 -97
- package/docs/spf.md +122 -122
- package/lib/dkim/body/relaxed.js +2 -2
- package/package.json +10 -10
package/docs/dkim.md
CHANGED
|
@@ -15,97 +15,97 @@ const result = await dkimVerify(message);
|
|
|
15
15
|
|
|
16
16
|
## Top-Level Result Object
|
|
17
17
|
|
|
18
|
-
| Field
|
|
19
|
-
|
|
20
|
-
| `headerFrom`
|
|
18
|
+
| Field | Type | Description |
|
|
19
|
+
| -------------- | --------------- | ------------------------------------------------------ |
|
|
20
|
+
| `headerFrom` | `string[]` | Array of email addresses from the From header |
|
|
21
21
|
| `envelopeFrom` | `string\|false` | Email address from Return-Path header or sender option |
|
|
22
|
-
| `results`
|
|
22
|
+
| `results` | `object[]` | Array of verification results for each DKIM signature |
|
|
23
23
|
|
|
24
24
|
## Signature Result Object
|
|
25
25
|
|
|
26
26
|
Each entry in the `results` array has the following structure:
|
|
27
27
|
|
|
28
|
-
| Field
|
|
29
|
-
|
|
30
|
-
| `id`
|
|
31
|
-
| `signingDomain`
|
|
32
|
-
| `selector`
|
|
33
|
-
| `signature`
|
|
34
|
-
| `algo`
|
|
35
|
-
| `format`
|
|
36
|
-
| `bodyHash`
|
|
37
|
-
| `bodyHashExpecting`
|
|
38
|
-
| `signingHeaders`
|
|
39
|
-
| `status`
|
|
40
|
-
| `signTime`
|
|
41
|
-
| `expiresAfter`
|
|
42
|
-
| `signatureTimeValid`
|
|
43
|
-
| `sourceBodyLength`
|
|
44
|
-
| `canonBodyLength`
|
|
45
|
-
| `canonBodyLengthTotal`
|
|
46
|
-
| `canonBodyLengthLimited` | `boolean`
|
|
47
|
-
| `canonBodyLengthLimit`
|
|
48
|
-
| `mimeStructureStart`
|
|
49
|
-
| `publicKey`
|
|
50
|
-
| `modulusLength`
|
|
51
|
-
| `rr`
|
|
52
|
-
| `info`
|
|
28
|
+
| Field | Type | Presence | Description |
|
|
29
|
+
| ------------------------ | -------------- | ---------------- | ----------------------------------------------------------------- |
|
|
30
|
+
| `id` | `string` | Always | SHA256 hash of signature value, or UUID if no signature |
|
|
31
|
+
| `signingDomain` | `string` | Signature exists | Domain from `d=` tag |
|
|
32
|
+
| `selector` | `string` | Signature exists | DKIM selector from `s=` tag |
|
|
33
|
+
| `signature` | `string` | Signature exists | Base64-encoded signature value from `b=` tag |
|
|
34
|
+
| `algo` | `string` | Signature exists | Signing algorithm (e.g., `"rsa-sha256"`, `"ed25519-sha256"`) |
|
|
35
|
+
| `format` | `string` | Signature exists | Canonicalization format from `c=` tag (e.g., `"relaxed/relaxed"`) |
|
|
36
|
+
| `bodyHash` | `string` | Signature exists | Calculated body hash (base64) |
|
|
37
|
+
| `bodyHashExpecting` | `string` | Signature exists | Expected body hash from `bh=` tag |
|
|
38
|
+
| `signingHeaders` | `object` | Signature exists | Signing header details (see below) |
|
|
39
|
+
| `status` | `object` | Always | Verification status (see below) |
|
|
40
|
+
| `signTime` | `string\|null` | Always | ISO 8601 timestamp from `t=` tag, or null |
|
|
41
|
+
| `expiresAfter` | `string\|null` | Always | ISO 8601 expiration from `x=` tag, or null |
|
|
42
|
+
| `signatureTimeValid` | `boolean` | Always | Whether signature is within validity window |
|
|
43
|
+
| `sourceBodyLength` | `number` | Body processed | Original body length in bytes |
|
|
44
|
+
| `canonBodyLength` | `number` | Body processed | Canonicalized bytes actually hashed |
|
|
45
|
+
| `canonBodyLengthTotal` | `number` | Body processed | Total canonicalized body length |
|
|
46
|
+
| `canonBodyLengthLimited` | `boolean` | Signature exists | Whether body length is limited by `l=` tag |
|
|
47
|
+
| `canonBodyLengthLimit` | `number` | `l=` tag present | Maximum body length from `l=` tag |
|
|
48
|
+
| `mimeStructureStart` | `number` | MIME detected | Position where MIME boundary structure starts |
|
|
49
|
+
| `publicKey` | `string` | Key retrieved | PEM-formatted public key |
|
|
50
|
+
| `modulusLength` | `number` | RSA key | RSA key length in bits |
|
|
51
|
+
| `rr` | `string` | DNS lookup done | Raw DNS TXT record value |
|
|
52
|
+
| `info` | `string` | Always | Formatted Authentication-Results header value |
|
|
53
53
|
|
|
54
54
|
### signingHeaders Object
|
|
55
55
|
|
|
56
|
-
| Field
|
|
57
|
-
|
|
58
|
-
| `keys`
|
|
59
|
-
| `headers`
|
|
60
|
-
| `canonicalizedHeader` | `string`
|
|
56
|
+
| Field | Type | Description |
|
|
57
|
+
| --------------------- | ---------- | ------------------------------------------- |
|
|
58
|
+
| `keys` | `string[]` | List of header field names that were signed |
|
|
59
|
+
| `headers` | `string[]` | Raw header lines that were signed |
|
|
60
|
+
| `canonicalizedHeader` | `string` | Base64-encoded canonicalized header data |
|
|
61
61
|
|
|
62
62
|
### status Object
|
|
63
63
|
|
|
64
|
-
| Field
|
|
65
|
-
|
|
66
|
-
| `result`
|
|
67
|
-
| `comment`
|
|
68
|
-
| `aligned`
|
|
69
|
-
| `header`
|
|
70
|
-
| `policy`
|
|
71
|
-
| `underSized` | `number`
|
|
64
|
+
| Field | Type | Presence | Description |
|
|
65
|
+
| ------------ | --------------- | --------------- | ------------------------------------ |
|
|
66
|
+
| `result` | `string` | Always | Verification result code (see below) |
|
|
67
|
+
| `comment` | `string` | On error/info | Human-readable explanation |
|
|
68
|
+
| `aligned` | `string\|false` | DKIM signatures | DMARC-aligned domain, or false |
|
|
69
|
+
| `header` | `object` | Always | Signature header info |
|
|
70
|
+
| `policy` | `object` | Policy result | Policy violation details |
|
|
71
|
+
| `underSized` | `number` | Body limited | Number of unsigned bytes |
|
|
72
72
|
|
|
73
73
|
#### status.header Object
|
|
74
74
|
|
|
75
|
-
| Field | Type
|
|
76
|
-
|
|
77
|
-
| `i`
|
|
78
|
-
| `s`
|
|
79
|
-
| `a`
|
|
80
|
-
| `b`
|
|
75
|
+
| Field | Type | Description |
|
|
76
|
+
| ----- | --------------- | ----------------------------------------------------- |
|
|
77
|
+
| `i` | `string\|false` | Signing domain with @ prefix (e.g., `"@example.com"`) |
|
|
78
|
+
| `s` | `string` | DKIM selector |
|
|
79
|
+
| `a` | `string` | Algorithm |
|
|
80
|
+
| `b` | `string` | First 8 characters of signature value |
|
|
81
81
|
|
|
82
82
|
## Result Values
|
|
83
83
|
|
|
84
|
-
| Result
|
|
85
|
-
|
|
86
|
-
| `pass`
|
|
87
|
-
| `fail`
|
|
88
|
-
| `neutral`
|
|
89
|
-
| `policy`
|
|
90
|
-
| `temperror` | Temporary error (DNS failure)
|
|
91
|
-
| `none`
|
|
84
|
+
| Result | Description |
|
|
85
|
+
| ----------- | -------------------------------------------------------------------------- |
|
|
86
|
+
| `pass` | Signature verified successfully |
|
|
87
|
+
| `fail` | Signature verification failed (bad signature) |
|
|
88
|
+
| `neutral` | Signature could not be verified (missing key, expired, body hash mismatch) |
|
|
89
|
+
| `policy` | Signature failed policy check (e.g., weak key) |
|
|
90
|
+
| `temperror` | Temporary error (DNS failure) |
|
|
91
|
+
| `none` | Message not signed |
|
|
92
92
|
|
|
93
93
|
## Comment Values
|
|
94
94
|
|
|
95
95
|
Common values for `status.comment`:
|
|
96
96
|
|
|
97
|
-
| Comment
|
|
98
|
-
|
|
99
|
-
| `"body hash did not verify"` | Calculated body hash does not match `bh=` tag
|
|
100
|
-
| `"bad signature"`
|
|
101
|
-
| `"invalid expiration"`
|
|
102
|
-
| `"expired"`
|
|
103
|
-
| `"no key"`
|
|
104
|
-
| `"unknown key version"`
|
|
105
|
-
| `"unknown key type"`
|
|
106
|
-
| `"invalid public key"`
|
|
107
|
-
| `"DNS failure: {code}"`
|
|
108
|
-
| `"message not signed"`
|
|
97
|
+
| Comment | Description |
|
|
98
|
+
| ---------------------------- | ------------------------------------------------ |
|
|
99
|
+
| `"body hash did not verify"` | Calculated body hash does not match `bh=` tag |
|
|
100
|
+
| `"bad signature"` | Cryptographic signature verification failed |
|
|
101
|
+
| `"invalid expiration"` | Expiration timestamp is before signing timestamp |
|
|
102
|
+
| `"expired"` | Signature has expired (past `x=` timestamp) |
|
|
103
|
+
| `"no key"` | No DKIM key found in DNS |
|
|
104
|
+
| `"unknown key version"` | Unsupported key version in DNS record |
|
|
105
|
+
| `"unknown key type"` | Unsupported key type in DNS record |
|
|
106
|
+
| `"invalid public key"` | Public key in DNS record is malformed |
|
|
107
|
+
| `"DNS failure: {code}"` | DNS lookup failed with error code |
|
|
108
|
+
| `"message not signed"` | No DKIM-Signature headers found |
|
|
109
109
|
|
|
110
110
|
## Example Output
|
|
111
111
|
|
|
@@ -113,46 +113,46 @@ Common values for `status.comment`:
|
|
|
113
113
|
|
|
114
114
|
```json
|
|
115
115
|
{
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
116
|
+
"headerFrom": ["sender@example.com"],
|
|
117
|
+
"envelopeFrom": "sender@example.com",
|
|
118
|
+
"results": [
|
|
119
|
+
{
|
|
120
|
+
"id": "a1b2c3d4e5f6...",
|
|
121
|
+
"signingDomain": "example.com",
|
|
122
|
+
"selector": "selector1",
|
|
123
|
+
"signature": "dGhpcyBpcyBhIHNpZ25hdHVyZQ==",
|
|
124
|
+
"algo": "rsa-sha256",
|
|
125
|
+
"format": "relaxed/relaxed",
|
|
126
|
+
"bodyHash": "YWJjZGVmZ2hpamtsbW5vcA==",
|
|
127
|
+
"bodyHashExpecting": "YWJjZGVmZ2hpamtsbW5vcA==",
|
|
128
|
+
"signingHeaders": {
|
|
129
|
+
"keys": ["from", "to", "subject", "date"],
|
|
130
|
+
"headers": ["From: sender@example.com", "..."],
|
|
131
|
+
"canonicalizedHeader": "..."
|
|
132
|
+
},
|
|
133
|
+
"status": {
|
|
134
|
+
"result": "pass",
|
|
135
|
+
"aligned": "example.com",
|
|
136
|
+
"header": {
|
|
137
|
+
"i": "@example.com",
|
|
138
|
+
"s": "selector1",
|
|
139
|
+
"a": "rsa-sha256",
|
|
140
|
+
"b": "dGhpcyBp"
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"signTime": "2024-01-15T10:30:00.000Z",
|
|
144
|
+
"expiresAfter": null,
|
|
145
|
+
"signatureTimeValid": true,
|
|
146
|
+
"sourceBodyLength": 1024,
|
|
147
|
+
"canonBodyLength": 1020,
|
|
148
|
+
"canonBodyLengthTotal": 1020,
|
|
149
|
+
"canonBodyLengthLimited": false,
|
|
150
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\n...",
|
|
151
|
+
"modulusLength": 2048,
|
|
152
|
+
"rr": "v=DKIM1; k=rsa; p=...",
|
|
153
|
+
"info": "dkim=pass header.i=@example.com header.s=selector1 header.a=rsa-sha256 header.b=\"dGhpcyBp\""
|
|
141
154
|
}
|
|
142
|
-
|
|
143
|
-
"signTime": "2024-01-15T10:30:00.000Z",
|
|
144
|
-
"expiresAfter": null,
|
|
145
|
-
"signatureTimeValid": true,
|
|
146
|
-
"sourceBodyLength": 1024,
|
|
147
|
-
"canonBodyLength": 1020,
|
|
148
|
-
"canonBodyLengthTotal": 1020,
|
|
149
|
-
"canonBodyLengthLimited": false,
|
|
150
|
-
"publicKey": "-----BEGIN PUBLIC KEY-----\n...",
|
|
151
|
-
"modulusLength": 2048,
|
|
152
|
-
"rr": "v=DKIM1; k=rsa; p=...",
|
|
153
|
-
"info": "dkim=pass header.i=@example.com header.s=selector1 header.a=rsa-sha256 header.b=\"dGhpcyBp\""
|
|
154
|
-
}
|
|
155
|
-
]
|
|
155
|
+
]
|
|
156
156
|
}
|
|
157
157
|
```
|
|
158
158
|
|
|
@@ -160,26 +160,26 @@ Common values for `status.comment`:
|
|
|
160
160
|
|
|
161
161
|
```json
|
|
162
162
|
{
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
163
|
+
"headerFrom": ["sender@example.com"],
|
|
164
|
+
"envelopeFrom": "sender@example.com",
|
|
165
|
+
"results": [
|
|
166
|
+
{
|
|
167
|
+
"id": "a1b2c3d4e5f6...",
|
|
168
|
+
"signingDomain": "example.com",
|
|
169
|
+
"selector": "selector1",
|
|
170
|
+
"status": {
|
|
171
|
+
"result": "neutral",
|
|
172
|
+
"comment": "no key",
|
|
173
|
+
"header": {
|
|
174
|
+
"i": "@example.com",
|
|
175
|
+
"s": "selector1",
|
|
176
|
+
"a": "rsa-sha256",
|
|
177
|
+
"b": "dGhpcyBp"
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
"info": "dkim=neutral (no key) header.i=@example.com header.s=selector1 header.a=rsa-sha256 header.b=\"dGhpcyBp\""
|
|
178
181
|
}
|
|
179
|
-
|
|
180
|
-
"info": "dkim=neutral (no key) header.i=@example.com header.s=selector1 header.a=rsa-sha256 header.b=\"dGhpcyBp\""
|
|
181
|
-
}
|
|
182
|
-
]
|
|
182
|
+
]
|
|
183
183
|
}
|
|
184
184
|
```
|
|
185
185
|
|
|
@@ -187,16 +187,16 @@ Common values for `status.comment`:
|
|
|
187
187
|
|
|
188
188
|
```json
|
|
189
189
|
{
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
190
|
+
"headerFrom": ["sender@example.com"],
|
|
191
|
+
"envelopeFrom": "sender@example.com",
|
|
192
|
+
"results": [
|
|
193
|
+
{
|
|
194
|
+
"status": {
|
|
195
|
+
"result": "none",
|
|
196
|
+
"comment": "message not signed"
|
|
197
|
+
},
|
|
198
|
+
"info": "dkim=none (message not signed)"
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
201
|
}
|
|
202
202
|
```
|