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/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 | Type | Description |
19
- |-------|------|-------------|
20
- | `headerFrom` | `string[]` | Array of email addresses from the From header |
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` | `object[]` | Array of verification results for each DKIM signature |
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 | 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 |
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 | 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 |
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 | 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 |
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 | 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 |
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 | 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 |
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 | 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 |
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
- "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"
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
- "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"
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
- "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
- ]
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
  ```