imapflow 1.7.8 → 2.0.0

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 (296) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +8 -2
  3. package/dist/cjs/charsets.d.ts +1 -0
  4. package/dist/cjs/charsets.js +294 -0
  5. package/dist/cjs/commands/append.d.ts +22 -0
  6. package/dist/cjs/commands/append.js +151 -0
  7. package/dist/cjs/commands/authenticate.d.ts +24 -0
  8. package/dist/cjs/commands/authenticate.js +223 -0
  9. package/dist/cjs/commands/capability.d.ts +8 -0
  10. package/dist/cjs/commands/capability.js +32 -0
  11. package/dist/cjs/commands/close.d.ts +8 -0
  12. package/dist/cjs/commands/close.js +39 -0
  13. package/dist/cjs/commands/compress.d.ts +8 -0
  14. package/dist/cjs/commands/compress.js +56 -0
  15. package/dist/cjs/commands/copy.d.ts +13 -0
  16. package/dist/cjs/commands/copy.js +44 -0
  17. package/dist/cjs/commands/copyuid-parser.d.ts +11 -0
  18. package/dist/cjs/commands/copyuid-parser.js +32 -0
  19. package/dist/cjs/commands/create.d.ts +11 -0
  20. package/dist/cjs/commands/create.js +80 -0
  21. package/dist/cjs/commands/delete.d.ts +11 -0
  22. package/dist/cjs/commands/delete.js +40 -0
  23. package/dist/cjs/commands/enable.d.ts +9 -0
  24. package/dist/cjs/commands/enable.js +61 -0
  25. package/dist/cjs/commands/esearch-parser.d.ts +17 -0
  26. package/dist/cjs/commands/esearch-parser.js +91 -0
  27. package/dist/cjs/commands/expunge.d.ts +12 -0
  28. package/dist/cjs/commands/expunge.js +60 -0
  29. package/dist/cjs/commands/fetch.d.ts +30 -0
  30. package/dist/cjs/commands/fetch.js +241 -0
  31. package/dist/cjs/commands/id.d.ts +10 -0
  32. package/dist/cjs/commands/id.js +80 -0
  33. package/dist/cjs/commands/idle.d.ts +9 -0
  34. package/dist/cjs/commands/idle.js +347 -0
  35. package/dist/cjs/commands/list.d.ts +16 -0
  36. package/dist/cjs/commands/list.js +518 -0
  37. package/dist/cjs/commands/login.d.ts +11 -0
  38. package/dist/cjs/commands/login.js +42 -0
  39. package/dist/cjs/commands/logout.d.ts +8 -0
  40. package/dist/cjs/commands/logout.js +47 -0
  41. package/dist/cjs/commands/move.d.ts +13 -0
  42. package/dist/cjs/commands/move.js +57 -0
  43. package/dist/cjs/commands/namespace.d.ts +25 -0
  44. package/dist/cjs/commands/namespace.js +139 -0
  45. package/dist/cjs/commands/noop.d.ts +8 -0
  46. package/dist/cjs/commands/noop.js +22 -0
  47. package/dist/cjs/commands/quota.d.ts +10 -0
  48. package/dist/cjs/commands/quota.js +119 -0
  49. package/dist/cjs/commands/rename.d.ts +12 -0
  50. package/dist/cjs/commands/rename.js +48 -0
  51. package/dist/cjs/commands/search.d.ts +15 -0
  52. package/dist/cjs/commands/search.js +228 -0
  53. package/dist/cjs/commands/select.d.ts +25 -0
  54. package/dist/cjs/commands/select.js +250 -0
  55. package/dist/cjs/commands/starttls.d.ts +8 -0
  56. package/dist/cjs/commands/starttls.js +30 -0
  57. package/dist/cjs/commands/status-fields.d.ts +14 -0
  58. package/dist/cjs/commands/status-fields.js +61 -0
  59. package/dist/cjs/commands/status.d.ts +12 -0
  60. package/dist/cjs/commands/status.js +108 -0
  61. package/dist/cjs/commands/store.d.ts +19 -0
  62. package/dist/cjs/commands/store.js +93 -0
  63. package/dist/cjs/commands/subscribe.d.ts +9 -0
  64. package/dist/cjs/commands/subscribe.js +31 -0
  65. package/dist/cjs/commands/unsubscribe.d.ts +9 -0
  66. package/dist/cjs/commands/unsubscribe.js +31 -0
  67. package/dist/cjs/connection-deadline.d.ts +49 -0
  68. package/dist/cjs/connection-deadline.js +91 -0
  69. package/dist/cjs/errors.d.ts +83 -0
  70. package/dist/cjs/errors.js +13 -0
  71. package/dist/cjs/handler/imap-compiler.d.ts +24 -0
  72. package/dist/cjs/handler/imap-compiler.js +285 -0
  73. package/dist/cjs/handler/imap-formal-syntax.d.ts +28 -0
  74. package/dist/cjs/handler/imap-formal-syntax.js +121 -0
  75. package/dist/cjs/handler/imap-handler.d.ts +9 -0
  76. package/dist/cjs/handler/imap-handler.js +10 -0
  77. package/dist/cjs/handler/imap-parser.d.ts +16 -0
  78. package/dist/cjs/handler/imap-parser.js +90 -0
  79. package/dist/cjs/handler/imap-stream.d.ts +181 -0
  80. package/dist/cjs/handler/imap-stream.js +446 -0
  81. package/dist/cjs/handler/limits.d.ts +25 -0
  82. package/dist/cjs/handler/limits.js +51 -0
  83. package/dist/cjs/handler/parser-instance.d.ts +68 -0
  84. package/dist/cjs/handler/parser-instance.js +223 -0
  85. package/dist/cjs/handler/token-parser.d.ts +91 -0
  86. package/dist/cjs/handler/token-parser.js +673 -0
  87. package/dist/cjs/handler/types.d.ts +91 -0
  88. package/dist/cjs/handler/types.js +4 -0
  89. package/dist/cjs/imap-commands.d.ts +16 -0
  90. package/dist/cjs/imap-commands.js +74 -0
  91. package/dist/cjs/imap-flow.d.ts +676 -0
  92. package/dist/cjs/imap-flow.js +3949 -0
  93. package/dist/cjs/jp-decoder.d.ts +12 -0
  94. package/dist/cjs/jp-decoder.js +79 -0
  95. package/dist/cjs/limited-passthrough.d.ts +25 -0
  96. package/dist/cjs/limited-passthrough.js +54 -0
  97. package/dist/cjs/logger.d.ts +3 -0
  98. package/dist/cjs/logger.js +11 -0
  99. package/dist/cjs/package-info.d.ts +3 -0
  100. package/dist/cjs/package-info.js +7 -0
  101. package/dist/cjs/package.json +3 -0
  102. package/dist/cjs/proxy-connection.d.ts +33 -0
  103. package/dist/cjs/proxy-connection.js +392 -0
  104. package/dist/cjs/search-compiler.d.ts +34 -0
  105. package/dist/cjs/search-compiler.js +476 -0
  106. package/dist/cjs/special-use.d.ts +22 -0
  107. package/dist/cjs/special-use.js +911 -0
  108. package/dist/cjs/tools.d.ts +427 -0
  109. package/dist/cjs/tools.js +1496 -0
  110. package/{lib/imap-flow.d.ts → dist/cjs/types.d.ts} +386 -516
  111. package/dist/cjs/types.js +5 -0
  112. package/dist/esm/charsets.d.ts +1 -0
  113. package/{lib → dist/esm}/charsets.js +1 -6
  114. package/dist/esm/commands/append.d.ts +22 -0
  115. package/{lib → dist/esm}/commands/append.js +22 -52
  116. package/dist/esm/commands/authenticate.d.ts +24 -0
  117. package/{lib → dist/esm}/commands/authenticate.js +62 -87
  118. package/dist/esm/commands/capability.d.ts +8 -0
  119. package/{lib → dist/esm}/commands/capability.js +6 -9
  120. package/dist/esm/commands/close.d.ts +8 -0
  121. package/{lib → dist/esm}/commands/close.js +6 -10
  122. package/dist/esm/commands/compress.d.ts +8 -0
  123. package/{lib → dist/esm}/commands/compress.js +7 -11
  124. package/dist/esm/commands/copy.d.ts +13 -0
  125. package/{lib → dist/esm}/commands/copy.js +12 -20
  126. package/dist/esm/commands/copyuid-parser.d.ts +11 -0
  127. package/{lib → dist/esm}/commands/copyuid-parser.js +9 -15
  128. package/dist/esm/commands/create.d.ts +11 -0
  129. package/{lib → dist/esm}/commands/create.js +13 -27
  130. package/dist/esm/commands/delete.d.ts +11 -0
  131. package/{lib → dist/esm}/commands/delete.js +9 -14
  132. package/dist/esm/commands/enable.d.ts +9 -0
  133. package/{lib → dist/esm}/commands/enable.js +23 -30
  134. package/dist/esm/commands/esearch-parser.d.ts +17 -0
  135. package/dist/esm/commands/esearch-parser.js +88 -0
  136. package/dist/esm/commands/expunge.d.ts +12 -0
  137. package/{lib → dist/esm}/commands/expunge.js +17 -22
  138. package/dist/esm/commands/fetch.d.ts +30 -0
  139. package/{lib → dist/esm}/commands/fetch.js +32 -64
  140. package/dist/esm/commands/id.d.ts +10 -0
  141. package/{lib → dist/esm}/commands/id.js +17 -23
  142. package/dist/esm/commands/idle.d.ts +9 -0
  143. package/{lib → dist/esm}/commands/idle.js +47 -81
  144. package/dist/esm/commands/list.d.ts +16 -0
  145. package/{lib → dist/esm}/commands/list.js +56 -121
  146. package/dist/esm/commands/login.d.ts +11 -0
  147. package/{lib → dist/esm}/commands/login.js +10 -15
  148. package/dist/esm/commands/logout.d.ts +8 -0
  149. package/{lib → dist/esm}/commands/logout.js +9 -11
  150. package/dist/esm/commands/move.d.ts +13 -0
  151. package/{lib → dist/esm}/commands/move.js +13 -21
  152. package/dist/esm/commands/namespace.d.ts +25 -0
  153. package/{lib → dist/esm}/commands/namespace.js +34 -44
  154. package/dist/esm/commands/noop.d.ts +8 -0
  155. package/{lib → dist/esm}/commands/noop.js +6 -7
  156. package/dist/esm/commands/quota.d.ts +10 -0
  157. package/{lib → dist/esm}/commands/quota.js +18 -36
  158. package/dist/esm/commands/rename.d.ts +12 -0
  159. package/{lib → dist/esm}/commands/rename.js +10 -15
  160. package/dist/esm/commands/search.d.ts +15 -0
  161. package/{lib → dist/esm}/commands/search.js +36 -135
  162. package/dist/esm/commands/select.d.ts +25 -0
  163. package/{lib → dist/esm}/commands/select.js +33 -64
  164. package/dist/esm/commands/starttls.d.ts +8 -0
  165. package/{lib → dist/esm}/commands/starttls.js +6 -8
  166. package/dist/esm/commands/status-fields.d.ts +14 -0
  167. package/{lib → dist/esm}/commands/status-fields.js +5 -16
  168. package/dist/esm/commands/status.d.ts +12 -0
  169. package/{lib → dist/esm}/commands/status.js +18 -29
  170. package/dist/esm/commands/store.d.ts +19 -0
  171. package/{lib → dist/esm}/commands/store.js +24 -37
  172. package/dist/esm/commands/subscribe.d.ts +9 -0
  173. package/{lib → dist/esm}/commands/subscribe.js +8 -12
  174. package/dist/esm/commands/unsubscribe.d.ts +9 -0
  175. package/{lib → dist/esm}/commands/unsubscribe.js +8 -12
  176. package/dist/esm/connection-deadline.d.ts +49 -0
  177. package/{lib → dist/esm}/connection-deadline.js +14 -25
  178. package/dist/esm/errors.d.ts +83 -0
  179. package/dist/esm/errors.js +9 -0
  180. package/dist/esm/handler/imap-compiler.d.ts +24 -0
  181. package/{lib → dist/esm}/handler/imap-compiler.js +22 -80
  182. package/dist/esm/handler/imap-formal-syntax.d.ts +28 -0
  183. package/dist/esm/handler/imap-formal-syntax.js +117 -0
  184. package/dist/esm/handler/imap-handler.d.ts +9 -0
  185. package/dist/esm/handler/imap-handler.js +9 -0
  186. package/dist/esm/handler/imap-parser.d.ts +16 -0
  187. package/{lib → dist/esm}/handler/imap-parser.js +31 -44
  188. package/dist/esm/handler/imap-stream.d.ts +181 -0
  189. package/{lib → dist/esm}/handler/imap-stream.js +29 -121
  190. package/dist/esm/handler/limits.d.ts +25 -0
  191. package/{lib → dist/esm}/handler/limits.js +13 -22
  192. package/dist/esm/handler/parser-instance.d.ts +68 -0
  193. package/{lib → dist/esm}/handler/parser-instance.js +19 -47
  194. package/dist/esm/handler/token-parser.d.ts +91 -0
  195. package/{lib → dist/esm}/handler/token-parser.js +71 -155
  196. package/dist/esm/handler/types.d.ts +91 -0
  197. package/dist/esm/handler/types.js +3 -0
  198. package/dist/esm/imap-commands.d.ts +16 -0
  199. package/dist/esm/imap-commands.js +67 -0
  200. package/dist/esm/imap-flow.d.ts +676 -0
  201. package/{lib → dist/esm}/imap-flow.js +761 -1789
  202. package/dist/esm/jp-decoder.d.ts +12 -0
  203. package/{lib → dist/esm}/jp-decoder.js +6 -21
  204. package/dist/esm/limited-passthrough.d.ts +25 -0
  205. package/{lib → dist/esm}/limited-passthrough.js +7 -20
  206. package/dist/esm/logger.d.ts +3 -0
  207. package/dist/esm/logger.js +4 -0
  208. package/dist/esm/package-info.d.ts +3 -0
  209. package/dist/esm/package-info.js +4 -0
  210. package/dist/esm/package.json +3 -0
  211. package/dist/esm/proxy-connection.d.ts +33 -0
  212. package/{lib → dist/esm}/proxy-connection.js +56 -127
  213. package/dist/esm/search-compiler.d.ts +34 -0
  214. package/{lib → dist/esm}/search-compiler.js +54 -110
  215. package/dist/esm/special-use.d.ts +22 -0
  216. package/dist/esm/special-use.js +907 -0
  217. package/dist/esm/tools.d.ts +427 -0
  218. package/dist/esm/tools.js +1446 -0
  219. package/dist/esm/types.d.ts +828 -0
  220. package/dist/esm/types.js +4 -0
  221. package/package.json +60 -20
  222. package/.gitattributes +0 -1
  223. package/.github/CODE_OF_CONDUCT.md +0 -76
  224. package/.github/FUNDING.yml +0 -4
  225. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
  226. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
  227. package/.github/contributing.md +0 -17
  228. package/.github/workflows/release.yaml +0 -36
  229. package/.github/workflows/stale.yml +0 -29
  230. package/.github/workflows/test.yml +0 -51
  231. package/.ncurc.js +0 -4
  232. package/.prettierignore +0 -4
  233. package/.prettierrc.js +0 -8
  234. package/.release-please-manifest.json +0 -3
  235. package/CLAUDE.md +0 -104
  236. package/Gruntfile.js +0 -23
  237. package/eslint.config.js +0 -45
  238. package/lib/handler/imap-formal-syntax.js +0 -189
  239. package/lib/handler/imap-handler.js +0 -17
  240. package/lib/imap-commands.js +0 -45
  241. package/lib/logger.js +0 -5
  242. package/lib/special-use.js +0 -923
  243. package/lib/tools.js +0 -1612
  244. package/release-please-config.json +0 -10
  245. package/test/authentication-test.js +0 -101
  246. package/test/auto-idle-test.js +0 -470
  247. package/test/bodystructure-test.js +0 -899
  248. package/test/charsets-test.js +0 -161
  249. package/test/commands-branches-test.js +0 -1095
  250. package/test/commands-integration-test.js +0 -11124
  251. package/test/commands-test.js +0 -73
  252. package/test/connection-edge-cases-test.js +0 -1828
  253. package/test/connection-test.js +0 -162
  254. package/test/copyuid-parser-test.js +0 -173
  255. package/test/fetch-generator-test.js +0 -218
  256. package/test/fixtures/fake-timers.js +0 -115
  257. package/test/fixtures/serialized-mimetorture.js +0 -2738
  258. package/test/fixtures/test-client.js +0 -101
  259. package/test/fixtures/test-tls.js +0 -8
  260. package/test/handler-branches-test.js +0 -310
  261. package/test/idle-polling-test.js +0 -518
  262. package/test/imap-compiler-test.js +0 -809
  263. package/test/imap-flow-compress-test.js +0 -166
  264. package/test/imap-flow-coverage-test.js +0 -612
  265. package/test/imap-flow-fetch-download-test.js +0 -909
  266. package/test/imap-flow-internals-test.js +0 -725
  267. package/test/imap-flow-methods-test.js +0 -889
  268. package/test/imap-flow-proxy-paths-test.js +0 -366
  269. package/test/imap-flow-secure-test.js +0 -573
  270. package/test/imap-flow-server-test.js +0 -1474
  271. package/test/imap-formal-syntax-test.js +0 -293
  272. package/test/imap-parser-test.js +0 -1474
  273. package/test/imap-stream-edge-cases-test.js +0 -666
  274. package/test/imap-stream-test.js +0 -177
  275. package/test/imapflow-test.js +0 -258
  276. package/test/integration/README.md +0 -52
  277. package/test/integration/dovecot-test.conf +0 -27
  278. package/test/integration/rev2-live-test.js +0 -431
  279. package/test/integration/run-rev2-tests.sh +0 -75
  280. package/test/integration-test.js +0 -83
  281. package/test/jp-decoder-test.js +0 -304
  282. package/test/limited-passthrough-test.js +0 -299
  283. package/test/memory-cleanup-test.js +0 -144
  284. package/test/memory-leak-test.js +0 -667
  285. package/test/parser-limits-test.js +0 -292
  286. package/test/proxy-connection-test.js +0 -738
  287. package/test/reliability-improvements-test.js +0 -548
  288. package/test/search-compiler-test.js +0 -1300
  289. package/test/search-test.js +0 -329
  290. package/test/special-use-test.js +0 -418
  291. package/test/starttls-injection-test.js +0 -181
  292. package/test/tag-correlation-test.js +0 -333
  293. package/test/timer-policy-test.js +0 -227
  294. package/test/token-parser-test.js +0 -456
  295. package/test/tools-test.js +0 -2013
  296. package/test/unhandled-rejection-test.js +0 -661
