@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.
Files changed (175) hide show
  1. package/.jsii +8 -8
  2. package/lib/rootmail.js +1 -1
  3. package/lib/ses-receive.js +1 -1
  4. package/node_modules/@aws-sdk/checksums/package.json +4 -4
  5. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-cjs/index.js +1 -1
  6. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/CloudWatchLogsClient.d.ts +2 -1
  7. package/node_modules/@aws-sdk/client-cloudwatch-logs/package.json +5 -5
  8. package/node_modules/@aws-sdk/client-route-53/dist-cjs/index.js +1 -1
  9. package/node_modules/@aws-sdk/client-route-53/dist-types/Route53Client.d.ts +2 -1
  10. package/node_modules/@aws-sdk/client-route-53/package.json +6 -6
  11. package/node_modules/@aws-sdk/client-s3/dist-cjs/index.js +1 -1
  12. package/node_modules/@aws-sdk/client-s3/dist-types/S3Client.d.ts +2 -1
  13. package/node_modules/@aws-sdk/client-s3/package.json +9 -9
  14. package/node_modules/@aws-sdk/client-ses/dist-cjs/index.js +1 -1
  15. package/node_modules/@aws-sdk/client-ses/dist-types/SESClient.d.ts +2 -1
  16. package/node_modules/@aws-sdk/client-ses/package.json +5 -5
  17. package/node_modules/@aws-sdk/client-ssm/dist-cjs/index.js +1 -1
  18. package/node_modules/@aws-sdk/client-ssm/dist-types/SSMClient.d.ts +2 -1
  19. package/node_modules/@aws-sdk/client-ssm/package.json +5 -5
  20. package/node_modules/@aws-sdk/core/package.json +3 -3
  21. package/node_modules/@aws-sdk/credential-provider-env/package.json +4 -4
  22. package/node_modules/@aws-sdk/credential-provider-http/package.json +4 -4
  23. package/node_modules/@aws-sdk/credential-provider-ini/package.json +11 -11
  24. package/node_modules/@aws-sdk/credential-provider-login/package.json +5 -5
  25. package/node_modules/@aws-sdk/credential-provider-node/package.json +9 -9
  26. package/node_modules/@aws-sdk/credential-provider-process/package.json +4 -4
  27. package/node_modules/@aws-sdk/credential-provider-sso/package.json +6 -6
  28. package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +5 -5
  29. package/node_modules/@aws-sdk/middleware-sdk-route53/package.json +2 -2
  30. package/node_modules/@aws-sdk/middleware-sdk-s3/package.json +5 -5
  31. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +1 -1
  32. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +1 -1
  33. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +1 -1
  34. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +1 -1
  35. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +1 -1
  36. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/cognito-identity/CognitoIdentityClient.d.ts +2 -1
  37. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/signin/SigninClient.d.ts +2 -1
  38. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso/SSOClient.d.ts +2 -1
  39. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sso-oidc/SSOOIDCClient.d.ts +2 -1
  40. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/sts/STSClient.d.ts +2 -1
  41. package/node_modules/@aws-sdk/nested-clients/package.json +5 -5
  42. package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +2 -2
  43. package/node_modules/@aws-sdk/token-providers/package.json +5 -5
  44. package/node_modules/@aws-sdk/types/dist-types/feature-ids.d.ts +3 -0
  45. package/node_modules/@aws-sdk/types/dist-types/ts3.4/feature-ids.d.ts +3 -0
  46. package/node_modules/@aws-sdk/types/package.json +1 -1
  47. package/node_modules/@smithy/core/dist-cjs/submodules/client/index.js +15 -2
  48. package/node_modules/@smithy/core/dist-cjs/submodules/event-streams/index.browser.js +10 -0
  49. package/node_modules/@smithy/core/dist-cjs/submodules/event-streams/index.js +10 -0
  50. package/node_modules/@smithy/core/dist-cjs/submodules/protocols/index.js +5 -5
  51. package/node_modules/@smithy/core/dist-es/submodules/client/smithy-client/command.js +16 -2
  52. package/node_modules/@smithy/core/dist-es/submodules/event-streams/eventstream-codec/HeaderMarshaller.js +10 -0
  53. package/node_modules/@smithy/core/dist-es/submodules/protocols/json/codec-v2/JsonShapeSerializer2.js +5 -5
  54. package/node_modules/@smithy/core/package.json +1 -1
  55. package/node_modules/@zone-eu/mailsplit/lib/message-splitter.js +39 -27
  56. package/node_modules/@zone-eu/mailsplit/lib/mime-node.d.ts +1 -1
  57. package/node_modules/@zone-eu/mailsplit/lib/mime-node.js +38 -61
  58. package/node_modules/@zone-eu/mailsplit/lib/types.d.ts +1 -1
  59. package/node_modules/@zone-eu/mailsplit/package.json +2 -2
  60. package/node_modules/libmime/CHANGELOG.md +36 -0
  61. package/node_modules/libmime/README.md +40 -3
  62. package/node_modules/libmime/dist/cjs/charset.d.ts +36 -0
  63. package/node_modules/libmime/dist/cjs/charset.js +165 -2
  64. package/node_modules/libmime/dist/cjs/charsets.js +8 -2
  65. package/node_modules/libmime/dist/cjs/libmime.d.ts +20 -3
  66. package/node_modules/libmime/dist/cjs/libmime.js +100 -6
  67. package/node_modules/libmime/dist/cjs/types.d.ts +28 -0
  68. package/node_modules/libmime/dist/esm/charset.d.ts +36 -0
  69. package/node_modules/libmime/dist/esm/charset.js +162 -2
  70. package/node_modules/libmime/dist/esm/charsets.js +8 -2
  71. package/node_modules/libmime/dist/esm/libmime.d.ts +20 -3
  72. package/node_modules/libmime/dist/esm/libmime.js +100 -6
  73. package/node_modules/libmime/dist/esm/types.d.ts +28 -0
  74. package/node_modules/libmime/package.json +3 -3
  75. package/node_modules/mailparser/CHANGELOG.md +51 -0
  76. package/node_modules/mailparser/README.md +32 -1
  77. package/node_modules/mailparser/dist/cjs/address-header.d.ts +19 -0
  78. package/node_modules/mailparser/dist/cjs/address-header.js +185 -0
  79. package/node_modules/mailparser/dist/cjs/index.d.ts +3 -1
  80. package/node_modules/mailparser/dist/cjs/index.js +4 -2
  81. package/node_modules/mailparser/dist/cjs/mail-parser.js +36 -183
  82. package/node_modules/mailparser/dist/cjs/stream-hash.d.ts +5 -4
  83. package/node_modules/mailparser/dist/cjs/stream-hash.js +8 -5
  84. package/node_modules/mailparser/dist/cjs/types.d.ts +33 -6
  85. package/node_modules/mailparser/dist/esm/address-header.d.ts +19 -0
  86. package/node_modules/mailparser/dist/esm/address-header.js +176 -0
  87. package/node_modules/mailparser/dist/esm/index.d.ts +3 -1
  88. package/node_modules/mailparser/dist/esm/index.js +3 -2
  89. package/node_modules/mailparser/dist/esm/mail-parser.js +36 -183
  90. package/node_modules/mailparser/dist/esm/stream-hash.d.ts +5 -4
  91. package/node_modules/mailparser/dist/esm/stream-hash.js +8 -5
  92. package/node_modules/mailparser/dist/esm/types.d.ts +33 -6
  93. package/node_modules/mailparser/package.json +6 -7
  94. package/node_modules/nodemailer/CHANGELOG.md +23 -0
  95. package/node_modules/nodemailer/dist/cjs/addressparser/index.js +2 -5
  96. package/node_modules/nodemailer/dist/cjs/dkim/index.js +1 -3
  97. package/node_modules/nodemailer/dist/cjs/errors.d.ts +19 -0
  98. package/node_modules/nodemailer/dist/cjs/errors.js +14 -1
  99. package/node_modules/nodemailer/dist/cjs/fetch/cookies.js +2 -4
  100. package/node_modules/nodemailer/dist/cjs/fetch/index.js +2 -8
  101. package/node_modules/nodemailer/dist/cjs/mail-composer/index.js +42 -9
  102. package/node_modules/nodemailer/dist/cjs/mailer/mail-message.js +5 -6
  103. package/node_modules/nodemailer/dist/cjs/mime-funcs/index.d.ts +18 -1
  104. package/node_modules/nodemailer/dist/cjs/mime-funcs/index.js +43 -1
  105. package/node_modules/nodemailer/dist/cjs/mime-funcs/mime-types.js +3 -12
  106. package/node_modules/nodemailer/dist/cjs/mime-node/index.d.ts +34 -1
  107. package/node_modules/nodemailer/dist/cjs/mime-node/index.js +40 -15
  108. package/node_modules/nodemailer/dist/cjs/package-info.d.ts +1 -1
  109. package/node_modules/nodemailer/dist/cjs/package-info.js +1 -1
  110. package/node_modules/nodemailer/dist/cjs/qp/index.js +3 -12
  111. package/node_modules/nodemailer/dist/cjs/sendmail-transport/index.js +1 -3
  112. package/node_modules/nodemailer/dist/cjs/shared/index.js +2 -6
  113. package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.js +1 -1
  114. package/node_modules/nodemailer/dist/cjs/smtp-connection/index.d.ts +6 -0
  115. package/node_modules/nodemailer/dist/cjs/smtp-connection/index.js +15 -12
  116. package/node_modules/nodemailer/dist/cjs/smtp-connection/server-message-id.d.ts +14 -0
  117. package/node_modules/nodemailer/dist/cjs/smtp-connection/server-message-id.js +53 -0
  118. package/node_modules/nodemailer/dist/cjs/smtp-pool/index.d.ts +11 -0
  119. package/node_modules/nodemailer/dist/cjs/smtp-pool/index.js +25 -1
  120. package/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.js +2 -5
  121. package/node_modules/nodemailer/dist/esm/addressparser/index.js +2 -5
  122. package/node_modules/nodemailer/dist/esm/dkim/index.js +1 -3
  123. package/node_modules/nodemailer/dist/esm/errors.d.ts +19 -0
  124. package/node_modules/nodemailer/dist/esm/errors.js +12 -0
  125. package/node_modules/nodemailer/dist/esm/fetch/cookies.js +2 -4
  126. package/node_modules/nodemailer/dist/esm/fetch/index.js +2 -8
  127. package/node_modules/nodemailer/dist/esm/mail-composer/index.js +42 -9
  128. package/node_modules/nodemailer/dist/esm/mailer/mail-message.js +5 -6
  129. package/node_modules/nodemailer/dist/esm/mime-funcs/index.d.ts +18 -1
  130. package/node_modules/nodemailer/dist/esm/mime-funcs/index.js +43 -1
  131. package/node_modules/nodemailer/dist/esm/mime-funcs/mime-types.js +3 -12
  132. package/node_modules/nodemailer/dist/esm/mime-node/index.d.ts +34 -1
  133. package/node_modules/nodemailer/dist/esm/mime-node/index.js +40 -15
  134. package/node_modules/nodemailer/dist/esm/package-info.d.ts +1 -1
  135. package/node_modules/nodemailer/dist/esm/package-info.js +1 -1
  136. package/node_modules/nodemailer/dist/esm/qp/index.js +3 -12
  137. package/node_modules/nodemailer/dist/esm/sendmail-transport/index.js +1 -3
  138. package/node_modules/nodemailer/dist/esm/shared/index.js +2 -6
  139. package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.js +1 -1
  140. package/node_modules/nodemailer/dist/esm/smtp-connection/index.d.ts +6 -0
  141. package/node_modules/nodemailer/dist/esm/smtp-connection/index.js +16 -13
  142. package/node_modules/nodemailer/dist/esm/smtp-connection/server-message-id.d.ts +14 -0
  143. package/node_modules/nodemailer/dist/esm/smtp-connection/server-message-id.js +50 -0
  144. package/node_modules/nodemailer/dist/esm/smtp-pool/index.d.ts +11 -0
  145. package/node_modules/nodemailer/dist/esm/smtp-pool/index.js +25 -1
  146. package/node_modules/nodemailer/dist/esm/smtp-pool/pool-resource.js +2 -5
  147. package/node_modules/nodemailer/package.json +11 -9
  148. package/package.json +9 -9
  149. package/node_modules/mailparser/node_modules/iconv-lite/LICENSE +0 -21
  150. package/node_modules/mailparser/node_modules/iconv-lite/README.md +0 -138
  151. package/node_modules/mailparser/node_modules/iconv-lite/encodings/dbcs-codec.js +0 -532
  152. package/node_modules/mailparser/node_modules/iconv-lite/encodings/dbcs-data.js +0 -185
  153. package/node_modules/mailparser/node_modules/iconv-lite/encodings/index.js +0 -23
  154. package/node_modules/mailparser/node_modules/iconv-lite/encodings/internal.js +0 -218
  155. package/node_modules/mailparser/node_modules/iconv-lite/encodings/sbcs-codec.js +0 -75
  156. package/node_modules/mailparser/node_modules/iconv-lite/encodings/sbcs-data-generated.js +0 -451
  157. package/node_modules/mailparser/node_modules/iconv-lite/encodings/sbcs-data.js +0 -180
  158. package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/big5-added.json +0 -122
  159. package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/cp936.json +0 -264
  160. package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/cp949.json +0 -273
  161. package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/cp950.json +0 -177
  162. package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/eucjp.json +0 -182
  163. package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json +0 -1
  164. package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/gbk-added.json +0 -56
  165. package/node_modules/mailparser/node_modules/iconv-lite/encodings/tables/shiftjis.json +0 -125
  166. package/node_modules/mailparser/node_modules/iconv-lite/encodings/utf16.js +0 -187
  167. package/node_modules/mailparser/node_modules/iconv-lite/encodings/utf32.js +0 -314
  168. package/node_modules/mailparser/node_modules/iconv-lite/encodings/utf7.js +0 -283
  169. package/node_modules/mailparser/node_modules/iconv-lite/lib/bom-handling.js +0 -48
  170. package/node_modules/mailparser/node_modules/iconv-lite/lib/helpers/merge-exports.js +0 -13
  171. package/node_modules/mailparser/node_modules/iconv-lite/lib/index.d.ts +0 -129
  172. package/node_modules/mailparser/node_modules/iconv-lite/lib/index.js +0 -182
  173. package/node_modules/mailparser/node_modules/iconv-lite/lib/streams.js +0 -105
  174. package/node_modules/mailparser/node_modules/iconv-lite/package.json +0 -70
  175. 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._encodeHeaderValue(key, value);
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 for use in the generated rfc2822 email.
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
- * @param key Header key
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
- * @internal
1323
+ * @returns Encoded header value
1320
1324
  */
