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,101 +0,0 @@
1
- 'use strict';
2
-
3
- // Shared ImapFlow construction for unit tests that poke at internals without a live server.
4
- // One definition instead of a per-file copy, so a change to what the constructor needs lands
5
- // in one place and cannot drift between suites.
6
-
7
- const { Writable } = require('node:stream');
8
-
9
- const { ImapFlow } = require('../../lib/imap-flow');
10
-
11
- // A socket stub complete enough for setSocketHandlers(), clearSocketHandlers() and close() to
12
- // run against. removeListener/removeAllListeners matter most: close() removes the handlers it
13
- // installed, and a stub without them makes close() throw half-way through teardown with the
14
- // client still holding its socket and streamer references.
15
- const makeSocketStub = () => ({
16
- destroyed: false,
17
- destroy: () => {},
18
- on: () => {},
19
- once: () => {},
20
- end: () => {},
21
- unpipe: () => {},
22
- removeListener: () => {},
23
- removeAllListeners: () => {},
24
- setKeepAlive: () => {},
25
- setTimeout: () => {}
26
- });
27
-
28
- // Bare construction: no socket, no state overrides. Tests that need a transport use
29
- // makeSocketStub() or makeIdleReadyClient() instead of reaching for their own object literals.
30
- const makeClient = (overrides = {}) =>
31
- new ImapFlow({
32
- host: '127.0.0.1',
33
- port: 993,
34
- logger: false,
35
- auth: { user: 'test', pass: 'secret' },
36
- ...overrides
37
- });
38
-
39
- // A client parked in SELECTED with a stubbed socket and a no-op idle(), ready for autoidle(),
40
- // lock handling and watchdog behavior to be exercised directly
41
- const makeIdleReadyClient = (overrides = {}) => {
42
- let client = makeClient({ maxLockHoldTime: 0, ...overrides });
43
- client.socket = makeSocketStub();
44
- client.usable = true;
45
- client.state = client.states.SELECTED;
46
- client.mailbox = { path: 'INBOX', readOnly: false };
47
- client.idle = async () => {};
48
- return client;
49
- };
50
-
51
- // A fetchOne stand-in that serves `body` back in download()'s chunk-query shape
52
- // ({source: {start, maxLength}}), so download tests do not each restate that contract
53
- const chunkedFetchOne = body => async (range, query) => {
54
- let start = query.source.start;
55
- let maxLength = query.source.maxLength;
56
- return { uid: 1, size: body.length, source: body.subarray(start, start + maxLength) };
57
- };
58
-
59
- // Installs a process-level unhandledRejection detector for one test. Shared because getting the
60
- // teardown wrong leaks a process listener into every test that runs after it, and because the
61
- // assertion has to read the same way wherever a suite checks that nothing escaped.
62
- const installRejectionDetector = test => {
63
- // Tracked as a separate flag rather than by testing the reason: a rejection can carry a falsy
64
- // value, and that is still an escaped rejection.
65
- let unhandled = false;
66
- let unhandledReason = null;
67
- const handler = reason => {
68
- unhandled = true;
69
- unhandledReason = reason;
70
- };
71
- process.on('unhandledRejection', handler);
72
-
73
- return {
74
- check() {
75
- process.removeListener('unhandledRejection', handler);
76
- test.equal(unhandled, false, 'no unhandledRejection should fire' + (unhandledReason ? ': ' + unhandledReason.message : ''));
77
- }
78
- };
79
- };
80
-
81
- // A Writable that always defers its callback, so writing to a stream piped into it fills the
82
- // pipeline and forces the producer into backpressure. `delay` is only for tests that also need
83
- // wall-clock time to pass; deferring at all is what triggers the drain wait.
84
- const slowConsumer = (options = {}) => {
85
- let { delay = 0, onChunk } = options;
86
- return new Writable({
87
- highWaterMark: 1,
88
- write(chunk, enc, cb) {
89
- if (typeof onChunk === 'function') {
90
- onChunk(chunk);
91
- }
92
- if (delay) {
93
- setTimeout(cb, delay);
94
- } else {
95
- setImmediate(cb);
96
- }
97
- }
98
- });
99
- };
100
-
101
- module.exports = { makeClient, makeIdleReadyClient, makeSocketStub, chunkedFetchOne, installRejectionDetector, slowConsumer };
@@ -1,8 +0,0 @@
1
- 'use strict';
2
-
3
- // Self-signed certificate + key for in-process TLS/STARTTLS mock servers in tests.
4
- // Generated once with: openssl req -x509 -newkey rsa:2048 -nodes -subj "/CN=localhost"
5
- module.exports = {
6
- cert: '-----BEGIN CERTIFICATE-----\nMIIDCTCCAfGgAwIBAgIUQSc0WP7RlcOqGCdsMaxzCA97mfkwDQYJKoZIhvcNAQEL\nBQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI2MDYwODA0Mzg1NFoXDTM2MDYw\nNTA0Mzg1NFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF\nAAOCAQ8AMIIBCgKCAQEA4TYnyK2nEn6wXEgVeEI3I9CDlONvWDO1Y51mslOaUwZR\nfuZp3YMUZDINNdZuFrREkD1WJfClRZtDKEurw9FfjEfA0gsM9RPvkQYXZ2zzhXgW\nx86li0Ra/Zx2RmajsWc+THTEpdOK0nqOqMMKFxiYJ7E+KiJY0X6HqKjdaB9CpZv7\nA1ROJoLjTnsdDG/NT9MCQxFbw05N2Bbbq+McKyXIEzxiZguYLIXsMKCi9MQOozvY\nT8X0AFWpFJCa8mRCW7LQngeSRQQckDONzHyELXnbvgIskr/WcmBEXMraTts3Z3QW\nouee6HFnYzi/pgCtVKX1Wu3oZm/nMblsWtopqg/YDwIDAQABo1MwUTAdBgNVHQ4E\nFgQUF5oycZ3ZaPs1fTaxZb666FQt+KcwHwYDVR0jBBgwFoAUF5oycZ3ZaPs1fTax\nZb666FQt+KcwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAWFk0\nMGw2pdkeU/s5j0T9GL8GjbOVC0G7H8tlx92XhQICmt/9GNHeb5nm84DgqRbkiTwS\nOXPoMsSvVEubnX0j/sqcbi5yQ6/YBG6Vx5E9CnfUbo4m9x1GofDkLdl+e6l636Mj\nWB5kJpNCH9sm2xPdLpl47pv/lwvyYjdy1DaATHn5nMGoM73IeEt0d4xoNN8Bso7B\nTTkjKRJ1QWgI2EjgU93x8tG4AqTj0CeH8Z6DDmfLhvJ6E0hSws4OQSnxWudh2aX8\niN+FkHgRobPS1GVCtibr+FxH1DtBv/grXhAbs4xP3Nf3m3Pn6AE0/lMtto3e67As\np4lf866gU9nbRkODqw==\n-----END CERTIFICATE-----\n',
7
- key: '-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhNifIracSfrBc\nSBV4Qjcj0IOU429YM7VjnWayU5pTBlF+5mndgxRkMg011m4WtESQPVYl8KVFm0Mo\nS6vD0V+MR8DSCwz1E++RBhdnbPOFeBbHzqWLRFr9nHZGZqOxZz5MdMSl04rSeo6o\nwwoXGJgnsT4qIljRfoeoqN1oH0Klm/sDVE4mguNOex0Mb81P0wJDEVvDTk3YFtur\n4xwrJcgTPGJmC5gshewwoKL0xA6jO9hPxfQAVakUkJryZEJbstCeB5JFBByQM43M\nfIQtedu+AiySv9ZyYERcytpO2zdndBai557ocWdjOL+mAK1UpfVa7ehmb+cxuWxa\n2imqD9gPAgMBAAECggEACgBGqgG+0/JuUIV0S/UyJP6t098kYwKrgR33S99XO21M\nvIRCRUT8kyp/La81D6sNCb6/jvXDJnaA9/l29OjdA7TCr6aFT8jahafYmDjdY5rz\n9Vw25nAFqRIuqm0FGJa2Id0O8oeUuEjFrGGPltD6c3Yf2u0li+rA3tDeQYZ0hjge\nsVXzgI58SbO1Z1XCAXcdbcJOqjpEJ3w99GB5J/B1dDui3KR5Q6+L34HfoW8XmY/X\nCLe+Jcuk06Xa31iZ+0NEMIPOhVoCW//PfgEWD/dfG3jXhk84/Pb8DXaGahOvRPTY\nH1AVrqRBqW6PezR4qU4PdUfU3sp5NEBZl3oaW7/weQKBgQD8CKI7ek00KUhc9j5m\nHGuSR+lUzLziXRBt7xw0JXLa1rfok2RGDeTdIEGSjBr8xsNOe5aga843geoLptNe\n7LRrtJajgHl39NXnblroNidufmXjt9CRgjUsQuIREpjq9NyUGIh8o26/uZLB/Knq\nJ7Uum9YUHI/eEztmI/CZDbnUbQKBgQDkwXaf5UxkY9tsdbw8jHhV5Ypy/hwLXAcI\n90sCI9/mSQAOA9qNa+944MbRfReTseM+OFXHJRHXfuMXPPOrtObtVN94ECwFVePO\n2MI5CHc/SYZ/4Icf+jpPY+TAJtEW/39muwak43cmLhmrSmb9ExMhwfDoQotFBDOQ\nLyPPfMo46wKBgFwpWBHB1kt1sSV1UjoKuHdkXnmI6KUp/OEGZ9zVuNs3W0br5uYL\nHJ6Ttga9vvyiPjcL0HfXFDCODCS4m2CB1DPydIdTapen6zRW0V1KuD6ab+3GgLlE\n0ObfikVN9KcuZR6unfJd3Ri05mqTVxrt7D4f9DekfiNqCvV9vPRq5YI9AoGBAMeS\nYUOucK9EzzIYpVjN1E5cLCWWvDDM4PZZiP8c/UGTfpC7m/i1qf7zW4F4eRFJqM+n\npm5PUPmIoeasLoonETENUskUktM008KqKQhI8oAsTUNTR5AGZsjMhc1+D/zYevXN\nRUaljFWq8ooWJzOzaIWTBfIb3BUiTToFZmCmpmZxAoGAH2W3eDhuKrsE50ntofhZ\nx9Uy0OD30nztyecen26kuljcX7qdWh564mBob75wGSAoYzGSePZjJ/tQ4FznXUes\n6F4gM8Y58d3YZOjNq3xnT7AfaJHNnnjxA4pfnGRVr3wA2vwyrD3McgAPXf+mnB23\nl8nz6wxk97WnaIyo7Ofi/+A=\n-----END PRIVATE KEY-----\n'
8
- };
@@ -1,310 +0,0 @@
1
- /* eslint no-unused-expressions: 0, prefer-arrow-callback: 0, new-cap: 0 */
2
-
3
- 'use strict';
4
-
5
- const { parser, compiler } = require('../lib/handler/imap-handler');
6
- const { ImapStream } = require('../lib/handler/imap-stream');
7
- const { ParserInstance } = require('../lib/handler/parser-instance');
8
- const { TokenParser } = require('../lib/handler/token-parser');
9
- const { searchCompiler } = require('../lib/search-compiler');
10
-
11
- let asyncWrapper = (test, handler) => {
12
- handler(test)
13
- .then(() => test.done())
14
- .catch(err => {
15
- test.ifError(err);
16
- test.done();
17
- });
18
- };
19
-
20
- // ============================================================================
21
- // imap-compiler.js
22
- // ============================================================================
23
-
24
- // formatRespEntry: `return entry` when entry is a Buffer (line 23-25). A literal
25
- // whose value is a Buffer, compiled in non-logging mode, passes the Buffer straight
26
- // through formatRespEntry.
27
- module.exports['imap-compiler: Buffer literal value passes through formatRespEntry'] = test =>
28
- asyncWrapper(test, async test => {
29
- let out = (
30
- await compiler({
31
- tag: '*',
32
- command: 'CMD',
33
- attributes: [{ type: 'LITERAL', value: Buffer.from('hello world') }]
34
- })
35
- ).toString();
36
- test.equal(out, '* CMD {11}\r\nhello world');
37
- });
38
-
39
- // number node === 0 -> `Math.round(node) || 0` falls back to 0 (line 117). A bare
40
- // numeric attribute of 0 exercises the `|| 0` right side.
41
- module.exports['imap-compiler: bare number 0 attribute uses fallback'] = test =>
42
- asyncWrapper(test, async test => {
43
- let out = (
44
- await compiler({
45
- tag: '*',
46
- command: 'CMD',
47
- attributes: [0]
48
- })
49
- ).toString();
50
- test.equal(out, '* CMD 0');
51
- });
52
-
53
- // LITERAL node with empty value -> `!node.value ? 0 : ...` true side (line 133).
54
- module.exports['imap-compiler: LITERAL with empty string value yields {0}'] = test =>
55
- asyncWrapper(test, async test => {
56
- let out = (
57
- await compiler({
58
- tag: '*',
59
- command: 'CMD',
60
- attributes: [{ type: 'LITERAL', value: '' }]
61
- })
62
- ).toString();
63
- test.equal(out, '* CMD {0}\r\n');
64
- });
65
-
66
- // LITERAL- (literalMinus) with literal <= 4096 bytes in asArray mode -> exercises the
67
- // `(literalMinus && literalLength <= 4096)` branch of canAppend (line 139) and usePlus.
68
- module.exports['imap-compiler: LITERAL- inlines small literals in asArray mode'] = test =>
69
- asyncWrapper(test, async test => {
70
- let out = (
71
- await compiler(
72
- {
73
- tag: '*',
74
- command: 'CMD',
75
- attributes: [{ type: 'LITERAL', value: 'small' }]
76
- },
77
- { asArray: true, literalMinus: true }
78
- )
79
- ).map(entry => entry.toString());
80
- // LITERAL- still appends a non-synchronizing '+' marker for inlined literals
81
- test.deepEqual(out, ['* CMD {5+}\r\nsmall']);
82
- });
83
-
84
- // LITERAL- with a literal larger than 4096 bytes in asArray mode -> canAppend false,
85
- // so the synchronizing-literal split path runs. The new resp segment is seeded with
86
- // `formatRespEntry(node.value, true) || []`. Using a Buffer value keeps formatRespEntry
87
- // returning the Buffer (the `|| []` right side, line 156, is the focus together with the
88
- // split branch).
89
- module.exports['imap-compiler: LITERAL- large literal splits (synchronizing) in asArray mode'] = test =>
90
- asyncWrapper(test, async test => {
91
- let big = Buffer.alloc(5000, 0x61); // 5000 bytes > 4096
92
- let out = (
93
- await compiler(
94
- {
95
- tag: '*',
96
- command: 'CMD',
97
- attributes: [{ type: 'LITERAL', value: big }]
98
- },
99
- { asArray: true, literalMinus: true }
100
- )
101
- ).map(entry => entry.toString());
102
- test.equal(out.length, 2);
103
- test.equal(out[0], '* CMD {5000}\r\n');
104
- test.equal(out[1], big.toString());
105
- });
106
-
107
- // Synchronizing literal whose value is not a recognized type -> formatRespEntry(value, true)
108
- // returns null, so `|| []` kicks in (line 156 right side) and the seeded resp is empty.
109
- module.exports['imap-compiler: synchronizing literal with non-buffer value seeds empty segment'] = test =>
110
- asyncWrapper(test, async test => {
111
- let out = (
112
- await compiler(
113
- {
114
- tag: '*',
115
- command: 'CMD',
116
- // value is an object that is neither string/number/Buffer, so the size
117
- // marker derives from the UTF-8 byte length of its stringified form
118
- // ('[object Object]', 15 bytes) while formatRespEntry(value, true)
119
- // returns null -> the seeded resp falls back to [] (line 156 right side).
120
- attributes: [{ type: 'LITERAL', value: { length: 10 } }]
121
- },
122
- { asArray: true }
123
- )
124
- ).map(entry => entry.toString());
125
- // Only the header segment is emitted; the empty seeded data segment is dropped
126
- // because `if (resp.length)` is false at the end.
127
- test.deepEqual(out, ['* CMD {15}\r\n']);
128
- });
129
-
130
- // STRING node with falsy value -> `(node.value || '')` right side (line 165).
131
- module.exports['imap-compiler: STRING with empty/falsy value compiles to empty quoted string'] = test =>
132
- asyncWrapper(test, async test => {
133
- let out = (
134
- await compiler({
135
- tag: '*',
136
- command: 'CMD',
137
- attributes: [{ type: 'STRING', value: '' }]
138
- })
139
- ).toString();
140
- test.equal(out, '* CMD ""');
141
- });
142
-
143
- // response.attributes that is a single (non-array) object -> `[].concat(response.attributes)`
144
- // right side of the ternary on line 215.
145
- module.exports['imap-compiler: single non-array attributes object is wrapped'] = test =>
146
- asyncWrapper(test, async test => {
147
- let out = (
148
- await compiler({
149
- tag: '*',
150
- command: 'CMD',
151
- attributes: { type: 'ATOM', value: 'EXPUNGE' }
152
- })
153
- ).toString();
154
- test.equal(out, '* CMD EXPUNGE');
155
- });
156
-
157
- // ============================================================================
158
- // imap-stream.js
159
- // ============================================================================
160
-
161
- // Provide a logger object so the constructor takes the `this.options.logger` branch
162
- // (lines 61-62) instead of creating a child logger.
163
- module.exports['imap-stream: explicit logger option is used as-is'] = test => {
164
- let calls = [];
165
- let fakeLogger = {
166
- trace: m => calls.push(m),
167
- child: () => {
168
- throw new Error('child should not be called when a logger is supplied');
169
- }
170
- };
171
- let stream = new ImapStream({ cid: 'x', logger: fakeLogger });
172
- test.equal(stream.log, fakeLogger, 'supplied logger object is used directly');
173
- test.done();
174
- };
175
-
176
- // checkLiteralMarker: a line that is all digits + "}\r\n" but has no opening "{" makes
177
- // the backward scan run off the start of the line, hitting the final `return false`
178
- // (line 154).
179
- module.exports['imap-stream: checkLiteralMarker returns false when no opening brace is found'] = test => {
180
- let stream = new ImapStream({ cid: 'x' });
181
- // "12}\n": scan finds '}', then digits '2','1', runs past index 0 -> final return false
182
- test.equal(stream.checkLiteralMarker(Buffer.from('12}\n')), false);
183
- // also exercise the CRLF variant
184
- test.equal(stream.checkLiteralMarker(Buffer.from('99}\r\n')), false);
185
- test.done();
186
- };
187
-
188
- // _transform with a string chunk -> `chunk = Buffer.from(chunk, encoding)` (lines 299-301).
189
- // Call _transform directly with a string so the typeof === 'string' branch runs.
190
- // The string->Buffer conversion and byte counting happen synchronously, before the
191
- // chunk is queued for async processing, so readBytesCounter reflects the decoded length.
192
- module.exports['imap-stream: _transform converts string chunks to Buffers'] = test => {
193
- let stream = new ImapStream({ cid: 'x' });
194
- stream._transform('A1 NOOP\r\n', 'utf8', () => {});
195
- test.equal(stream.readBytesCounter, Buffer.byteLength('A1 NOOP\r\n'), 'decoded byte length was counted');
196
- stream.destroy();
197
- test.done();
198
- };
199
-
200
- // ============================================================================
201
- // parser-instance.js
202
- // ============================================================================
203
-
204
- // Drive ParserInstance directly so getCommand is reached with a falsy (empty-string)
205
- // command and a non-"+" tag, exercising the `(this.command || '')` right side (line 71).
206
- // This state is not produced by normal parsing, so we construct it explicitly.
207
- module.exports['parser-instance: getCommand falls back to empty string for falsy command'] = test =>
208
- asyncWrapper(test, async test => {
209
- let inst = new ParserInstance('* ', {});
210
- inst.tag = '*'; // not '+', so the early continuation branch is skipped
211
- // Pre-set command to a value getElement would have produced, then blank the
212
- // remainder so the `if (!this.command)` re-fetch path throws? No - instead we
213
- // set command to empty string and clear remainder so getElement is NOT re-run
214
- // is impossible (empty string is falsy). Use a getElement stub on the instance
215
- // to deterministically yield an empty command without touching lib/ source.
216
- inst.getElement = async () => '';
217
- let command = await inst.getCommand();
218
- test.equal(command, '', 'command is the empty string');
219
- });
220
-
221
- // ============================================================================
222
- // token-parser.js
223
- // ============================================================================
224
-
225
- // Construct TokenParser directly with a falsy str, undefined options and a falsy
226
- // startPos to cover the `str || ''` (40), `options || {}` (41) and `startPos || 0`
227
- // (45) fallbacks. These cannot occur through ParserInstance.getAttributes (which
228
- // guards against an empty remainder), so direct construction is required.
229
- module.exports['token-parser: constructor fallbacks for empty str / no options / zero startPos'] = test =>
230
- asyncWrapper(test, async test => {
231
- let parent = { command: 'FETCH' };
232
- let tp = new TokenParser(parent, 0, undefined, undefined);
233
- test.equal(tp.str, '');
234
- test.deepEqual(tp.options, {});
235
- test.equal(tp.pos, 0);
236
- let attrs = await tp.getAttributes();
237
- test.deepEqual(attrs, []);
238
- });
239
-
240
- // Cover the `(node.type || '')` fallback (line 85) by walking a tree that contains a
241
- // closed child node with a falsy type. Normal parsing always assigns a type, so the
242
- // tree is constructed explicitly.
243
- module.exports['token-parser: walk handles a closed node with a falsy type'] = test =>
244
- asyncWrapper(test, async test => {
245
- let parent = { command: 'FETCH' };
246
- let tp = new TokenParser(parent, 0, '', {});
247
- tp.tree = {
248
- type: 'TREE',
249
- isClosed: true,
250
- childNodes: [{ type: false, isClosed: true, value: '', childNodes: [] }]
251
- };
252
- let attrs = await tp.getAttributes();
253
- test.deepEqual(attrs, []);
254
- });
255
-
256
- // ============================================================================
257
- // search-compiler.js
258
- // ============================================================================
259
-
260
- let createMockConnection = (options = {}) => ({
261
- capabilities: new Map(options.capabilities || [['IMAP4rev1', true]]),
262
- enabled: new Set(options.enabled || []),
263
- mailbox: options.mailbox || {
264
- flags: new Set(['\\Seen']),
265
- permanentFlags: new Set(['\\*'])
266
- }
267
- });
268
-
269
- // setOpt NOT branch (lines 46-48): EMAILID/THREADID call setOpt with an unguarded
270
- // params[term]. Passing the boolean `false` as the value reaches `value === false`
271
- // and pushes a leading NOT atom. (A `null` value also enters this branch, but setOpt
272
- // then crashes on `value.toString()` at line 56, so `false` is the only value that
273
- // drives this branch to completion through the public API.)
274
- module.exports['search-compiler: threadid false triggers setOpt NOT branch'] = test => {
275
- let connection = createMockConnection({ capabilities: [['OBJECTID', true]] });
276
- let attrs = searchCompiler(connection, { threadid: false });
277
- test.deepEqual(attrs, [
278
- { type: 'ATOM', value: 'NOT' },
279
- { type: 'ATOM', value: 'THREADID' },
280
- { type: 'ATOM', value: 'false' }
281
- ]);
282
- test.done();
283
- };
284
-
285
- // KEYWORD search where the flag is NOT usable via canUseFlag but IS already present in
286
- // the mailbox flags set -> exercises the `mailbox.flags.has(flag)` right side (line 297).
287
- module.exports['search-compiler: keyword already present in mailbox flags is accepted'] = test => {
288
- // permanentFlags has no '\\*', so canUseFlag(mailbox, customFlag) is false, but the
289
- // flag is in mailbox.flags, so the OR short-circuits to the right operand.
290
- let connection = createMockConnection({
291
- mailbox: {
292
- flags: new Set(['$Label1']),
293
- permanentFlags: new Set(['\\Seen']) // no '\\*' wildcard -> custom flags not auto-usable
294
- }
295
- });
296
- let attrs = searchCompiler(connection, { keyword: '$Label1' });
297
- test.deepEqual(attrs, [
298
- { type: 'ATOM', value: 'KEYWORD' },
299
- { type: 'ATOM', value: '$Label1' }
300
- ]);
301
- test.done();
302
- };
303
-
304
- // ============================================================================
305
- // Sanity: untagged parse still round-trips, just to keep the parser import exercised.
306
- module.exports['sanity: parser/compiler round-trip'] = test =>
307
- asyncWrapper(test, async test => {
308
- let parsed = await parser('* OK Ready', { allowUntagged: true });
309
- test.equal(parsed.command, 'OK');
310
- });