mailauth 4.4.2 → 4.5.1
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 +51 -0
- package/cli.md +30 -0
- package/lib/bimi/index.js +22 -73
- package/lib/commands/bodyhash.js +66 -0
- package/lib/commands/sign.js +3 -3
- package/lib/dkim/body/index.js +5 -2
- package/lib/dkim/dkim-signer.js +6 -2
- package/lib/dkim/header/index.js +5 -2
- package/lib/tools.js +6 -2
- package/licenses.txt +2 -2
- package/man/mailauth.1 +1 -1
- package/package.json +8 -7
package/bin/mailauth.js
CHANGED
|
@@ -12,6 +12,7 @@ const commandSign = require('../lib/commands/sign');
|
|
|
12
12
|
const commandSeal = require('../lib/commands/seal');
|
|
13
13
|
const commandSpf = require('../lib/commands/spf');
|
|
14
14
|
const commandVmc = require('../lib/commands/vmc');
|
|
15
|
+
const commandBodyhash = require('../lib/commands/bodyhash');
|
|
15
16
|
|
|
16
17
|
const fs = require('fs');
|
|
17
18
|
const pathlib = require('path');
|
|
@@ -100,6 +101,12 @@ const argv = yargs(hideBin(process.argv))
|
|
|
100
101
|
description: 'Key selector for signing (s= tag)',
|
|
101
102
|
demandOption: true
|
|
102
103
|
})
|
|
104
|
+
.option('algo', {
|
|
105
|
+
alias: 'a',
|
|
106
|
+
type: 'string',
|
|
107
|
+
description: 'Signing algorithm. Defaults either to rsa-sha256 or ed25519-sha256 depending on the private key format.',
|
|
108
|
+
default: 'rsa-sha256'
|
|
109
|
+
})
|
|
103
110
|
.option('canonicalization', {
|
|
104
111
|
alias: 'c',
|
|
105
112
|
type: 'string',
|
|
@@ -344,6 +351,50 @@ const argv = yargs(hideBin(process.argv))
|
|
|
344
351
|
});
|
|
345
352
|
}
|
|
346
353
|
)
|
|
354
|
+
.command(
|
|
355
|
+
['bodyhash [email]'],
|
|
356
|
+
'Generate a signature body hash for an email',
|
|
357
|
+
yargs => {
|
|
358
|
+
yargs
|
|
359
|
+
|
|
360
|
+
.option('algo', {
|
|
361
|
+
alias: 'a',
|
|
362
|
+
type: 'string',
|
|
363
|
+
description: 'Hashing algorithm. Defaults to sha256.',
|
|
364
|
+
default: 'sha256'
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
.option('canonicalization', {
|
|
368
|
+
alias: 'c',
|
|
369
|
+
type: 'string',
|
|
370
|
+
description: 'Canonicalization algorithm (c= tag)',
|
|
371
|
+
default: 'relaxed'
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
.option('body-length', {
|
|
375
|
+
alias: 'l',
|
|
376
|
+
type: 'number',
|
|
377
|
+
description: 'Maximum length of canonicalizated body to sign (l= tag)'
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
yargs.positional('email', {
|
|
381
|
+
describe: 'Path to the email message file in EML format. If not specified then content is read from stdin'
|
|
382
|
+
});
|
|
383
|
+
},
|
|
384
|
+
argv => {
|
|
385
|
+
commandBodyhash(argv)
|
|
386
|
+
.then(() => {
|
|
387
|
+
process.exit();
|
|
388
|
+
})
|
|
389
|
+
.catch(err => {
|
|
390
|
+
if (!err.suppress) {
|
|
391
|
+
console.error('Failed to calculate body hash for the input message');
|
|
392
|
+
console.error(err);
|
|
393
|
+
}
|
|
394
|
+
process.exit(1);
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
)
|
|
347
398
|
.command(
|
|
348
399
|
['license'],
|
|
349
400
|
'Show license information',
|
package/cli.md
CHANGED
|
@@ -14,6 +14,7 @@ Command line utility and a [Node.js library](README.md) for email authentication
|
|
|
14
14
|
- [seal](#seal) - to seal an email with ARC
|
|
15
15
|
- [spf](#spf) - to validate SPF for an IP address and an email address
|
|
16
16
|
- [vmc](#vmc) - to validate BIMI VMC logo files
|
|
17
|
+
- [bodyhash](#bodyhash) - to generate the signature body hash value for an email
|
|
17
18
|
- [license](#license) - display licenses for `mailauth` and included modules
|
|
18
19
|
- [DNS cache file](#dns-cache-file)
|
|
19
20
|
|
|
@@ -320,6 +321,35 @@ $ mailauth vmc -p /path/to/vmc-with-invalid-svg.pem
|
|
|
320
321
|
}
|
|
321
322
|
```
|
|
322
323
|
|
|
324
|
+
### bodyhash
|
|
325
|
+
|
|
326
|
+
`bodyhash` command takes an email message and calculates the body hash value for it
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
$ mailauth bodyhash [options] [email]
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Where
|
|
333
|
+
|
|
334
|
+
- **options** are option flags and arguments
|
|
335
|
+
- **email** is the path to EML formatted email message file. If not provided then email message is read from standard input
|
|
336
|
+
|
|
337
|
+
**Options**
|
|
338
|
+
|
|
339
|
+
- `--algo sha256` or `-a sha256` is the signing algorithm. Defaults to "sha256". Can also use the a= tag format ("rsa-sha256").
|
|
340
|
+
- `--canonicalization algo` or `-c algo` is the body canonicalization algorithm, defaults to "relaxed". Can also use the c= tag format ("relaxed/relaxed").
|
|
341
|
+
- `--body-length 12345` or `-l 12345` is the maximum length of canonicalizated body to sign (l= tag)
|
|
342
|
+
|
|
343
|
+
**Example**
|
|
344
|
+
|
|
345
|
+
```
|
|
346
|
+
$ mailauth bodyhash /path/message.eml -a sha1 --verbose
|
|
347
|
+
Hashing algorithm: sha1
|
|
348
|
+
Body canonicalization algorithm: relaxed
|
|
349
|
+
--------
|
|
350
|
+
j+dD7whKXS1yDmyoWtvClYSyYiQ=
|
|
351
|
+
```
|
|
352
|
+
|
|
323
353
|
### license
|
|
324
354
|
|
|
325
355
|
Display licenses for `mailauth` and included modules.
|
package/lib/bimi/index.js
CHANGED
|
@@ -4,18 +4,19 @@ const crypto = require('crypto');
|
|
|
4
4
|
const dns = require('dns');
|
|
5
5
|
const { formatAuthHeaderRow, parseDkimHeaders, formatDomain, getAlignment } = require('../tools');
|
|
6
6
|
const Joi = require('joi');
|
|
7
|
-
const packageData = require('../../package.json');
|
|
7
|
+
//const packageData = require('../../package.json');
|
|
8
8
|
const httpsSchema = Joi.string().uri({
|
|
9
9
|
scheme: ['https']
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
|
|
12
|
+
const FETCH_TIMEOUT = 5 * 1000;
|
|
13
|
+
|
|
14
|
+
const { fetch: fetchCmd, Agent } = require('undici');
|
|
15
|
+
const fetchAgent = new Agent({ connect: { timeout: FETCH_TIMEOUT } });
|
|
16
|
+
|
|
14
17
|
const { vmc } = require('@postalsys/vmc');
|
|
15
18
|
const { validateSvg } = require('./validate-svg');
|
|
16
19
|
|
|
17
|
-
const HTTP_REQUEST_TIMEOUT = 15 * 1000;
|
|
18
|
-
|
|
19
20
|
const lookup = async data => {
|
|
20
21
|
let { dmarc, headers, resolver, bimiWithAlignedDkim } = data;
|
|
21
22
|
let headerRows = (headers && headers.parsed) || [];
|
|
@@ -177,7 +178,7 @@ const lookup = async data => {
|
|
|
177
178
|
return response;
|
|
178
179
|
};
|
|
179
180
|
|
|
180
|
-
const downloadPromise = (url, cachedFile) => {
|
|
181
|
+
const downloadPromise = async (url, cachedFile) => {
|
|
181
182
|
if (cachedFile) {
|
|
182
183
|
return cachedFile;
|
|
183
184
|
}
|
|
@@ -186,76 +187,24 @@ const downloadPromise = (url, cachedFile) => {
|
|
|
186
187
|
return false;
|
|
187
188
|
}
|
|
188
189
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const options = {
|
|
192
|
-
protocol: parsedUrl.protocol,
|
|
193
|
-
host: parsedUrl.host,
|
|
190
|
+
let res = await fetchCmd(url, {
|
|
194
191
|
headers: {
|
|
195
|
-
|
|
196
|
-
'User-Agent': `mailauth/${packageData.version} (+${packageData.homepage}`
|
|
192
|
+
// Comment: AKAMAI does some strange UA based filtering that messes up the request
|
|
193
|
+
// 'User-Agent': `mailauth/${packageData.version} (+${packageData.homepage}`
|
|
197
194
|
},
|
|
198
|
-
|
|
199
|
-
port: 443,
|
|
200
|
-
path: parsedUrl.pathname,
|
|
201
|
-
method: 'GET',
|
|
202
|
-
rejectUnauthorized: true,
|
|
203
|
-
|
|
204
|
-
timeout: HTTP_REQUEST_TIMEOUT
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
return new Promise((resolve, reject) => {
|
|
208
|
-
let protoHandler;
|
|
209
|
-
switch (parsedUrl.protocol) {
|
|
210
|
-
case 'https:':
|
|
211
|
-
protoHandler = https;
|
|
212
|
-
break;
|
|
213
|
-
case 'http:':
|
|
214
|
-
protoHandler = http;
|
|
215
|
-
break;
|
|
216
|
-
default:
|
|
217
|
-
reject(new Error(`Unknown protocol ${parsedUrl.protocol}`));
|
|
218
|
-
}
|
|
219
|
-
const req = protoHandler.request(options, res => {
|
|
220
|
-
let chunks = [],
|
|
221
|
-
chunklen = 0;
|
|
222
|
-
res.on('readable', () => {
|
|
223
|
-
let chunk;
|
|
224
|
-
while ((chunk = res.read()) !== null) {
|
|
225
|
-
chunks.push(chunk);
|
|
226
|
-
chunklen += chunk.length;
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
res.on('end', () => {
|
|
230
|
-
let data = Buffer.concat(chunks, chunklen);
|
|
231
|
-
if (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {
|
|
232
|
-
let err = new Error(`Invalid response code ${res.statusCode || '-'}`);
|
|
233
|
-
err.code = 'http_status_' + (res.statusCode || 'na');
|
|
234
|
-
if (res.headers.location && res.statusCode >= 300 && res.statusCode < 400) {
|
|
235
|
-
err.redirect = {
|
|
236
|
-
code: res.statusCode,
|
|
237
|
-
location: res.headers.location
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
return reject(err);
|
|
241
|
-
}
|
|
242
|
-
resolve(data);
|
|
243
|
-
});
|
|
244
|
-
res.on('error', err => reject(err));
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
req.on('timeout', () => {
|
|
248
|
-
req.destroy(); // cancel request
|
|
249
|
-
let error = new Error(`Request timeout for ${parsedUrl.href}`);
|
|
250
|
-
error.code = 'HTTP_SOCKET_TIMEOUT';
|
|
251
|
-
reject(error);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
req.on('error', err => {
|
|
255
|
-
reject(err);
|
|
256
|
-
});
|
|
257
|
-
req.end();
|
|
195
|
+
dispatcher: fetchAgent
|
|
258
196
|
});
|
|
197
|
+
|
|
198
|
+
if (!res.ok) {
|
|
199
|
+
let error = new Error(`Request failed with status ${res.status}`);
|
|
200
|
+
error.code = 'HTTP_REQUEST_FAILED';
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
let ab = await res.arrayBuffer();
|
|
205
|
+
process.stdout.write(Buffer.from(ab));
|
|
206
|
+
|
|
207
|
+
return Buffer.from(ab);
|
|
259
208
|
};
|
|
260
209
|
|
|
261
210
|
const validateVMC = async (bimiData, opts) => {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { DkimSigner } = require('../dkim/dkim-signer');
|
|
4
|
+
const { writeToStream } = require('../tools');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
|
|
7
|
+
const cmd = async argv => {
|
|
8
|
+
let source = argv.email;
|
|
9
|
+
let useStdin = false;
|
|
10
|
+
let stream;
|
|
11
|
+
|
|
12
|
+
if (!source) {
|
|
13
|
+
useStdin = true;
|
|
14
|
+
source = 'standard input';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (argv.verbose) {
|
|
18
|
+
console.error(`Reading email message from ${source}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (useStdin) {
|
|
22
|
+
stream = process.stdin;
|
|
23
|
+
} else {
|
|
24
|
+
stream = fs.createReadStream(source);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (isNaN(argv.bodyLength) || argv.bodyLength < 0) {
|
|
28
|
+
argv.bodyLength = null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let signatureOpts = {
|
|
32
|
+
type: 'DKIM',
|
|
33
|
+
privateKey: true, // force hash calculation
|
|
34
|
+
canonicalization: argv.canonicalization && (argv.canonicalization.includes('/') ? argv.canonicalization : `/${argv.canonicalization}`),
|
|
35
|
+
algorithm: argv.algo,
|
|
36
|
+
maxBodyLength: argv.bodyLength
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
let dkimSigner = new DkimSigner({ signatureData: [signatureOpts] });
|
|
40
|
+
|
|
41
|
+
let { hashAlgo } = dkimSigner.getAlgorithm(signatureOpts);
|
|
42
|
+
let { bodyCanon } = dkimSigner.getCanonicalization(signatureOpts);
|
|
43
|
+
|
|
44
|
+
if (argv.verbose) {
|
|
45
|
+
if (hashAlgo) {
|
|
46
|
+
console.error(`Hashing algorithm: ${hashAlgo}`);
|
|
47
|
+
}
|
|
48
|
+
if (bodyCanon) {
|
|
49
|
+
console.error(`Body canonicalization algorithm: ${bodyCanon}`);
|
|
50
|
+
}
|
|
51
|
+
if (signatureOpts.maxBodyLength) {
|
|
52
|
+
console.error(`Maximum body length: ${signatureOpts.maxBodyLength}`);
|
|
53
|
+
}
|
|
54
|
+
console.error('--------');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
await writeToStream(dkimSigner, stream);
|
|
58
|
+
|
|
59
|
+
let hashKey = `${bodyCanon}:${hashAlgo}:${typeof argv.bodyLength === 'number' ? argv.bodyLength : ''}`;
|
|
60
|
+
const bodyHash = dkimSigner.bodyHashes.get(hashKey)?.hash;
|
|
61
|
+
if (bodyHash) {
|
|
62
|
+
process.stdout.write(bodyHash);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
module.exports = cmd;
|
package/lib/commands/sign.js
CHANGED
|
@@ -48,12 +48,12 @@ const cmd = async argv => {
|
|
|
48
48
|
if (signatureOpts.selector) {
|
|
49
49
|
console.error(`Key selector: ${signatureOpts.selector}`);
|
|
50
50
|
}
|
|
51
|
-
if (signatureOpts.canonicalization) {
|
|
52
|
-
console.error(`Canonicalization algorithm: ${signatureOpts.canonicalization}`);
|
|
53
|
-
}
|
|
54
51
|
if (signatureOpts.algorithm) {
|
|
55
52
|
console.error(`Hashing algorithm: ${signatureOpts.algorithm}`);
|
|
56
53
|
}
|
|
54
|
+
if (signatureOpts.canonicalization) {
|
|
55
|
+
console.error(`Canonicalization algorithm: ${signatureOpts.canonicalization}`);
|
|
56
|
+
}
|
|
57
57
|
if (signatureOpts.maxBodyLength) {
|
|
58
58
|
console.error(`Maximum body length: ${signatureOpts.maxBodyLength}`);
|
|
59
59
|
}
|
package/lib/dkim/body/index.js
CHANGED
|
@@ -10,8 +10,11 @@ const dkimBody = (canonicalization, ...options) => {
|
|
|
10
10
|
return new SimpleHash(...options);
|
|
11
11
|
case 'relaxed':
|
|
12
12
|
return new RelaxedHash(...options);
|
|
13
|
-
default:
|
|
14
|
-
|
|
13
|
+
default: {
|
|
14
|
+
let error = new Error('Unknown body canonicalization');
|
|
15
|
+
error.canonicalization = canonicalization;
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
15
18
|
}
|
|
16
19
|
};
|
|
17
20
|
|
package/lib/dkim/dkim-signer.js
CHANGED
|
@@ -96,11 +96,15 @@ class DkimSigner extends MessageParser {
|
|
|
96
96
|
let [header, body] = canonicalization.split('/');
|
|
97
97
|
|
|
98
98
|
if (!['relaxed', 'simple'].includes(header)) {
|
|
99
|
-
|
|
99
|
+
let error = new Error('Unknown header canonicalization');
|
|
100
|
+
error.canonicalization = header;
|
|
101
|
+
throw error;
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
if (!['relaxed', 'simple'].includes(body)) {
|
|
103
|
-
|
|
105
|
+
let error = new Error('Unknown body canonicalization');
|
|
106
|
+
error.canonicalization = body;
|
|
107
|
+
throw error;
|
|
104
108
|
}
|
|
105
109
|
} catch (err) {
|
|
106
110
|
err.code = 'EINVALIDCANON';
|
package/lib/dkim/header/index.js
CHANGED
|
@@ -11,8 +11,11 @@ const generateCanonicalizedHeader = (type, signingHeaderLines, options) => {
|
|
|
11
11
|
return simpleHeaders(type, signingHeaderLines, options);
|
|
12
12
|
case 'relaxed':
|
|
13
13
|
return relaxedHeaders(type, signingHeaderLines, options);
|
|
14
|
-
default:
|
|
15
|
-
|
|
14
|
+
default: {
|
|
15
|
+
let error = new Error('Unknown header canonicalization');
|
|
16
|
+
error.canonicalization = canonicalization;
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
16
19
|
}
|
|
17
20
|
};
|
|
18
21
|
|
package/lib/tools.js
CHANGED
|
@@ -450,11 +450,15 @@ const validateAlgorithm = (algorithm, strict) => {
|
|
|
450
450
|
let [signAlgo, hashAlgo] = algorithm.toLowerCase().split('-');
|
|
451
451
|
|
|
452
452
|
if (!['rsa', 'ed25519'].includes(signAlgo)) {
|
|
453
|
-
|
|
453
|
+
let error = new Error('Unknown signing algorithm');
|
|
454
|
+
error.signAlgo = signAlgo;
|
|
455
|
+
throw error;
|
|
454
456
|
}
|
|
455
457
|
|
|
456
458
|
if (!['sha256'].concat(!strict ? 'sha1' : []).includes(hashAlgo)) {
|
|
457
|
-
|
|
459
|
+
let error = new Error('Unknown hashing algorithm');
|
|
460
|
+
error.hashAlgo = hashAlgo;
|
|
461
|
+
throw error;
|
|
458
462
|
}
|
|
459
463
|
} catch (err) {
|
|
460
464
|
err.code = 'EINVALIDALGO';
|
package/licenses.txt
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
name license type link installed version author
|
|
2
2
|
---- ------------ ---- ----------------- ------
|
|
3
3
|
@postalsys/vmc MIT https://registry.npmjs.org/@postalsys/vmc/-/vmc-1.0.6.tgz 1.0.6 Postal Systems OÜ
|
|
4
|
-
fast-xml-parser MIT git+https://github.com/NaturalIntelligence/fast-xml-parser.git 4.2.
|
|
4
|
+
fast-xml-parser MIT git+https://github.com/NaturalIntelligence/fast-xml-parser.git 4.2.7 Amit Gupta (https://amitguptagwl.github.io)
|
|
5
5
|
ipaddr.js MIT git://github.com/whitequark/ipaddr.js.git 2.1.0 whitequark <whitequark@whitequark.org>
|
|
6
6
|
joi BSD-3-Clause git://github.com/hapijs/joi.git 17.9.2 n/a
|
|
7
7
|
libmime MIT git://github.com/andris9/libmime.git 5.2.1 Andris Reinman <andris@kreata.ee>
|
|
8
|
-
nodemailer MIT-0 git+https://github.com/nodemailer/nodemailer.git 6.9.
|
|
8
|
+
nodemailer MIT-0 git+https://github.com/nodemailer/nodemailer.git 6.9.4 Andris Reinman
|
|
9
9
|
psl MIT git+ssh://git@github.com/lupomontero/psl.git 1.9.0 Lupo Montero <lupomontero@gmail.com> (https://lupomontero.com/)
|
|
10
10
|
punycode MIT git+https://github.com/mathiasbynens/punycode.js.git 2.3.0 Mathias Bynens https://mathiasbynens.be/
|
|
11
11
|
yargs MIT git+https://github.com/yargs/yargs.git 17.7.2 n/a
|
package/man/mailauth.1
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mailauth",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.1",
|
|
4
4
|
"description": "Email authentication library for Node.js",
|
|
5
5
|
"main": "lib/mailauth.js",
|
|
6
6
|
"scripts": {
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
"homepage": "https://github.com/postalsys/mailauth",
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"chai": "4.3.7",
|
|
36
|
-
"eslint": "8.
|
|
36
|
+
"eslint": "8.46.0",
|
|
37
37
|
"eslint-config-nodemailer": "1.2.0",
|
|
38
|
-
"eslint-config-prettier": "8.
|
|
38
|
+
"eslint-config-prettier": "8.10.0",
|
|
39
39
|
"js-yaml": "4.1.0",
|
|
40
40
|
"license-report": "6.4.0",
|
|
41
41
|
"marked": "0.7.0",
|
|
@@ -46,13 +46,14 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@postalsys/vmc": "1.0.6",
|
|
49
|
-
"fast-xml-parser": "4.2.
|
|
49
|
+
"fast-xml-parser": "4.2.7",
|
|
50
50
|
"ipaddr.js": "2.1.0",
|
|
51
51
|
"joi": "17.9.2",
|
|
52
52
|
"libmime": "5.2.1",
|
|
53
53
|
"nodemailer": "6.9.4",
|
|
54
54
|
"psl": "1.9.0",
|
|
55
55
|
"punycode": "2.3.0",
|
|
56
|
+
"undici": "5.23.0",
|
|
56
57
|
"yargs": "17.7.2"
|
|
57
58
|
},
|
|
58
59
|
"engines": {
|
|
@@ -71,10 +72,10 @@
|
|
|
71
72
|
"LICENSE.txt"
|
|
72
73
|
],
|
|
73
74
|
"targets": [
|
|
74
|
-
"
|
|
75
|
-
"
|
|
75
|
+
"node18-linux-x64",
|
|
76
|
+
"node18-macos-x64",
|
|
76
77
|
"node18-macos-arm64",
|
|
77
|
-
"
|
|
78
|
+
"node18-win-x64"
|
|
78
79
|
],
|
|
79
80
|
"outputPath": "ee-dist"
|
|
80
81
|
}
|