imapflow 1.7.8 → 2.0.1

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 +27 -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 +520 -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 +3956 -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} +387 -517
  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 +60 -123
  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 +769 -1790
  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
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = status;
4
+ const tools_js_1 = require("../tools.js");
5
+ const status_fields_js_1 = require("./status-fields.js");
6
+ // STATUS fields that also refresh the live mailbox state when the queried mailbox is the
7
+ // currently selected one. Keyed by the output property name parseStatusList() reports.
8
+ const MAILBOX_UPDATERS = {
9
+ messages: (value, connection, path) => {
10
+ let mailbox = connection.mailbox;
11
+ let prevCount = mailbox.exists;
12
+ if (prevCount !== value) {
13
+ mailbox.exists = value;
14
+ connection.emit('exists', { path, count: value, prevCount });
15
+ }
16
+ },
17
+ uidNext: (value, connection) => {
18
+ connection.mailbox.uidNext = value;
19
+ },
20
+ highestModseq: (value, connection) => {
21
+ connection.mailbox.highestModseq = value;
22
+ }
23
+ };
24
+ /**
25
+ * Requests status information about a mailbox.
26
+ *
27
+ * @param connection - IMAP connection instance
28
+ * @param path - Mailbox path to query
29
+ * @param query - Status data items to request (e.g., {messages: true, uidNext: true, unseen: true})
30
+ * @returns Status information object, or false if preconditions not met or on failure
31
+ * @throws {Error} If the mailbox does not exist
32
+ */
33
+ async function status(connection, path, query) {
34
+ if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !path) {
35
+ // nothing to do here
36
+ return false;
37
+ }
38
+ path = (0, tools_js_1.normalizePath)(connection, path);
39
+ let encodedPath = (0, tools_js_1.encodePath)(connection, path);
40
+ // Use quoted STRING if the encoded path contains '&' (modified UTF-7 marker),
41
+ // otherwise use unquoted ATOM. Same approach as in SELECT.
42
+ let attributes = [{ type: encodedPath.indexOf('&') >= 0 ? 'STRING' : 'ATOM', value: encodedPath }];
43
+ // Build the list of STATUS data items the caller wants
44
+ let queryAttributes = (0, tools_js_1.buildStatusQueryAttributes)(connection, query);
45
+ // RECENT does not exist in IMAP4rev2 so it is never requested from a rev2
46
+ // session; its defined value there is always 0. Synthesizing it keeps the
47
+ // return shape identical to a rev1 session for the same query.
48
+ let syntheticRecent = query && query.recent && (0, tools_js_1.isRev2Active)(connection);
49
+ if (!queryAttributes.length) {
50
+ // A query that only contained items unavailable on this session - the
51
+ // caller still gets a status object if every such item has a defined value
52
+ return syntheticRecent ? { path, recent: 0 } : false;
53
+ }
54
+ attributes.push(queryAttributes);
55
+ let response;
56
+ try {
57
+ let map = { path };
58
+ response = await connection.exec('STATUS', attributes, {
59
+ untagged: {
60
+ // STATUS response: * STATUS <mailbox> (<key> <value> <key> <value> ...)
61
+ // Parsed as alternating key-value pairs (i % 2 pattern).
62
+ STATUS: async (untagged) => {
63
+ // If querying the currently selected mailbox, also update the
64
+ // connection's live mailbox state and emit events for changes.
65
+ let updateCurrent = connection.state === connection.states.SELECTED && path === connection.mailbox.path;
66
+ let list = untagged.attributes && Array.isArray(untagged.attributes[1]) ? untagged.attributes[1] : false;
67
+ if (!list) {
68
+ return;
69
+ }
70
+ (0, status_fields_js_1.parseStatusList)(list, (key, value) => {
71
+ map[key] = value;
72
+ let updater = MAILBOX_UPDATERS[key];
73
+ if (updateCurrent && updater) {
74
+ updater(value, connection, path);
75
+ }
76
+ });
77
+ }
78
+ }
79
+ });
80
+ response.next();
81
+ if (syntheticRecent) {
82
+ map.recent = 0;
83
+ }
84
+ return map;
85
+ }
86
+ catch (err) {
87
+ // A NO response usually means the mailbox doesn't exist. Verify by
88
+ // running LIST: if no results, throw a clear NotFound error instead
89
+ // of the generic IMAP error.
90
+ // Note: this uses run(), so when STATUS was dispatched by fallback polling through
91
+ // runInternal() the LIST awaits that polling session's own preCheck and cancels it.
92
+ // Not a deadlock, and only reachable when the server rejects the STATUS, but a polled
93
+ // STATUS of a missing folder ends the poll early.
94
+ if (err.responseStatus === 'NO') {
95
+ let folders = await connection.run('LIST', '', path, { listOnly: true });
96
+ if (folders && !folders.length) {
97
+ let error = new Error(`Mailbox doesn't exist: ${path}`);
98
+ error.code = 'NotFound';
99
+ error.response = err;
100
+ throw error;
101
+ }
102
+ }
103
+ connection.log.warn({ err, cid: connection.id });
104
+ return false;
105
+ }
106
+ }
107
+ module.exports = exports.default;
108
+ Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
@@ -0,0 +1,19 @@
1
+ import type { ImapFlow } from '../imap-flow.js';
2
+ import type { StoreOptions } from '../types.js';
3
+ /**
4
+ * Options for the STORE command
5
+ */
6
+ export interface StoreCommandOptions extends StoreOptions {
7
+ /** Operation type: 'set', 'add', or 'remove' */
8
+ operation?: string | undefined;
9
+ }
10
+ /**
11
+ * Updates flags or labels for messages in the selected mailbox.
12
+ *
13
+ * @param connection - IMAP connection instance
14
+ * @param range - Message sequence number or UID range
15
+ * @param flags - Flag(s) to set, add, or remove
16
+ * @param options - Store options
17
+ * @returns True on success, false on failure or if nothing to do
18
+ */
19
+ export default function store(connection: ImapFlow, range: string, flags: string | string[], options: StoreCommandOptions): Promise<boolean>;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = store;
4
+ const tools_js_1 = require("../tools.js");
5
+ /**
6
+ * Updates flags or labels for messages in the selected mailbox.
7
+ *
8
+ * @param connection - IMAP connection instance
9
+ * @param range - Message sequence number or UID range
10
+ * @param flags - Flag(s) to set, add, or remove
11
+ * @param options - Store options
12
+ * @returns True on success, false on failure or if nothing to do
13
+ */
14
+ async function store(connection, range, flags, options) {
15
+ if (connection.state !== connection.states.SELECTED || !range || (options.useLabels && !connection.capabilities.has('X-GM-EXT-1'))) {
16
+ // nothing to do here
17
+ return false;
18
+ }
19
+ /* c8 ignore next */ // options.useLabels is dereferenced in the guard above, so options is always defined here
20
+ options = options || {};
21
+ // Build the IMAP STORE operation name. The format is:
22
+ // [+|-]FLAGS[.SILENT] or [+|-]X-GM-LABELS
23
+ // Where: no prefix = replace all, + = add, - = remove
24
+ // .SILENT suppresses the server from sending back updated flags (saves bandwidth).
25
+ let operation = 'FLAGS';
26
+ if (options.useLabels) {
27
+ // Gmail labels (X-GM-EXT-1 extension): operates on labels instead of IMAP flags
28
+ operation = 'X-GM-LABELS';
29
+ }
30
+ else if (options.silent) {
31
+ operation = `${operation}.SILENT`;
32
+ }
33
+ // Prefix determines the operation: none = set (replace), + = add, - = remove
34
+ switch ((options.operation || '').toLowerCase()) {
35
+ case 'set':
36
+ break;
37
+ case 'remove':
38
+ operation = `-${operation}`;
39
+ break;
40
+ case 'add':
41
+ default:
42
+ operation = `+${operation}`;
43
+ break;
44
+ }
45
+ // Validate each flag: format it (normalize backslash prefix for system flags),
46
+ // then check if the mailbox's permanentFlags allow it. Removal is always allowed
47
+ // since it doesn't require the flag to be in permanentFlags.
48
+ flags = (Array.isArray(flags) ? flags : [].concat(flags || []))
49
+ .map(flag => {
50
+ let formatted = (0, tools_js_1.formatFlag)(flag);
51
+ if (!(0, tools_js_1.canUseFlag)(connection.mailbox, formatted) && options.operation !== 'remove') {
52
+ return false;
53
+ }
54
+ return formatted;
55
+ })
56
+ .filter((flag) => !!flag);
57
+ // Allow empty flags only for 'set' operation (which clears all flags)
58
+ if (!flags.length && options.operation !== 'set') {
59
+ return false;
60
+ }
61
+ let attributes = [
62
+ { type: 'SEQUENCE', value: range },
63
+ { type: 'ATOM', value: operation },
64
+ flags.map(flag => ({ type: 'ATOM', value: flag }))
65
+ ];
66
+ // CONDSTORE (RFC 7162): UNCHANGEDSINCE modifier prevents updating messages whose
67
+ // mod-sequence is higher than the specified value, avoiding overwriting concurrent changes.
68
+ if (options.unchangedSince && connection.enabled.has('CONDSTORE') && !connection.mailbox.noModseq) {
69
+ attributes.push([
70
+ {
71
+ type: 'ATOM',
72
+ value: 'UNCHANGEDSINCE'
73
+ },
74
+ {
75
+ type: 'ATOM',
76
+ value: options.unchangedSince.toString()
77
+ }
78
+ ]);
79
+ }
80
+ let response;
81
+ try {
82
+ response = await connection.exec(options.uid ? 'UID STORE' : 'STORE', attributes);
83
+ response.next();
84
+ return true;
85
+ }
86
+ catch (err) {
87
+ await (0, tools_js_1.enhanceCommandError)(err);
88
+ connection.log.warn({ err, cid: connection.id });
89
+ return false;
90
+ }
91
+ }
92
+ module.exports = exports.default;
93
+ Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
@@ -0,0 +1,9 @@
1
+ import type { ImapFlow } from '../imap-flow.js';
2
+ /**
3
+ * Subscribes to a mailbox.
4
+ *
5
+ * @param connection - IMAP connection instance
6
+ * @param path - Mailbox path to subscribe to
7
+ * @returns True on success, false on failure, or undefined if preconditions not met
8
+ */
9
+ export default function subscribe(connection: ImapFlow, path: string | string[]): Promise<boolean | undefined>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = subscribe;
4
+ const tools_js_1 = require("../tools.js");
5
+ /**
6
+ * Subscribes to a mailbox.
7
+ *
8
+ * @param connection - IMAP connection instance
9
+ * @param path - Mailbox path to subscribe to
10
+ * @returns True on success, false on failure, or undefined if preconditions not met
11
+ */
12
+ async function subscribe(connection, path) {
13
+ if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
14
+ // nothing to do here
15
+ return;
16
+ }
17
+ path = (0, tools_js_1.normalizePath)(connection, path);
18
+ let response;
19
+ try {
20
+ response = await connection.exec('SUBSCRIBE', [{ type: 'ATOM', value: (0, tools_js_1.encodePath)(connection, path) }]);
21
+ response.next();
22
+ return true;
23
+ }
24
+ catch (err) {
25
+ await (0, tools_js_1.enhanceCommandError)(err);
26
+ connection.log.warn({ err, cid: connection.id });
27
+ return false;
28
+ }
29
+ }
30
+ module.exports = exports.default;
31
+ Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
@@ -0,0 +1,9 @@
1
+ import type { ImapFlow } from '../imap-flow.js';
2
+ /**
3
+ * Unsubscribes from a mailbox.
4
+ *
5
+ * @param connection - IMAP connection instance
6
+ * @param path - Mailbox path to unsubscribe from
7
+ * @returns True on success, false on failure, or undefined if preconditions not met
8
+ */
9
+ export default function unsubscribe(connection: ImapFlow, path: string | string[]): Promise<boolean | undefined>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = unsubscribe;
4
+ const tools_js_1 = require("../tools.js");
5
+ /**
6
+ * Unsubscribes from a mailbox.
7
+ *
8
+ * @param connection - IMAP connection instance
9
+ * @param path - Mailbox path to unsubscribe from
10
+ * @returns True on success, false on failure, or undefined if preconditions not met
11
+ */
12
+ async function unsubscribe(connection, path) {
13
+ if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
14
+ // nothing to do here
15
+ return;
16
+ }
17
+ path = (0, tools_js_1.normalizePath)(connection, path);
18
+ let response;
19
+ try {
20
+ response = await connection.exec('UNSUBSCRIBE', [{ type: 'ATOM', value: (0, tools_js_1.encodePath)(connection, path) }]);
21
+ response.next();
22
+ return true;
23
+ }
24
+ catch (err) {
25
+ await (0, tools_js_1.enhanceCommandError)(err);
26
+ connection.log.warn({ err, cid: connection.id });
27
+ return false;
28
+ }
29
+ }
30
+ module.exports = exports.default;
31
+ Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
@@ -0,0 +1,49 @@
1
+ import type { ImapFlowError } from './errors.js';
2
+ export declare const CONNECT_TIMEOUT: number;
3
+ /**
4
+ * One deadline for an entire connection attempt.
5
+ *
6
+ * DNS resolution, proxy negotiation and the transport handshake all draw from the same budget, so
7
+ * a phase that stalls cannot extend the documented `connectionTimeout`. Every expiry - whether it
8
+ * comes from this deadline or is normalized from a dependency - is reported with the same
9
+ * `CONNECT_TIMEOUT` error shape, so callers do not need to know which phase was blocked.
10
+ */
11
+ export declare class ConnectionDeadline {
12
+ timeout: number;
13
+ startedAt: number;
14
+ /**
15
+ * @param timeout Configured connection timeout in milliseconds. Normalized once
16
+ * here; 0 and any other falsy or invalid value fall back to the 90 second default.
17
+ */
18
+ constructor(timeout?: number | string | undefined);
19
+ /**
20
+ * @returns Milliseconds left in the budget, never negative.
21
+ */
22
+ remaining(): number;
23
+ /**
24
+ * @returns The shared `CONNECT_TIMEOUT` error.
25
+ */
26
+ error(): ImapFlowError;
27
+ /**
28
+ * Maps a dependency's own expiry onto the shared `CONNECT_TIMEOUT` shape, so callers see one
29
+ * timeout error whichever layer noticed first. The original error is kept as `_err`. Anything
30
+ * that is not a timeout is returned unchanged.
31
+ *
32
+ * @param err Error raised by a dependency during a connection phase.
33
+ * @returns Either the normalized timeout error or the original error.
34
+ */
35
+ normalize<T extends ImapFlowError | null | undefined>(err: T): T | ImapFlowError;
36
+ /**
37
+ * Throws before a phase is started if the budget is already used up, so no work is begun
38
+ * that could only ever time out.
39
+ */
40
+ check(): void;
41
+ /**
42
+ * Races a phase against the remaining budget. The timer is always cleared, so a completed
43
+ * phase never leaves a pending timer behind.
44
+ *
45
+ * @param promise Phase to run under the deadline.
46
+ * @returns Resolves with the phase result, rejects with `CONNECT_TIMEOUT`.
47
+ */
48
+ race<T>(promise: Promise<T>): Promise<T>;
49
+ }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectionDeadline = exports.CONNECT_TIMEOUT = void 0;
4
+ const tools_js_1 = require("./tools.js");
5
+ // Default upper bound for establishing a usable transport, including DNS and proxy negotiation.
6
+ exports.CONNECT_TIMEOUT = 90 * 1000;
7
+ /**
8
+ * One deadline for an entire connection attempt.
9
+ *
10
+ * DNS resolution, proxy negotiation and the transport handshake all draw from the same budget, so
11
+ * a phase that stalls cannot extend the documented `connectionTimeout`. Every expiry - whether it
12
+ * comes from this deadline or is normalized from a dependency - is reported with the same
13
+ * `CONNECT_TIMEOUT` error shape, so callers do not need to know which phase was blocked.
14
+ */
15
+ class ConnectionDeadline {
16
+ /**
17
+ * @param timeout Configured connection timeout in milliseconds. Normalized once
18
+ * here; 0 and any other falsy or invalid value fall back to the 90 second default.
19
+ */
20
+ constructor(timeout) {
21
+ this.timeout = Number(timeout) || exports.CONNECT_TIMEOUT;
22
+ this.startedAt = Date.now();
23
+ }
24
+ /**
25
+ * @returns Milliseconds left in the budget, never negative.
26
+ */
27
+ remaining() {
28
+ return Math.max(0, this.timeout - (Date.now() - this.startedAt));
29
+ }
30
+ /**
31
+ * @returns The shared `CONNECT_TIMEOUT` error.
32
+ */
33
+ error() {
34
+ let err = new Error('Failed to establish connection in required time');
35
+ err.code = 'CONNECT_TIMEOUT';
36
+ err.details = { connectionTimeout: this.timeout };
37
+ return err;
38
+ }
39
+ /**
40
+ * Maps a dependency's own expiry onto the shared `CONNECT_TIMEOUT` shape, so callers see one
41
+ * timeout error whichever layer noticed first. The original error is kept as `_err`. Anything
42
+ * that is not a timeout is returned unchanged.
43
+ *
44
+ * @param err Error raised by a dependency during a connection phase.
45
+ * @returns Either the normalized timeout error or the original error.
46
+ */
47
+ normalize(err) {
48
+ if (!err || err.code === 'CONNECT_TIMEOUT') {
49
+ return err;
50
+ }
51
+ // The `socks` client reports its own expiry as "Proxy connection timed out"
52
+ if (err.code !== 'ETIMEDOUT' && !/timed out/i.test(err.message || '')) {
53
+ return err;
54
+ }
55
+ let normalized = this.error();
56
+ normalized._err = err;
57
+ return normalized;
58
+ }
59
+ /**
60
+ * Throws before a phase is started if the budget is already used up, so no work is begun
61
+ * that could only ever time out.
62
+ */
63
+ check() {
64
+ if (!this.remaining()) {
65
+ throw this.error();
66
+ }
67
+ }
68
+ /**
69
+ * Races a phase against the remaining budget. The timer is always cleared, so a completed
70
+ * phase never leaves a pending timer behind.
71
+ *
72
+ * @param promise Phase to run under the deadline.
73
+ * @returns Resolves with the phase result, rejects with `CONNECT_TIMEOUT`.
74
+ */
75
+ async race(promise) {
76
+ this.check();
77
+ let timer = null;
78
+ try {
79
+ return await Promise.race([
80
+ promise,
81
+ new Promise((_resolve, reject) => {
82
+ timer = setTimeout(() => reject(this.error()), this.remaining());
83
+ })
84
+ ]);
85
+ }
86
+ finally {
87
+ (0, tools_js_1.clearTimer)(timer);
88
+ }
89
+ }
90
+ }
91
+ exports.ConnectionDeadline = ConnectionDeadline;
@@ -0,0 +1,83 @@
1
+ import type { ImapResponse } from './handler/types.js';
2
+ /**
3
+ * An Error raised by ImapFlow, with the extra properties the library attaches to describe
4
+ * the failure. Every property is optional: which ones are present depends on where the
5
+ * error came from.
6
+ */
7
+ export interface ImapFlowError extends Error {
8
+ /** Error code, e.g. 'NoConnection', 'ETIMEOUT', 'LockTimeout' or a parser error code */
9
+ code?: string | undefined;
10
+ /** Connection id the error belongs to */
11
+ cid?: string | undefined;
12
+ /** Connection id, stamped by emitError() */
13
+ _connId?: string | undefined;
14
+ /** Which internal site rejected with this error */
15
+ rejectedFrom?: string | undefined;
16
+ /** The command that was affected */
17
+ command?: string | undefined;
18
+ /** The mailbox path that was affected */
19
+ path?: string | undefined;
20
+ /** Status of the tagged response that failed the command: 'NO' or 'BAD' */
21
+ responseStatus?: string | undefined;
22
+ /** Human readable text of the failed tagged response */
23
+ responseText?: string | undefined;
24
+ /** The server response: the parsed response, or its text once enhanceCommandError() ran */
25
+ response?: ImapResponse | string | false | undefined;
26
+ /** Response code of the failed tagged response, e.g. 'AUTHENTICATIONFAILED' */
27
+ serverResponseCode?: string | undefined;
28
+ /** The command as it was sent, for logging */
29
+ executedCommand?: string | undefined;
30
+ /** Set when authentication failed */
31
+ authenticationFailed?: boolean | undefined;
32
+ /** Set when a TLS or STARTTLS upgrade failed */
33
+ tlsFailed?: boolean | undefined;
34
+ /** Server suggested back-off in milliseconds for an ETHROTTLE error */
35
+ throttleReset?: number | undefined;
36
+ /** Additional details, e.g. the timeouts that applied */
37
+ details?: {
38
+ [key: string]: any;
39
+ } | undefined;
40
+ /** The underlying error */
41
+ _err?: Error | undefined;
42
+ /** Server BYE reason */
43
+ reason?: string | undefined;
44
+ /** Set when a mailbox could not be selected because it does not exist */
45
+ mailboxMissing?: boolean | undefined;
46
+ /** Id of the mailbox lock that timed out */
47
+ lockId?: number | undefined;
48
+ /** The parser error that failed a command completion */
49
+ parserError?: ImapFlowError | undefined;
50
+ /** Parser diagnostics */
51
+ parserContext?: {
52
+ [key: string]: any;
53
+ } | undefined;
54
+ /** The tag the parser had already read before it failed */
55
+ parsedTag?: string | undefined;
56
+ /** The declared size of a rejected literal */
57
+ literalSize?: number | undefined;
58
+ /** The length of a rejected line */
59
+ lineLength?: number | undefined;
60
+ /** The size of a rejected response */
61
+ responseSize?: number | undefined;
62
+ /** The bound that was exceeded */
63
+ maxSize?: number | undefined;
64
+ /** OAuth error details from the server, for XOAUTH2 authentication failures */
65
+ oauthError?: any;
66
+ /** The IMAP string that could not be parsed */
67
+ _imapStr?: string | undefined;
68
+ }
69
+ /**
70
+ * The fields a connection error is stamped with to say where it was rejected, see
71
+ * buildConnectionError() in tools.ts
72
+ */
73
+ export type ConnectionErrorSite = Pick<ImapFlowError, 'rejectedFrom' | 'command' | 'path'>;
74
+ /**
75
+ * Error subclass thrown when IMAP authentication fails.
76
+ */
77
+ export declare class AuthenticationFailure extends Error implements ImapFlowError {
78
+ authenticationFailed: true;
79
+ serverResponseCode?: string | undefined;
80
+ /** Text of the server's error response */
81
+ response?: string | undefined;
82
+ oauthError?: any;
83
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AuthenticationFailure = void 0;
4
+ /**
5
+ * Error subclass thrown when IMAP authentication fails.
6
+ */
7
+ class AuthenticationFailure extends Error {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.authenticationFailed = true;
11
+ }
12
+ }
13
+ exports.AuthenticationFailure = AuthenticationFailure;
@@ -0,0 +1,24 @@
1
+ import type { CompilerOptions, ImapCompileInput } from './types.js';
2
+ /**
3
+ * Compiles an input object into a sequence of Buffers representing an IMAP protocol response string.
4
+ * Handles various node types including literals, strings, atoms, sections, sequences, and nested lists.
5
+ *
6
+ * @param response - The response object to compile.
7
+ * @param response.tag - The IMAP command tag (e.g., "*" or a sequence number).
8
+ * @param response.command - The IMAP command name.
9
+ * @param response.attributes - The response attributes to compile into IMAP format.
10
+ * @param options - Compilation options.
11
+ * @param options.asArray - If true, returns an array of Buffers (one per literal segment); otherwise returns a single concatenated Buffer.
12
+ * @param options.isLogging - If true, redacts sensitive values and truncates long strings/literals for logging purposes.
13
+ * @param options.literalPlus - If true, uses the LITERAL+ extension (appends "+" to literal length markers).
14
+ * @param options.literalMinus - If true, uses the LITERAL- extension for literals up to 4096 bytes.
15
+ * @returns A promise that resolves to an array of Buffers (if asArray is true) or a single concatenated Buffer.
16
+ */
17
+ declare function compiler(response: ImapCompileInput, options: CompilerOptions & {
18
+ asArray: true;
19
+ }): Promise<Buffer[]>;
20
+ declare function compiler(response: ImapCompileInput, options?: (CompilerOptions & {
21
+ asArray?: false | undefined;
22
+ }) | undefined): Promise<Buffer>;
23
+ declare function compiler(response: ImapCompileInput, options?: CompilerOptions | undefined): Promise<Buffer | Buffer[]>;
24
+ export default compiler;