@mavogel/awscdk-rootmail 0.1.27 → 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 +7 -7
- 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
|
@@ -117,9 +117,7 @@ function exceedsDomainLimits(domain) {
|
|
|
117
117
|
*/
|
|
118
118
|
function normalizeDomain(domain, toUnicode) {
|
|
119
119
|
// domainToASCII and domainToUnicode landed in Node 7, the bundled codec covers Node 6
|
|
120
|
-
if (typeof urlModule.domainToASCII === 'function' &&
|
|
121
|
-
typeof urlModule.domainToUnicode === 'function' &&
|
|
122
|
-
!URL_PARSER_UNSAFE.test(domain)) {
|
|
120
|
+
if (typeof urlModule.domainToASCII === 'function' && typeof urlModule.domainToUnicode === 'function' && !URL_PARSER_UNSAFE.test(domain)) {
|
|
123
121
|
// The U-label form is decoded from the A-label form rather than from the input:
|
|
124
122
|
// Deno's domainToASCII returns an empty string for a label it cannot decode, while
|
|
125
123
|
// its domainToUnicode returns the label with U+FFFD in place of the bad part
|
|
@@ -618,23 +616,24 @@ class MimeNode {
|
|
|
618
616
|
return;
|
|
619
617
|
}
|
|
620
618
|
switch (header.key) {
|
|
619
|
+
// The comments of a MIME header are not part of its value and are dropped, so a
|
|
620
|
+
// caller supplied 'boundary=b (comment)' is the boundary b it names, and the
|
|
621
|
+
// header goes out without the comment
|
|
621
622
|
case 'Content-Disposition':
|
|
622
|
-
structured = mimeFuncs.parseHeaderValue(value);
|
|
623
|
+
structured = mimeFuncs.parseHeaderValue(value, { stripComments: true });
|
|
623
624
|
if (this.filename) {
|
|
624
625
|
structured.params.filename = this.filename;
|
|
625
626
|
}
|
|
626
627
|
value = mimeFuncs.buildHeaderValue(structured);
|
|
627
628
|
break;
|
|
628
629
|
case 'Content-Type':
|
|
629
|
-
structured = mimeFuncs.parseHeaderValue(value);
|
|
630
|
+
structured = mimeFuncs.parseHeaderValue(value, { stripComments: true });
|
|
630
631
|
// the type token decides multipart and charset below, so clean it before
|
|
631
632
|
// those run and not just on the way out, otherwise a control char makes
|
|
632
633
|
// the checks miss and the header ends up claiming a type it is not set up for
|
|
633
634
|
structured.value = (structured.value || '').toString().replace(/[\x00-\x1f\x7f]/g, '');
|
|
634
635
|
this._handleContentType(structured);
|
|
635
|
-
if (structured.value.match(/^text\/plain\b/) &&
|
|
636
|
-
typeof this.content === 'string' &&
|
|
637
|
-
/[\u0080-\uFFFF]/.test(this.content)) {
|
|
636
|
+
if (structured.value.match(/^text\/plain\b/) && typeof this.content === 'string' && /[\u0080-\uFFFF]/.test(this.content)) {
|
|
638
637
|
structured.params.charset = 'utf-8';
|
|
639
638
|
}
|
|
640
639
|
if (this.filename) {
|
|
@@ -675,7 +674,7 @@ class MimeNode {
|
|
|
675
674
|
}
|
|
676
675
|
break;
|
|
677
676
|
}
|
|
678
|
-
value = this.
|
|
677
|
+
value = this.encodeHeaderValue(key, value);
|
|
679
678
|
// skip empty lines
|
|
680
679
|
if (!(value || '').toString().trim()) {
|
|
681
680
|
return;
|
|
@@ -1293,8 +1292,7 @@ class MimeNode {
|
|
|
1293
1292
|
// where it came from. MimeNode is exported and subclassable, so the generator is
|
|
1294
1293
|
// not necessarily the one below. Stripping twice costs nothing, it is idempotent.
|
|
1295
1294
|
const declared = _stripBoundaryControls(structured.params.boundary || this.boundary || '');
|
|
1296
|
-
this.boundary = structured.params.boundary =
|
|
1297
|
-
declared || _stripBoundaryControls(this._generateBoundary());
|
|
1295
|
+
this.boundary = structured.params.boundary = declared || _stripBoundaryControls(this._generateBoundary());
|
|
1298
1296
|
}
|
|
1299
1297
|
else {
|
|
1300
1298
|
this.boundary = false;
|
|
@@ -1312,13 +1310,19 @@ class MimeNode {
|
|
|
1312
1310
|
return _stripBoundaryControls(this.rootNode.boundaryPrefix + '-' + this.rootNode.baseBoundary) + '-Part_' + this._nodeId;
|
|
1313
1311
|
}
|
|
1314
1312
|
/**
|
|
1315
|
-
* Encodes a header value
|
|
1313
|
+
* Encodes a header value the way this node encodes it in the generated message:
|
|
1314
|
+
* address headers are punycoded and mime encoded, message id headers get their
|
|
1315
|
+
* angle brackets, a Date object is formatted and any other value is mime encoded
|
|
1316
|
+
* when it holds non-ascii or control characters (using the node's `textEncoding`).
|
|
1316
1317
|
*
|
|
1317
|
-
*
|
|
1318
|
+
* The result is a single unfolded line without the key. Fold it before writing it
|
|
1319
|
+
* into a message, `key + ': ' + value` folded at 76 characters is what the node does.
|
|
1320
|
+
*
|
|
1321
|
+
* @param key Header key, case insensitive
|
|
1318
1322
|
* @param value Header value
|
|
1319
|
-
* @
|
|
1323
|
+
* @returns Encoded header value
|
|
1320
1324
|
*/
|
|
1321
|
-
|
|
1325
|
+
encodeHeaderValue(key, value) {
|
|
1322
1326
|
key = this._normalizeHeaderKey(key);
|
|
1323
1327
|
switch (key) {
|
|
1324
1328
|
// Structured headers
|
|
@@ -1383,6 +1387,27 @@ class MimeNode {
|
|
|
1383
1387
|
return this._encodeHeaderText(value);
|
|
1384
1388
|
}
|
|
1385
1389
|
}
|
|
1390
|
+
/**
|
|
1391
|
+
* Encodes a header value without a node at hand. Same as the instance method of a
|
|
1392
|
+
* node created with the given options.
|
|
1393
|
+
*
|
|
1394
|
+
* @param key Header key, case insensitive
|
|
1395
|
+
* @param value Header value
|
|
1396
|
+
* @param [options] Encoding options
|
|
1397
|
+
* @param [options.textEncoding] either 'Q' (the default) or 'B'
|
|
1398
|
+
* @returns Encoded header value
|
|
1399
|
+
*/
|
|
1400
|
+
static encodeHeaderValue(key, value, options) {
|
|
1401
|
+
return new MimeNode(false, { textEncoding: options?.textEncoding }).encodeHeaderValue(key, value);
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* Alias of encodeHeaderValue, kept for callers that used the method before it was public
|
|
1405
|
+
*
|
|
1406
|
+
* @internal
|
|
1407
|
+
*/
|
|
1408
|
+
_encodeHeaderValue(key, value) {
|
|
1409
|
+
return this.encodeHeaderValue(key, value);
|
|
1410
|
+
}
|
|
1386
1411
|
/**
|
|
1387
1412
|
* Rebuilds address object using punycode and other adjustments
|
|
1388
1413
|
*
|
|
@@ -45,15 +45,9 @@ function encodeBytes(buffer, next, binary, previous) {
|
|
|
45
45
|
for (let i = 0; i < len; i++) {
|
|
46
46
|
const ord = buffer[i];
|
|
47
47
|
const following = i + 1 < len ? buffer[i + 1] : next;
|
|
48
|
-
const lineBreakByte = binary && (ord === 0x0d || ord === 0x0a)
|
|
49
|
-
? ord === 0x0d
|
|
50
|
-
? following === 0x0a
|
|
51
|
-
: (i > 0 ? buffer[i - 1] : previous) === 0x0d
|
|
52
|
-
: true;
|
|
48
|
+
const lineBreakByte = binary && (ord === 0x0d || ord === 0x0a) ? (ord === 0x0d ? following === 0x0a : (i > 0 ? buffer[i - 1] : previous) === 0x0d) : true;
|
|
53
49
|
// if the char is in allowed range, then keep as is, unless it is a WS in the end of a line
|
|
54
|
-
if (QP_LITERAL[ord] &&
|
|
55
|
-
lineBreakByte &&
|
|
56
|
-
!(isWhitespace(ord) && (following === undefined || following === 0x0a || following === 0x0d))) {
|
|
50
|
+
if (QP_LITERAL[ord] && lineBreakByte && !(isWhitespace(ord) && (following === undefined || following === 0x0a || following === 0x0d))) {
|
|
57
51
|
output[pos++] = ord;
|
|
58
52
|
continue;
|
|
59
53
|
}
|
|
@@ -114,10 +108,7 @@ export function wrap(str, lineLength) {
|
|
|
114
108
|
line = line.substr(0, line.length - match[0].length);
|
|
115
109
|
}
|
|
116
110
|
// ensure that utf-8 sequences are not split
|
|
117
|
-
while (line.length > 3 &&
|
|
118
|
-
line.length < len - pos &&
|
|
119
|
-
!line.match(/^(?:=[\da-f]{2}){1,4}$/i) &&
|
|
120
|
-
(match = line.match(/[=][\da-f]{2}$/gi))) {
|
|
111
|
+
while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/[=][\da-f]{2}$/gi))) {
|
|
121
112
|
code = parseInt(match[0].substr(1, 2), 16);
|
|
122
113
|
if (code < 128) {
|
|
123
114
|
break;
|
|
@@ -71,9 +71,7 @@ class SendmailTransport {
|
|
|
71
71
|
return done(err);
|
|
72
72
|
}
|
|
73
73
|
// force -i to keep single dots
|
|
74
|
-
const args = this.args
|
|
75
|
-
? ['-i'].concat(this.args).concat(envelope.to)
|
|
76
|
-
: ['-i'].concat(envelope.from ? ['-f', envelope.from] : []).concat(envelope.to);
|
|
74
|
+
const args = this.args ? ['-i'].concat(this.args).concat(envelope.to) : ['-i'].concat(envelope.from ? ['-f', envelope.from] : []).concat(envelope.to);
|
|
77
75
|
const callback = (err) => {
|
|
78
76
|
if (returned) {
|
|
79
77
|
// ignore any additional responses, already done
|
|
@@ -217,9 +217,7 @@ export const resolveHostname = (options, callback) => {
|
|
|
217
217
|
return respond(err);
|
|
218
218
|
}
|
|
219
219
|
// Get all supported addresses from dns.lookup
|
|
220
|
-
const supportedAddresses = addresses
|
|
221
|
-
? addresses.filter(addr => isFamilySupported(addr.family)).map(addr => addr.address)
|
|
222
|
-
: [];
|
|
220
|
+
const supportedAddresses = addresses ? addresses.filter(addr => isFamilySupported(addr.family)).map(addr => addr.address) : [];
|
|
223
221
|
if (addresses && addresses.length && !supportedAddresses.length) {
|
|
224
222
|
// there are addresses but none can be used
|
|
225
223
|
console.warn(`Failed to resolve IPv${addresses[0].family} addresses with current network`);
|
|
@@ -549,9 +547,7 @@ export const assign = function (...args) {
|
|
|
549
547
|
if (isProtoKey(key)) {
|
|
550
548
|
return;
|
|
551
549
|
}
|
|
552
|
-
if (['tls', 'auth'].includes(key) &&
|
|
553
|
-
source[key] &&
|
|
554
|
-
typeof source[key] === 'object') {
|
|
550
|
+
if (['tls', 'auth'].includes(key) && source[key] && typeof source[key] === 'object') {
|
|
555
551
|
// tls and auth are special keys that need to be enumerated separately
|
|
556
552
|
// other objects are passed as is. Enumerating is a copy of user supplied
|
|
557
553
|
// keys just like the loop above, so it gets the same treatment
|
|
@@ -9,7 +9,7 @@ import * as errors from '../errors.js';
|
|
|
9
9
|
// never sends \r\n\r\n cannot grow memory unboundedly before the socket times out.
|
|
10
10
|
const MAX_RESPONSE_HEADER_BYTES = 64 * 1024;
|
|
11
11
|
// URL hostnames keep the brackets around an IPv6 literal, socket options and net.isIPv6 take it without
|
|
12
|
-
const unbracket = (host) => typeof host === 'string' && host.startsWith('[') && host.endsWith(']') ? host.slice(1, -1) : host;
|
|
12
|
+
const unbracket = (host) => (typeof host === 'string' && host.startsWith('[') && host.endsWith(']') ? host.slice(1, -1) : host);
|
|
13
13
|
function httpProxyClient(proxyUrl, destinationPort, destinationHost, tlsOptions, callback) {
|
|
14
14
|
if (typeof tlsOptions === 'function') {
|
|
15
15
|
callback = tlsOptions;
|
|
@@ -245,6 +245,12 @@ export interface SMTPConnectionSendInfo extends SMTPConnectionEnvelopeInfo {
|
|
|
245
245
|
messageSize: number;
|
|
246
246
|
/** Final server response for the message */
|
|
247
247
|
response: string;
|
|
248
|
+
/**
|
|
249
|
+
* Message-ID the server gave the message, with angle brackets, when its final reply names
|
|
250
|
+
* one in a known format (Microsoft 365 and Outlook.com, Amazon SES). Such a server replaces
|
|
251
|
+
* the Message-ID header, so the delivered copy carries this id instead of messageId
|
|
252
|
+
*/
|
|
253
|
+
serverMessageId?: string | undefined;
|
|
248
254
|
}
|
|
249
255
|
/**
|
|
250
256
|
* Callback for send(), receives the result once the server accepted the message. The error
|
|
@@ -7,7 +7,8 @@ import crypto from 'node:crypto';
|
|
|
7
7
|
import DataStream from './data-stream.js';
|
|
8
8
|
import { PassThrough } from 'node:stream';
|
|
9
9
|
import * as shared from '../shared/index.js';
|
|
10
|
-
import {
|
|
10
|
+
import { parseServerMessageId } from './server-message-id.js';
|
|
11
|
+
import { ERR_ACCESS_DENIED, isPermanentResponseCode, isTransientError } from '../errors.js';
|
|
11
12
|
// default timeout values in ms
|
|
12
13
|
const CONNECTION_TIMEOUT = 2 * 60 * 1000; // how much to wait for the connection to be established
|
|
13
14
|
const SOCKET_TIMEOUT = 10 * 60 * 1000; // how much to wait for socket inactivity before disconnecting the client
|
|
@@ -361,9 +362,7 @@ class SMTPConnection extends EventEmitter {
|
|
|
361
362
|
if (this._destroyed || this._closing) {
|
|
362
363
|
return;
|
|
363
364
|
}
|
|
364
|
-
const connectFn = secure
|
|
365
|
-
? tls.connect
|
|
366
|
-
: net.connect;
|
|
365
|
+
const connectFn = secure ? tls.connect : net.connect;
|
|
367
366
|
try {
|
|
368
367
|
this._socket = connectFn(opts, () => this._onConnect());
|
|
369
368
|
this._setupConnectionHandlers();
|
|
@@ -701,6 +700,16 @@ class SMTPConnection extends EventEmitter {
|
|
|
701
700
|
result.messageTime = Date.now() - envelopeTime;
|
|
702
701
|
result.messageSize = stream.outByteCount;
|
|
703
702
|
result.response = str;
|
|
703
|
+
const serverMessageId = parseServerMessageId(result.response, this.options.host);
|
|
704
|
+
if (serverMessageId) {
|
|
705
|
+
result.serverMessageId = serverMessageId;
|
|
706
|
+
}
|
|
707
|
+
// an LMTP server answers the message once per recipient, so recipients can be
|
|
708
|
+
// refused after the envelope info was built without any rejected errors on it
|
|
709
|
+
const rejectedErrors = this._envelope?.rejectedErrors;
|
|
710
|
+
if (!result.rejectedErrors && rejectedErrors && rejectedErrors.length) {
|
|
711
|
+
result.rejectedErrors = rejectedErrors;
|
|
712
|
+
}
|
|
704
713
|
return callback(null, result);
|
|
705
714
|
});
|
|
706
715
|
if (typeof message.pipe === 'function') {
|
|
@@ -928,6 +937,7 @@ class SMTPConnection extends EventEmitter {
|
|
|
928
937
|
const responseCode = (typeof response === 'string' && Number((response.match(/^\d+/) || [])[0])) || false;
|
|
929
938
|
if (responseCode) {
|
|
930
939
|
err.responseCode = responseCode;
|
|
940
|
+
err.permanent = isPermanentResponseCode(responseCode);
|
|
931
941
|
}
|
|
932
942
|
if (command) {
|
|
933
943
|
err.command = command;
|
|
@@ -970,12 +980,7 @@ class SMTPConnection extends EventEmitter {
|
|
|
970
980
|
this.close();
|
|
971
981
|
return;
|
|
972
982
|
}
|
|
973
|
-
if (!failureResponse &&
|
|
974
|
-
this.stage === 'connected' &&
|
|
975
|
-
!this._responseActions.length &&
|
|
976
|
-
!this._pendingSend &&
|
|
977
|
-
!this._destroyed &&
|
|
978
|
-
!this._closing) {
|
|
983
|
+
if (!failureResponse && this.stage === 'connected' && !this._responseActions.length && !this._pendingSend && !this._destroyed && !this._closing) {
|
|
979
984
|
// nothing was waiting for the server, so this is the server ending an idle session
|
|
980
985
|
// (usually after its idle timeout), not a failure
|
|
981
986
|
this.logger.info({
|
|
@@ -1196,9 +1201,7 @@ class SMTPConnection extends EventEmitter {
|
|
|
1196
1201
|
const args = [];
|
|
1197
1202
|
let useSmtpUtf8 = false;
|
|
1198
1203
|
this._envelope = (envelope || {});
|
|
1199
|
-
this._envelope.from = ((this._envelope.from && this._envelope.from.address) || this._envelope.from || '')
|
|
1200
|
-
.toString()
|
|
1201
|
-
.trim();
|
|
1204
|
+
this._envelope.from = ((this._envelope.from && this._envelope.from.address) || this._envelope.from || '').toString().trim();
|
|
1202
1205
|
this._envelope.to = []
|
|
1203
1206
|
.concat(this._envelope.to || [])
|
|
1204
1207
|
.map(to => ((to && to.address) || to || '').toString().trim());
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the Message-ID a receiving server gave the message out of its final 250 reply. Some
|
|
3
|
+
* servers replace the Message-ID header of a submitted message with one of their own, and
|
|
4
|
+
* the copy the recipients and the sent folder get carries that one instead of the id the
|
|
5
|
+
* message was built with. Only replies in a format known to carry such an id are read.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Reads the server assigned Message-ID out of the final reply to a message
|
|
9
|
+
*
|
|
10
|
+
* @param response Final server reply for the message
|
|
11
|
+
* @param [host] Hostname the connection was made to, SES replies are only read for an SES host
|
|
12
|
+
* @returns The Message-ID with its angle brackets, or undefined when the reply names none
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseServerMessageId(response: string | undefined, host?: string): string | undefined;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the Message-ID a receiving server gave the message out of its final 250 reply. Some
|
|
3
|
+
* servers replace the Message-ID header of a submitted message with one of their own, and
|
|
4
|
+
* the copy the recipients and the sent folder get carries that one instead of the id the
|
|
5
|
+
* message was built with. Only replies in a format known to carry such an id are read.
|
|
6
|
+
*/
|
|
7
|
+
// Microsoft 365 and Outlook.com: "250 2.0.0 OK <id@host.prod.outlook.com> [Hostname=...]"
|
|
8
|
+
const OUTLOOK_REPLY = /^250 2\.0\.0 OK (<[^<>\s]+\.prod\.outlook\.com>)/i;
|
|
9
|
+
// Amazon SES: "250 Ok 0100018b5c3c0a4f-...-000000", the local part of the Message-ID it sets
|
|
10
|
+
const SES_REPLY = /^250 Ok ([0-9a-f]+(?:-[0-9a-f]+)+)$/i;
|
|
11
|
+
// an AWS region name such as us-east-1 or ap-southeast-2
|
|
12
|
+
const AWS_REGION = /^[a-z]{2}(?:-[a-z]+)+-\d+$/;
|
|
13
|
+
/**
|
|
14
|
+
* Finds the AWS region an SES SMTP endpoint is in from its hostname, such as
|
|
15
|
+
* email-smtp.eu-west-1.amazonaws.com or a VPC endpoint name under it
|
|
16
|
+
*
|
|
17
|
+
* @param host SMTP hostname
|
|
18
|
+
* @returns Region name, or undefined for a host outside amazonaws.com and awsapps.com
|
|
19
|
+
*/
|
|
20
|
+
function sesRegion(host) {
|
|
21
|
+
const labels = host.toLowerCase().replace(/\.$/, '').split('.');
|
|
22
|
+
const domain = labels.slice(-2).join('.');
|
|
23
|
+
if (domain !== 'amazonaws.com' && domain !== 'awsapps.com') {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
return labels.slice(0, -2).find(label => AWS_REGION.test(label));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Reads the server assigned Message-ID out of the final reply to a message
|
|
30
|
+
*
|
|
31
|
+
* @param response Final server reply for the message
|
|
32
|
+
* @param [host] Hostname the connection was made to, SES replies are only read for an SES host
|
|
33
|
+
* @returns The Message-ID with its angle brackets, or undefined when the reply names none
|
|
34
|
+
*/
|
|
35
|
+
export function parseServerMessageId(response, host) {
|
|
36
|
+
const reply = (response || '').toString().trim();
|
|
37
|
+
const outlook = reply.match(OUTLOOK_REPLY);
|
|
38
|
+
if (outlook) {
|
|
39
|
+
return outlook[1];
|
|
40
|
+
}
|
|
41
|
+
const ses = reply.match(SES_REPLY);
|
|
42
|
+
if (ses && host) {
|
|
43
|
+
const region = sesRegion(host);
|
|
44
|
+
if (region) {
|
|
45
|
+
// the SES Message-ID domain is email.amazonses.com in us-east-1 and the region elsewhere
|
|
46
|
+
return '<' + ses[1].toLowerCase() + '@' + (region === 'us-east-1' ? 'email' : region) + '.amazonses.com>';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
@@ -110,6 +110,17 @@ declare class SMTPPool extends EventEmitter {
|
|
|
110
110
|
* Returns true if there are free slots in the queue
|
|
111
111
|
*/
|
|
112
112
|
isIdle(): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Counts the messages the pool has not finished with yet: the ones waiting in the queue
|
|
115
|
+
* plus the ones a connection is transmitting right now. isIdle() only tells whether the
|
|
116
|
+
* pool can take another message, it is already true while a message is still being sent,
|
|
117
|
+
* so use this to check that nothing would be lost by closing the pool. A message that is
|
|
118
|
+
* re-queued after its connection dropped is counted until its callback runs, also while it waits to be put back on the queue, and
|
|
119
|
+
* it is no longer counted by the time its callback runs.
|
|
120
|
+
*
|
|
121
|
+
* @returns Number of queued and in-flight messages
|
|
122
|
+
*/
|
|
123
|
+
pendingCount(): number;
|
|
113
124
|
/**
|
|
114
125
|
* Verifies SMTP configuration
|
|
115
126
|
*
|
|
@@ -62,6 +62,7 @@ class SMTPPool extends EventEmitter {
|
|
|
62
62
|
this._queue = [];
|
|
63
63
|
this._connections = [];
|
|
64
64
|
this._connectionCounter = 0;
|
|
65
|
+
this._pending = 0;
|
|
65
66
|
this.idling = true;
|
|
66
67
|
setImmediate(() => {
|
|
67
68
|
if (this.idling) {
|
|
@@ -94,10 +95,20 @@ class SMTPPool extends EventEmitter {
|
|
|
94
95
|
setImmediate(() => callback(err));
|
|
95
96
|
return false;
|
|
96
97
|
}
|
|
98
|
+
// counted until the callback runs, whichever path runs it: delivered, failed, requeued
|
|
99
|
+
// until it gives up, or drained by close()
|
|
100
|
+
let counted = true;
|
|
101
|
+
this._pending++;
|
|
97
102
|
this._queue.push({
|
|
98
103
|
mail,
|
|
99
104
|
requeueAttempts: 0,
|
|
100
|
-
callback
|
|
105
|
+
callback: (err, info) => {
|
|
106
|
+
if (counted) {
|
|
107
|
+
counted = false;
|
|
108
|
+
this._pending--;
|
|
109
|
+
}
|
|
110
|
+
callback(err, info);
|
|
111
|
+
}
|
|
101
112
|
});
|
|
102
113
|
if (this.idling && this._queue.length >= this.options.maxConnections) {
|
|
103
114
|
this.idling = false;
|
|
@@ -441,6 +452,19 @@ class SMTPPool extends EventEmitter {
|
|
|
441
452
|
isIdle() {
|
|
442
453
|
return this.idling;
|
|
443
454
|
}
|
|
455
|
+
/**
|
|
456
|
+
* Counts the messages the pool has not finished with yet: the ones waiting in the queue
|
|
457
|
+
* plus the ones a connection is transmitting right now. isIdle() only tells whether the
|
|
458
|
+
* pool can take another message, it is already true while a message is still being sent,
|
|
459
|
+
* so use this to check that nothing would be lost by closing the pool. A message that is
|
|
460
|
+
* re-queued after its connection dropped is counted until its callback runs, also while it waits to be put back on the queue, and
|
|
461
|
+
* it is no longer counted by the time its callback runs.
|
|
462
|
+
*
|
|
463
|
+
* @returns Number of queued and in-flight messages
|
|
464
|
+
*/
|
|
465
|
+
pendingCount() {
|
|
466
|
+
return this._pending;
|
|
467
|
+
}
|
|
444
468
|
verify(callback) {
|
|
445
469
|
let promise;
|
|
446
470
|
if (!callback) {
|
|
@@ -19,8 +19,7 @@ export default class PoolResource extends EventEmitter {
|
|
|
19
19
|
switch ((this.options.auth.type || '').toString().toUpperCase()) {
|
|
20
20
|
case 'OAUTH2': {
|
|
21
21
|
const oauth2 = new XOAuth2(this.options.auth, this.logger);
|
|
22
|
-
oauth2.provisionCallback =
|
|
23
|
-
(this.pool.mailer && this.pool.mailer.get('oauth2_provision_cb')) || oauth2.provisionCallback;
|
|
22
|
+
oauth2.provisionCallback = (this.pool.mailer && this.pool.mailer.get('oauth2_provision_cb')) || oauth2.provisionCallback;
|
|
24
23
|
this.auth = {
|
|
25
24
|
type: 'OAUTH2',
|
|
26
25
|
user: this.options.auth.user,
|
|
@@ -208,9 +207,7 @@ export default class PoolResource extends EventEmitter {
|
|
|
208
207
|
this.connection.close();
|
|
209
208
|
return;
|
|
210
209
|
}
|
|
211
|
-
if ((err.code === errors.EENVELOPE || err.code === errors.EMESSAGE) &&
|
|
212
|
-
err.responseCode !== 421 &&
|
|
213
|
-
!this.connection._destroyed) {
|
|
210
|
+
if ((err.code === errors.EENVELOPE || err.code === errors.EMESSAGE) && err.responseCode !== 421 && !this.connection._destroyed) {
|
|
214
211
|
// The server refused this message, the connection itself is fine. Reset the
|
|
215
212
|
// session and keep using it instead of opening a new one
|
|
216
213
|
this.connection.reset(resetErr => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodemailer",
|
|
3
|
-
"version": "10.1
|
|
3
|
+
"version": "10.2.1",
|
|
4
4
|
"description": "Easy as cake e-mail sending from your Node.js applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/nodemailer.js",
|
|
@@ -128,6 +128,8 @@
|
|
|
128
128
|
"test": "node --import tsx --test --test-concurrency=1 $(find test \\( -name '*-test.ts' -o -name '*.test.ts' \\))",
|
|
129
129
|
"pretest:coverage": "npm run build",
|
|
130
130
|
"test:coverage": "c8 node --import tsx --test --test-concurrency=1 $(find test \\( -name '*-test.ts' -o -name '*.test.ts' \\))",
|
|
131
|
+
"pretest:cjs": "npm run build",
|
|
132
|
+
"test:cjs": "NODE_OPTIONS=--no-experimental-require-module node test/package/cjs-smoke.cjs",
|
|
131
133
|
"pretest:bun": "npm run build",
|
|
132
134
|
"test:bun": "bun test --timeout 60000 $(find ./test \\( -name '*-test.ts' -o -name '*.test.ts' \\))",
|
|
133
135
|
"format": "prettier --write \"**/*.{js,cjs,ts,json,md}\"",
|
|
@@ -151,24 +153,24 @@
|
|
|
151
153
|
},
|
|
152
154
|
"homepage": "https://nodemailer.com/",
|
|
153
155
|
"devDependencies": {
|
|
154
|
-
"@aws-sdk/client-sesv2": "3.
|
|
156
|
+
"@aws-sdk/client-sesv2": "3.1155.0",
|
|
155
157
|
"@types/node": "20.19.43",
|
|
156
158
|
"bunyan": "1.8.15",
|
|
157
159
|
"c8": "12.0.0",
|
|
158
|
-
"eslint": "10.
|
|
160
|
+
"eslint": "10.13.0",
|
|
159
161
|
"eslint-config-prettier": "10.1.8",
|
|
160
162
|
"globals": "17.13.0",
|
|
161
|
-
"libbase64": "1.
|
|
162
|
-
"libmime": "5.
|
|
163
|
-
"libqp": "
|
|
164
|
-
"mailauth": "
|
|
163
|
+
"libbase64": "1.4.1",
|
|
164
|
+
"libmime": "5.6.3",
|
|
165
|
+
"libqp": "3.0.1",
|
|
166
|
+
"mailauth": "8.0.2",
|
|
165
167
|
"prettier": "3.9.10",
|
|
166
168
|
"proxy": "1.0.2",
|
|
167
169
|
"proxy-test-server": "1.0.0",
|
|
168
|
-
"smtp-server": "3.
|
|
170
|
+
"smtp-server": "3.21.0",
|
|
169
171
|
"tsx": "4.23.15",
|
|
170
172
|
"typescript": "6.0.3",
|
|
171
|
-
"typescript-eslint": "8.
|
|
173
|
+
"typescript-eslint": "8.72.0"
|
|
172
174
|
},
|
|
173
175
|
"engines": {
|
|
174
176
|
"node": ">=20.0.0"
|
package/package.json
CHANGED
|
@@ -79,15 +79,15 @@
|
|
|
79
79
|
"constructs": "^10.5.1"
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
|
-
"@aws-sdk/client-cloudwatch-logs": "^3.
|
|
83
|
-
"@aws-sdk/client-route-53": "^3.
|
|
84
|
-
"@aws-sdk/client-s3": "^3.
|
|
85
|
-
"@aws-sdk/client-ses": "^3.
|
|
86
|
-
"@aws-sdk/client-ssm": "^3.
|
|
82
|
+
"@aws-sdk/client-cloudwatch-logs": "^3.1156.0",
|
|
83
|
+
"@aws-sdk/client-route-53": "^3.1156.0",
|
|
84
|
+
"@aws-sdk/client-s3": "^3.1156.0",
|
|
85
|
+
"@aws-sdk/client-ses": "^3.1156.0",
|
|
86
|
+
"@aws-sdk/client-ssm": "^3.1156.0",
|
|
87
87
|
"@mavogel/mvc-projen": "^0.0.62",
|
|
88
88
|
"cdk-nag": "^3.0.1",
|
|
89
89
|
"constructs": "^10.5.1",
|
|
90
|
-
"mailparser": "^3.
|
|
90
|
+
"mailparser": "^3.12.4",
|
|
91
91
|
"uuid": "^14.0.3"
|
|
92
92
|
},
|
|
93
93
|
"bundledDependencies": [
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"publishConfig": {
|
|
123
123
|
"access": "public"
|
|
124
124
|
},
|
|
125
|
-
"version": "0.1.
|
|
125
|
+
"version": "0.1.28",
|
|
126
126
|
"jest": {
|
|
127
127
|
"coverageProvider": "v8",
|
|
128
128
|
"transformIgnorePatterns": [
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2011 Alexander Shtuchkin
|
|
2
|
-
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
-
a copy of this software and associated documentation files (the
|
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
-
the following conditions:
|
|
10
|
-
|
|
11
|
-
The above copyright notice and this permission notice shall be
|
|
12
|
-
included in all copies or substantial portions of the Software.
|
|
13
|
-
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
21
|
-
|