@mavogel/awscdk-rootmail 0.1.26 → 0.1.28
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/.jsii +8 -8
- package/lib/rootmail.js +1 -1
- package/lib/ses-receive.js +1 -1
- package/node_modules/@aws-sdk/checksums/package.json +4 -4
- package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-cjs/index.js +1 -1
- package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/CloudWatchLogsClient.d.ts +2 -1
- package/node_modules/@aws-sdk/client-cloudwatch-logs/package.json +5 -5
- package/node_modules/@aws-sdk/client-route-53/dist-cjs/index.js +1 -1
- package/node_modules/@aws-sdk/client-route-53/dist-types/Route53Client.d.ts +2 -1
- package/node_modules/@aws-sdk/client-route-53/package.json +6 -6
- package/node_modules/@aws-sdk/client-s3/dist-cjs/index.js +1 -1
- package/node_modules/@aws-sdk/client-s3/dist-types/S3Client.d.ts +2 -1
- package/node_modules/@aws-sdk/client-s3/package.json +9 -9
- package/node_modules/@aws-sdk/client-ses/dist-cjs/index.js +1 -1
- package/node_modules/@aws-sdk/client-ses/dist-types/SESClient.d.ts +2 -1
- package/node_modules/@aws-sdk/client-ses/package.json +5 -5
- package/node_modules/@aws-sdk/client-ssm/dist-cjs/index.js +1 -1
- package/node_modules/@aws-sdk/client-ssm/dist-types/SSMClient.d.ts +2 -1
- package/node_modules/@aws-sdk/client-ssm/package.json +5 -5
- package/node_modules/@aws-sdk/core/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-env/package.json +4 -4
- package/node_modules/@aws-sdk/credential-provider-http/package.json +4 -4
- package/node_modules/@aws-sdk/credential-provider-ini/package.json +11 -11
- package/node_modules/@aws-sdk/credential-provider-login/package.json +5 -5
- package/node_modules/@aws-sdk/credential-provider-node/package.json +9 -9
- package/node_modules/@aws-sdk/credential-provider-process/package.json +4 -4
- package/node_modules/@aws-sdk/credential-provider-sso/package.json +6 -6
- package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +5 -5
- package/node_modules/@aws-sdk/middleware-sdk-route53/package.json +2 -2
- package/node_modules/@aws-sdk/middleware-sdk-s3/package.json +5 -5
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/cognito-identity/CognitoIdentityClient.d.ts +2 -1
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/signin/SigninClient.d.ts +2 -1
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso/SSOClient.d.ts +2 -1
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso-oidc/SSOOIDCClient.d.ts +2 -1
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sts/STSClient.d.ts +2 -1
- package/node_modules/@aws-sdk/nested-clients/package.json +5 -5
- package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +2 -2
- package/node_modules/@aws-sdk/token-providers/package.json +5 -5
- package/node_modules/@aws-sdk/types/dist-types/feature-ids.d.ts +3 -0
- package/node_modules/@aws-sdk/types/dist-types/ts3.4/feature-ids.d.ts +3 -0
- package/node_modules/@aws-sdk/types/package.json +1 -1
- package/node_modules/@smithy/core/dist-cjs/submodules/client/index.js +15 -2
- package/node_modules/@smithy/core/dist-cjs/submodules/event-streams/index.browser.js +10 -0
- package/node_modules/@smithy/core/dist-cjs/submodules/event-streams/index.js +10 -0
- package/node_modules/@smithy/core/dist-cjs/submodules/protocols/index.js +5 -5
- package/node_modules/@smithy/core/dist-es/submodules/client/smithy-client/command.js +16 -2
- package/node_modules/@smithy/core/dist-es/submodules/event-streams/eventstream-codec/HeaderMarshaller.js +10 -0
- package/node_modules/@smithy/core/dist-es/submodules/protocols/json/codec-v2/JsonShapeSerializer2.js +5 -5
- package/node_modules/@smithy/core/package.json +1 -1
- package/node_modules/@zone-eu/mailsplit/lib/message-splitter.js +39 -27
- package/node_modules/@zone-eu/mailsplit/lib/mime-node.d.ts +1 -1
- package/node_modules/@zone-eu/mailsplit/lib/mime-node.js +38 -61
- package/node_modules/@zone-eu/mailsplit/lib/types.d.ts +1 -1
- package/node_modules/@zone-eu/mailsplit/package.json +2 -2
- package/node_modules/libmime/CHANGELOG.md +36 -0
- package/node_modules/libmime/README.md +40 -3
- package/node_modules/libmime/dist/cjs/charset.d.ts +36 -0
- package/node_modules/libmime/dist/cjs/charset.js +165 -2
- package/node_modules/libmime/dist/cjs/charsets.js +8 -2
- package/node_modules/libmime/dist/cjs/libmime.d.ts +20 -3
- package/node_modules/libmime/dist/cjs/libmime.js +100 -6
- package/node_modules/libmime/dist/cjs/types.d.ts +28 -0
- package/node_modules/libmime/dist/esm/charset.d.ts +36 -0
- package/node_modules/libmime/dist/esm/charset.js +162 -2
- package/node_modules/libmime/dist/esm/charsets.js +8 -2
- package/node_modules/libmime/dist/esm/libmime.d.ts +20 -3
- package/node_modules/libmime/dist/esm/libmime.js +100 -6
- package/node_modules/libmime/dist/esm/types.d.ts +28 -0
- package/node_modules/libmime/package.json +3 -3
- package/node_modules/mailparser/CHANGELOG.md +51 -0
- package/node_modules/mailparser/README.md +32 -1
- package/node_modules/mailparser/dist/cjs/address-header.d.ts +19 -0
- package/node_modules/mailparser/dist/cjs/address-header.js +185 -0
- package/node_modules/mailparser/dist/cjs/index.d.ts +3 -1
- package/node_modules/mailparser/dist/cjs/index.js +4 -2
- package/node_modules/mailparser/dist/cjs/mail-parser.js +36 -183
- package/node_modules/mailparser/dist/cjs/stream-hash.d.ts +5 -4
- package/node_modules/mailparser/dist/cjs/stream-hash.js +8 -5
- package/node_modules/mailparser/dist/cjs/types.d.ts +33 -6
- package/node_modules/mailparser/dist/esm/address-header.d.ts +19 -0
- package/node_modules/mailparser/dist/esm/address-header.js +176 -0
- package/node_modules/mailparser/dist/esm/index.d.ts +3 -1
- package/node_modules/mailparser/dist/esm/index.js +3 -2
- package/node_modules/mailparser/dist/esm/mail-parser.js +36 -183
- package/node_modules/mailparser/dist/esm/stream-hash.d.ts +5 -4
- package/node_modules/mailparser/dist/esm/stream-hash.js +8 -5
- package/node_modules/mailparser/dist/esm/types.d.ts +33 -6
- package/node_modules/mailparser/package.json +6 -7
- package/node_modules/nodemailer/CHANGELOG.md +23 -0
- package/node_modules/nodemailer/dist/cjs/addressparser/index.js +2 -5
- package/node_modules/nodemailer/dist/cjs/dkim/index.js +1 -3
- package/node_modules/nodemailer/dist/cjs/errors.d.ts +19 -0
- package/node_modules/nodemailer/dist/cjs/errors.js +14 -1
- package/node_modules/nodemailer/dist/cjs/fetch/cookies.js +2 -4
- package/node_modules/nodemailer/dist/cjs/fetch/index.js +2 -8
- package/node_modules/nodemailer/dist/cjs/mail-composer/index.js +42 -9
- package/node_modules/nodemailer/dist/cjs/mailer/mail-message.js +5 -6
- package/node_modules/nodemailer/dist/cjs/mime-funcs/index.d.ts +18 -1
- package/node_modules/nodemailer/dist/cjs/mime-funcs/index.js +43 -1
- package/node_modules/nodemailer/dist/cjs/mime-funcs/mime-types.js +3 -12
- package/node_modules/nodemailer/dist/cjs/mime-node/index.d.ts +34 -1
- package/node_modules/nodemailer/dist/cjs/mime-node/index.js +40 -15
- package/node_modules/nodemailer/dist/cjs/package-info.d.ts +1 -1
- package/node_modules/nodemailer/dist/cjs/package-info.js +1 -1
- package/node_modules/nodemailer/dist/cjs/qp/index.js +3 -12
- package/node_modules/nodemailer/dist/cjs/sendmail-transport/index.js +1 -3
- package/node_modules/nodemailer/dist/cjs/shared/index.js +2 -6
- package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.js +1 -1
- package/node_modules/nodemailer/dist/cjs/smtp-connection/index.d.ts +6 -0
- package/node_modules/nodemailer/dist/cjs/smtp-connection/index.js +15 -12
- package/node_modules/nodemailer/dist/cjs/smtp-connection/server-message-id.d.ts +14 -0
- package/node_modules/nodemailer/dist/cjs/smtp-connection/server-message-id.js +53 -0
- package/node_modules/nodemailer/dist/cjs/smtp-pool/index.d.ts +11 -0
- package/node_modules/nodemailer/dist/cjs/smtp-pool/index.js +25 -1
- package/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.js +2 -5
- package/node_modules/nodemailer/dist/esm/addressparser/index.js +2 -5
- package/node_modules/nodemailer/dist/esm/dkim/index.js +1 -3
- package/node_modules/nodemailer/dist/esm/errors.d.ts +19 -0
- package/node_modules/nodemailer/dist/esm/errors.js +12 -0
- package/node_modules/nodemailer/dist/esm/fetch/cookies.js +2 -4
- package/node_modules/nodemailer/dist/esm/fetch/index.js +2 -8
- package/node_modules/nodemailer/dist/esm/mail-composer/index.js +42 -9
- package/node_modules/nodemailer/dist/esm/mailer/mail-message.js +5 -6
- package/node_modules/nodemailer/dist/esm/mime-funcs/index.d.ts +18 -1
- package/node_modules/nodemailer/dist/esm/mime-funcs/index.js +43 -1
- package/node_modules/nodemailer/dist/esm/mime-funcs/mime-types.js +3 -12
- package/node_modules/nodemailer/dist/esm/mime-node/index.d.ts +34 -1
- package/node_modules/nodemailer/dist/esm/mime-node/index.js +40 -15
- package/node_modules/nodemailer/dist/esm/package-info.d.ts +1 -1
- package/node_modules/nodemailer/dist/esm/package-info.js +1 -1
- package/node_modules/nodemailer/dist/esm/qp/index.js +3 -12
- package/node_modules/nodemailer/dist/esm/sendmail-transport/index.js +1 -3
- package/node_modules/nodemailer/dist/esm/shared/index.js +2 -6
- package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.js +1 -1
- package/node_modules/nodemailer/dist/esm/smtp-connection/index.d.ts +6 -0
- package/node_modules/nodemailer/dist/esm/smtp-connection/index.js +16 -13
- package/node_modules/nodemailer/dist/esm/smtp-connection/server-message-id.d.ts +14 -0
- package/node_modules/nodemailer/dist/esm/smtp-connection/server-message-id.js +50 -0
- package/node_modules/nodemailer/dist/esm/smtp-pool/index.d.ts +11 -0
- package/node_modules/nodemailer/dist/esm/smtp-pool/index.js +25 -1
- package/node_modules/nodemailer/dist/esm/smtp-pool/pool-resource.js +2 -5
- package/node_modules/nodemailer/package.json +11 -9
- package/package.json +9 -9
- package/node_modules/mailparser/node_modules/iconv-lite/LICENSE +0 -21
- package/node_modules/mailparser/node_modules/iconv-lite/README.md +0 -138
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/dbcs-codec.js +0 -532
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/dbcs-data.js +0 -185
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/index.js +0 -23
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/internal.js +0 -218
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/sbcs-codec.js +0 -75
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/sbcs-data-generated.js +0 -451
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/sbcs-data.js +0 -180
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/big5-added.json +0 -122
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/cp936.json +0 -264
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/cp949.json +0 -273
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/cp950.json +0 -177
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/eucjp.json +0 -182
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json +0 -1
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/gbk-added.json +0 -56
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/shiftjis.json +0 -125
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/utf16.js +0 -187
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/utf32.js +0 -314
- package/node_modules/mailparser/node_modules/iconv-lite/encodings/utf7.js +0 -283
- package/node_modules/mailparser/node_modules/iconv-lite/lib/bom-handling.js +0 -48
- package/node_modules/mailparser/node_modules/iconv-lite/lib/helpers/merge-exports.js +0 -13
- package/node_modules/mailparser/node_modules/iconv-lite/lib/index.d.ts +0 -129
- package/node_modules/mailparser/node_modules/iconv-lite/lib/index.js +0 -182
- package/node_modules/mailparser/node_modules/iconv-lite/lib/streams.js +0 -105
- package/node_modules/mailparser/node_modules/iconv-lite/package.json +0 -70
- package/node_modules/mailparser/node_modules/iconv-lite/types/encodings.d.ts +0 -425
|
@@ -6,6 +6,26 @@ import * as libcharset from './charset.js';
|
|
|
6
6
|
import * as mimetypes from './mimetypes.js';
|
|
7
7
|
const STAGE_KEY = 0x1001;
|
|
8
8
|
const STAGE_VALUE = 0x1002;
|
|
9
|
+
/**
|
|
10
|
+
* Offset of the ")" that closes the rfc822 comment opening at `start`, or -1 when the
|
|
11
|
+
* comment never closes. Comments nest, and a backslash escapes the character after it
|
|
12
|
+
*/
|
|
13
|
+
const findCommentEnd = (str, start) => {
|
|
14
|
+
let depth = 0;
|
|
15
|
+
for (let i = start, len = str.length; i < len; i++) {
|
|
16
|
+
let chr = str.charAt(i);
|
|
17
|
+
if (chr === '\\') {
|
|
18
|
+
i++;
|
|
19
|
+
}
|
|
20
|
+
else if (chr === '(') {
|
|
21
|
+
depth++;
|
|
22
|
+
}
|
|
23
|
+
else if (chr === ')' && --depth === 0) {
|
|
24
|
+
return i;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return -1;
|
|
28
|
+
};
|
|
9
29
|
// Sets an own property on a plain object. A regular assignment with a
|
|
10
30
|
// '__proto__' key would silently modify the object's prototype instead of
|
|
11
31
|
// creating an own property, so it needs special handling.
|
|
@@ -22,6 +42,9 @@ const setOwnProperty = (obj, key, value) => {
|
|
|
22
42
|
obj[key] = value;
|
|
23
43
|
}
|
|
24
44
|
};
|
|
45
|
+
// Header names decodeHeaders() leaves out with the skipPrototypeKeys option. Keys are lowercased,
|
|
46
|
+
// so of these only '__proto__' and 'constructor' can ever match
|
|
47
|
+
const PROTOTYPE_KEYS = new Set(Object.getOwnPropertyNames(Object.prototype));
|
|
25
48
|
// Whitespace that separates the tokens of a header value. Kept as a char comparison,
|
|
26
49
|
// a regex test would be run for every single char of every parsed header
|
|
27
50
|
const isWSP = (chr) => chr === ' ' || chr === '\t' || chr === '\r' || chr === '\n' || chr === '\f' || chr === '\v';
|
|
@@ -259,6 +282,18 @@ export class Libmime {
|
|
|
259
282
|
normalizeCharset(charset) {
|
|
260
283
|
return libcharset.normalizeCharset(charset);
|
|
261
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Creates a Transform stream that decodes a body in the given charset into UTF-8 Buffers,
|
|
287
|
+
* resolving the charset name and handling the Japanese charsets the same way header
|
|
288
|
+
* decoding does. An unknown or refused charset (UTF-7, base64, hex) is decoded as UTF-8,
|
|
289
|
+
* and the stream says so with `supported` set to false.
|
|
290
|
+
*
|
|
291
|
+
* @param {String} [charset='UTF-8'] Charset the input is encoded in
|
|
292
|
+
* @return {DecodeStream} Transform stream with `charset` and `supported` properties
|
|
293
|
+
*/
|
|
294
|
+
createDecodeStream(charset) {
|
|
295
|
+
return libcharset.createDecodeStream(charset);
|
|
296
|
+
}
|
|
262
297
|
/**
|
|
263
298
|
* Decodes the inner payload of a single mime encoded-word into a unicode string.
|
|
264
299
|
* Expects the three components of `=?charset?encoding?text?=` already separated.
|
|
@@ -417,9 +452,11 @@ export class Libmime {
|
|
|
417
452
|
* header might have its own rules (eg. formatted email addresses and such)
|
|
418
453
|
*
|
|
419
454
|
* @param {String} headers Headers string
|
|
455
|
+
* @param {Object} [options] Options
|
|
456
|
+
* @param {Boolean} [options.skipPrototypeKeys] Leave out headers named like an Object.prototype member, eg. `__proto__` and `constructor`
|
|
420
457
|
* @return {Object} An object of headers, where header keys are object keys and every value is an Array of the values for that key
|
|
421
458
|
*/
|
|
422
|
-
decodeHeaders(headers) {
|
|
459
|
+
decodeHeaders(headers, options) {
|
|
423
460
|
let lines = headers.split(/\r?\n|\r/), headersObj = {}, header, i, len;
|
|
424
461
|
// Empty lines in front of the block are not part of any header, a caller might
|
|
425
462
|
// include the line break that separates a mime part boundary from its headers
|
|
@@ -445,6 +482,9 @@ export class Libmime {
|
|
|
445
482
|
lines = unfolded;
|
|
446
483
|
for (i = 0, len = lines.length; i < len; i++) {
|
|
447
484
|
header = this.decodeHeader(lines[i]);
|
|
485
|
+
if (options?.skipPrototypeKeys && PROTOTYPE_KEYS.has(header.key)) {
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
448
488
|
// own properties only, an attacker controlled key such as '__proto__' or 'toString' would
|
|
449
489
|
// otherwise resolve to an inherited Object.prototype member
|
|
450
490
|
if (!Object.hasOwn(headersObj, header.key)) {
|
|
@@ -513,9 +553,12 @@ export class Libmime {
|
|
|
513
553
|
* decoded, so a caller that runs decodeWords() over the params has to leave them out
|
|
514
554
|
*
|
|
515
555
|
* @param {String} str Header value
|
|
556
|
+
* @param {Object} [options] Options, see ParseHeaderValueOptions
|
|
516
557
|
* @return {Object} Header value as a parsed structure
|
|
517
558
|
*/
|
|
518
|
-
parseHeaderValue(str) {
|
|
559
|
+
parseHeaderValue(str, options) {
|
|
560
|
+
// Cleared again by an unclosed "(", see the loop
|
|
561
|
+
let stripComments = !!options?.stripComments;
|
|
519
562
|
let response = {
|
|
520
563
|
value: '',
|
|
521
564
|
params: {}
|
|
@@ -535,10 +578,23 @@ export class Libmime {
|
|
|
535
578
|
let valueEnd = 0;
|
|
536
579
|
let stage = STAGE_VALUE;
|
|
537
580
|
let quote = false;
|
|
581
|
+
// A quoted string has closed and the ";" that ends the parameter has not come yet
|
|
582
|
+
let quoteClosed = false;
|
|
538
583
|
let escaped = false;
|
|
539
584
|
let chr;
|
|
585
|
+
// Whether a "(" would continue the unquoted token of a parameter value, which it does
|
|
586
|
+
// right behind the "=" and behind a character of the token: `filename=Invoice(1).pdf`
|
|
587
|
+
// names the file and `boundary=(c)b` the boundary `(c)b`, as they do for Python and
|
|
588
|
+
// postal-mime. Anywhere else, in the type, in a parameter name, behind whitespace or
|
|
589
|
+
// behind a quoted string, a "(" opens a comment
|
|
590
|
+
let tokenOpen = false;
|
|
540
591
|
// Stores the collected value, either as the default value, as the value for the
|
|
541
|
-
// current key, or as a key that has no value at all. Runs once per parameter
|
|
592
|
+
// current key, or as a key that has no value at all. Runs once per parameter.
|
|
593
|
+
//
|
|
594
|
+
// A parameter given twice keeps its first value, as it does for Python and for
|
|
595
|
+
// postal-mime. Letting the last one win read `boundary=b; boundary=c` as a multipart
|
|
596
|
+
// of the parts under `--c`, which the other readers leave in the epilogue of the
|
|
597
|
+
// parts under `--b`
|
|
542
598
|
let commit = () => {
|
|
543
599
|
let collected = value.substring(0, valueEnd);
|
|
544
600
|
value = '';
|
|
@@ -546,21 +602,42 @@ export class Libmime {
|
|
|
546
602
|
if (stage === STAGE_KEY) {
|
|
547
603
|
// key without a value, see emptykey:
|
|
548
604
|
// Header-Key: somevalue; key=value; emptykey
|
|
549
|
-
|
|
550
|
-
|
|
605
|
+
let name = collected.toLowerCase();
|
|
606
|
+
if (name && !Object.hasOwn(response.params, name)) {
|
|
607
|
+
setOwnProperty(response.params, name, '');
|
|
551
608
|
}
|
|
552
609
|
}
|
|
553
610
|
else if (key === false) {
|
|
554
611
|
// default value
|
|
555
612
|
response.value = collected;
|
|
556
613
|
}
|
|
557
|
-
else {
|
|
614
|
+
else if (!Object.hasOwn(response.params, key)) {
|
|
558
615
|
// subkey value
|
|
559
616
|
setOwnProperty(response.params, key, collected);
|
|
560
617
|
}
|
|
561
618
|
};
|
|
562
619
|
for (let i = 0, len = str.length; i < len; i++) {
|
|
563
620
|
chr = str.charAt(i);
|
|
621
|
+
// With stripComments, an rfc822 comment stands anywhere outside a quoted string
|
|
622
|
+
// but right behind a token it would continue. Read as content, `boundary=b (comment)`
|
|
623
|
+
// named a boundary no delimiter line matches, so the parts that Python and
|
|
624
|
+
// postal-mime find stayed hidden from a splitter built on this
|
|
625
|
+
if (stripComments && chr === '(' && !quote && !escaped && !tokenOpen) {
|
|
626
|
+
let end = findCommentEnd(str, i);
|
|
627
|
+
if (end < 0 && str.indexOf(';', i) < 0) {
|
|
628
|
+
// A comment that never closes runs to the end of the value, as it does for
|
|
629
|
+
// Python. One that a parameter follows is content instead, with everything
|
|
630
|
+
// after it, so that the parameter survives, as postal-mime keeps it
|
|
631
|
+
end = len - 1;
|
|
632
|
+
}
|
|
633
|
+
if (end >= 0) {
|
|
634
|
+
i = end;
|
|
635
|
+
continue;
|
|
636
|
+
}
|
|
637
|
+
// Looking for a closing ")" again would scan a run of unclosed "(" to its end
|
|
638
|
+
// once for each of them
|
|
639
|
+
stripComments = false;
|
|
640
|
+
}
|
|
564
641
|
switch (stage) {
|
|
565
642
|
case STAGE_KEY:
|
|
566
643
|
if (chr === '=') {
|
|
@@ -568,6 +645,7 @@ export class Libmime {
|
|
|
568
645
|
value = '';
|
|
569
646
|
valueEnd = 0;
|
|
570
647
|
stage = STAGE_VALUE;
|
|
648
|
+
tokenOpen = true;
|
|
571
649
|
}
|
|
572
650
|
else if (chr === ';') {
|
|
573
651
|
// key without a value, eg. the "inline" in "attachment; inline; filename=a.txt"
|
|
@@ -584,9 +662,19 @@ export class Libmime {
|
|
|
584
662
|
}
|
|
585
663
|
break;
|
|
586
664
|
case STAGE_VALUE:
|
|
665
|
+
if (quoteClosed && chr !== ';') {
|
|
666
|
+
// Nothing behind a closed quoted string reaches the value: a parameter
|
|
667
|
+
// value is a token or a quoted string, not both (rfc2045 section 5.1),
|
|
668
|
+
// so what follows one is junk up to the ";" that ends the parameter, as
|
|
669
|
+
// Python and postal-mime read it. Read on, `boundary="b"c` named a
|
|
670
|
+
// boundary bc that no delimiter line of the message matches
|
|
671
|
+
escaped = false;
|
|
672
|
+
break;
|
|
673
|
+
}
|
|
587
674
|
if (escaped) {
|
|
588
675
|
value += chr;
|
|
589
676
|
valueEnd = value.length;
|
|
677
|
+
tokenOpen = key !== false && !quote;
|
|
590
678
|
}
|
|
591
679
|
else if (chr === '\\') {
|
|
592
680
|
escaped = true;
|
|
@@ -594,20 +682,26 @@ export class Libmime {
|
|
|
594
682
|
}
|
|
595
683
|
else if (chr === '"') {
|
|
596
684
|
// every char between the quotes is significant, including whitespace
|
|
685
|
+
quoteClosed = quote;
|
|
597
686
|
quote = !quote;
|
|
687
|
+
tokenOpen = false;
|
|
598
688
|
}
|
|
599
689
|
else if (!quote && chr === ';') {
|
|
600
690
|
commit();
|
|
601
691
|
stage = STAGE_KEY;
|
|
692
|
+
tokenOpen = false;
|
|
693
|
+
quoteClosed = false;
|
|
602
694
|
}
|
|
603
695
|
else if (!quote && isWSP(chr)) {
|
|
604
696
|
if (value.length) {
|
|
605
697
|
value += chr;
|
|
606
698
|
}
|
|
699
|
+
tokenOpen = false;
|
|
607
700
|
}
|
|
608
701
|
else {
|
|
609
702
|
value += chr;
|
|
610
703
|
valueEnd = value.length;
|
|
704
|
+
tokenOpen = key !== false && !quote;
|
|
611
705
|
}
|
|
612
706
|
escaped = false;
|
|
613
707
|
break;
|
|
@@ -15,6 +15,34 @@ export interface HeaderLine {
|
|
|
15
15
|
* Parsed header block, every key holds the values of all the header lines with that key
|
|
16
16
|
*/
|
|
17
17
|
export type HeaderObject = Record<string, string[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Options of decodeHeaders()
|
|
20
|
+
*/
|
|
21
|
+
export interface DecodeHeadersOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Leave out the headers whose name is also the name of an Object.prototype member, such as
|
|
24
|
+
* `__proto__` and `constructor`. By default they are kept as own properties of the result,
|
|
25
|
+
* where a lookup with the `in` operator or a merge into another object can not tell them
|
|
26
|
+
* apart from the inherited members
|
|
27
|
+
*/
|
|
28
|
+
skipPrototypeKeys?: boolean | undefined;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Options of parseHeaderValue()
|
|
32
|
+
*/
|
|
33
|
+
export interface ParseHeaderValueOptions {
|
|
34
|
+
/**
|
|
35
|
+
* Drop the RFC 822 comments outside quoted strings. The MIME headers (Content-Type,
|
|
36
|
+
* Content-Disposition) allow them and they are not part of the value, so `boundary=b (comment)`
|
|
37
|
+
* names the boundary `b`. A parenthesis right behind the `=` of a parameter or behind a token
|
|
38
|
+
* of its value continues the token, as it does for Python and postal-mime: `filename=Invoice(1).pdf`
|
|
39
|
+
* keeps its name and `boundary=(c)b` names the boundary `(c)b`. A comment that never closes runs to the end
|
|
40
|
+
* of the value, unless a parameter follows it, in which case it is content and the parameter
|
|
41
|
+
* survives. By default comments are kept as they are, since a header such as
|
|
42
|
+
* Authentication-Results carries information in them
|
|
43
|
+
*/
|
|
44
|
+
stripComments?: boolean | undefined;
|
|
45
|
+
}
|
|
18
46
|
/**
|
|
19
47
|
* Header value with key=value parameters as returned by parseHeaderValue()
|
|
20
48
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "libmime",
|
|
3
3
|
"description": "Encode and decode quoted printable and base64 strings",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.6.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/libmime.js",
|
|
7
7
|
"types": "./dist/cjs/libmime.d.ts",
|
|
@@ -75,11 +75,11 @@
|
|
|
75
75
|
"eslint": "10.13.0",
|
|
76
76
|
"eslint-config-prettier": "10.1.8",
|
|
77
77
|
"globals": "17.13.0",
|
|
78
|
-
"nodemailer": "10.
|
|
78
|
+
"nodemailer": "10.2.0",
|
|
79
79
|
"prettier": "3.9.10",
|
|
80
80
|
"tsx": "4.23.15",
|
|
81
81
|
"typescript": "6.0.3",
|
|
82
|
-
"typescript-eslint": "8.
|
|
82
|
+
"typescript-eslint": "8.72.0"
|
|
83
83
|
},
|
|
84
84
|
"engines": {
|
|
85
85
|
"node": ">=20.0.0"
|
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.12.4](https://github.com/nodemailer/mailparser/compare/v3.12.3...v3.12.4) (2026-10-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* update dependencies ([fe3b459](https://github.com/nodemailer/mailparser/commit/fe3b4596140eccfdd8e224ab4576094e0e49ef54))
|
|
9
|
+
|
|
10
|
+
## [3.12.3](https://github.com/nodemailer/mailparser/compare/v3.12.2...v3.12.3) (2026-10-22)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **deps:** bump mailsplit to 5.4.28 and libmime to 5.6.3 ([996a18f](https://github.com/nodemailer/mailparser/commit/996a18f06a8a7e93c3042e293a35f3abb4d159bf))
|
|
16
|
+
* **deps:** bump mailsplit to 5.4.29, which reads an RFC 2231 filename the same way ([7ccd32b](https://github.com/nodemailer/mailparser/commit/7ccd32b72a1321543a02bddbfe0ef2c372ec0e0f))
|
|
17
|
+
* drop the comments of a Content-Type or Content-Disposition in the headers map ([eaf345b](https://github.com/nodemailer/mailparser/commit/eaf345b8bb9c94866da3bf1722aede6a88a7e11b))
|
|
18
|
+
* tell an RFC 2231 parameter apart by what libmime decoded, not by a second scan of the header ([eba8da2](https://github.com/nodemailer/mailparser/commit/eba8da294cd077d4816398a5499b14f1a79031d5))
|
|
19
|
+
|
|
20
|
+
## [3.12.2](https://github.com/nodemailer/mailparser/compare/v3.12.1...v3.12.2) (2026-10-21)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* the html and text forms parseAddressHeader() builds lazily can be assigned again ([bc6c421](https://github.com/nodemailer/mailparser/commit/bc6c4215c531a448c71540027c5ade74b4d60fab))
|
|
26
|
+
|
|
27
|
+
## [3.12.1](https://github.com/nodemailer/mailparser/compare/v3.12.0...v3.12.1) (2026-10-21)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Bug Fixes
|
|
31
|
+
|
|
32
|
+
* parseAddressHeader() builds the html and text forms only when they are read ([e08de61](https://github.com/nodemailer/mailparser/commit/e08de61740d04bdd534f8006d5b88eba6e4f89ed))
|
|
33
|
+
|
|
34
|
+
## [3.12.0](https://github.com/nodemailer/mailparser/compare/v3.11.0...v3.12.0) (2026-10-21)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
### Features
|
|
38
|
+
|
|
39
|
+
* parseAddressHeader() accepts decodePunycode: false to keep IDN domains in ASCII form ([0652c3f](https://github.com/nodemailer/mailparser/commit/0652c3fca470d975aed0e6ec5b1a4ca8e53d95f1))
|
|
40
|
+
|
|
41
|
+
## [3.11.0](https://github.com/nodemailer/mailparser/compare/v3.10.0...v3.11.0) (2026-10-21)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
### Features
|
|
45
|
+
|
|
46
|
+
* accept checksumAlgo: false to skip hashing attachments ([21f806c](https://github.com/nodemailer/mailparser/commit/21f806cd03b0b98644ad7a5b95678cc259f838db))
|
|
47
|
+
* export parseAddressHeader() for parsing an address header value ([8ac364e](https://github.com/nodemailer/mailparser/commit/8ac364e330fbc815b45986a0f64251b382b88421))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
### Bug Fixes
|
|
51
|
+
|
|
52
|
+
* decode text bodies with libmime's decode stream ([b9a5e41](https://github.com/nodemailer/mailparser/commit/b9a5e4125f1bf0a4aa88d275da5fbdb282cb779c))
|
|
53
|
+
|
|
3
54
|
## [3.10.0](https://github.com/nodemailer/mailparser/compare/v3.9.47...v3.10.0) (2026-10-19)
|
|
4
55
|
|
|
5
56
|
|
|
@@ -24,13 +24,44 @@ const mailparser = require('mailparser');
|
|
|
24
24
|
or, from an ES module or TypeScript (type declarations are included):
|
|
25
25
|
|
|
26
26
|
```js
|
|
27
|
-
import { simpleParser, MailParser } from 'mailparser';
|
|
27
|
+
import { simpleParser, MailParser, parseAddressHeader } from 'mailparser';
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
## Usage
|
|
31
31
|
|
|
32
32
|
See [mailparser homepage](https://nodemailer.com/extras/mailparser/) for documentation and terms.
|
|
33
33
|
|
|
34
|
+
### Parsing an address header
|
|
35
|
+
|
|
36
|
+
`parseAddressHeader(value, [options])` parses the value of an address header (`From`, `To`, `Cc`, `Reply-To` and the like) into the same `{ value, html, text }` object `MailParser` and `simpleParser` produce for one, for when the header comes from somewhere else than a message being parsed, for example an IMAP `HEADER.FIELDS` fetch.
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
const { parseAddressHeader } = require('mailparser');
|
|
40
|
+
|
|
41
|
+
parseAddressHeader('=?utf-8?Q?J=C3=B5geva?= <info@xn--mnchen-3ya.example>, Team: a@example.com;');
|
|
42
|
+
// {
|
|
43
|
+
// value: [
|
|
44
|
+
// { address: 'info@münchen.example', name: 'Jõgeva' },
|
|
45
|
+
// { name: 'Team', group: [{ address: 'a@example.com', name: '' }] }
|
|
46
|
+
// ],
|
|
47
|
+
// html: '<span class="mp_address_group">...',
|
|
48
|
+
// text: '"Jõgeva" <info@münchen.example>, "Team": a@example.com;'
|
|
49
|
+
// }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- **value** - the header value without the `Name:` prefix, as a string. Folded lines are fine, raw 8-bit bytes have to be decoded into the string first. An array of values (a repeated header) is parsed one value at a time and the addresses are listed in order. An empty or missing value gives an empty list
|
|
53
|
+
- **options.flatten** - if `true`, every group is replaced with its members and the group names are dropped, so `value` lists mailboxes only
|
|
54
|
+
|
|
55
|
+
Each entry of `value` has a `name` (an empty string when there is none, encoded words decoded) and either an `address` (a punycode domain decoded to Unicode) or, for a group, a `group` list of the same entries. RFC 2047 does not allow encoded words in the address itself, so an address part hiding one is kept only when it decodes to a plain `local@domain`, otherwise `address` is an empty string; a display name that decodes to something looking like an address stays a name.
|
|
56
|
+
|
|
57
|
+
### Character sets
|
|
58
|
+
|
|
59
|
+
Text bodies are decoded with libmime's `createDecodeStream()`, which resolves charset aliases, decodes the Japanese charsets iconv-lite does not support (ISO-2022-JP and friends) and keeps a multibyte character that is split across chunks intact. A body in a charset that is not known, or one that is refused, is decoded as UTF-8 with invalid bytes replaced by U+FFFD, the same fallback encoded words in headers get. The refused charsets are UTF-7 (and its aliases), which can carry markup past a filter that looks for `<` (`+ADw-script+AD4-` decodes to `<script>`), and the base64 and hex transfer encodings. A UTF-7 body therefore keeps its `+ADw-` sequences as literal text. The refusal applies with the `Iconv` option as well.
|
|
60
|
+
|
|
61
|
+
### Attachment checksums
|
|
62
|
+
|
|
63
|
+
Every attachment gets a `checksum` (hex, md5 unless the `checksumAlgo` option names another algorithm `crypto.createHash()` accepts) and a `size`. Set `checksumAlgo: false` to skip hashing altogether, for example where MD5 is not available (FIPS mode) or the checksum is not used. `checksum` is then not set on the attachments, `size` still is.
|
|
64
|
+
|
|
34
65
|
### Limits
|
|
35
66
|
|
|
36
67
|
- `simpleParser` replaces `cid:` image references in the HTML with `data:` URLs. The total length of the URLs written into the HTML is capped by the `maxInlinedImagesSize` option (default 20 MB, counted in characters of the inserted URLs). References past the cap stay as `cid:` links. The same cap applies to URLs returned from a custom `updateImageLinks()` callback.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AddressObject, ParseAddressHeaderOptions } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parses the value of an address header (`From`, `To`, `Cc`, `Reply-To` and the like) into the
|
|
4
|
+
* {@link AddressObject} `MailParser` and `simpleParser` produce for one: display names have their
|
|
5
|
+
* encoded words decoded, an internationalized (punycode) domain is decoded to Unicode (unless
|
|
6
|
+
* `decodePunycode` is false), and an
|
|
7
|
+
* address part that hides an encoded word is dropped unless it decodes to a plain `local@domain`
|
|
8
|
+
* (RFC 2047 keeps encoded words out of the address, so `=?utf-8?B?...?=@example.com` naming
|
|
9
|
+
* another address is not taken at its word).
|
|
10
|
+
*
|
|
11
|
+
* The value is the header value without the `Name:` prefix, as a string. Line folding may be left
|
|
12
|
+
* in. Raw 8-bit bytes have to be decoded into the string first, eg. `buffer.toString('utf-8')`.
|
|
13
|
+
* Several values (a header that occurs more than once) can be given as an array: each is parsed
|
|
14
|
+
* on its own and the addresses are listed in order.
|
|
15
|
+
*
|
|
16
|
+
* @param value The header value, or several of them
|
|
17
|
+
* @param options See {@link ParseAddressHeaderOptions}
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseAddressHeader(value: string | string[] | null | undefined, options?: ParseAddressHeaderOptions): AddressObject;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.decodeAddresses = decodeAddresses;
|
|
7
|
+
exports.formatAddressesHTML = formatAddressesHTML;
|
|
8
|
+
exports.formatAddressesText = formatAddressesText;
|
|
9
|
+
exports.parseAddressHeader = parseAddressHeader;
|
|
10
|
+
const he_1 = __importDefault(require("he"));
|
|
11
|
+
const libmime_1 = __importDefault(require("libmime"));
|
|
12
|
+
const addressparser_1 = __importDefault(require("nodemailer/lib/addressparser"));
|
|
13
|
+
const punycode_js_1 = __importDefault(require("punycode.js"));
|
|
14
|
+
// An RFC 2047 encoded word
|
|
15
|
+
const ENCODED_WORD = /[=]\?[^?]+\?[BbQq]\?[^?]*\?[=]/;
|
|
16
|
+
/**
|
|
17
|
+
* Decodes the addresses addressparser produced, in place: encoded words in display names, an
|
|
18
|
+
* internationalized (punycode) domain, and the members of a group.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
function decodeAddresses(addresses, decoder = libmime_1.default, decodePunycode = true) {
|
|
23
|
+
for (let address of addresses) {
|
|
24
|
+
address.name = (address.name || '').toString().trim();
|
|
25
|
+
// An encoded word decodes into the display name and nothing else, whatever it
|
|
26
|
+
// decodes to. RFC 2047 section 5 keeps encoded words out of the addr-spec, so a
|
|
27
|
+
// name that decodes to "CEO" <ceo@bank.com> is still only a name: parsing it
|
|
28
|
+
// again would report an address the header never carried
|
|
29
|
+
if (address.name) {
|
|
30
|
+
try {
|
|
31
|
+
address.name = decoder.decodeWords(address.name);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
//ignore, keep as is
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Security fix: detect RFC 2047 encoded-words in the address field.
|
|
38
|
+
// Per RFC 2047 Section 5, encoded-words MUST NOT appear in addr-spec.
|
|
39
|
+
// If found, decode and validate; reject if result is not a simple local@domain.
|
|
40
|
+
if (address.address && ENCODED_WORD.test(address.address)) {
|
|
41
|
+
try {
|
|
42
|
+
let decodedAddr = decoder.decodeWords(address.address);
|
|
43
|
+
if (/^[^\s@]+@[^\s@]+$/.test(decodedAddr) && !/[=]\?/.test(decodedAddr)) {
|
|
44
|
+
address.address = decodedAddr;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
address.address = '';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
address.address = '';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (decodePunycode && address.address && /@xn--/.test(address.address)) {
|
|
55
|
+
try {
|
|
56
|
+
address.address =
|
|
57
|
+
address.address.slice(0, address.address.lastIndexOf('@') + 1) +
|
|
58
|
+
punycode_js_1.default.toUnicode(address.address.slice(address.address.lastIndexOf('@') + 1));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// Not a valid punycode string; keep as is
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (address.group) {
|
|
65
|
+
decodeAddresses(address.group, decoder, decodePunycode);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Formats parsed addresses for an HTML context, every value HTML-escaped.
|
|
71
|
+
*
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
74
|
+
function formatAddressesHTML(value) {
|
|
75
|
+
let formatSingleLevel = (addresses) => addresses
|
|
76
|
+
.map(address => {
|
|
77
|
+
let str = '<span class="mp_address_group">';
|
|
78
|
+
if (address.name) {
|
|
79
|
+
str += '<span class="mp_address_name">' + he_1.default.encode(address.name) + (address.group ? ': ' : '') + '</span>';
|
|
80
|
+
}
|
|
81
|
+
if (address.address) {
|
|
82
|
+
let link = '<a href="mailto:' + he_1.default.encode(address.address) + '" class="mp_address_email">' + he_1.default.encode(address.address) + '</a>';
|
|
83
|
+
if (address.name) {
|
|
84
|
+
str += ' <' + link + '>';
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
str += link;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (address.group) {
|
|
91
|
+
str += formatSingleLevel(address.group) + ';';
|
|
92
|
+
}
|
|
93
|
+
return str + '</span>';
|
|
94
|
+
})
|
|
95
|
+
.join(', ');
|
|
96
|
+
return formatSingleLevel([].concat(value || []));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Formats parsed addresses as plain text, display names quoted.
|
|
100
|
+
*
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
function formatAddressesText(value) {
|
|
104
|
+
let formatSingleLevel = (addresses) => addresses
|
|
105
|
+
.map(address => {
|
|
106
|
+
let str = '';
|
|
107
|
+
if (address.name) {
|
|
108
|
+
// a quoted-string, so a quote or backslash inside the name is escaped
|
|
109
|
+
str += `"${address.name.replace(/["\\]/g, '\\$&')}"` + (address.group ? ': ' : '');
|
|
110
|
+
}
|
|
111
|
+
if (address.address) {
|
|
112
|
+
let link = address.address;
|
|
113
|
+
if (address.name) {
|
|
114
|
+
str += ' <' + link + '>';
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
str += link;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (address.group) {
|
|
121
|
+
str += formatSingleLevel(address.group) + ';';
|
|
122
|
+
}
|
|
123
|
+
return str;
|
|
124
|
+
})
|
|
125
|
+
.join(', ');
|
|
126
|
+
return formatSingleLevel([].concat(value || []));
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Parses the value of an address header (`From`, `To`, `Cc`, `Reply-To` and the like) into the
|
|
130
|
+
* {@link AddressObject} `MailParser` and `simpleParser` produce for one: display names have their
|
|
131
|
+
* encoded words decoded, an internationalized (punycode) domain is decoded to Unicode (unless
|
|
132
|
+
* `decodePunycode` is false), and an
|
|
133
|
+
* address part that hides an encoded word is dropped unless it decodes to a plain `local@domain`
|
|
134
|
+
* (RFC 2047 keeps encoded words out of the address, so `=?utf-8?B?...?=@example.com` naming
|
|
135
|
+
* another address is not taken at its word).
|
|
136
|
+
*
|
|
137
|
+
* The value is the header value without the `Name:` prefix, as a string. Line folding may be left
|
|
138
|
+
* in. Raw 8-bit bytes have to be decoded into the string first, eg. `buffer.toString('utf-8')`.
|
|
139
|
+
* Several values (a header that occurs more than once) can be given as an array: each is parsed
|
|
140
|
+
* on its own and the addresses are listed in order.
|
|
141
|
+
*
|
|
142
|
+
* @param value The header value, or several of them
|
|
143
|
+
* @param options See {@link ParseAddressHeaderOptions}
|
|
144
|
+
*/
|
|
145
|
+
function parseAddressHeader(value, options) {
|
|
146
|
+
let addresses = [];
|
|
147
|
+
for (let entry of [].concat(value)) {
|
|
148
|
+
if (typeof entry !== 'string' || !entry) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
let parsed = (0, addressparser_1.default)(entry, { flatten: !!options?.flatten });
|
|
152
|
+
decodeAddresses(parsed, libmime_1.default, options?.decodePunycode !== false);
|
|
153
|
+
for (let address of parsed) {
|
|
154
|
+
addresses.push(address);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return withLazyFormats(addresses);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The AddressObject for parsed addresses, with `html` and `text` built on first read: a caller
|
|
161
|
+
* that only wants the addresses (eg. for an SMTP envelope) pays for neither. Both stay enumerable
|
|
162
|
+
* and assignable, to read, compare, serialize and overwrite like the plain values they were.
|
|
163
|
+
*/
|
|
164
|
+
function withLazyFormats(addresses) {
|
|
165
|
+
let html;
|
|
166
|
+
let text;
|
|
167
|
+
const result = { value: addresses };
|
|
168
|
+
Object.defineProperties(result, {
|
|
169
|
+
html: {
|
|
170
|
+
enumerable: true,
|
|
171
|
+
get: () => (html ??= formatAddressesHTML(addresses)),
|
|
172
|
+
set: value => {
|
|
173
|
+
html = value;
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
text: {
|
|
177
|
+
enumerable: true,
|
|
178
|
+
get: () => (text ??= formatAddressesText(addresses)),
|
|
179
|
+
set: value => {
|
|
180
|
+
text = value;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import MailParser from './mail-parser.js';
|
|
2
2
|
import simpleParser from './simple-parser.js';
|
|
3
|
-
|
|
3
|
+
import { parseAddressHeader } from './address-header.js';
|
|
4
|
+
export { MailParser, simpleParser, parseAddressHeader };
|
|
4
5
|
export type { SimpleParserCallback } from './simple-parser.js';
|
|
5
6
|
export type * from './types.js';
|
|
6
7
|
declare const _default: {
|
|
7
8
|
MailParser: typeof MailParser;
|
|
8
9
|
simpleParser: typeof simpleParser;
|
|
10
|
+
parseAddressHeader: typeof parseAddressHeader;
|
|
9
11
|
};
|
|
10
12
|
export default _default;
|
|
@@ -3,10 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.simpleParser = exports.MailParser = void 0;
|
|
6
|
+
exports.parseAddressHeader = exports.simpleParser = exports.MailParser = void 0;
|
|
7
7
|
const mail_parser_js_1 = __importDefault(require("./mail-parser.js"));
|
|
8
8
|
exports.MailParser = mail_parser_js_1.default;
|
|
9
9
|
const simple_parser_js_1 = __importDefault(require("./simple-parser.js"));
|
|
10
10
|
exports.simpleParser = simple_parser_js_1.default;
|
|
11
|
-
|
|
11
|
+
const address_header_js_1 = require("./address-header.js");
|
|
12
|
+
Object.defineProperty(exports, "parseAddressHeader", { enumerable: true, get: function () { return address_header_js_1.parseAddressHeader; } });
|
|
13
|
+
exports.default = { MailParser: mail_parser_js_1.default, simpleParser: simple_parser_js_1.default, parseAddressHeader: address_header_js_1.parseAddressHeader };
|
|
12
14
|
Object.defineProperty(exports, 'default', { value: exports, enumerable: false, writable: true, configurable: true });
|