1321
- _encodeHeaderValue(key, value) {
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
  *
@@ -1,3 +1,3 @@
1
1
  export declare const name = "nodemailer";
2
- export declare const version = "10.1.7";
2
+ export declare const version = "10.2.1";
3
3
  export declare const homepage = "https://nodemailer.com/";
@@ -1,4 +1,4 @@
1
1
  // Generated by scripts/build.js from package.json. Do not edit by hand.
2
2
  export const name = 'nodemailer';
3
- export const version = '10.1.7';
3
+ export const version = '10.2.1';
4
4
  export const homepage = 'https://nodemailer.com/';
@@ -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 { ERR_ACCESS_DENIED, isTransientError } from '../errors.js';
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.7",
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.1151.0",
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.12.0",
160
+ "eslint": "10.13.0",
159
161
  "eslint-config-prettier": "10.1.8",
160
162
  "globals": "17.13.0",
161
- "libbase64": "1.3.2",
162
- "libmime": "5.4.7",
163
- "libqp": "2.1.2",
164
- "mailauth": "7.3.0",
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.19.21",
170
+ "smtp-server": "3.21.0",
169
171
  "tsx": "4.23.15",
170
172
  "typescript": "6.0.3",
171
- "typescript-eslint": "8.71.2"
173
+ "typescript-eslint": "8.72.0"
172
174
  },
173
175
  "engines": {
174
176
  "node": ">=20.0.0"
package/package.json CHANGED
@@ -64,9 +64,9 @@
64
64
  "jest": "^30.5.2",
65
65
  "jest-junit": "^17",
66
66
  "jsii": "~5.9.0",
67
- "jsii-diff": "^1.141.0",
67
+ "jsii-diff": "^1.142.0",
68
68
  "jsii-docgen": "^10.5.0",
69
- "jsii-pacmak": "^1.141.0",
69
+ "jsii-pacmak": "^1.142.0",
70
70
  "jsii-rosetta": "~5.9.0",
71
71
  "jsonfile": "^6.2.1",
72
72
  "projen": "^0.104.8",
@@ -79,15 +79,15 @@
79
79
  "constructs": "^10.5.1"
80
80
  },
81
81
  "dependencies": {
82
- "@aws-sdk/client-cloudwatch-logs": "^3.1153.0",
83
- "@aws-sdk/client-route-53": "^3.1153.0",
84
- "@aws-sdk/client-s3": "^3.1153.0",
85
- "@aws-sdk/client-ses": "^3.1153.0",
86
- "@aws-sdk/client-ssm": "^3.1153.0",
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.10.0",
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.26",
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
-