@mavogel/awscdk-rootmail 0.1.7 → 0.1.9

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 (167) hide show
  1. package/.jsii +10 -10
  2. package/lib/rootmail.js +1 -1
  3. package/lib/ses-receive.js +1 -1
  4. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-cjs/index.js +5 -5
  5. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-es/schemas/schemas_0.js +4 -4
  6. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/commands/DescribeDeliveryDestinationsCommand.d.ts +1 -0
  7. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/commands/GetDeliveryDestinationCommand.d.ts +1 -0
  8. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/commands/PutAccountPolicyCommand.d.ts +4 -1
  9. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/commands/PutDeliveryDestinationCommand.d.ts +2 -0
  10. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/models/models_0.d.ts +80 -36
  11. package/node_modules/@aws-sdk/client-cloudwatch-logs/dist-types/ts3.4/models/models_0.d.ts +2 -0
  12. package/node_modules/@aws-sdk/client-cloudwatch-logs/package.json +1 -1
  13. package/node_modules/@aws-sdk/client-route-53/dist-cjs/index.js +1 -1
  14. package/node_modules/@aws-sdk/client-route-53/package.json +1 -1
  15. package/node_modules/@aws-sdk/client-s3/dist-cjs/index.js +2 -1
  16. package/node_modules/@aws-sdk/client-s3/dist-es/models/enums.js +1 -0
  17. package/node_modules/@aws-sdk/client-s3/dist-types/commands/GetBucketInventoryConfigurationCommand.d.ts +1 -1
  18. package/node_modules/@aws-sdk/client-s3/dist-types/commands/ListBucketInventoryConfigurationsCommand.d.ts +1 -1
  19. package/node_modules/@aws-sdk/client-s3/dist-types/commands/PutBucketInventoryConfigurationCommand.d.ts +1 -1
  20. package/node_modules/@aws-sdk/client-s3/dist-types/models/enums.d.ts +1 -0
  21. package/node_modules/@aws-sdk/client-s3/dist-types/ts3.4/models/enums.d.ts +1 -0
  22. package/node_modules/@aws-sdk/client-s3/package.json +2 -2
  23. package/node_modules/@aws-sdk/client-ses/dist-cjs/index.js +1 -1
  24. package/node_modules/@aws-sdk/client-ses/package.json +1 -1
  25. package/node_modules/@aws-sdk/client-ssm/dist-cjs/index.js +9 -3
  26. package/node_modules/@aws-sdk/client-ssm/dist-es/models/enums.js +4 -0
  27. package/node_modules/@aws-sdk/client-ssm/dist-es/schemas/schemas_0.js +3 -2
  28. package/node_modules/@aws-sdk/client-ssm/dist-types/commands/DeleteResourcePolicyCommand.d.ts +6 -0
  29. package/node_modules/@aws-sdk/client-ssm/dist-types/commands/PutResourcePolicyCommand.d.ts +12 -0
  30. package/node_modules/@aws-sdk/client-ssm/dist-types/models/enums.d.ts +12 -0
  31. package/node_modules/@aws-sdk/client-ssm/dist-types/models/models_0.d.ts +20 -1
  32. package/node_modules/@aws-sdk/client-ssm/dist-types/models/models_1.d.ts +2 -2
  33. package/node_modules/@aws-sdk/client-ssm/dist-types/ts3.4/models/enums.d.ts +5 -0
  34. package/node_modules/@aws-sdk/client-ssm/dist-types/ts3.4/models/models_0.d.ts +2 -0
  35. package/node_modules/@aws-sdk/client-ssm/package.json +1 -1
  36. package/node_modules/@zone-eu/mailsplit/lib/flowed-decoder.js +1 -5
  37. package/node_modules/@zone-eu/mailsplit/lib/headers.js +35 -25
  38. package/node_modules/@zone-eu/mailsplit/lib/message-splitter.js +126 -79
  39. package/node_modules/@zone-eu/mailsplit/lib/mime-node.js +27 -5
  40. package/node_modules/@zone-eu/mailsplit/lib/node-rewriter.js +3 -2
  41. package/node_modules/@zone-eu/mailsplit/lib/types.d.ts +0 -3
  42. package/node_modules/@zone-eu/mailsplit/package.json +5 -5
  43. package/node_modules/libbase64/.github/workflows/release.yaml +12 -10
  44. package/node_modules/libbase64/.ncurc.js +7 -1
  45. package/node_modules/libbase64/CHANGELOG.md +7 -0
  46. package/node_modules/libbase64/lib/libbase64.js +27 -0
  47. package/node_modules/libbase64/package.json +4 -4
  48. package/node_modules/libmime/CHANGELOG.md +14 -0
  49. package/node_modules/libmime/lib/libmime.js +41 -21
  50. package/node_modules/libmime/package.json +3 -3
  51. package/node_modules/libqp/.github/workflows/release.yaml +12 -10
  52. package/node_modules/libqp/CHANGELOG.md +7 -0
  53. package/node_modules/libqp/lib/libqp.js +6 -4
  54. package/node_modules/libqp/package.json +2 -2
  55. package/node_modules/libqp/test/libqp-test.js +71 -14
  56. package/node_modules/mailparser/.release-please-manifest.json +1 -1
  57. package/node_modules/mailparser/CHANGELOG.md +42 -0
  58. package/node_modules/mailparser/README.md +5 -0
  59. package/node_modules/mailparser/lib/mail-parser.js +107 -32
  60. package/node_modules/mailparser/lib/simple-parser.js +12 -0
  61. package/node_modules/mailparser/lib/stream-hash.js +1 -1
  62. package/node_modules/mailparser/package.json +6 -6
  63. package/node_modules/nodemailer/CHANGELOG.md +38 -0
  64. package/node_modules/nodemailer/README.md +1 -1
  65. package/node_modules/nodemailer/dist/cjs/addressparser/index.d.ts +16 -2
  66. package/node_modules/nodemailer/dist/cjs/addressparser/index.js +147 -28
  67. package/node_modules/nodemailer/dist/cjs/base64/index.js +2 -1
  68. package/node_modules/nodemailer/dist/cjs/dkim/index.d.ts +13 -1
  69. package/node_modules/nodemailer/dist/cjs/dkim/index.js +25 -8
  70. package/node_modules/nodemailer/dist/cjs/dkim/message-parser.d.ts +10 -1
  71. package/node_modules/nodemailer/dist/cjs/dkim/message-parser.js +28 -4
  72. package/node_modules/nodemailer/dist/cjs/dkim/relaxed-body.d.ts +10 -1
  73. package/node_modules/nodemailer/dist/cjs/dkim/sign.d.ts +3 -0
  74. package/node_modules/nodemailer/dist/cjs/dkim/sign.js +18 -1
  75. package/node_modules/nodemailer/dist/cjs/errors.d.ts +3 -2
  76. package/node_modules/nodemailer/dist/cjs/fetch/cookies.d.ts +12 -1
  77. package/node_modules/nodemailer/dist/cjs/fetch/index.d.ts +15 -1
  78. package/node_modules/nodemailer/dist/cjs/fetch/index.js +39 -64
  79. package/node_modules/nodemailer/dist/cjs/json-transport/index.d.ts +14 -4
  80. package/node_modules/nodemailer/dist/cjs/json-transport/index.js +2 -0
  81. package/node_modules/nodemailer/dist/cjs/mail-composer/index.d.ts +8 -3
  82. package/node_modules/nodemailer/dist/cjs/mailer/index.d.ts +43 -25
  83. package/node_modules/nodemailer/dist/cjs/mailer/mail-message.d.ts +11 -4
  84. package/node_modules/nodemailer/dist/cjs/mime-funcs/index.d.ts +7 -3
  85. package/node_modules/nodemailer/dist/cjs/mime-funcs/index.js +198 -84
  86. package/node_modules/nodemailer/dist/cjs/mime-node/index.d.ts +5 -2
  87. package/node_modules/nodemailer/dist/cjs/mime-node/index.js +2 -1
  88. package/node_modules/nodemailer/dist/cjs/nodemailer.d.ts +38 -16
  89. package/node_modules/nodemailer/dist/cjs/nodemailer.js +1 -0
  90. package/node_modules/nodemailer/dist/cjs/package-info.d.ts +1 -1
  91. package/node_modules/nodemailer/dist/cjs/package-info.js +1 -1
  92. package/node_modules/nodemailer/dist/cjs/punycode/index.js +1 -0
  93. package/node_modules/nodemailer/dist/cjs/qp/index.d.ts +2 -0
  94. package/node_modules/nodemailer/dist/cjs/qp/index.js +10 -1
  95. package/node_modules/nodemailer/dist/cjs/sendmail-transport/index.d.ts +2 -0
  96. package/node_modules/nodemailer/dist/cjs/ses-transport/index.d.ts +39 -2
  97. package/node_modules/nodemailer/dist/cjs/shared/index.d.ts +43 -7
  98. package/node_modules/nodemailer/dist/cjs/shared/index.js +5 -2
  99. package/node_modules/nodemailer/dist/cjs/smtp-connection/data-stream.d.ts +2 -1
  100. package/node_modules/nodemailer/dist/cjs/smtp-connection/data-stream.js +32 -24
  101. package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.d.ts +13 -5
  102. package/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.js +23 -11
  103. package/node_modules/nodemailer/dist/cjs/smtp-connection/index.d.ts +59 -24
  104. package/node_modules/nodemailer/dist/cjs/smtp-connection/index.js +156 -75
  105. package/node_modules/nodemailer/dist/cjs/smtp-pool/index.d.ts +12 -4
  106. package/node_modules/nodemailer/dist/cjs/smtp-pool/index.js +39 -11
  107. package/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.js +27 -31
  108. package/node_modules/nodemailer/dist/cjs/smtp-transport/index.d.ts +19 -6
  109. package/node_modules/nodemailer/dist/cjs/smtp-transport/index.js +25 -33
  110. package/node_modules/nodemailer/dist/cjs/stream-transport/index.d.ts +2 -0
  111. package/node_modules/nodemailer/dist/cjs/well-known/services.js +6 -0
  112. package/node_modules/nodemailer/dist/cjs/xoauth2/index.d.ts +13 -3
  113. package/node_modules/nodemailer/dist/cjs/xoauth2/index.js +25 -13
  114. package/node_modules/nodemailer/dist/esm/addressparser/index.d.ts +16 -2
  115. package/node_modules/nodemailer/dist/esm/addressparser/index.js +147 -27
  116. package/node_modules/nodemailer/dist/esm/base64/index.js +2 -1
  117. package/node_modules/nodemailer/dist/esm/dkim/index.d.ts +13 -1
  118. package/node_modules/nodemailer/dist/esm/dkim/index.js +25 -8
  119. package/node_modules/nodemailer/dist/esm/dkim/message-parser.d.ts +10 -1
  120. package/node_modules/nodemailer/dist/esm/dkim/message-parser.js +30 -5
  121. package/node_modules/nodemailer/dist/esm/dkim/relaxed-body.d.ts +10 -1
  122. package/node_modules/nodemailer/dist/esm/dkim/relaxed-body.js +2 -1
  123. package/node_modules/nodemailer/dist/esm/dkim/sign.d.ts +3 -0
  124. package/node_modules/nodemailer/dist/esm/dkim/sign.js +18 -1
  125. package/node_modules/nodemailer/dist/esm/errors.d.ts +3 -2
  126. package/node_modules/nodemailer/dist/esm/fetch/cookies.d.ts +12 -1
  127. package/node_modules/nodemailer/dist/esm/fetch/cookies.js +2 -1
  128. package/node_modules/nodemailer/dist/esm/fetch/index.d.ts +15 -1
  129. package/node_modules/nodemailer/dist/esm/fetch/index.js +39 -64
  130. package/node_modules/nodemailer/dist/esm/json-transport/index.d.ts +14 -4
  131. package/node_modules/nodemailer/dist/esm/json-transport/index.js +2 -0
  132. package/node_modules/nodemailer/dist/esm/mail-composer/index.d.ts +8 -3
  133. package/node_modules/nodemailer/dist/esm/mailer/index.d.ts +43 -25
  134. package/node_modules/nodemailer/dist/esm/mailer/mail-message.d.ts +11 -4
  135. package/node_modules/nodemailer/dist/esm/mime-funcs/index.d.ts +7 -3
  136. package/node_modules/nodemailer/dist/esm/mime-funcs/index.js +198 -84
  137. package/node_modules/nodemailer/dist/esm/mime-node/index.d.ts +5 -2
  138. package/node_modules/nodemailer/dist/esm/mime-node/index.js +2 -1
  139. package/node_modules/nodemailer/dist/esm/nodemailer.d.ts +38 -16
  140. package/node_modules/nodemailer/dist/esm/package-info.d.ts +1 -1
  141. package/node_modules/nodemailer/dist/esm/package-info.js +1 -1
  142. package/node_modules/nodemailer/dist/esm/punycode/index.js +1 -0
  143. package/node_modules/nodemailer/dist/esm/qp/index.d.ts +2 -0
  144. package/node_modules/nodemailer/dist/esm/qp/index.js +10 -1
  145. package/node_modules/nodemailer/dist/esm/sendmail-transport/index.d.ts +2 -0
  146. package/node_modules/nodemailer/dist/esm/ses-transport/index.d.ts +39 -2
  147. package/node_modules/nodemailer/dist/esm/shared/index.d.ts +43 -7
  148. package/node_modules/nodemailer/dist/esm/shared/index.js +5 -2
  149. package/node_modules/nodemailer/dist/esm/smtp-connection/data-stream.d.ts +2 -1
  150. package/node_modules/nodemailer/dist/esm/smtp-connection/data-stream.js +32 -24
  151. package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.d.ts +13 -5
  152. package/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.js +23 -11
  153. package/node_modules/nodemailer/dist/esm/smtp-connection/index.d.ts +59 -24
  154. package/node_modules/nodemailer/dist/esm/smtp-connection/index.js +156 -75
  155. package/node_modules/nodemailer/dist/esm/smtp-pool/index.d.ts +12 -4
  156. package/node_modules/nodemailer/dist/esm/smtp-pool/index.js +39 -11
  157. package/node_modules/nodemailer/dist/esm/smtp-pool/pool-resource.js +27 -31
  158. package/node_modules/nodemailer/dist/esm/smtp-transport/index.d.ts +19 -6
  159. package/node_modules/nodemailer/dist/esm/smtp-transport/index.js +25 -33
  160. package/node_modules/nodemailer/dist/esm/stream-transport/index.d.ts +2 -0
  161. package/node_modules/nodemailer/dist/esm/well-known/services.js +6 -0
  162. package/node_modules/nodemailer/dist/esm/xoauth2/index.d.ts +13 -3
  163. package/node_modules/nodemailer/dist/esm/xoauth2/index.js +25 -13
  164. package/node_modules/nodemailer/dist/well-known/services.json +7 -0
  165. package/node_modules/nodemailer/package.json +16 -12
  166. package/package.json +18 -16
  167. package/renovate.json5 +59 -0
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.3.1](https://github.com/nodemailer/libbase64/compare/v1.3.0...v1.3.1) (2026-09-28)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **decoder:** decode every padded segment instead of stopping at the first padding ([d9ba154](https://github.com/nodemailer/libbase64/commit/d9ba154ba13e45338936a55acec417dfb6ae2e52))
9
+
3
10
  ## [1.3.0](https://github.com/nodemailer/libbase64/compare/v1.2.1...v1.3.0) (2024-02-23)
4
11
 
5
12
 
@@ -26,6 +26,22 @@ function encode(buffer) {
26
26
  */
27
27
  function decode(str) {
28
28
  str = str || '';
29
+
30
+ // Buffer.from() stops decoding at the first padding char, so input made of several
31
+ // padded segments (eg. every line padded on its own) is decoded segment by segment
32
+ if (typeof str === 'string') {
33
+ let padPos = str.indexOf('=');
34
+ if (padPos >= 0 && /[a-zA-Z0-9+/\-_]/.test(str.substr(padPos))) {
35
+ let parts = [];
36
+ for (let segment of str.split(/[=]+/)) {
37
+ if (segment) {
38
+ parts.push(Buffer.from(segment, 'base64'));
39
+ }
40
+ }
41
+ return Buffer.concat(parts);
42
+ }
43
+ }
44
+
29
45
  return Buffer.from(str, 'base64');
30
46
  }
31
47
 
@@ -215,6 +231,15 @@ class Decoder extends Transform {
215
231
  b64 = b64.replace(/[^a-zA-Z0-9+/=]/g, '');
216
232
  }
217
233
 
234
+ // everything up to the last padding char ends in complete segments, quartets are
235
+ // only counted from there on as a padding run restarts the quartet alignment
236
+ let padded = '';
237
+ let lastPad = b64.lastIndexOf('=');
238
+ if (lastPad >= 0) {
239
+ padded = b64.substr(0, lastPad + 1);
240
+ b64 = b64.substr(lastPad + 1);
241
+ }
242
+
218
243
  if (b64.length < 4) {
219
244
  this._curLine = b64;
220
245
  b64 = '';
@@ -223,6 +248,8 @@ class Decoder extends Transform {
223
248
  b64 = b64.substr(0, b64.length - this._curLine.length);
224
249
  }
225
250
 
251
+ b64 = padded + b64;
252
+
226
253
  if (b64) {
227
254
  let buf = decode(b64);
228
255
  this.outputBytes += buf.length;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libbase64",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Encode and decode base64 encoded strings",
5
5
  "main": "lib/libbase64.js",
6
6
  "scripts": {
@@ -24,9 +24,9 @@
24
24
  "devDependencies": {
25
25
  "chai": "4.4.1",
26
26
  "eslint-config-nodemailer": "1.2.0",
27
- "eslint-config-prettier": "9.1.0",
28
- "grunt": "1.6.1",
29
- "grunt-cli": "1.4.3",
27
+ "eslint-config-prettier": "10.1.8",
28
+ "grunt": "1.6.3",
29
+ "grunt-cli": "1.5.0",
30
30
  "grunt-eslint": "24.3.0",
31
31
  "grunt-mocha-test": "0.13.3",
32
32
  "mocha": "10.3.0"
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.4.6](https://github.com/nodemailer/libmime/compare/v5.4.5...v5.4.6) (2026-09-28)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * decode B-encoded words through libbase64 ([362f5ff](https://github.com/nodemailer/libmime/commit/362f5ff9cab6afab4a7673763f57b66d54d0f3e3))
9
+
10
+ ## [5.4.5](https://github.com/nodemailer/libmime/compare/v5.4.4...v5.4.5) (2026-09-28)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * linear-time flowed decoding and header unfolding ([4035752](https://github.com/nodemailer/libmime/commit/4035752083f9eee25dff595062f2f9b9bbabee2e))
16
+
3
17
  ## [5.4.4](https://github.com/nodemailer/libmime/compare/v5.4.3...v5.4.4) (2026-09-15)
4
18
 
5
19
 
@@ -82,35 +82,55 @@ class Libmime {
82
82
 
83
83
  let lines = str.split(/\r?\n/);
84
84
 
85
- let result = [],
86
- buffer = null;
85
+ let result = [];
86
+
87
+ // The current paragraph is kept as a list of non-empty pieces and joined once when it
88
+ // ends. Appending to one string and testing it with a regex on every line re-scans (and
89
+ // flattens) the whole paragraph each time, which is quadratic on long soft-wrapped bodies.
90
+ let parts = null,
91
+ partsLength = 0;
92
+
93
+ let pushPart = part => {
94
+ if (part) {
95
+ parts.push(part);
96
+ partsLength += part.length;
97
+ }
98
+ };
87
99
 
88
100
  // remove soft linebreaks
89
101
  // soft linebreaks are added after space symbols
90
102
  for (let i = 0; i < lines.length; i++) {
91
103
  let line = lines[i];
92
104
 
93
- let isSoftBreak = buffer !== null && / $/.test(buffer) && !/(^|\n)-- $/.test(buffer);
105
+ // the last piece is never empty, so it holds the last character of the paragraph
106
+ let last = parts !== null && parts.length ? parts[parts.length - 1] : '';
107
+
108
+ // Lines never contain a line break, so a signature separator can only be the whole
109
+ // paragraph being exactly "-- "
110
+ let isSoftBreak = last.endsWith(' ') && !(partsLength === 3 && parts.join('') === '-- ');
94
111
 
95
112
  if (isSoftBreak) {
96
113
  if (delSp) {
97
114
  // delsp adds space to text to be able to fold it
98
115
  // these spaces can be removed once the text is unfolded
99
- buffer = buffer.slice(0, -1) + line;
100
- } else {
101
- buffer += line;
116
+ parts.pop();
117
+ partsLength -= last.length;
118
+ pushPart(last.slice(0, -1));
102
119
  }
120
+ pushPart(line);
103
121
  } else {
104
- if (buffer !== null) {
105
- result.push(buffer);
122
+ if (parts !== null) {
123
+ result.push(parts.join(''));
106
124
  }
107
125
 
108
- buffer = line;
126
+ parts = [];
127
+ partsLength = 0;
128
+ pushPart(line);
109
129
  }
110
130
  }
111
131
 
112
- if (buffer) {
113
- result.push(buffer);
132
+ if (parts !== null && partsLength) {
133
+ result.push(parts.join(''));
114
134
  }
115
135
 
116
136
  // remove whitespace stuffing
@@ -279,12 +299,8 @@ class Libmime {
279
299
  }
280
300
  str = Buffer.from(bytes);
281
301
  } else if (encoding === 'B') {
282
- str = Buffer.concat(
283
- str
284
- .split('=')
285
- .filter(s => s !== '') // filter empty string
286
- .map(str => Buffer.from(str, 'base64'))
287
- );
302
+ // libbase64 decodes input made of several padded segments segment by segment
303
+ str = libbase64.decode(str);
288
304
  } else {
289
305
  // keep as is, convert Buffer to unicode string, assume utf8
290
306
  str = Buffer.from(str);
@@ -433,12 +449,16 @@ class Libmime {
433
449
  lines = lines.slice(headersPos, bodyPos >= 0 ? bodyPos : lines.length);
434
450
 
435
451
  // unfold folded lines, a continuation line always starts with a space or a tab
436
- for (i = lines.length - 1; i > 0; i--) {
437
- if (/^[ \t]/.test(lines[i])) {
438
- lines[i - 1] += '\r\n' + lines[i];
439
- lines.splice(i, 1);
452
+ // Built in one forward pass, removing continuation lines with splice() is quadratic
453
+ let unfolded = [];
454
+ for (i = 0, len = lines.length; i < len; i++) {
455
+ if (unfolded.length && /^[ \t]/.test(lines[i])) {
456
+ unfolded[unfolded.length - 1] += '\r\n' + lines[i];
457
+ } else {
458
+ unfolded.push(lines[i]);
440
459
  }
441
460
  }
461
+ lines = unfolded;
442
462
 
443
463
  for (i = 0, len = lines.length; i < len; i++) {
444
464
  header = this.decodeHeader(lines[i]);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "libmime",
3
3
  "description": "Encode and decode quoted printable and base64 strings",
4
- "version": "5.4.4",
4
+ "version": "5.4.6",
5
5
  "main": "lib/libmime.js",
6
6
  "files": [
7
7
  "lib",
@@ -26,8 +26,8 @@
26
26
  "dependencies": {
27
27
  "encoding-japanese": "2.4.0",
28
28
  "iconv-lite": "0.7.3",
29
- "libbase64": "1.3.0",
30
- "libqp": "2.1.1"
29
+ "libbase64": "1.3.1",
30
+ "libqp": "2.1.2"
31
31
  },
32
32
  "devDependencies": {
33
33
  "chai": "4.4.1",
@@ -2,6 +2,9 @@ on:
2
2
  push:
3
3
  branches:
4
4
  - master
5
+ # Manual run: publish the version currently on master (used when a release was cut
6
+ # but the publish step failed)
7
+ workflow_dispatch:
5
8
 
6
9
  permissions:
7
10
  contents: write
@@ -15,23 +18,22 @@ jobs:
15
18
  steps:
16
19
  - uses: google-github-actions/release-please-action@v3
17
20
  id: release
21
+ if: ${{ github.event_name == 'push' }}
18
22
  with:
19
23
  release-type: node
20
24
  package-name: ${{vars.NPM_MODULE_NAME}}
21
25
  pull-request-title-pattern: 'chore${scope}: release ${version} [skip-ci]'
22
- # The logic below handles the npm publication:
26
+ # The logic below handles the npm publication through npm trusted publishing
27
+ # (OIDC, no token secret): it runs when a new release is created, or on a
28
+ # manual dispatch.
23
29
  - uses: actions/checkout@v4
24
- # these if statements ensure that a publication only occurs when
25
- # a new release is created:
26
- if: ${{ steps.release.outputs.release_created }}
30
+ if: ${{ steps.release.outputs.release_created || github.event_name == 'workflow_dispatch' }}
27
31
  - uses: actions/setup-node@v4
28
32
  with:
29
- node-version: 20
33
+ node-version: 24
30
34
  registry-url: 'https://registry.npmjs.org'
31
- if: ${{ steps.release.outputs.release_created }}
35
+ if: ${{ steps.release.outputs.release_created || github.event_name == 'workflow_dispatch' }}
32
36
  - run: npm ci
33
- if: ${{ steps.release.outputs.release_created }}
37
+ if: ${{ steps.release.outputs.release_created || github.event_name == 'workflow_dispatch' }}
34
38
  - run: npm publish --provenance --access public
35
- env:
36
- NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
37
- if: ${{ steps.release.outputs.release_created }}
39
+ if: ${{ steps.release.outputs.release_created || github.event_name == 'workflow_dispatch' }}
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.1.2](https://github.com/nodemailer/libqp/compare/v2.1.1...v2.1.2) (2026-09-28)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **decoder:** keep raw 8-bit bytes intact when decoding ([7bbdcbe](https://github.com/nodemailer/libqp/commit/7bbdcbeac4475e5e16b7f24a578ed6209de133a8))
9
+
3
10
  ## [2.1.1](https://github.com/nodemailer/libqp/compare/v2.1.0...v2.1.1) (2024-11-29)
4
11
 
5
12
 
@@ -45,12 +45,14 @@ function encode(buffer) {
45
45
  /**
46
46
  * Decodes a Quoted-Printable encoded string to a Buffer object
47
47
  *
48
- * @param {String} str Quoted-Printable encoded string
48
+ * @param {String|Buffer} str Quoted-Printable encoded string. A Buffer is read byte for byte,
49
+ * so raw 8-bit bytes in the input are copied to the output unchanged
49
50
  * @returns {Buffer} Decoded value
50
51
  */
51
52
  function decode(str) {
52
- str = (str || '')
53
- .toString()
53
+ // 'binary' maps every byte to one char code 0-255. A UTF-8 read would collapse raw
54
+ // multi-byte chars into one byte below and turn raw latin1 bytes into U+FFFD
55
+ str = (Buffer.isBuffer(str) ? str.toString('binary') : (str || '').toString())
54
56
  // remove invalid whitespace from the end of lines
55
57
  .replace(/[\t ]+$/gm, '')
56
58
  // remove soft line breaks
@@ -292,7 +294,7 @@ class Decoder extends Transform {
292
294
 
293
295
  _flush(done) {
294
296
  if (this.inputBytes) {
295
- let buf = decode(Buffer.concat(this.qpChunks, this.inputBytes).toString());
297
+ let buf = decode(Buffer.concat(this.qpChunks, this.inputBytes));
296
298
  this.outputBytes += buf.length;
297
299
  this.push(buf);
298
300
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libqp",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "Encode and decode quoted-printable strings according to rfc2045",
5
5
  "main": "lib/libqp.js",
6
6
  "scripts": {
@@ -23,6 +23,6 @@
23
23
  "homepage": "https://github.com/nodemailer/libqp",
24
24
  "devDependencies": {
25
25
  "eslint-config-nodemailer": "1.2.0",
26
- "eslint-config-prettier": "9.1.0"
26
+ "eslint-config-prettier": "10.1.8"
27
27
  }
28
28
  }
@@ -42,12 +42,8 @@ test('Encoding tests', async t => {
42
42
 
43
43
  test('Decoding tests', async t => {
44
44
  // Example taken from RFC2045 section 6.7
45
- const encoded =
46
- "Now's the time =\r\n" +
47
- "for all folk to come=\r\n" +
48
- " to the aid of their country."
49
- const expectedDecoded =
50
- "Now's the time for all folk to come to the aid of their country."
45
+ const encoded = "Now's the time =\r\n" + 'for all folk to come=\r\n' + ' to the aid of their country.';
46
+ const expectedDecoded = "Now's the time for all folk to come to the aid of their country.";
51
47
 
52
48
  await t.test('simple string', async () => {
53
49
  const decoded = libqp.decode(encoded).toString();
@@ -81,8 +77,8 @@ test('Decoding tests', async t => {
81
77
 
82
78
  await t.test('stream, multiple chunks', async () => {
83
79
  const encodedChunk1Length = 3;
84
- const encodedChunk1 = encoded.substring(0, encodedChunk1Length)
85
- const encodedChunk2 = encoded.substring(encodedChunk1Length)
80
+ const encodedChunk1 = encoded.substring(0, encodedChunk1Length);
81
+ const encodedChunk2 = encoded.substring(encodedChunk1Length);
86
82
 
87
83
  const decoder = new libqp.Decoder();
88
84
 
@@ -111,8 +107,8 @@ test('Decoding tests', async t => {
111
107
 
112
108
  await t.test('stream, space at end of chunk', async () => {
113
109
  const encodedChunk1Length = encoded.indexOf(' ') + 1;
114
- const encodedChunk1 = encoded.substring(0, encodedChunk1Length)
115
- const encodedChunk2 = encoded.substring(encodedChunk1Length)
110
+ const encodedChunk1 = encoded.substring(0, encodedChunk1Length);
111
+ const encodedChunk2 = encoded.substring(encodedChunk1Length);
116
112
 
117
113
  const decoder = new libqp.Decoder();
118
114
 
@@ -141,8 +137,8 @@ test('Decoding tests', async t => {
141
137
 
142
138
  await t.test('stream, soft line break equals sign at end of chunk', async () => {
143
139
  const encodedChunk1Length = encoded.indexOf('=') + 1;
144
- const encodedChunk1 = encoded.substring(0, encodedChunk1Length)
145
- const encodedChunk2 = encoded.substring(encodedChunk1Length)
140
+ const encodedChunk1 = encoded.substring(0, encodedChunk1Length);
141
+ const encodedChunk2 = encoded.substring(encodedChunk1Length);
146
142
 
147
143
  const decoder = new libqp.Decoder();
148
144
 
@@ -171,8 +167,8 @@ test('Decoding tests', async t => {
171
167
 
172
168
  await t.test('stream, CR at end of chunk', async () => {
173
169
  const encodedChunk1Length = encoded.indexOf('\r') + 1;
174
- const encodedChunk1 = encoded.substring(0, encodedChunk1Length)
175
- const encodedChunk2 = encoded.substring(encodedChunk1Length)
170
+ const encodedChunk1 = encoded.substring(0, encodedChunk1Length);
171
+ const encodedChunk2 = encoded.substring(encodedChunk1Length);
176
172
 
177
173
  const decoder = new libqp.Decoder();
178
174
 
@@ -199,3 +195,64 @@ test('Decoding tests', async t => {
199
195
  assert.strictEqual(decoded, expectedDecoded);
200
196
  });
201
197
  });
198
+
199
+ test('Raw 8-bit bytes in Quoted-Printable input', async t => {
200
+ const decodeStream = async chunks =>
201
+ await new Promise((resolve, reject) => {
202
+ const decoder = new libqp.Decoder();
203
+ const output = [];
204
+ decoder.on('data', chunk => output.push(chunk));
205
+ decoder.on('end', () => resolve(Buffer.concat(output)));
206
+ decoder.on('error', reject);
207
+ for (const chunk of chunks) {
208
+ decoder.write(chunk);
209
+ }
210
+ decoder.end();
211
+ });
212
+
213
+ // "caf\xC3\xA9 \xE2\x82\xAC =C3=A9", raw UTF-8 bytes mixed with an escape
214
+ const utf8Input = Buffer.concat([Buffer.from('caf'), Buffer.from([0xc3, 0xa9, 0x20, 0xe2, 0x82, 0xac]), Buffer.from(' =C3=A9')]);
215
+ const utf8Expected = Buffer.from('café € é');
216
+
217
+ // "caf\xE9 =E9", a raw latin1 byte next to the same byte escaped
218
+ const latin1Input = Buffer.concat([Buffer.from('caf'), Buffer.from([0xe9]), Buffer.from(' =E9')]);
219
+ const latin1Expected = Buffer.from([0x63, 0x61, 0x66, 0xe9, 0x20, 0xe9]);
220
+
221
+ await t.test('decode() keeps raw UTF-8 bytes from a Buffer', async () => {
222
+ assert.deepStrictEqual(libqp.decode(utf8Input), utf8Expected);
223
+ });
224
+
225
+ await t.test('decode() keeps raw latin1 bytes from a Buffer', async () => {
226
+ assert.deepStrictEqual(libqp.decode(latin1Input), latin1Expected);
227
+ });
228
+
229
+ await t.test('decode() of a binary string still maps char codes to bytes', async () => {
230
+ assert.deepStrictEqual(libqp.decode(latin1Input.toString('binary')), latin1Expected);
231
+ });
232
+
233
+ await t.test('Decoder keeps raw UTF-8 bytes', async () => {
234
+ assert.deepStrictEqual(await decodeStream([utf8Input]), utf8Expected);
235
+ });
236
+
237
+ await t.test('Decoder keeps raw latin1 bytes', async () => {
238
+ assert.deepStrictEqual(await decodeStream([latin1Input]), latin1Expected);
239
+ });
240
+
241
+ await t.test('Decoder keeps raw bytes and escapes split byte by byte', async () => {
242
+ const chunks = [];
243
+ for (let i = 0; i < utf8Input.length; i++) {
244
+ chunks.push(utf8Input.subarray(i, i + 1));
245
+ }
246
+ assert.deepStrictEqual(await decodeStream(chunks), utf8Expected);
247
+ });
248
+
249
+ await t.test('Decoder handles an escape split across chunks', async () => {
250
+ // split inside "=C3", once after "=" and once after "=C"
251
+ const input = Buffer.from('ab=C3=A9=\r\ncd');
252
+ const expected = Buffer.from('abécd');
253
+ assert.deepStrictEqual(await decodeStream([input.subarray(0, 3), input.subarray(3)]), expected);
254
+ assert.deepStrictEqual(await decodeStream([input.subarray(0, 4), input.subarray(4)]), expected);
255
+ // soft line break split between "=" and CRLF
256
+ assert.deepStrictEqual(await decodeStream([input.subarray(0, 9), input.subarray(9)]), expected);
257
+ });
258
+ });
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "3.9.28"
2
+ ".": "3.9.34"
3
3
  }
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.9.34](https://github.com/nodemailer/mailparser/compare/v3.9.33...v3.9.34) (2026-10-03)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **deps:** update nodemailer to 10.0.14 ([f79334d](https://github.com/nodemailer/mailparser/commit/f79334d4f2b1cd296a7b4770710ee5095a78c43a))
9
+
10
+ ## [3.9.33](https://github.com/nodemailer/mailparser/compare/v3.9.32...v3.9.33) (2026-10-01)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * report an unavailable checksum algorithm as a parser error ([dc24878](https://github.com/nodemailer/mailparser/commit/dc248783a735c379627c0afd76ee3d7ff5400ce0))
16
+
17
+ ## [3.9.32](https://github.com/nodemailer/mailparser/compare/v3.9.31...v3.9.32) (2026-09-30)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **deps:** update nodemailer to 10.0.13 ([c0dfdf8](https://github.com/nodemailer/mailparser/commit/c0dfdf87cdee539ae40a46a09d6a3f5f1b47cd3c))
23
+
24
+ ## [3.9.31](https://github.com/nodemailer/mailparser/compare/v3.9.30...v3.9.31) (2026-09-28)
25
+
26
+
27
+ ### Bug Fixes
28
+
29
+ * **deps:** update libmime to 5.4.6 and mailsplit to 5.4.19 ([bdaf7c3](https://github.com/nodemailer/mailparser/commit/bdaf7c3945d1c3dc0bebb0300c5dd9cd243e2746))
30
+
31
+ ## [3.9.30](https://github.com/nodemailer/mailparser/compare/v3.9.29...v3.9.30) (2026-09-28)
32
+
33
+
34
+ ### Bug Fixes
35
+
36
+ * cap inlined cid images, report late splitter errors, settle once, honour attachment backpressure, derive partId from the part number ([af3fe56](https://github.com/nodemailer/mailparser/commit/af3fe56719ae6bf5d867f22faf3bf81942659bdd))
37
+
38
+ ## [3.9.29](https://github.com/nodemailer/mailparser/compare/v3.9.28...v3.9.29) (2026-09-27)
39
+
40
+
41
+ ### Bug Fixes
42
+
43
+ * **deps:** update nodemailer to 10.0.11 ([bd1407a](https://github.com/nodemailer/mailparser/commit/bd1407a1f653e4fdb95df406e779184164ddee38))
44
+
3
45
  ## [3.9.28](https://github.com/nodemailer/mailparser/compare/v3.9.27...v3.9.28) (2026-09-15)
4
46
 
5
47
 
@@ -25,6 +25,11 @@ const mailparser = require('mailparser');
25
25
 
26
26
  See [mailparser homepage](https://nodemailer.com/extras/mailparser/) for documentation and terms.
27
27
 
28
+ ### Limits
29
+
30
+ - `simpleParser` replaces `cid:` image references in the HTML with `data:` URLs. The total length of the URLs written into the HTML is capped by the `maxInlinedImagesSize` option (default 20 MB, counted in characters of the inserted URLs). References past the cap stay as `cid:` links. The same cap applies to URLs returned from a custom `updateImageLinks()` callback.
31
+ - `simpleParser` calls its callback, or settles its promise, exactly once. When `MailParser` reports a non-fatal error (for example HTML longer than `maxHtmlLengthToParse`), that error is what the caller receives. `MailParser` itself still emits the `'error'` event and then finishes parsing.
32
+
28
33
  ### License
29
34
 
30
35
  Licensed under MIT