mailauth 4.0.1 → 4.0.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/lib/dkim/body/relaxed.js +1 -1
- package/lib/dkim/body/simple.js +13 -0
- package/lib/dkim/dkim-signer.js +6 -1
- package/lib/dkim/dkim-verifier.js +21 -1
- package/lib/dkim/header/relaxed.js +7 -10
- package/lib/dkim/header/simple.js +7 -10
- package/lib/parse-dkim-headers.js +1 -1
- package/lib/tools.js +26 -1
- package/licenses.txt +2 -2
- package/man/mailauth.1 +1 -1
- package/package.json +5 -5
package/lib/dkim/body/relaxed.js
CHANGED
package/lib/dkim/body/simple.js
CHANGED
|
@@ -21,12 +21,18 @@ class SimpleHash {
|
|
|
21
21
|
this.byteLength = 0;
|
|
22
22
|
|
|
23
23
|
this.bodyHashedBytes = 0;
|
|
24
|
+
|
|
24
25
|
this.maxBodyLength = maxBodyLength;
|
|
26
|
+
this.maxSizeReached = maxBodyLength === 0;
|
|
25
27
|
|
|
26
28
|
this.lastNewline = false;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
_updateBodyHash(chunk) {
|
|
32
|
+
if (this.maxSizeReached) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
30
36
|
// the following is needed for l= option
|
|
31
37
|
if (
|
|
32
38
|
typeof this.maxBodyLength === 'number' &&
|
|
@@ -34,10 +40,12 @@ class SimpleHash {
|
|
|
34
40
|
this.maxBodyLength >= 0 &&
|
|
35
41
|
this.bodyHashedBytes + chunk.length > this.maxBodyLength
|
|
36
42
|
) {
|
|
43
|
+
this.maxSizeReached = true;
|
|
37
44
|
if (this.bodyHashedBytes >= this.maxBodyLength) {
|
|
38
45
|
// nothing to do here, skip entire chunk
|
|
39
46
|
return;
|
|
40
47
|
}
|
|
48
|
+
|
|
41
49
|
// only use allowed size of bytes
|
|
42
50
|
chunk = chunk.slice(0, this.maxBodyLength - this.bodyHashedBytes);
|
|
43
51
|
}
|
|
@@ -49,6 +57,11 @@ class SimpleHash {
|
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
update(chunk) {
|
|
60
|
+
this.byteLength += (chunk && chunk.length) || 0;
|
|
61
|
+
if (this.maxSizeReached) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
52
65
|
if (this.remainder.length) {
|
|
53
66
|
// see if we can release the last remainder
|
|
54
67
|
for (let i = 0; i < chunk.length; i++) {
|
package/lib/dkim/dkim-signer.js
CHANGED
|
@@ -10,14 +10,16 @@ class DkimSigner extends MessageParser {
|
|
|
10
10
|
constructor(options) {
|
|
11
11
|
super();
|
|
12
12
|
|
|
13
|
-
let { canonicalization, algorithm, signTime, headerList, signatureData, arc, bodyHash, headers, getARChain } = options || {};
|
|
13
|
+
let { canonicalization, algorithm, signTime, headerList, signatureData, arc, bodyHash, headers, getARChain, expires } = options || {};
|
|
14
14
|
|
|
15
15
|
this.algorithm = algorithm || false;
|
|
16
16
|
this.canonicalization = canonicalization || 'relaxed/relaxed';
|
|
17
17
|
|
|
18
18
|
this.errors = [];
|
|
19
19
|
|
|
20
|
+
this.expires = expires;
|
|
20
21
|
this.signTime = signTime;
|
|
22
|
+
|
|
21
23
|
this.headerList = headerList;
|
|
22
24
|
|
|
23
25
|
this.signatureData = [].concat(signatureData || []).map(entry => {
|
|
@@ -243,7 +245,10 @@ class DkimSigner extends MessageParser {
|
|
|
243
245
|
instance: this.arc?.instance, // ARC only
|
|
244
246
|
algorithm,
|
|
245
247
|
canonicalization: this.getCanonicalization(signatureData).canonicalization,
|
|
248
|
+
|
|
246
249
|
signTime: this.signTime,
|
|
250
|
+
expires: this.expires,
|
|
251
|
+
|
|
247
252
|
bodyHash: this.bodyHashes.has(hashKey) ? this.bodyHashes.get(hashKey).hash : null
|
|
248
253
|
},
|
|
249
254
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { getSigningHeaderLines, getPublicKey, parseDkimHeaders, formatAuthHeaderRow, getAlignment } = require('../../lib/tools');
|
|
3
|
+
const { getSigningHeaderLines, getPublicKey, parseDkimHeaders, formatAuthHeaderRow, getAlignment, getCurTime } = require('../../lib/tools');
|
|
4
4
|
const { MessageParser } = require('./message-parser');
|
|
5
5
|
const { dkimBody } = require('./body');
|
|
6
6
|
const { generateCanonicalizedHeader } = require('./header');
|
|
@@ -16,6 +16,8 @@ class DkimVerifier extends MessageParser {
|
|
|
16
16
|
this.resolver = this.options.resolver;
|
|
17
17
|
this.minBitLength = this.options.minBitLength;
|
|
18
18
|
|
|
19
|
+
this.curTime = getCurTime(this.options.curTime);
|
|
20
|
+
|
|
19
21
|
this.results = [];
|
|
20
22
|
|
|
21
23
|
this.signatureHeaders = [];
|
|
@@ -114,6 +116,12 @@ class DkimVerifier extends MessageParser {
|
|
|
114
116
|
signatureHeader.signingDomain = signatureHeader.parsed?.d?.value || '';
|
|
115
117
|
signatureHeader.selector = signatureHeader.parsed?.s?.value || '';
|
|
116
118
|
|
|
119
|
+
signatureHeader.timestamp =
|
|
120
|
+
signatureHeader.parsed?.t && !isNaN(signatureHeader.parsed?.t?.value) ? new Date(signatureHeader.parsed?.t?.value * 1000) : null;
|
|
121
|
+
|
|
122
|
+
signatureHeader.expiration =
|
|
123
|
+
signatureHeader.parsed?.x && !isNaN(signatureHeader.parsed?.x?.value) ? new Date(signatureHeader.parsed?.x?.value * 1000) : null;
|
|
124
|
+
|
|
117
125
|
signatureHeader.maxBodyLength =
|
|
118
126
|
signatureHeader.parsed?.l?.value && !isNaN(signatureHeader.parsed?.l?.value) ? signatureHeader.parsed?.l?.value : '';
|
|
119
127
|
|
|
@@ -228,6 +236,18 @@ class DkimVerifier extends MessageParser {
|
|
|
228
236
|
if (status.result === 'fail') {
|
|
229
237
|
status.comment = 'bad signature';
|
|
230
238
|
}
|
|
239
|
+
|
|
240
|
+
if (status.result === 'pass') {
|
|
241
|
+
if (signatureHeader.expiration && signatureHeader.timestamp && signatureHeader.expiration < signatureHeader.timestamp) {
|
|
242
|
+
status.result = 'neutral';
|
|
243
|
+
status.comment = 'invalid expiration';
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (signatureHeader.expiration && signatureHeader.expiration < this.curTime) {
|
|
247
|
+
status.result = 'neutral';
|
|
248
|
+
status.comment = 'expired';
|
|
249
|
+
}
|
|
250
|
+
}
|
|
231
251
|
} catch (err) {
|
|
232
252
|
status.result = 'neutral';
|
|
233
253
|
status.comment = err.message;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { formatSignatureHeaderLine, formatRelaxedLine } = require('../../../lib/tools');
|
|
3
|
+
const { formatSignatureHeaderLine, formatRelaxedLine, getCurTime } = require('../../../lib/tools');
|
|
4
4
|
|
|
5
5
|
// generate headers for signing
|
|
6
6
|
const relaxedHeaders = (type, signingHeaderLines, options) => {
|
|
7
|
-
let { signatureHeaderLine, signingDomain, selector, algorithm, canonicalization, bodyHash, signTime, signature, instance, bodyHashedBytes } =
|
|
7
|
+
let { signatureHeaderLine, signingDomain, selector, algorithm, canonicalization, bodyHash, signTime, signature, instance, bodyHashedBytes, expires } =
|
|
8
|
+
options || {};
|
|
8
9
|
let chunks = [];
|
|
9
10
|
|
|
10
11
|
for (let signedHeaderLine of signingHeaderLines.headers) {
|
|
@@ -33,15 +34,11 @@ const relaxedHeaders = (type, signingHeaderLines, options) => {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
if (signTime) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
37
|
+
opts.t = Math.floor(getCurTime(signTime).getTime() / 1000);
|
|
38
|
+
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
signTime = Math.round(signTime.getTime() / 1000);
|
|
43
|
-
opts.t = signTime;
|
|
44
|
-
}
|
|
40
|
+
if (expires) {
|
|
41
|
+
opts.x = Math.floor(getCurTime(expires).getTime() / 1000);
|
|
45
42
|
}
|
|
46
43
|
|
|
47
44
|
signatureHeaderLine = formatSignatureHeaderLine(
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { formatSignatureHeaderLine } = require('../../../lib/tools');
|
|
3
|
+
const { formatSignatureHeaderLine, getCurTime } = require('../../../lib/tools');
|
|
4
4
|
|
|
5
5
|
const formatSimpleLine = (line, suffix) => Buffer.from(line.toString('binary') + (suffix ? suffix : ''), 'binary');
|
|
6
6
|
|
|
7
7
|
// generate headers for signing
|
|
8
8
|
const simpleHeaders = (type, signingHeaderLines, options) => {
|
|
9
|
-
let { signatureHeaderLine, signingDomain, selector, algorithm, canonicalization, bodyHash, signTime, signature, instance, bodyHashedBytes } =
|
|
9
|
+
let { signatureHeaderLine, signingDomain, selector, algorithm, canonicalization, bodyHash, signTime, signature, instance, bodyHashedBytes, expires } =
|
|
10
|
+
options || {};
|
|
10
11
|
let chunks = [];
|
|
11
12
|
|
|
12
13
|
for (let signedHeaderLine of signingHeaderLines.headers) {
|
|
@@ -35,15 +36,11 @@ const simpleHeaders = (type, signingHeaderLines, options) => {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
if (signTime) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
39
|
+
opts.t = Math.floor(getCurTime(signTime).getTime() / 1000);
|
|
40
|
+
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
signTime = Math.round(signTime.getTime() / 1000);
|
|
45
|
-
opts.t = signTime;
|
|
46
|
-
}
|
|
42
|
+
if (expires) {
|
|
43
|
+
opts.x = Math.floor(getCurTime(expires).getTime() / 1000);
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
signatureHeaderLine = formatSignatureHeaderLine(
|
|
@@ -245,7 +245,7 @@ const headerParser = buf => {
|
|
|
245
245
|
} else if (['bh', 'b', 'p', 'h'].includes(parts[i].key)) {
|
|
246
246
|
// remove unneeded whitespace
|
|
247
247
|
parts[i].value = parts[i].value.replace(/\s+/g, '');
|
|
248
|
-
} else if (['l', 'v', 't'].includes(parts[i].key) && !isNaN(parts[i].value)) {
|
|
248
|
+
} else if (['l', 'v', 't', 'x'].includes(parts[i].key) && !isNaN(parts[i].value)) {
|
|
249
249
|
parts[i].value = Number(parts[i].value);
|
|
250
250
|
} else if (parts[i].key === 'i' && /^arc-/i.test(headerKey)) {
|
|
251
251
|
parts[i].value = Number(parts[i].value);
|
package/lib/tools.js
CHANGED
|
@@ -485,6 +485,29 @@ const getPtrHostname = parsedAddr => {
|
|
|
485
485
|
}
|
|
486
486
|
};
|
|
487
487
|
|
|
488
|
+
function getCurTime(timeValue) {
|
|
489
|
+
if (timeValue) {
|
|
490
|
+
if (typeof timeValue === 'object' && typeof timeValue.toISOString === 'function') {
|
|
491
|
+
return timeValue;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (typeof timeValue === 'number' || !isNaN(timeValue)) {
|
|
495
|
+
let timestamp = Number(timeValue);
|
|
496
|
+
let curTime = new Date(timestamp);
|
|
497
|
+
if (curTime.toString !== 'Invalid Date') {
|
|
498
|
+
return curTime;
|
|
499
|
+
}
|
|
500
|
+
} else if (typeof timeValue === 'string') {
|
|
501
|
+
let curTime = new Date(timeValue);
|
|
502
|
+
if (curTime.toString !== 'Invalid Date') {
|
|
503
|
+
return curTime;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
return new Date();
|
|
509
|
+
}
|
|
510
|
+
|
|
488
511
|
module.exports = {
|
|
489
512
|
writeToStream,
|
|
490
513
|
parseHeaders,
|
|
@@ -508,5 +531,7 @@ module.exports = {
|
|
|
508
531
|
formatRelaxedLine,
|
|
509
532
|
formatDomain,
|
|
510
533
|
|
|
511
|
-
getPtrHostname
|
|
534
|
+
getPtrHostname,
|
|
535
|
+
|
|
536
|
+
getCurTime
|
|
512
537
|
};
|
package/licenses.txt
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
name license type link installed version author
|
|
2
2
|
---- ------------ ---- ----------------- ------
|
|
3
|
-
@postalsys/vmc MIT https://registry.npmjs.org/@postalsys/vmc/-/vmc-1.0.
|
|
3
|
+
@postalsys/vmc MIT https://registry.npmjs.org/@postalsys/vmc/-/vmc-1.0.6.tgz 1.0.6 Postal Systems OÜ
|
|
4
4
|
fast-xml-parser MIT git+https://github.com/NaturalIntelligence/fast-xml-parser.git 4.0.9 Amit Gupta (https://amitkumargupta.work/)
|
|
5
5
|
ipaddr.js MIT git://github.com/whitequark/ipaddr.js.git 2.0.1 whitequark <whitequark@whitequark.org>
|
|
6
6
|
joi BSD-3-Clause git://github.com/sideway/joi.git 17.6.0 n/a
|
|
7
7
|
libmime MIT git://github.com/andris9/libmime.git 5.1.0 Andris Reinman <andris@kreata.ee>
|
|
8
8
|
node-forge (BSD-3-Clause OR GPL-2.0) git+https://github.com/digitalbazaar/forge.git 1.3.1 Digital Bazaar, Inc. support@digitalbazaar.com http://digitalbazaar.com/
|
|
9
|
-
nodemailer MIT git+https://github.com/nodemailer/nodemailer.git 6.7.
|
|
9
|
+
nodemailer MIT git+https://github.com/nodemailer/nodemailer.git 6.7.8 Andris Reinman
|
|
10
10
|
psl MIT git+ssh://git@github.com/lupomontero/psl.git 1.9.0 Lupo Montero <lupomontero@gmail.com> (https://lupomontero.com/)
|
|
11
11
|
punycode MIT git+https://github.com/bestiejs/punycode.js.git 2.1.1 Mathias Bynens https://mathiasbynens.be/
|
|
12
12
|
yargs MIT git+https://github.com/yargs/yargs.git 17.5.1 n/a
|
package/man/mailauth.1
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mailauth",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.2",
|
|
4
4
|
"description": "Email authentication library for Node.js",
|
|
5
5
|
"main": "lib/mailauth.js",
|
|
6
6
|
"scripts": {
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"homepage": "https://github.com/postalsys/mailauth",
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"chai": "4.3.6",
|
|
36
|
-
"eslint": "8.
|
|
36
|
+
"eslint": "8.24.0",
|
|
37
37
|
"eslint-config-nodemailer": "1.2.0",
|
|
38
38
|
"eslint-config-prettier": "8.5.0",
|
|
39
39
|
"js-yaml": "4.1.0",
|
|
40
|
-
"license-report": "6.
|
|
40
|
+
"license-report": "6.1.0",
|
|
41
41
|
"marked": "0.7.0",
|
|
42
42
|
"marked-man": "0.7.0",
|
|
43
43
|
"mbox-reader": "1.1.5",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@postalsys/vmc": "1.0.6",
|
|
49
|
-
"fast-xml-parser": "4.0.
|
|
49
|
+
"fast-xml-parser": "4.0.10",
|
|
50
50
|
"ipaddr.js": "2.0.1",
|
|
51
|
-
"joi": "17.6.
|
|
51
|
+
"joi": "17.6.1",
|
|
52
52
|
"libmime": "5.1.0",
|
|
53
53
|
"node-forge": "1.3.1",
|
|
54
54
|
"nodemailer": "6.7.8",
|