@@ -1,28 +1,22 @@
1
- 'use strict';
2
-
3
- const imapFormalSyntax = require('./imap-formal-syntax');
4
- const { ParserInstance } = require('./parser-instance');
5
-
1
+ import imapFormalSyntax from './imap-formal-syntax.js';
2
+ import { ParserInstance } from './parser-instance.js';
6
3
  /**
7
4
  * Parses a raw IMAP command or response buffer into a structured object.
8
5
  * Handles edge cases such as null-byte-padded responses from buggy servers and
9
6
  * multi-word commands like UID and AUTHENTICATE.
10
7
  *
11
- * @param {Buffer|string} command - The raw IMAP command or response data to parse.
12
- * @param {Object} [options] - Parser options passed through to the underlying ParserInstance and TokenParser.
13
- * @param {boolean} [options.literalPlus] - Whether the LITERAL+ extension is in use.
14
- * @param {Array<Buffer>} [options.literals] - Pre-parsed literal values extracted from the input stream.
15
- * @returns {Promise<Object>} A promise that resolves to a parsed response object.
16
- * @returns {string} return.tag - The IMAP tag (e.g., "*", "+", or a command tag like "A1").
17
- * @returns {string} return.command - The IMAP command or response name (e.g., "OK", "FETCH").
18
- * @returns {Array} [return.attributes] - Parsed attributes of the response.
19
- * @returns {number} [return.nullBytesRemoved] - Number of leading null bytes removed, if any.
8
+ * @param command - The raw IMAP command or response data to parse.
9
+ * @param options - Parser options passed through to the underlying ParserInstance and TokenParser.
10
+ * @param options.literalPlus - Whether the LITERAL+ extension is in use.
11
+ * @param options.literals - Pre-parsed literal values extracted from the input stream.
12
+ * @returns A promise that resolves to a parsed response object with `tag` (the IMAP tag, e.g. "*",
13
+ * "+", or a command tag like "A1"), `command` (the IMAP command or response name, e.g. "OK",
14
+ * "FETCH"), `attributes` (parsed attributes of the response) and `nullBytesRemoved` (number of
15
+ * leading null bytes removed, if any).
20
16
  */
