mailauth 4.0.0 → 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/bin/mailauth.js +6 -0
- package/lib/arc/index.js +0 -1
- package/lib/bimi/index.js +3 -2
- package/lib/commands/report.js +14 -1
- package/lib/commands/seal.js +14 -1
- package/lib/commands/spf.js +7 -19
- package/lib/commands/vmc.js +14 -1
- 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 +22 -2
- 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 +5 -2
- package/package.json +7 -7
package/bin/mailauth.js
CHANGED
|
@@ -324,6 +324,12 @@ const argv = yargs(hideBin(process.argv))
|
|
|
324
324
|
type: 'string',
|
|
325
325
|
description: 'Sending domain to validate',
|
|
326
326
|
demandOption: false
|
|
327
|
+
})
|
|
328
|
+
.option('date', {
|
|
329
|
+
alias: 't',
|
|
330
|
+
type: 'string',
|
|
331
|
+
description: 'ISO formatted timestamp for the certificate expiration checks',
|
|
332
|
+
demandOption: false
|
|
327
333
|
});
|
|
328
334
|
},
|
|
329
335
|
argv => {
|
package/lib/arc/index.js
CHANGED
|
@@ -351,7 +351,6 @@ const arc = async (data, opts) => {
|
|
|
351
351
|
if (result.authenticationResults.dkim && result.authenticationResults.dkim.length) {
|
|
352
352
|
result.authenticationResults.dkim = result.authenticationResults.dkim.map(entry => {
|
|
353
353
|
let result = entry.value;
|
|
354
|
-
|
|
355
354
|
delete entry.value;
|
|
356
355
|
return Object.assign({ result }, entry);
|
|
357
356
|
});
|
package/lib/bimi/index.js
CHANGED
|
@@ -240,7 +240,8 @@ const downloadPromise = (url, cachedFile) => {
|
|
|
240
240
|
});
|
|
241
241
|
};
|
|
242
242
|
|
|
243
|
-
const validateVMC = async bimiData => {
|
|
243
|
+
const validateVMC = async (bimiData, opts) => {
|
|
244
|
+
opts = opts || {};
|
|
244
245
|
if (!bimiData) {
|
|
245
246
|
return false;
|
|
246
247
|
}
|
|
@@ -302,7 +303,7 @@ const validateVMC = async bimiData => {
|
|
|
302
303
|
|
|
303
304
|
if (authorityValue) {
|
|
304
305
|
try {
|
|
305
|
-
let vmcData = await vmc(authorityValue);
|
|
306
|
+
let vmcData = await vmc(authorityValue, opts);
|
|
306
307
|
|
|
307
308
|
if (!vmcData.logoFile) {
|
|
308
309
|
let error = new Error('VMC does not contain a log file');
|
package/lib/commands/report.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { authenticate } = require('../mailauth');
|
|
4
4
|
const fs = require('fs');
|
|
5
|
+
const { resolve } = require('dns').promises;
|
|
5
6
|
|
|
6
7
|
const cmd = async argv => {
|
|
7
8
|
let source = argv.email;
|
|
@@ -52,7 +53,7 @@ const cmd = async argv => {
|
|
|
52
53
|
let match = dnsCache?.[name]?.[rr];
|
|
53
54
|
|
|
54
55
|
if (argv.verbose) {
|
|
55
|
-
console.error(`DNS query for ${rr} ${name}: ${match ? JSON.stringify(match) : 'not found'}`);
|
|
56
|
+
console.error(`DNS query for ${rr} ${name}: ${match ? JSON.stringify(match) : 'not found'} (using cache)`);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
if (!match) {
|
|
@@ -63,6 +64,18 @@ const cmd = async argv => {
|
|
|
63
64
|
|
|
64
65
|
return match;
|
|
65
66
|
};
|
|
67
|
+
} else if (argv.verbose) {
|
|
68
|
+
opts.resolver = async (name, rr) => {
|
|
69
|
+
let match;
|
|
70
|
+
try {
|
|
71
|
+
match = await resolve(name, rr);
|
|
72
|
+
console.error(`DNS query for ${rr} ${name}: ${match ? JSON.stringify(match) : 'not found'}`);
|
|
73
|
+
return match;
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error(`DNS query for ${rr} ${name}: ${err.message}${err.code ? ` [${err.code}]` : ''}`);
|
|
76
|
+
throw err;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
66
79
|
}
|
|
67
80
|
|
|
68
81
|
let result = await authenticate(stream, opts);
|
package/lib/commands/seal.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const { authenticate } = require('../mailauth');
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const { GathererStream } = require('../gatherer-stream');
|
|
6
|
+
const { resolve } = require('dns').promises;
|
|
6
7
|
|
|
7
8
|
const cmd = async argv => {
|
|
8
9
|
let source = argv.email;
|
|
@@ -82,7 +83,7 @@ const cmd = async argv => {
|
|
|
82
83
|
let match = dnsCache?.[name]?.[rr];
|
|
83
84
|
|
|
84
85
|
if (argv.verbose) {
|
|
85
|
-
console.error(`DNS query for ${rr} ${name}: ${match ? JSON.stringify(match) : 'not found'}`);
|
|
86
|
+
console.error(`DNS query for ${rr} ${name}: ${match ? JSON.stringify(match) : 'not found'} (using cache)`);
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
if (!match) {
|
|
@@ -93,6 +94,18 @@ const cmd = async argv => {
|
|
|
93
94
|
|
|
94
95
|
return match;
|
|
95
96
|
};
|
|
97
|
+
} else if (argv.verbose) {
|
|
98
|
+
opts.resolver = async (name, rr) => {
|
|
99
|
+
let match;
|
|
100
|
+
try {
|
|
101
|
+
match = await resolve(name, rr);
|
|
102
|
+
console.error(`DNS query for ${rr} ${name}: ${match ? JSON.stringify(match) : 'not found'}`);
|
|
103
|
+
return match;
|
|
104
|
+
} catch (err) {
|
|
105
|
+
console.error(`DNS query for ${rr} ${name}: ${err.message}${err.code ? ` [${err.code}]` : ''}`);
|
|
106
|
+
throw err;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
96
109
|
}
|
|
97
110
|
|
|
98
111
|
let result = await authenticate(gatherer, opts);
|
package/lib/commands/spf.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { spf } = require('../spf');
|
|
4
4
|
const fs = require('fs');
|
|
5
|
-
const
|
|
5
|
+
const { resolve } = require('dns').promises;
|
|
6
6
|
|
|
7
7
|
const cmd = async argv => {
|
|
8
8
|
let address = argv.sender;
|
|
@@ -45,7 +45,7 @@ const cmd = async argv => {
|
|
|
45
45
|
let match = dnsCache?.[name]?.[rr];
|
|
46
46
|
|
|
47
47
|
if (argv.verbose) {
|
|
48
|
-
console.error(`DNS query for ${rr} ${name}: ${match ? JSON.stringify(match) : 'not found'}`);
|
|
48
|
+
console.error(`DNS query for ${rr} ${name}: ${match ? JSON.stringify(match) : 'not found'} (using cache)`);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
if (!match) {
|
|
@@ -56,29 +56,17 @@ const cmd = async argv => {
|
|
|
56
56
|
|
|
57
57
|
return match;
|
|
58
58
|
};
|
|
59
|
-
} else {
|
|
59
|
+
} else if (argv.verbose) {
|
|
60
60
|
opts.resolver = async (name, rr) => {
|
|
61
61
|
let match;
|
|
62
62
|
try {
|
|
63
|
-
match = await
|
|
64
|
-
} catch (err) {
|
|
65
|
-
if (argv.verbose) {
|
|
66
|
-
console.error(`DNS query for ${rr} ${name}: ${err.code || err.message}`);
|
|
67
|
-
}
|
|
68
|
-
throw err;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (argv.verbose) {
|
|
63
|
+
match = await resolve(name, rr);
|
|
72
64
|
console.error(`DNS query for ${rr} ${name}: ${match ? JSON.stringify(match) : 'not found'}`);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
let err = new Error('Error');
|
|
77
|
-
err.code = 'ENOTFOUND';
|
|
65
|
+
return match;
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error(`DNS query for ${rr} ${name}: ${err.message}${err.code ? ` [${err.code}]` : ''}`);
|
|
78
68
|
throw err;
|
|
79
69
|
}
|
|
80
|
-
|
|
81
|
-
return match;
|
|
82
70
|
};
|
|
83
71
|
}
|
|
84
72
|
|
package/lib/commands/vmc.js
CHANGED
|
@@ -18,7 +18,20 @@ const cmd = async argv => {
|
|
|
18
18
|
bimiData.status = { header: { d: argv.domain } };
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
let opts = {};
|
|
22
|
+
if (argv.date) {
|
|
23
|
+
let date = new Date(argv.date);
|
|
24
|
+
if (date.toString() !== 'Invalid Date') {
|
|
25
|
+
opts.now = date;
|
|
26
|
+
if (argv.verbose) {
|
|
27
|
+
console.error(`Setting date to: ${argv.date}`);
|
|
28
|
+
}
|
|
29
|
+
} else if (argv.verbose) {
|
|
30
|
+
console.error(`Invalid date argument: ${argv.date}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const result = await validateVMC(bimiData, opts);
|
|
22
35
|
process.stdout.write(JSON.stringify(result.authority, false, 2) + '\n');
|
|
23
36
|
};
|
|
24
37
|
|
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
|
|
|
@@ -225,9 +233,21 @@ class DkimVerifier extends MessageParser {
|
|
|
225
233
|
? 'pass'
|
|
226
234
|
: 'fail';
|
|
227
235
|
|
|
228
|
-
if (status === 'fail') {
|
|
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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.TH "MAILAUTH" "1" "
|
|
1
|
+
.TH "MAILAUTH" "1" "September 2022" "v4.0.1" "Mailauth Help"
|
|
2
2
|
.SH "NAME"
|
|
3
3
|
\fBmailauth\fR
|
|
4
4
|
.QP
|
|
@@ -107,7 +107,10 @@ Colon separated list of header field names to sign\. (\fBsign\fP, \fBseal\fP)
|
|
|
107
107
|
Return signing headers only\. By default, the entire message is printed to the console\. (\fBsign\fP, \fBseal\fP, \fBspf\fP)
|
|
108
108
|
.IP \(bu 2
|
|
109
109
|
\fB\-\-max\-lookups\fP, \fB\-x\fP
|
|
110
|
-
How many DNS lookups allowed for SPF validation\. Defaults to
|
|
110
|
+
How many DNS lookups allowed for SPF validation\. Defaults to 10\. (\fBreport\fP, \fBspf\fP)
|
|
111
|
+
.IP \(bu 2
|
|
112
|
+
\fB\-\-max\-void\-lookups\fP, \fB\-z\fP
|
|
113
|
+
How many empty DNS lookups allowed for SPF validation\. Defaults to 2\. (\fBreport\fP, \fBspf\fP)
|
|
111
114
|
|
|
112
115
|
.RE
|
|
113
116
|
.SH DNS CACHE
|
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",
|
|
@@ -45,13 +45,13 @@
|
|
|
45
45
|
"pkg": "5.8.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@postalsys/vmc": "1.0.
|
|
49
|
-
"fast-xml-parser": "4.0.
|
|
48
|
+
"@postalsys/vmc": "1.0.6",
|
|
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
|
-
"nodemailer": "6.7.
|
|
54
|
+
"nodemailer": "6.7.8",
|
|
55
55
|
"psl": "1.9.0",
|
|
56
56
|
"punycode": "2.1.1",
|
|
57
57
|
"yargs": "17.5.1"
|