nodemailer 10.1.2 → 10.1.4
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/CHANGELOG.md +22 -0
- package/dist/cjs/addressparser/index.js +297 -31
- package/dist/cjs/mailer/mail-message.js +4 -1
- package/dist/cjs/mime-node/index.js +48 -16
- package/dist/cjs/package-info.d.ts +1 -1
- package/dist/cjs/package-info.js +1 -1
- package/dist/cjs/shared/url.js +22 -5
- package/dist/esm/addressparser/index.js +297 -31
- package/dist/esm/mailer/mail-message.js +4 -1
- package/dist/esm/mime-node/index.js +48 -16
- package/dist/esm/package-info.d.ts +1 -1
- package/dist/esm/package-info.js +1 -1
- package/dist/esm/shared/url.js +22 -5
- package/package.json +1 -1
|
@@ -26,6 +26,35 @@ const QUOTED_STRING = /^"(?:[^"\\]|\\[\s\S])*"$/;
|
|
|
26
26
|
// else goes into angle brackets so that the header can not be read as more addresses than
|
|
27
27
|
// the envelope carries
|
|
28
28
|
const PLAIN_ADDRESS = /^[^\s"(),:;<>@[\\\]]+@[^\s"(),:;<>@[\\\]]+$/;
|
|
29
|
+
/**
|
|
30
|
+
* A domain literal that ends an address, see _normalizeAddress
|
|
31
|
+
*/
|
|
32
|
+
const DOMAIN_LITERAL_TAIL = /@(\[[^[\]\\]*\])$/;
|
|
33
|
+
/**
|
|
34
|
+
* Removes the whitespace inside every <...> of a References value. A "<" with no ">" after
|
|
35
|
+
* it is left as it is. An index scan, the regex /<[^>]*>/g rescans the rest of the value
|
|
36
|
+
* from every such "<"
|
|
37
|
+
*
|
|
38
|
+
* @param value References header value
|
|
39
|
+
* @returns The value with the msg-ids closed up
|
|
40
|
+
*/
|
|
41
|
+
function stripWhitespaceInAngleBrackets(value) {
|
|
42
|
+
let result = '';
|
|
43
|
+
let pos = 0;
|
|
44
|
+
for (;;) {
|
|
45
|
+
const open = value.indexOf('<', pos);
|
|
46
|
+
if (open < 0) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
const close = value.indexOf('>', open + 1);
|
|
50
|
+
if (close < 0) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
result += value.slice(pos, open) + value.slice(open, close + 1).replace(/\s/g, '');
|
|
54
|
+
pos = close + 1;
|
|
55
|
+
}
|
|
56
|
+
return result + value.slice(pos);
|
|
57
|
+
}
|
|
29
58
|
// domainToASCII and domainToUnicode are WHATWG host parsers rather than plain IDNA
|
|
30
59
|
// mappers, so they do more than map: they cut the host at '/', '\\', '?' and '#', drop C0
|
|
31
60
|
// controls, and percent-decode. Handing them 'evil.example/mail.corp.example' returns the
|
|
@@ -1319,26 +1348,26 @@ class MimeNode {
|
|
|
1319
1348
|
}
|
|
1320
1349
|
return value;
|
|
1321
1350
|
// space separated list of values enclosed in <>
|
|
1322
|
-
case 'References':
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
elm = (
|
|
1351
|
+
case 'References': {
|
|
1352
|
+
const ids = [];
|
|
1353
|
+
for (const entry of [].concat(value || '')) {
|
|
1354
|
+
const elm = (entry || '')
|
|
1326
1355
|
.toString()
|
|
1327
1356
|
.replace(/\r?\n|\r/g, ' ')
|
|
1328
1357
|
.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, '')
|
|
1329
1358
|
.trim();
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1359
|
+
for (let id of stripWhitespaceInAngleBrackets(elm).split(/\s+/)) {
|
|
1360
|
+
if (id.charAt(0) !== '<') {
|
|
1361
|
+
id = '<' + id;
|
|
1362
|
+
}
|
|
1363
|
+
if (id.charAt(id.length - 1) !== '>') {
|
|
1364
|
+
id = id + '>';
|
|
1365
|
+
}
|
|
1366
|
+
ids.push(id);
|
|
1338
1367
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1368
|
+
}
|
|
1369
|
+
return ids.join(' ').trim();
|
|
1370
|
+
}
|
|
1342
1371
|
case 'Date':
|
|
1343
1372
|
if (Object.prototype.toString.call(value) === '[object Date]') {
|
|
1344
1373
|
return value.toUTCString().replace(/GMT/, '+0000');
|
|
@@ -1417,7 +1446,10 @@ class MimeNode {
|
|
|
1417
1446
|
// callers use an empty value to detect a missing address
|
|
1418
1447
|
return address;
|
|
1419
1448
|
}
|
|
1420
|
-
|
|
1449
|
+
// dtext includes '@', so a domain literal is split off at the '@' in front of it and
|
|
1450
|
+
// not at the last one, which delivered 'a@[x@evil.com]' to evil.com
|
|
1451
|
+
const literal = address.charAt(address.length - 1) === ']' ? DOMAIN_LITERAL_TAIL.exec(address) : null;
|
|
1452
|
+
const lastAt = literal ? address.length - literal[1].length - 1 : address.lastIndexOf('@');
|
|
1421
1453
|
if (lastAt < 0) {
|
|
1422
1454
|
// Bare username, there is no domain to split off
|
|
1423
1455
|
return this._normalizeLocalPart(address);
|
package/dist/esm/package-info.js
CHANGED
package/dist/esm/shared/url.js
CHANGED
|
@@ -19,10 +19,27 @@ import * as punycode from '../punycode/index.js';
|
|
|
19
19
|
// Matches a "scheme:" not followed by "//" (and with something after it), used
|
|
20
20
|
// to re-insert the authority separator the legacy parser did not require.
|
|
21
21
|
const SLASHLESS_AUTHORITY = /^([a-zA-Z][a-zA-Z0-9+.-]*:)(?!\/\/)([\s\S]+)$/;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Drops the leading and trailing C0 controls and spaces, which the WHATWG parser strips
|
|
24
|
+
* before it looks at the input. Stripped up front so that the slash-less form is recognized
|
|
25
|
+
* in a value read from a file with a trailing newline as well. An index scan, the regex
|
|
26
|
+
* /^[\x00-\x20]+|[\x00-\x20]+$/g retried a run of spaces inside the value from every
|
|
27
|
+
* position in it
|
|
28
|
+
*
|
|
29
|
+
* @param input URL string
|
|
30
|
+
* @returns The string without the surrounding controls and spaces
|
|
31
|
+
*/
|
|
32
|
+
function stripSurroundingWhitespace(input) {
|
|
33
|
+
let start = 0;
|
|
34
|
+
let end = input.length;
|
|
35
|
+
while (start < end && input.charCodeAt(start) <= 0x20) {
|
|
36
|
+
start++;
|
|
37
|
+
}
|
|
38
|
+
while (end > start && input.charCodeAt(end - 1) <= 0x20) {
|
|
39
|
+
end--;
|
|
40
|
+
}
|
|
41
|
+
return input.slice(start, end);
|
|
42
|
+
}
|
|
26
43
|
// Leading characters legacy url.parse() skips before it reads the scheme
|
|
27
44
|
const LEGACY_TRIM = /^[\x00-\x20\u00a0\ufeff]+/;
|
|
28
45
|
// The authority of a "scheme://authority/..." or a scheme-relative "//authority/..."
|
|
@@ -117,7 +134,7 @@ function normalizeHostname(raw, href) {
|
|
|
117
134
|
return mapped;
|
|
118
135
|
}
|
|
119
136
|
export const parse = (input, parseQueryString) => {
|
|
120
|
-
input = (input || '')
|
|
137
|
+
input = stripSurroundingWhitespace(input || '');
|
|
121
138
|
// Legacy url.parse() parses a "user:pass@host:port" authority that follows
|
|
122
139
|
// the scheme even without the "//" separator, for schemes outside its
|
|
123
140
|
// built-in slashed-protocol list (smtp:/smtps:/socks:/...). The WHATWG
|