mailauth 4.6.0 → 4.6.2
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/.ncurc.js +12 -0
- package/CHANGELOG.md +14 -0
- package/lib/bimi/index.js +7 -0
- package/lib/dkim/body/relaxed.js +8 -1
- package/lib/dkim/body/simple.js +7 -1
- package/lib/dkim/dkim-signer.js +3 -1
- package/lib/dkim/dkim-verifier.js +24 -2
- package/lib/dmarc/verify.js +2 -2
- package/lib/mailauth.js +8 -1
- package/lib/tools.js +20 -7
- package/man/mailauth.1 +1 -1
- package/package.json +10 -8
- package/.ncurc.json +0 -4
package/.ncurc.js
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.6.2](https://github.com/postalsys/mailauth/compare/v4.6.1...v4.6.2) (2024-01-25)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **bimi:** skip bimi with oversized DKIM signatures ([d666d74](https://github.com/postalsys/mailauth/commit/d666d7476cbcae8b3161c78a7e737559ad112fd9))
|
|
9
|
+
|
|
10
|
+
## [4.6.1](https://github.com/postalsys/mailauth/compare/v4.6.0...v4.6.1) (2024-01-24)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **dkim-verify:** Show the length of the source body in DKIM results ([d28663b](https://github.com/postalsys/mailauth/commit/d28663b30b0bfaf07d395e9d3eaea044c9085657))
|
|
16
|
+
|
|
3
17
|
## [4.6.0](https://github.com/postalsys/mailauth/compare/v4.5.2...v4.6.0) (2023-11-02)
|
|
4
18
|
|
|
5
19
|
|
package/lib/bimi/index.js
CHANGED
|
@@ -51,6 +51,13 @@ const lookup = async data => {
|
|
|
51
51
|
return response;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
if (dmarc.alignment?.dkim?.overSized) {
|
|
55
|
+
response.status.result = 'skipped';
|
|
56
|
+
response.status.comment = 'Oversized DKIM signature';
|
|
57
|
+
response.info = formatAuthHeaderRow('bimi', response.status);
|
|
58
|
+
return response;
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
const authorDomain = dmarc.status?.header?.from;
|
|
55
62
|
const orgDomain = dmarc.domain;
|
|
56
63
|
|
package/lib/dkim/body/relaxed.js
CHANGED
|
@@ -26,9 +26,14 @@ class RelaxedHash {
|
|
|
26
26
|
this.bodyHash = crypto.createHash(algorithm);
|
|
27
27
|
|
|
28
28
|
this.remainder = false;
|
|
29
|
-
this.byteLength = 0;
|
|
30
29
|
|
|
30
|
+
// total body size
|
|
31
|
+
this.byteLength = 0;
|
|
32
|
+
// total canonicalized body size
|
|
33
|
+
this.canonicalizedLength = 0;
|
|
34
|
+
// hashed canonicalized body size (after l= tag)
|
|
31
35
|
this.bodyHashedBytes = 0;
|
|
36
|
+
|
|
32
37
|
this.maxBodyLength = maxBodyLength;
|
|
33
38
|
|
|
34
39
|
this.maxSizeReached = maxBodyLength === 0;
|
|
@@ -37,6 +42,8 @@ class RelaxedHash {
|
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
_updateBodyHash(chunk) {
|
|
45
|
+
this.canonicalizedLength += chunk.length;
|
|
46
|
+
|
|
40
47
|
if (this.maxSizeReached) {
|
|
41
48
|
return;
|
|
42
49
|
}
|
package/lib/dkim/body/simple.js
CHANGED
|
@@ -18,8 +18,12 @@ class SimpleHash {
|
|
|
18
18
|
this.bodyHash = crypto.createHash(algorithm);
|
|
19
19
|
|
|
20
20
|
this.remainder = [];
|
|
21
|
-
this.byteLength = 0;
|
|
22
21
|
|
|
22
|
+
// total body size
|
|
23
|
+
this.byteLength = 0;
|
|
24
|
+
// total canonicalized body size
|
|
25
|
+
this.canonicalizedLength = 0;
|
|
26
|
+
// hashed canonicalized body size (after l= tag)
|
|
23
27
|
this.bodyHashedBytes = 0;
|
|
24
28
|
|
|
25
29
|
this.maxBodyLength = maxBodyLength;
|
|
@@ -29,6 +33,8 @@ class SimpleHash {
|
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
_updateBodyHash(chunk) {
|
|
36
|
+
this.canonicalizedLength += chunk.length;
|
|
37
|
+
|
|
32
38
|
if (this.maxSizeReached) {
|
|
33
39
|
return;
|
|
34
40
|
}
|
package/lib/dkim/dkim-signer.js
CHANGED
|
@@ -259,7 +259,9 @@ class DkimSigner extends MessageParser {
|
|
|
259
259
|
// value for the l= tag (if needed)
|
|
260
260
|
typeof signatureData.maxBodyLength === 'number'
|
|
261
261
|
? {
|
|
262
|
-
bodyHashedBytes: this.bodyHashes.get(hashKey).hasher.bodyHashedBytes
|
|
262
|
+
bodyHashedBytes: this.bodyHashes.get(hashKey).hasher.bodyHashedBytes,
|
|
263
|
+
canonicalizedLength: this.bodyHashes.get(hashKey).hasher.canonicalizedLength,
|
|
264
|
+
sourceBodyLength: this.bodyHashes.get(hashKey).hasher.byteLength
|
|
263
265
|
}
|
|
264
266
|
: {}
|
|
265
267
|
)
|
|
@@ -7,6 +7,7 @@ const { generateCanonicalizedHeader } = require('./header');
|
|
|
7
7
|
const { getARChain } = require('../arc');
|
|
8
8
|
const addressparser = require('nodemailer/lib/addressparser');
|
|
9
9
|
const crypto = require('crypto');
|
|
10
|
+
const { v4: uuidv4 } = require('uuid');
|
|
10
11
|
|
|
11
12
|
class DkimVerifier extends MessageParser {
|
|
12
13
|
constructor(options) {
|
|
@@ -204,7 +205,9 @@ class DkimVerifier extends MessageParser {
|
|
|
204
205
|
};
|
|
205
206
|
|
|
206
207
|
if (signatureHeader.type === 'DKIM' && this.headerFrom?.length) {
|
|
207
|
-
status.aligned = this.headerFrom?.length
|
|
208
|
+
status.aligned = this.headerFrom?.length
|
|
209
|
+
? getAlignment(this.headerFrom[0].split('@').pop(), [signatureHeader.signingDomain])?.domain || false
|
|
210
|
+
: false;
|
|
208
211
|
}
|
|
209
212
|
|
|
210
213
|
let bodyHash = this.bodyHashes.get(signatureHeader.bodyHashKey)?.hash;
|
|
@@ -296,6 +299,8 @@ class DkimVerifier extends MessageParser {
|
|
|
296
299
|
}
|
|
297
300
|
|
|
298
301
|
signatureHeader.bodyHashedBytes = this.bodyHashes.get(signatureHeader.bodyHashKey)?.bodyHashedBytes;
|
|
302
|
+
signatureHeader.canonicalizedLength = this.bodyHashes.get(signatureHeader.bodyHashKey)?.canonicalizedLength;
|
|
303
|
+
signatureHeader.sourceBodyLength = this.bodyHashes.get(signatureHeader.bodyHashKey)?.byteLength;
|
|
299
304
|
|
|
300
305
|
if (typeof signatureHeader.maxBodyLength === 'number' && signatureHeader.maxBodyLength !== signatureHeader.bodyHashedBytes) {
|
|
301
306
|
status.result = 'fail';
|
|
@@ -303,6 +308,9 @@ class DkimVerifier extends MessageParser {
|
|
|
303
308
|
}
|
|
304
309
|
|
|
305
310
|
let result = {
|
|
311
|
+
id: signatureHeader.parsed?.b?.value
|
|
312
|
+
? crypto.createHash('sha256').update(Buffer.from(signatureHeader.parsed?.b?.value, 'base64')).digest('hex')
|
|
313
|
+
: uuidv4(),
|
|
306
314
|
signingDomain: signatureHeader.signingDomain,
|
|
307
315
|
selector: signatureHeader.selector,
|
|
308
316
|
signature: signatureHeader.parsed?.b?.value,
|
|
@@ -314,12 +322,26 @@ class DkimVerifier extends MessageParser {
|
|
|
314
322
|
status
|
|
315
323
|
};
|
|
316
324
|
|
|
325
|
+
if (typeof signatureHeader.sourceBodyLength === 'number') {
|
|
326
|
+
result.sourceBodyLength = signatureHeader.sourceBodyLength;
|
|
327
|
+
}
|
|
328
|
+
|
|
317
329
|
if (typeof signatureHeader.bodyHashedBytes === 'number') {
|
|
318
330
|
result.canonBodyLength = signatureHeader.bodyHashedBytes;
|
|
319
331
|
}
|
|
320
332
|
|
|
333
|
+
if (typeof signatureHeader.canonicalizedLength === 'number') {
|
|
334
|
+
result.canonBodyLengthTotal = signatureHeader.canonicalizedLength;
|
|
335
|
+
}
|
|
336
|
+
|
|
321
337
|
if (typeof signatureHeader.maxBodyLength === 'number') {
|
|
322
|
-
result.
|
|
338
|
+
result.canonBodyLengthLimited = true;
|
|
339
|
+
result.canonBodyLengthLimit = signatureHeader.maxBodyLength;
|
|
340
|
+
if (result.canonBodyLengthTotal > result.canonBodyLength) {
|
|
341
|
+
status.overSized = result.canonBodyLengthTotal - result.canonBodyLength;
|
|
342
|
+
}
|
|
343
|
+
} else {
|
|
344
|
+
result.canonBodyLengthLimited = false;
|
|
323
345
|
}
|
|
324
346
|
|
|
325
347
|
if (publicKey) {
|
package/lib/dmarc/verify.js
CHANGED
|
@@ -101,8 +101,8 @@ const verifyDmarc = async opts => {
|
|
|
101
101
|
rr: dmarcRecord.rr,
|
|
102
102
|
|
|
103
103
|
alignment: {
|
|
104
|
-
spf: { result: spfAlignment, strict: dmarcRecord.aspf === 's' },
|
|
105
|
-
dkim: { result: dkimAlignment, strict: dmarcRecord.adkim === 's' }
|
|
104
|
+
spf: { result: spfAlignment?.domain, strict: dmarcRecord.aspf === 's' },
|
|
105
|
+
dkim: { result: dkimAlignment?.domain, strict: dmarcRecord.adkim === 's', overSized: dkimAlignment?.overSized }
|
|
106
106
|
}
|
|
107
107
|
});
|
|
108
108
|
};
|
package/lib/mailauth.js
CHANGED
|
@@ -119,7 +119,14 @@ const authenticate = async (input, opts) => {
|
|
|
119
119
|
dmarcResult = await dmarc({
|
|
120
120
|
headerFrom: dkimResult.headerFrom,
|
|
121
121
|
spfDomains: [].concat((spfResult && spfResult.status.result === 'pass' && spfResult.domain) || []),
|
|
122
|
-
dkimDomains: (dkimResult.results || [])
|
|
122
|
+
dkimDomains: (dkimResult.results || [])
|
|
123
|
+
.filter(r => r.status.result === 'pass')
|
|
124
|
+
.map(r => ({
|
|
125
|
+
id: r.id,
|
|
126
|
+
domain: r.signingDomain,
|
|
127
|
+
aligned: r.status.aligned,
|
|
128
|
+
overSized: r.status.overSized
|
|
129
|
+
})),
|
|
123
130
|
arcResult,
|
|
124
131
|
resolver: opts.resolver
|
|
125
132
|
});
|
package/lib/tools.js
CHANGED
|
@@ -398,6 +398,10 @@ const formatAuthHeaderRow = (method, status) => {
|
|
|
398
398
|
|
|
399
399
|
parts.push(`${method}=${status.result || 'none'}`);
|
|
400
400
|
|
|
401
|
+
if (status.overSized) {
|
|
402
|
+
parts.push(`(${escapeCommentValue(`oversized signature ${status.overSized}B`)})`);
|
|
403
|
+
}
|
|
404
|
+
|
|
401
405
|
if (status.comment) {
|
|
402
406
|
parts.push(`(${escapeCommentValue(status.comment)})`);
|
|
403
407
|
}
|
|
@@ -443,23 +447,32 @@ const formatDomain = domain => {
|
|
|
443
447
|
};
|
|
444
448
|
|
|
445
449
|
const getAlignment = (fromDomain, domainList, strict) => {
|
|
446
|
-
domainList = []
|
|
450
|
+
domainList = []
|
|
451
|
+
.concat(domainList || [])
|
|
452
|
+
.map(entry => {
|
|
453
|
+
if (typeof entry === 'string') {
|
|
454
|
+
return { domain: entry };
|
|
455
|
+
}
|
|
456
|
+
return entry;
|
|
457
|
+
})
|
|
458
|
+
.sort((a, b) => (a.overSized || 0) - (b.overSized || 0));
|
|
459
|
+
|
|
447
460
|
if (strict) {
|
|
448
461
|
fromDomain = formatDomain(fromDomain);
|
|
449
|
-
for (let
|
|
450
|
-
domain = formatDomain(psl.get(domain) || domain);
|
|
462
|
+
for (let entry of domainList) {
|
|
463
|
+
let domain = formatDomain(psl.get(entry.domain) || entry.domain);
|
|
451
464
|
if (formatDomain(domain) === fromDomain) {
|
|
452
|
-
return
|
|
465
|
+
return entry;
|
|
453
466
|
}
|
|
454
467
|
}
|
|
455
468
|
}
|
|
456
469
|
|
|
457
470
|
// match org domains
|
|
458
471
|
fromDomain = formatDomain(psl.get(fromDomain) || fromDomain);
|
|
459
|
-
for (let
|
|
460
|
-
domain = formatDomain(psl.get(domain) || domain);
|
|
472
|
+
for (let entry of domainList) {
|
|
473
|
+
let domain = formatDomain(psl.get(entry.domain) || entry.domain);
|
|
461
474
|
if (domain === fromDomain) {
|
|
462
|
-
return
|
|
475
|
+
return entry;
|
|
463
476
|
}
|
|
464
477
|
}
|
|
465
478
|
|
package/man/mailauth.1
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mailauth",
|
|
3
|
-
"version": "4.6.
|
|
3
|
+
"version": "4.6.2",
|
|
4
4
|
"description": "Email authentication library for Node.js",
|
|
5
5
|
"main": "lib/mailauth.js",
|
|
6
6
|
"scripts": {
|
|
@@ -33,28 +33,30 @@
|
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://github.com/postalsys/mailauth",
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"chai": "4.
|
|
37
|
-
"eslint": "8.
|
|
36
|
+
"chai": "4.4.1",
|
|
37
|
+
"eslint": "8.56.0",
|
|
38
38
|
"eslint-config-nodemailer": "1.2.0",
|
|
39
|
-
"eslint-config-prettier": "9.
|
|
39
|
+
"eslint-config-prettier": "9.1.0",
|
|
40
40
|
"js-yaml": "4.1.0",
|
|
41
41
|
"license-report": "6.5.0",
|
|
42
42
|
"marked": "0.7.0",
|
|
43
43
|
"marked-man": "0.7.0",
|
|
44
44
|
"mbox-reader": "1.1.5",
|
|
45
45
|
"mocha": "10.2.0",
|
|
46
|
+
"npm-check-updates": "16.14.12",
|
|
46
47
|
"pkg": "5.8.1"
|
|
47
48
|
},
|
|
48
49
|
"dependencies": {
|
|
49
50
|
"@postalsys/vmc": "1.0.6",
|
|
50
|
-
"fast-xml-parser": "4.3.
|
|
51
|
+
"fast-xml-parser": "4.3.3",
|
|
51
52
|
"ipaddr.js": "2.1.0",
|
|
52
|
-
"joi": "17.
|
|
53
|
+
"joi": "17.12.0",
|
|
53
54
|
"libmime": "5.2.1",
|
|
54
|
-
"nodemailer": "6.9.
|
|
55
|
+
"nodemailer": "6.9.8",
|
|
55
56
|
"psl": "1.9.0",
|
|
56
57
|
"punycode": "2.3.1",
|
|
57
|
-
"undici": "5.
|
|
58
|
+
"undici": "5.28.2",
|
|
59
|
+
"uuid": "9.0.1",
|
|
58
60
|
"yargs": "17.7.2"
|
|
59
61
|
},
|
|
60
62
|
"engines": {
|
package/.ncurc.json
DELETED