21
- module.exports = async (command, options) => {
17
+ export default async function parser(command, options) {
22
18
  options = options || {};
23
-
24
19
  let nullBytesRemoved = 0;
25
-
26
20
  // Workaround for buggy IMAP servers that pad responses with leading NUL (\x00) bytes.
27
21
  // Some servers (observed in the wild) prepend null bytes to their output, which would
28
22
  // cause parsing to fail. We strip them and note how many were removed for diagnostics.
@@ -36,60 +30,53 @@ module.exports = async (command, options) => {
36
30
  }
37
31
  }
38
32
  if (firstNonNull === -1) {
39
- // All bytes are null -- treat as a BAD response
33
+ // All bytes are null, treat as a BAD response
40
34
  return { tag: '*', command: 'BAD', attributes: [] };
41
35
  }
42
36
  command = command.slice(firstNonNull);
43
37
  nullBytesRemoved = firstNonNull;
44
38
  }
45
-
46
- const parser = new ParserInstance(command, options);
39
+ const parserInstance = new ParserInstance(command, options);
47
40
  const response = {};
48
-
49
41
  try {
50
- response.tag = await parser.getTag();
51
-
52
- await parser.getSpace();
53
-
54
- response.command = await parser.getCommand();
55
-
42
+ response.tag = await parserInstance.getTag();
43
+ await parserInstance.getSpace();
44
+ response.command = await parserInstance.getCommand();
56
45
  if (nullBytesRemoved) {
57
46
  response.nullBytesRemoved = nullBytesRemoved;
58
47
  }
59
-
60
48
  // Some IMAP commands are multi-word: "UID FETCH", "UID STORE", "UID COPY",
61
49
  // "UID MOVE", "UID SEARCH", "UID EXPUNGE", and "AUTHENTICATE PLAIN", etc.
62
50
  // For these, the first word is consumed as the command, then we read the
63
51
  // subcommand and concatenate them (e.g., "UID" + " " + "FETCH" -> "UID FETCH").
64
52
  if (['UID', 'AUTHENTICATE'].includes((response.command || '').toUpperCase())) {
65
- await parser.getSpace();
66
- response.command += ' ' + (await parser.getElement(imapFormalSyntax.command()));
53
+ await parserInstance.getSpace();
54
+ response.command += ' ' + (await parserInstance.getElement(imapFormalSyntax.command()));
67
55
  }
68
-
69
- if (parser.remainder.trim().length) {
70
- await parser.getSpace();
71
- response.attributes = await parser.getAttributes();
56
+ if (parserInstance.remainder.trim().length) {
57
+ await parserInstance.getSpace();
58
+ response.attributes = await parserInstance.getAttributes();
72
59
  }
73
-
74
- if (parser.humanReadable) {
60
+ if (parserInstance.humanReadable) {
75
61
  response.attributes = (response.attributes || []).concat({
76
62
  type: 'TEXT',
77
- value: parser.humanReadable
63
+ value: parserInstance.humanReadable
78
64
  });
79
65
  }
80
- } catch (err) {
81
- if (err.code === 'ParserErrorExchange' && err.parserContext && err.parserContext.value) {
82
- return err.parserContext.value;
66
+ }
67
+ catch (err) {
68
+ let error = err;
69
+ if (error.code === 'ParserErrorExchange' && error.parserContext && error.parserContext.value) {
70
+ return error.parserContext.value;
83
71
  }
84
72
  if (response.tag) {
85
73
  // The tag had already been parsed when the rest of the line failed. Expose it
86
74
  // so the connection can settle the command this line was addressed to - unlike
87
75
  // re-deriving the tag from the raw bytes, this inherits the leading-NUL
88
76
  // workaround above.
89
- err.parsedTag = response.tag;
77
+ error.parsedTag = response.tag;
90
78
  }
91
- throw err;
79
+ throw error;
92
80
  }
93
-
94
81
  return response;
95
- };
82
+ }
@@ -0,0 +1,181 @@
1
+ import { Transform, type TransformCallback } from 'node:stream';
2
+ import type { Logger, InternalLogger } from '../types.js';
3
+ export interface ImapStreamOptions {
4
+ /** Connection identifier used for logging */
5
+ cid?: string | undefined;
6
+ /** A pino-compatible logger instance. If not provided, a default child logger is created */
7
+ logger?: Logger | InternalLogger | false | undefined;
8
+ /** If true, logs raw socket data at trace level */
9
+ logRaw?: boolean | undefined;
10
+ /** Whether the connection uses TLS */
11
+ secureConnection?: boolean | undefined;
12
+ /**
13
+ * Maximum allowed length (in bytes) of a single line (a response without a literal). Defaults
14
+ * to MAX_LITERAL_SIZE (1GB). Guards against a malicious or broken server that never sends a
15
+ * line terminator, which would otherwise grow the internal line buffer without bound. The line
16
+ * terminator counts toward the limit, and a line exactly at the limit is accepted. Exceeding it
17
+ * is terminal: the stream is destroyed with a `LineTooLarge` error and no further input is parsed.
18
+ */
19
+ maxLineLength?: number | undefined;
20
+ /**
21
+ * Maximum allowed size (in bytes) of a single literal block. Defaults to MAX_LITERAL_SIZE
22
+ * (1GB). Lower it to bound peak memory allocation against a malicious or broken server
23
+ * announcing an oversized literal. A literal exactly at the limit is accepted. Exceeding it is
24
+ * terminal: the stream is destroyed with a `LiteralTooLarge` error, the marker line is not
25
+ * emitted, and no byte of the rejected literal body is parsed as protocol.
26
+ */
27
+ maxLiteralSize?: number | undefined;
28
+ /**
29
+ * Maximum allowed total size (in bytes) of a single assembled response: every line segment and
30
+ * literal of one response combined. Defaults to MAX_RESPONSE_SIZE (2GB), which leaves room
31
+ * above the literal cap for a maximum-size literal plus its marker line. The per-line and
32
+ * per-literal caps alone cannot stop a server that spreads attacker-controlled bytes across an
33
+ * unbounded number of tokens of a single response. Declared literal sizes count when their
34
+ * marker is parsed, so an oversized total is rejected before the literal bytes arrive, and a
35
+ * line still being assembled counts against whatever budget is left. Exceeding the limit is
36
+ * terminal: the stream is destroyed with a `ResponseTooLarge` error and no further input is
37
+ * parsed.
38
+ */
39
+ maxResponseSize?: number | undefined;
40
+ }
41
+ /**
42
+ * A queued input chunk with the transform callback that releases it
43
+ */
44
+ export interface ImapStreamInputItem {
45
+ chunk: Buffer;
46
+ next: () => void;
47
+ released?: boolean | undefined;
48
+ }
49
+ /**
50
+ * A Transform stream that parses raw IMAP protocol data from a socket into structured
51
+ * command/response objects. Reads binary input, splits it into lines delimited by LF,
52
+ * extracts literal data blocks based on IMAP literal size markers (e.g., "{123}\r\n"),
53
+ * and emits each complete command as a readable object containing the payload Buffer
54
+ * and any associated literal Buffers. Enforces a maximum literal size of 1GB.
55
+ */
56
+ export declare class ImapStream extends Transform {
57
+ options: ImapStreamOptions;
58
+ cid: string | undefined;
59
+ log: InternalLogger;
60
+ readBytesCounter: number;
61
+ maxLineLength: number;
62
+ maxLiteralSize: number;
63
+ maxResponseSize: number;
64
+ state: number;
65
+ literalWaiting: number;
66
+ inputBuffer: Buffer[];
67
+ lineBuffer: Buffer[];
68
+ lineBytes: number;
69
+ literalBuffer: Buffer[];
70
+ literals: Buffer[];
71
+ responseBytes: number;
72
+ compress: boolean;
73
+ secureConnection: boolean | undefined;
74
+ processingInput: boolean;
75
+ inputQueue: ImapStreamInputItem[];
76
+ activeInput: ImapStreamInputItem | null;
77
+ pendingPush: (() => void) | null;
78
+ /**
79
+ * Creates a new ImapStream instance.
80
+ *
81
+ * @param options - Stream options, see ImapStreamOptions.
82
+ */
83
+ constructor(options?: ImapStreamOptions | undefined);
84
+ /**
85
+ * Terminally fails the stream. Used for response limit violations and for any other
86
+ * error raised while parsing.
87
+ *
88
+ * The stream is destroyed instead of only emitting `error`: emitting on a Transform leaves
89
+ * it running, so the caller would keep scanning the rejected payload and could emit it as
90
+ * protocol (an oversized literal body contains attacker-chosen CRLF delimited lines).
91
+ * Destroying stops all parsing, drops the offending line, and releases every queued
92
+ * transform callback exactly once (see `_destroy()`).
93
+ *
94
+ * `destroyed` (set synchronously by destroy()) is the single liveness flag every other path
95
+ * checks, so a second failure attempt is a no-op and nothing is parsed after the first.
96
+ *
97
+ * @param err - The error to destroy the stream with.
98
+ * @returns Always false, so callers can `return this.failStream(err)`.
99
+ */
100
+ failStream(err: Error): false;
101
+ /**
102
+ * Releases a queued input chunk's transform callback exactly once, signalling the writable
103
+ * side that the chunk was consumed. The mirror image of ImapFlow's releaseStreamData(), which
104
+ * releases the readable items this stream pushes downstream.
105
+ *
106
+ * @param item - Queue entry holding the chunk and its transform callback.
107
+ */
108
+ releaseInput(item: ImapStreamInputItem | null | undefined): void;
109
+ /**
110
+ * Checks whether the given line buffer ends with an IMAP literal size marker
111
+ * (e.g., "{123}\r\n"). If a valid marker is found and the literal size is within
112
+ * the allowed maximum, switches the stream state to LITERAL mode and records
113
+ * the expected number of literal bytes.
114
+ *
115
+ * @param line - The line buffer to check for a trailing literal marker.
116
+ * @returns True if a valid literal marker was found and literal state was activated, false otherwise.
117
+ */
118
+ checkLiteralMarker(line: Buffer): boolean;
119
+ /**
120
+ * Enforces the configured line-length cap for a projected line length. The projected length
121
+ * covers every byte of the line, the line terminator included, whether or not the line was
122
+ * split across input chunks. A line exactly at the limit is accepted.
123
+ *
124
+ * @param lineLength - Total length the current line would reach.
125
+ * @returns True if the line is within the limit, false if the stream was failed.
126
+ */
127
+ checkLineLength(lineLength: number): boolean;
128
+ /**
129
+ * Enforces the configured per-response size cap: the cumulative bytes of every line
130
+ * segment and declared literal of the response currently being assembled. Counting
131
+ * declared literal sizes at marker time means an oversized total is rejected before
132
+ * the literal bytes even arrive. The counter is reset when a response is emitted.
133
+ *
134
+ * @param additionalBytes - Bytes the next token would add to the response.
135
+ * @param peek - Measure only, without committing the bytes to the counter.
136
+ * Used for a line that is still being assembled: its bytes are committed once, when the
137
+ * line completes.
138
+ * @returns True if within the limit, false if the stream was failed.
139
+ */
140
+ checkResponseSize(additionalBytes: number, peek?: boolean | undefined): boolean;
141
+ /**
142
+ * Processes a single input chunk of raw data. In LINE state, scans for LF-terminated
143
+ * lines and checks for literal markers. In LITERAL state, collects the expected number
144
+ * of literal bytes. When a complete command (with all its literals) is assembled, it is
145
+ * pushed downstream as a readable object.
146
+ *
147
+ * @param chunk - The raw data chunk to process.
148
+ * @param startPos - The byte offset within the chunk to start processing from.
149
+ */
150
+ processInputChunk(chunk: Buffer, startPos?: number | undefined): Promise<void>;
151
+ /**
152
+ * Drains the input queue by processing each queued chunk sequentially.
153
+ * Yields to the event loop every 10 chunks to prevent CPU blocking on
154
+ * large bursts of incoming data.
155
+ */
156
+ processInput(): Promise<void>;
157
+ /**
158
+ * Transform stream implementation. Receives raw data chunks from the writable side,
159
+ * converts strings to Buffers, tracks total bytes read, optionally logs raw data,
160
+ * and queues the chunk for asynchronous processing.
161
+ *
162
+ * @param chunk - The incoming data chunk.
163
+ * @param encoding - The encoding if chunk is a string.
164
+ * @param next - Callback to signal that this chunk has been consumed.
165
+ */
166
+ _transform(chunk: Buffer | string, encoding: BufferEncoding, next: TransformCallback): void;
167
+ /**
168
+ * Flush implementation called when the writable side ends. Signals completion immediately.
169
+ *
170
+ * @param next - Callback to signal flush completion.
171
+ */
172
+ _flush(next: TransformCallback): void;
173
+ /**
174
+ * Destroy implementation for cleanup. Clears all internal buffers, drains the input queue
175
+ * by invoking pending callbacks, and forwards the error (if any) to the callback.
176
+ *
177
+ * @param err - The error that caused destruction, or null.
178
+ * @param callback - Callback to signal destruction completion.
179
+ */
180
+ _destroy(err: Error | null, callback: (error?: Error | null) => void): void;
181
+ }