@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
|
@@ -5,17 +5,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const mailsplit_1 = __importDefault(require("@zone-eu/mailsplit"));
|
|
7
7
|
const flowed_decoder_js_1 = __importDefault(require("@zone-eu/mailsplit/lib/flowed-decoder.js"));
|
|
8
|
-
const encoding_japanese_1 = __importDefault(require("encoding-japanese"));
|
|
9
8
|
const he_1 = __importDefault(require("he"));
|
|
10
9
|
const html_to_text_1 = require("html-to-text");
|
|
11
|
-
const iconv_lite_1 = __importDefault(require("iconv-lite"));
|
|
12
10
|
const libmime_1 = __importDefault(require("libmime"));
|
|
13
11
|
const linkify_it_1 = __importDefault(require("linkify-it"));
|
|
14
12
|
const addressparser_1 = __importDefault(require("nodemailer/lib/addressparser"));
|
|
15
|
-
const punycode_js_1 = __importDefault(require("punycode.js"));
|
|
16
13
|
const node_stream_1 = require("node:stream");
|
|
17
14
|
const tlds_cjs_1 = __importDefault(require("./tlds.cjs"));
|
|
18
15
|
const stream_hash_js_1 = __importDefault(require("./stream-hash.js"));
|
|
16
|
+
const address_header_js_1 = require("./address-header.js");
|
|
19
17
|
const { Splitter, ChunkedPassthrough } = mailsplit_1.default;
|
|
20
18
|
// Bounds for link detection in text bodies. Message content is untrusted and
|
|
21
19
|
// linkify-it backtracks heavily on crafted input: matching a host is quadratic
|
|
@@ -77,49 +75,6 @@ linkify.add('@', {
|
|
|
77
75
|
match.url = 'https://twitter.com/' + match.url.replace(/^@/, '');
|
|
78
76
|
}
|
|
79
77
|
});
|
|
80
|
-
// Lists the parameters a header value gives in RFC 2231 form (name*=, name*0= or
|
|
81
|
-
// name*0*=). libmime decodes those while parsing the header, so the result must not go
|
|
82
|
-
// through decodeWords as well: filename*=utf-8''a%3D%3Futf-8%3FQ%3F%3D2Eexe%3F%3D would
|
|
83
|
-
// otherwise come out as "a.exe" while a parser that decodes once sees the encoded word.
|
|
84
|
-
function rfc2231ParamNames(value) {
|
|
85
|
-
let names = new Set();
|
|
86
|
-
let quote = false;
|
|
87
|
-
let escaped = false;
|
|
88
|
-
let start = 0;
|
|
89
|
-
let addSegment = (end) => {
|
|
90
|
-
let segment = value.substring(start, end);
|
|
91
|
-
let eq = segment.indexOf('=');
|
|
92
|
-
if (eq < 0) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
let match = segment
|
|
96
|
-
.substring(0, eq)
|
|
97
|
-
.trim()
|
|
98
|
-
.toLowerCase()
|
|
99
|
-
.match(/^(.+?)\*(\d+\*?)?$/);
|
|
100
|
-
if (match) {
|
|
101
|
-
names.add(match[1]);
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
for (let i = 0; i < value.length; i++) {
|
|
105
|
-
let chr = value.charAt(i);
|
|
106
|
-
if (escaped) {
|
|
107
|
-
escaped = false;
|
|
108
|
-
}
|
|
109
|
-
else if (chr === '\\') {
|
|
110
|
-
escaped = true;
|
|
111
|
-
}
|
|
112
|
-
else if (chr === '"') {
|
|
113
|
-
quote = !quote;
|
|
114
|
-
}
|
|
115
|
-
else if (chr === ';' && !quote) {
|
|
116
|
-
addSegment(i);
|
|
117
|
-
start = i + 1;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
addSegment(value.length);
|
|
121
|
-
return names;
|
|
122
|
-
}
|
|
123
78
|
// Deepest element nesting html-to-text is asked to convert. htmlparser2 keeps its open
|
|
124
79
|
// element stack at the front of an array, so parsing alone is quadratic in the nesting
|
|
125
80
|
// depth (200k nested <b> took 9 s), and html-to-text's recursive walk overflows the call
|
|
@@ -189,6 +144,14 @@ function exceedsHtmlNestingDepth(html, maxDepth) {
|
|
|
189
144
|
}
|
|
190
145
|
return false;
|
|
191
146
|
}
|
|
147
|
+
// Charsets a body is never decoded from, matched the way iconv-lite and node-iconv compare names
|
|
148
|
+
// (case and punctuation ignored). UTF-7 can carry markup past a filter that looks for "<" (a body
|
|
149
|
+
// of +ADw-script+AD4- decodes to <script>), base64 and hex are transfer encodings. libmime's decode
|
|
150
|
+
// stream refuses the same names, this check applies the refusal to the native Iconv option as well
|
|
151
|
+
const REFUSED_CHARSET = /^(?:(?:cs)?unicode11)?utf7(?:imap)?$|^base64$|^hex$/;
|
|
152
|
+
function isRefusedCharset(charset) {
|
|
153
|
+
return REFUSED_CHARSET.test((charset || '').toLowerCase().replace(/[^a-z0-9]/g, ''));
|
|
154
|
+
}
|
|
192
155
|
class IconvDecoder extends node_stream_1.Transform {
|
|
193
156
|
constructor(Iconv, charset) {
|
|
194
157
|
super();
|
|
@@ -218,41 +181,6 @@ class IconvDecoder extends node_stream_1.Transform {
|
|
|
218
181
|
this.stream.end();
|
|
219
182
|
}
|
|
220
183
|
}
|
|
221
|
-
class JPDecoder extends node_stream_1.Transform {
|
|
222
|
-
constructor(charset) {
|
|
223
|
-
super();
|
|
224
|
-
this.charset = charset;
|
|
225
|
-
this.chunks = [];
|
|
226
|
-
this.chunklen = 0;
|
|
227
|
-
}
|
|
228
|
-
_transform(chunk, encoding, done) {
|
|
229
|
-
if (typeof chunk === 'string') {
|
|
230
|
-
chunk = Buffer.from(chunk, encoding);
|
|
231
|
-
}
|
|
232
|
-
this.chunks.push(chunk);
|
|
233
|
-
this.chunklen += chunk.length;
|
|
234
|
-
done();
|
|
235
|
-
}
|
|
236
|
-
_flush(done) {
|
|
237
|
-
let input = Buffer.concat(this.chunks, this.chunklen);
|
|
238
|
-
try {
|
|
239
|
-
let output = encoding_japanese_1.default.convert(input, {
|
|
240
|
-
to: 'UNICODE', // to_encoding
|
|
241
|
-
from: this.charset, // from_encoding
|
|
242
|
-
type: 'string'
|
|
243
|
-
});
|
|
244
|
-
if (typeof output === 'string') {
|
|
245
|
-
output = Buffer.from(output);
|
|
246
|
-
}
|
|
247
|
-
this.push(output);
|
|
248
|
-
}
|
|
249
|
-
catch {
|
|
250
|
-
// keep as is on errors
|
|
251
|
-
this.push(input);
|
|
252
|
-
}
|
|
253
|
-
done();
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
184
|
/**
|
|
257
185
|
* A lower level, streaming e-mail parser. It is a Transform stream: write the raw message in and
|
|
258
186
|
* read the parsed content out. It emits:
|
|
@@ -328,6 +256,10 @@ class MailParser extends node_stream_1.Transform {
|
|
|
328
256
|
// create wrapper
|
|
329
257
|
return {
|
|
330
258
|
decodeStream(charset) {
|
|
259
|
+
if (isRefusedCharset(charset)) {
|
|
260
|
+
// the same refusal as without the Iconv option, see below
|
|
261
|
+
return libmime_1.default.createDecodeStream(charset);
|
|
262
|
+
}
|
|
331
263
|
// node-iconv resolves its own charset aliases and needs charset-specific
|
|
332
264
|
// fixups (see IconvDecoder, eg. ks_c_5601-1987), so pass the charset through as is
|
|
333
265
|
return new IconvDecoder(Iconv, charset);
|
|
@@ -337,13 +269,12 @@ class MailParser extends node_stream_1.Transform {
|
|
|
337
269
|
else {
|
|
338
270
|
return {
|
|
339
271
|
decodeStream(charset) {
|
|
340
|
-
//
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
return iconv_lite_1.default.decodeStream(charset);
|
|
272
|
+
// libmime resolves charset aliases (eg. iso-8859-8-i -> ISO-8859-8), decodes the
|
|
273
|
+
// Japanese charsets iconv-lite lacks and keeps a multibyte character split across
|
|
274
|
+
// chunks intact. A charset it does not know or refuses (UTF-7, which would turn
|
|
275
|
+
// +ADw-script+AD4- into <script>, and the base64 and hex transfer encodings) is
|
|
276
|
+
// decoded as UTF-8 with invalid bytes replaced, the same as encoded words get
|
|
277
|
+
return libmime_1.default.createDecodeStream(charset || 'ascii');
|
|
347
278
|
}
|
|
348
279
|
};
|
|
349
280
|
}
|
|
@@ -446,9 +377,18 @@ class MailParser extends node_stream_1.Transform {
|
|
|
446
377
|
case 'content-type':
|
|
447
378
|
case 'content-disposition':
|
|
448
379
|
case 'dkim-signature': {
|
|
449
|
-
// a
|
|
450
|
-
|
|
451
|
-
|
|
380
|
+
// The comments of a MIME header are not part of its value, so they are
|
|
381
|
+
// dropped as mailsplit drops them for the structure: `boundary=b (comment)`
|
|
382
|
+
// names the boundary `b`. A DKIM-Signature is a tag list without comment
|
|
383
|
+
// syntax, so a parenthesis in a tag value is data
|
|
384
|
+
value = this.libmime.parseHeaderValue(value, { stripComments: key !== 'dkim-signature' });
|
|
385
|
+
// A parameter given in RFC 2231 form was decoded by parseHeaderValue already,
|
|
386
|
+
// which names it in decodedParams, and must not go through decodeWords as
|
|
387
|
+
// well: filename*=utf-8''a%3D%3Futf-8%3FQ%3F%3D2Eexe%3F%3D would otherwise come
|
|
388
|
+
// out as a.exe while a parser that decodes once sees the encoded word. A
|
|
389
|
+
// second scan of the raw header for the name used to decide this, and read
|
|
390
|
+
// `(c)filename*=` as `(c)filename` once the comment was dropped from the real one
|
|
391
|
+
let rfc2231 = new Set(value.decodedParams);
|
|
452
392
|
if (value.value) {
|
|
453
393
|
value.value = this.libmime.decodeWords(value.value);
|
|
454
394
|
}
|
|
@@ -681,52 +621,7 @@ class MailParser extends node_stream_1.Transform {
|
|
|
681
621
|
}
|
|
682
622
|
/** @internal */
|
|
683
623
|
decodeAddresses(addresses) {
|
|
684
|
-
|
|
685
|
-
let address = addresses[i];
|
|
686
|
-
address.name = (address.name || '').toString().trim();
|
|
687
|
-
// An encoded word decodes into the display name and nothing else, whatever it
|
|
688
|
-
// decodes to. RFC 2047 section 5 keeps encoded words out of the addr-spec, so a
|
|
689
|
-
// name that decodes to "CEO" <ceo@bank.com> is still only a name: parsing it
|
|
690
|
-
// again would report an address the header never carried
|
|
691
|
-
if (address.name) {
|
|
692
|
-
try {
|
|
693
|
-
address.name = this.libmime.decodeWords(address.name);
|
|
694
|
-
}
|
|
695
|
-
catch {
|
|
696
|
-
//ignore, keep as is
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
// Security fix: detect RFC 2047 encoded-words in the address field.
|
|
700
|
-
// Per RFC 2047 Section 5, encoded-words MUST NOT appear in addr-spec.
|
|
701
|
-
// If found, decode and validate; reject if result is not a simple local@domain.
|
|
702
|
-
if (address.address && /[=]\?[^?]+\?[BbQq]\?[^?]*\?[=]/.test(address.address)) {
|
|
703
|
-
try {
|
|
704
|
-
let decodedAddr = this.libmime.decodeWords(address.address);
|
|
705
|
-
if (/^[^\s@]+@[^\s@]+$/.test(decodedAddr) && !/[=]\?/.test(decodedAddr)) {
|
|
706
|
-
address.address = decodedAddr;
|
|
707
|
-
}
|
|
708
|
-
else {
|
|
709
|
-
address.address = '';
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
catch {
|
|
713
|
-
address.address = '';
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
if (address.address && /@xn--/.test(address.address)) {
|
|
717
|
-
try {
|
|
718
|
-
address.address =
|
|
719
|
-
address.address.slice(0, address.address.lastIndexOf('@') + 1) +
|
|
720
|
-
punycode_js_1.default.toUnicode(address.address.slice(address.address.lastIndexOf('@') + 1));
|
|
721
|
-
}
|
|
722
|
-
catch {
|
|
723
|
-
// Not a valid punycode string; keep as is
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (address.group) {
|
|
727
|
-
this.decodeAddresses(address.group);
|
|
728
|
-
}
|
|
729
|
-
}
|
|
624
|
+
(0, address_header_js_1.decodeAddresses)(addresses, this.libmime);
|
|
730
625
|
}
|
|
731
626
|
/** @internal */
|
|
732
627
|
createNode(node) {
|
|
@@ -1008,7 +903,8 @@ class MailParser extends node_stream_1.Transform {
|
|
|
1008
903
|
this.waitUntilAttachmentEnd = false;
|
|
1009
904
|
}
|
|
1010
905
|
};
|
|
1011
|
-
|
|
906
|
+
// false skips hashing, checksum is then left unset
|
|
907
|
+
let algo = this.options.checksumAlgo === false ? false : this.options.checksumAlgo || 'md5';
|
|
1012
908
|
let hasher;
|
|
1013
909
|
try {
|
|
1014
910
|
hasher = new stream_hash_js_1.default(attachment, algo);
|
|
@@ -1161,56 +1057,13 @@ class MailParser extends node_stream_1.Transform {
|
|
|
1161
1057
|
* Formats parsed addresses for an HTML context, every value HTML-escaped.
|
|
1162
1058
|
*/
|
|
1163
1059
|
getAddressesHTML(value) {
|
|
1164
|
-
|
|
1165
|
-
.map(address => {
|
|
1166
|
-
let str = '<span class="mp_address_group">';
|
|
1167
|
-
if (address.name) {
|
|
1168
|
-
str += '<span class="mp_address_name">' + he_1.default.encode(address.name) + (address.group ? ': ' : '') + '</span>';
|
|
1169
|
-
}
|
|
1170
|
-
if (address.address) {
|
|
1171
|
-
let link = '<a href="mailto:' + he_1.default.encode(address.address) + '" class="mp_address_email">' + he_1.default.encode(address.address) + '</a>';
|
|
1172
|
-
if (address.name) {
|
|
1173
|
-
str += ' <' + link + '>';
|
|
1174
|
-
}
|
|
1175
|
-
else {
|
|
1176
|
-
str += link;
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
if (address.group) {
|
|
1180
|
-
str += formatSingleLevel(address.group) + ';';
|
|
1181
|
-
}
|
|
1182
|
-
return str + '</span>';
|
|
1183
|
-
})
|
|
1184
|
-
.join(', ');
|
|
1185
|
-
return formatSingleLevel([].concat(value || []));
|
|
1060
|
+
return (0, address_header_js_1.formatAddressesHTML)(value);
|
|
1186
1061
|
}
|
|
1187
1062
|
/**
|
|
1188
1063
|
* Formats parsed addresses as plain text, display names quoted.
|
|
1189
1064
|
*/
|
|
1190
1065
|
getAddressesText(value) {
|
|
1191
|
-
|
|
1192
|
-
.map(address => {
|
|
1193
|
-
let str = '';
|
|
1194
|
-
if (address.name) {
|
|
1195
|
-
// a quoted-string, so a quote or backslash inside the name is escaped
|
|
1196
|
-
str += `"${address.name.replace(/["\\]/g, '\\$&')}"` + (address.group ? ': ' : '');
|
|
1197
|
-
}
|
|
1198
|
-
if (address.address) {
|
|
1199
|
-
let link = address.address;
|
|
1200
|
-
if (address.name) {
|
|
1201
|
-
str += ' <' + link + '>';
|
|
1202
|
-
}
|
|
1203
|
-
else {
|
|
1204
|
-
str += link;
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
if (address.group) {
|
|
1208
|
-
str += formatSingleLevel(address.group) + ';';
|
|
1209
|
-
}
|
|
1210
|
-
return str;
|
|
1211
|
-
})
|
|
1212
|
-
.join(', ');
|
|
1213
|
-
return formatSingleLevel([].concat(value || []));
|
|
1066
|
+
return (0, address_header_js_1.formatAddressesText)(value);
|
|
1214
1067
|
}
|
|
1215
1068
|
/**
|
|
1216
1069
|
* Replaces `cid:` links to image attachments in the HTML content. Call it once the parser has
|
|
@@ -10,14 +10,15 @@ export interface HashTarget {
|
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* A pass-through stream that records the checksum and byte size of what flows through it on the
|
|
13
|
-
* given object once the stream ends. Throws when the hash algorithm is not available.
|
|
13
|
+
* given object once the stream ends. Throws when the hash algorithm is not available. With `algo`
|
|
14
|
+
* set to `false` nothing is hashed and only the size is recorded.
|
|
14
15
|
*/
|
|
15
16
|
declare class StreamHash extends Transform {
|
|
16
17
|
attachment: HashTarget;
|
|
17
|
-
algo: string;
|
|
18
|
-
hash: crypto.Hash;
|
|
18
|
+
algo: string | false;
|
|
19
|
+
hash: crypto.Hash | null;
|
|
19
20
|
byteCount: number;
|
|
20
|
-
constructor(attachment: HashTarget, algo?: string);
|
|
21
|
+
constructor(attachment: HashTarget, algo?: string | false);
|
|
21
22
|
_transform(chunk: Buffer, encoding: BufferEncoding, done: TransformCallback): void;
|
|
22
23
|
_flush(done: TransformCallback): void;
|
|
23
24
|
}
|
|
@@ -7,23 +7,26 @@ const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
|
7
7
|
const node_stream_1 = require("node:stream");
|
|
8
8
|
/**
|
|
9
9
|
* A pass-through stream that records the checksum and byte size of what flows through it on the
|
|
10
|
-
* given object once the stream ends. Throws when the hash algorithm is not available.
|
|
10
|
+
* given object once the stream ends. Throws when the hash algorithm is not available. With `algo`
|
|
11
|
+
* set to `false` nothing is hashed and only the size is recorded.
|
|
11
12
|
*/
|
|
12
13
|
class StreamHash extends node_stream_1.Transform {
|
|
13
14
|
constructor(attachment, algo) {
|
|
14
15
|
super();
|
|
15
16
|
this.attachment = attachment;
|
|
16
|
-
this.algo = (algo || 'md5').toLowerCase();
|
|
17
|
-
this.hash = node_crypto_1.default.createHash(this.algo);
|
|
17
|
+
this.algo = algo === false ? false : (algo || 'md5').toLowerCase();
|
|
18
|
+
this.hash = this.algo === false ? null : node_crypto_1.default.createHash(this.algo);
|
|
18
19
|
this.byteCount = 0;
|
|
19
20
|
}
|
|
20
21
|
_transform(chunk, encoding, done) {
|
|
21
|
-
this.hash
|
|
22
|
+
this.hash?.update(chunk);
|
|
22
23
|
this.byteCount += chunk.length;
|
|
23
24
|
done(null, chunk);
|
|
24
25
|
}
|
|
25
26
|
_flush(done) {
|
|
26
|
-
|
|
27
|
+
if (this.hash) {
|
|
28
|
+
this.attachment.checksum = this.hash.digest('hex');
|
|
29
|
+
}
|
|
27
30
|
this.attachment.size = this.byteCount;
|
|
28
31
|
done();
|
|
29
32
|
}
|
|
@@ -37,6 +37,24 @@ export interface AddressObject {
|
|
|
37
37
|
/** The addresses formatted as plain text, display names quoted. */
|
|
38
38
|
text: string;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Options for `parseAddressHeader`.
|
|
42
|
+
*/
|
|
43
|
+
export interface ParseAddressHeaderOptions {
|
|
44
|
+
/**
|
|
45
|
+
* Replace every group with its members, so the result lists mailboxes only and the group names
|
|
46
|
+
* are dropped.
|
|
47
|
+
* @default false
|
|
48
|
+
*/
|
|
49
|
+
flatten?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Decode an internationalized (punycode) domain to Unicode. Set to false to keep the domain as
|
|
52
|
+
* it appears in the header, for an address that is going to be used to send mail, such as an
|
|
53
|
+
* SMTP envelope, where the ASCII form is the one every server accepts.
|
|
54
|
+
* @default true
|
|
55
|
+
*/
|
|
56
|
+
decodePunycode?: boolean;
|
|
57
|
+
}
|
|
40
58
|
/**
|
|
41
59
|
* One entry of the combined `list` header, built from a `List-*` header such as `List-Unsubscribe`.
|
|
42
60
|
*/
|
|
@@ -122,7 +140,10 @@ export interface AttachmentStream extends AttachmentCommon {
|
|
|
122
140
|
* message. Must be called for every attachment. Set to `null` once called.
|
|
123
141
|
*/
|
|
124
142
|
release: (() => void) | null;
|
|
125
|
-
/**
|
|
143
|
+
/**
|
|
144
|
+
* The hex encoded checksum of the content (md5 unless `checksumAlgo` says otherwise). Set once
|
|
145
|
+
* `content` has ended, never when `checksumAlgo` is `false`.
|
|
146
|
+
*/
|
|
126
147
|
checksum?: string;
|
|
127
148
|
/** The size of the decoded content in bytes. Set once `content` has ended. */
|
|
128
149
|
size?: number;
|
|
@@ -135,7 +156,11 @@ export interface Attachment extends AttachmentCommon {
|
|
|
135
156
|
content: Buffer;
|
|
136
157
|
/** Always `null`, `simpleParser` has released the attachment already. */
|
|
137
158
|
release: null;
|
|
138
|
-
/**
|
|
159
|
+
/**
|
|
160
|
+
* The hex encoded checksum of the content (md5 unless `checksumAlgo` says otherwise). Not set when
|
|
161
|
+
* `checksumAlgo` is `false`: the type keeps it a string so code written for the default does not
|
|
162
|
+
* have to check it, so a caller that turns hashing off must not read it.
|
|
163
|
+
*/
|
|
139
164
|
checksum: string;
|
|
140
165
|
/** The size of the decoded content in bytes. */
|
|
141
166
|
size: number;
|
|
@@ -211,16 +236,18 @@ export interface MailParserOptions {
|
|
|
211
236
|
*/
|
|
212
237
|
keepDeliveryStatus?: boolean;
|
|
213
238
|
/**
|
|
214
|
-
* Decode character sets with the native `iconv` module instead of
|
|
215
|
-
* `Iconv` class: `{ Iconv: require('iconv').Iconv }`.
|
|
239
|
+
* Decode the character sets of text bodies with the native `iconv` module instead of libmime's
|
|
240
|
+
* decoder (`iconv-lite`). Pass the `Iconv` class: `{ Iconv: require('iconv').Iconv }`. Bodies
|
|
241
|
+
* declared as UTF-7 are never decoded from it either way, see the note on charsets in the README.
|
|
216
242
|
*/
|
|
217
243
|
Iconv?: IconvConstructor;
|
|
218
244
|
/**
|
|
219
245
|
* The hash algorithm for attachment checksums, any name `crypto.createHash()` accepts. An algorithm
|
|
220
|
-
* that is not available makes the parser emit an error.
|
|
246
|
+
* that is not available makes the parser emit an error. `false` skips hashing attachments
|
|
247
|
+
* altogether, and their `checksum` is then not set (`size` still is).
|
|
221
248
|
* @default 'md5'
|
|
222
249
|
*/
|
|
223
|
-
checksumAlgo?: string;
|
|
250
|
+
checksumAlgo?: string | false;
|
|
224
251
|
/**
|
|
225
252
|
* The longest the URLs `updateImageLinks()` writes into the HTML may be in total, in characters.
|
|
226
253
|
* References past the limit are left as `cid:` links.
|
|
@@ -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,176 @@
|
|
|
1
|
+
import he from 'he';
|
|
2
|
+
import libmime from 'libmime';
|
|
3
|
+
import addressparser from 'nodemailer/lib/addressparser';
|
|
4
|
+
import punycode from 'punycode.js';
|
|
5
|
+
// An RFC 2047 encoded word
|
|
6
|
+
const ENCODED_WORD = /[=]\?[^?]+\?[BbQq]\?[^?]*\?[=]/;
|
|
7
|
+
/**
|
|
8
|
+
* Decodes the addresses addressparser produced, in place: encoded words in display names, an
|
|
9
|
+
* internationalized (punycode) domain, and the members of a group.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export function decodeAddresses(addresses, decoder = libmime, decodePunycode = true) {
|
|
14
|
+
for (let address of addresses) {
|
|
15
|
+
address.name = (address.name || '').toString().trim();
|
|
16
|
+
// An encoded word decodes into the display name and nothing else, whatever it
|
|
17
|
+
// decodes to. RFC 2047 section 5 keeps encoded words out of the addr-spec, so a
|
|
18
|
+
// name that decodes to "CEO" <ceo@bank.com> is still only a name: parsing it
|
|
19
|
+
// again would report an address the header never carried
|
|
20
|
+
if (address.name) {
|
|
21
|
+
try {
|
|
22
|
+
address.name = decoder.decodeWords(address.name);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
//ignore, keep as is
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Security fix: detect RFC 2047 encoded-words in the address field.
|
|
29
|
+
// Per RFC 2047 Section 5, encoded-words MUST NOT appear in addr-spec.
|
|
30
|
+
// If found, decode and validate; reject if result is not a simple local@domain.
|
|
31
|
+
if (address.address && ENCODED_WORD.test(address.address)) {
|
|
32
|
+
try {
|
|
33
|
+
let decodedAddr = decoder.decodeWords(address.address);
|
|
34
|
+
if (/^[^\s@]+@[^\s@]+$/.test(decodedAddr) && !/[=]\?/.test(decodedAddr)) {
|
|
35
|
+
address.address = decodedAddr;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
address.address = '';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
address.address = '';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (decodePunycode && address.address && /@xn--/.test(address.address)) {
|
|
46
|
+
try {
|
|
47
|
+
address.address =
|
|
48
|
+
address.address.slice(0, address.address.lastIndexOf('@') + 1) +
|
|
49
|
+
punycode.toUnicode(address.address.slice(address.address.lastIndexOf('@') + 1));
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// Not a valid punycode string; keep as is
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (address.group) {
|
|
56
|
+
decodeAddresses(address.group, decoder, decodePunycode);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Formats parsed addresses for an HTML context, every value HTML-escaped.
|
|
62
|
+
*
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
65
|
+
export function formatAddressesHTML(value) {
|
|
66
|
+
let formatSingleLevel = (addresses) => addresses
|
|
67
|
+
.map(address => {
|
|
68
|
+
let str = '<span class="mp_address_group">';
|
|
69
|
+
if (address.name) {
|
|
70
|
+
str += '<span class="mp_address_name">' + he.encode(address.name) + (address.group ? ': ' : '') + '</span>';
|
|
71
|
+
}
|
|
72
|
+
if (address.address) {
|
|
73
|
+
let link = '<a href="mailto:' + he.encode(address.address) + '" class="mp_address_email">' + he.encode(address.address) + '</a>';
|
|
74
|
+
if (address.name) {
|
|
75
|
+
str += ' <' + link + '>';
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
str += link;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (address.group) {
|
|
82
|
+
str += formatSingleLevel(address.group) + ';';
|
|
83
|
+
}
|
|
84
|
+
return str + '</span>';
|
|
85
|
+
})
|
|
86
|
+
.join(', ');
|
|
87
|
+
return formatSingleLevel([].concat(value || []));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Formats parsed addresses as plain text, display names quoted.
|
|
91
|
+
*
|
|
92
|
+
* @internal
|
|
93
|
+
*/
|
|
94
|
+
export function formatAddressesText(value) {
|
|
95
|
+
let formatSingleLevel = (addresses) => addresses
|
|
96
|
+
.map(address => {
|
|
97
|
+
let str = '';
|
|
98
|
+
if (address.name) {
|
|
99
|
+
// a quoted-string, so a quote or backslash inside the name is escaped
|
|
100
|
+
str += `"${address.name.replace(/["\\]/g, '\\$&')}"` + (address.group ? ': ' : '');
|
|
101
|
+
}
|
|
102
|
+
if (address.address) {
|
|
103
|
+
let link = address.address;
|
|
104
|
+
if (address.name) {
|
|
105
|
+
str += ' <' + link + '>';
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
str += link;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (address.group) {
|
|
112
|
+
str += formatSingleLevel(address.group) + ';';
|
|
113
|
+
}
|
|
114
|
+
return str;
|
|
115
|
+
})
|
|
116
|
+
.join(', ');
|
|
117
|
+
return formatSingleLevel([].concat(value || []));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Parses the value of an address header (`From`, `To`, `Cc`, `Reply-To` and the like) into the
|
|
121
|
+
* {@link AddressObject} `MailParser` and `simpleParser` produce for one: display names have their
|
|
122
|
+
* encoded words decoded, an internationalized (punycode) domain is decoded to Unicode (unless
|
|
123
|
+
* `decodePunycode` is false), and an
|
|
124
|
+
* address part that hides an encoded word is dropped unless it decodes to a plain `local@domain`
|
|
125
|
+
* (RFC 2047 keeps encoded words out of the address, so `=?utf-8?B?...?=@example.com` naming
|
|
126
|
+
* another address is not taken at its word).
|
|
127
|
+
*
|
|
128
|
+
* The value is the header value without the `Name:` prefix, as a string. Line folding may be left
|
|
129
|
+
* in. Raw 8-bit bytes have to be decoded into the string first, eg. `buffer.toString('utf-8')`.
|
|
130
|
+
* Several values (a header that occurs more than once) can be given as an array: each is parsed
|
|
131
|
+
* on its own and the addresses are listed in order.
|
|
132
|
+
*
|
|
133
|
+
* @param value The header value, or several of them
|
|
134
|
+
* @param options See {@link ParseAddressHeaderOptions}
|
|
135
|
+
*/
|
|
136
|
+
export function parseAddressHeader(value, options) {
|
|
137
|
+
let addresses = [];
|
|
138
|
+
for (let entry of [].concat(value)) {
|
|
139
|
+
if (typeof entry !== 'string' || !entry) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
let parsed = addressparser(entry, { flatten: !!options?.flatten });
|
|
143
|
+
decodeAddresses(parsed, libmime, options?.decodePunycode !== false);
|
|
144
|
+
for (let address of parsed) {
|
|
145
|
+
addresses.push(address);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return withLazyFormats(addresses);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* The AddressObject for parsed addresses, with `html` and `text` built on first read: a caller
|
|
152
|
+
* that only wants the addresses (eg. for an SMTP envelope) pays for neither. Both stay enumerable
|
|
153
|
+
* and assignable, to read, compare, serialize and overwrite like the plain values they were.
|
|
154
|
+
*/
|
|
155
|
+
function withLazyFormats(addresses) {
|
|
156
|
+
let html;
|
|
157
|
+
let text;
|
|
158
|
+
const result = { value: addresses };
|
|
159
|
+
Object.defineProperties(result, {
|
|
160
|
+
html: {
|
|
161
|
+
enumerable: true,
|
|
162
|
+
get: () => (html ??= formatAddressesHTML(addresses)),
|
|
163
|
+
set: value => {
|
|
164
|
+
html = value;
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
text: {
|
|
168
|
+
enumerable: true,
|
|
169
|
+
get: () => (text ??= formatAddressesText(addresses)),
|
|
170
|
+
set: value => {
|
|
171
|
+
text = value;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
@@ -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;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import MailParser from './mail-parser.js';
|
|
2
2
|
import simpleParser from './simple-parser.js';
|
|
3
|
-
|
|
4
|
-
export
|
|
3
|
+
import { parseAddressHeader } from './address-header.js';
|
|
4
|
+
export { MailParser, simpleParser, parseAddressHeader };
|
|
5
|
+
export default { MailParser, simpleParser, parseAddressHeader };
|