imapflow 1.7.7 → 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 +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 +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 +785 -1802
  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 -57
  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 -873
  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 -593
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = move;
4
+ const tools_js_1 = require("../tools.js");
5
+ const copyuid_parser_js_1 = require("./copyuid-parser.js");
6
+ /**
7
+ * Moves messages from the current mailbox to another mailbox.
8
+ *
9
+ * @param connection - IMAP connection instance
10
+ * @param range - Message sequence number or UID range
11
+ * @param destination - Destination mailbox path
12
+ * @param options - Move options
13
+ * @param options.uid - If true, use UID MOVE instead of MOVE
14
+ * @returns Move result with UID mapping if available, false on failure, or undefined if preconditions not met
15
+ */
16
+ async function move(connection, range, destination, options) {
17
+ if (connection.state !== connection.states.SELECTED || !range || !destination) {
18
+ // nothing to do here
19
+ return;
20
+ }
21
+ options = options || {};
22
+ destination = (0, tools_js_1.normalizePath)(connection, destination);
23
+ let attributes = [
24
+ { type: 'SEQUENCE', value: range },
25
+ { type: 'ATOM', value: (0, tools_js_1.encodePath)(connection, destination) }
26
+ ];
27
+ let map = { path: connection.mailbox.path, destination };
28
+ // Fallback for servers without the MOVE extension (RFC 6851):
29
+ // emulate MOVE using COPY + flag as \Deleted + EXPUNGE.
30
+ if (!(0, tools_js_1.hasCapability)(connection, 'MOVE')) {
31
+ let result = await connection.messageCopy(range, destination, options);
32
+ await connection.messageDelete(range, Object.assign({ silent: true }, options));
33
+ return result;
34
+ }
35
+ let response;
36
+ try {
37
+ // Some servers send COPYUID in an untagged OK before the tagged response,
38
+ // others include it in the tagged OK. We check both to be safe.
39
+ response = await connection.exec(options.uid ? 'UID MOVE' : 'MOVE', attributes, {
40
+ untagged: {
41
+ OK: async (untagged) => {
42
+ (0, copyuid_parser_js_1.parseCopyUid)(untagged, map);
43
+ }
44
+ }
45
+ });
46
+ response.next();
47
+ (0, copyuid_parser_js_1.parseCopyUid)(response.response, map);
48
+ return map;
49
+ }
50
+ catch (err) {
51
+ await (0, tools_js_1.enhanceCommandError)(err);
52
+ connection.log.warn({ err, cid: connection.id });
53
+ return false;
54
+ }
55
+ }
56
+ module.exports = exports.default;
57
+ Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
@@ -0,0 +1,25 @@
1
+ import type { ImapFlow } from '../imap-flow.js';
2
+ import type { NamespaceObject } from '../types.js';
3
+ /**
4
+ * Returned instead of a namespace when the NAMESPACE command failed
5
+ */
6
+ export interface NamespaceErrorResult {
7
+ error: true;
8
+ status: string | undefined;
9
+ text: string | undefined;
10
+ }
11
+ /**
12
+ * Prefix and delimiter derived from `LIST "" ""`
13
+ */
14
+ export interface ListPrefixInfo {
15
+ flags?: Set<string> | undefined;
16
+ delimiter?: string | null | undefined;
17
+ prefix?: string | undefined;
18
+ }
19
+ /**
20
+ * Requests NAMESPACE info from the server.
21
+ *
22
+ * @param connection - IMAP connection instance
23
+ * @returns The primary personal namespace, or an error object on failure
24
+ */
25
+ export default function namespace(connection: ImapFlow): Promise<NamespaceObject | NamespaceErrorResult | undefined>;
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = namespace;
4
+ const tools_js_1 = require("../tools.js");
5
+ /**
6
+ * Requests NAMESPACE info from the server.
7
+ *
8
+ * @param connection - IMAP connection instance
9
+ * @returns The primary personal namespace, or an error object on failure
10
+ */
11
+ async function namespace(connection) {
12
+ if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
13
+ // nothing to do here
14
+ return;
15
+ }
16
+ if (!(0, tools_js_1.hasCapability)(connection, 'NAMESPACE')) {
17
+ // Fallback: when the server does not support the NAMESPACE extension (RFC 2342),
18
+ // derive the prefix and delimiter from a LIST "" "" command, which returns
19
+ // the hierarchy delimiter and root name for the default mailbox hierarchy.
20
+ let { prefix, delimiter } = await getListPrefix(connection);
21
+ // Ensure the prefix ends with the delimiter so that appending a mailbox name
22
+ // produces a valid path (e.g., "INBOX." + "Sent" = "INBOX.Sent").
23
+ if (delimiter && prefix && prefix.charAt(prefix.length - 1) !== delimiter) {
24
+ prefix += delimiter;
25
+ }
26
+ let map = {
27
+ personal: [{ prefix: prefix || '', delimiter }],
28
+ other: false,
29
+ shared: false
30
+ };
31
+ connection.namespaces = map;
32
+ connection.namespace = connection.namespaces.personal[0];
33
+ return connection.namespace;
34
+ }
35
+ let response;
36
+ try {
37
+ let map = {};
38
+ response = await connection.exec('NAMESPACE', false, {
39
+ untagged: {
40
+ // The NAMESPACE response (RFC 2342) contains exactly three sections:
41
+ // [0] = personal namespaces (user's own mailboxes)
42
+ // [1] = other users' namespaces (shared by other users)
43
+ // [2] = shared namespaces (public/organizational folders)
44
+ // Each section is either NIL or a list of (prefix, delimiter) pairs.
45
+ NAMESPACE: async (untagged) => {
46
+ if (!untagged.attributes || !untagged.attributes.length) {
47
+ return;
48
+ }
49
+ map.personal = getNamsepaceInfo(untagged.attributes[0]);
50
+ map.other = getNamsepaceInfo(untagged.attributes[1]);
51
+ map.shared = getNamsepaceInfo(untagged.attributes[2]);
52
+ }
53
+ }
54
+ });
55
+ connection.namespaces = map;
56
+ // make sure that we have the first personal namespace always set
57
+ if (!connection.namespaces.personal[0]) {
58
+ connection.namespaces.personal[0] = { prefix: '', delimiter: '.' };
59
+ }
60
+ connection.namespaces.personal[0].prefix = connection.namespaces.personal[0].prefix || '';
61
+ response.next();
62
+ connection.namespace = connection.namespaces.personal[0];
63
+ return connection.namespace;
64
+ }
65
+ catch (err) {
66
+ connection.log.warn({ err, cid: connection.id });
67
+ return {
68
+ error: true,
69
+ status: err.responseStatus,
70
+ text: err.responseText
71
+ };
72
+ }
73
+ }
74
+ /**
75
+ * Derives namespace prefix and delimiter from a LIST command when NAMESPACE is not supported.
76
+ *
77
+ * @param connection - IMAP connection instance
78
+ * @returns Object with prefix, delimiter, and flags, or empty object on failure
79
+ */
80
+ async function getListPrefix(connection) {
81
+ let response;
82
+ try {
83
+ let map = {};
84
+ // LIST "" "" is a special form that returns only the hierarchy delimiter
85
+ // and the root name, without listing any actual mailboxes.
86
+ response = await connection.exec('LIST', ['', ''], {
87
+ untagged: {
88
+ LIST: async (untagged) => {
89
+ if (!untagged.attributes || !untagged.attributes.length) {
90
+ return;
91
+ }
92
+ map.flags = new Set((0, tools_js_1.getStringList)(untagged.attributes[0]));
93
+ map.delimiter = (untagged.attributes[1] && untagged.attributes[1].value);
94
+ map.prefix = ((untagged.attributes[2] && untagged.attributes[2].value) || '');
95
+ if (map.delimiter && map.prefix.charAt(0) === map.delimiter) {
96
+ map.prefix = map.prefix.slice(1);
97
+ }
98
+ }
99
+ }
100
+ });
101
+ response.next();
102
+ return map;
103
+ }
104
+ catch (err) {
105
+ connection.log.warn({ err, cid: connection.id });
106
+ return {};
107
+ }
108
+ }
109
+ /**
110
+ * Parses namespace information from an IMAP NAMESPACE response attribute.
111
+ *
112
+ * @param attribute - Namespace attribute array from the server response
113
+ * @returns Array of namespace entries, or false if empty
114
+ */
115
+ function getNamsepaceInfo(attribute) {
116
+ if (!attribute || !Array.isArray(attribute) || !attribute.length) {
117
+ return false;
118
+ }
119
+ return attribute
120
+ .filter(entry => {
121
+ let pair = entry;
122
+ // RFC 2342 section 5 allows the delimiter to be NIL when the namespace has
123
+ // no hierarchy. The token parser emits a literal `null` for NIL.
124
+ return pair.length >= 2 && pair[0] && typeof pair[0].value === 'string' && (pair[1] === null || (pair[1] && typeof pair[1].value === 'string'));
125
+ })
126
+ .map(entry => {
127
+ let pair = entry;
128
+ let prefix = pair[0].value;
129
+ let delimiter = pair[1] === null ? null : pair[1].value;
130
+ // Append the delimiter to the prefix if it doesn't already end with one,
131
+ // so callers can construct full paths by simply concatenating prefix + name.
132
+ if (delimiter && prefix && prefix.charAt(prefix.length - 1) !== delimiter) {
133
+ prefix += delimiter;
134
+ }
135
+ return { prefix, delimiter };
136
+ });
137
+ }
138
+ module.exports = exports.default;
139
+ Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
@@ -0,0 +1,8 @@
1
+ import type { ImapFlow } from '../imap-flow.js';
2
+ /**
3
+ * Sends a NOOP command to the server.
4
+ *
5
+ * @param connection - IMAP connection instance
6
+ * @returns True on success, false on failure
7
+ */
8
+ export default function noop(connection: ImapFlow): Promise<boolean>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = noop;
4
+ /**
5
+ * Sends a NOOP command to the server.
6
+ *
7
+ * @param connection - IMAP connection instance
8
+ * @returns True on success, false on failure
9
+ */
10
+ async function noop(connection) {
11
+ try {
12
+ let response = await connection.exec('NOOP', false, { comment: 'Requested by command' });
13
+ response.next();
14
+ return true;
15
+ }
16
+ catch (err) {
17
+ connection.log.warn({ err, cid: connection.id });
18
+ return false;
19
+ }
20
+ }
21
+ module.exports = exports.default;
22
+ Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
@@ -0,0 +1,10 @@
1
+ import type { ImapFlow } from '../imap-flow.js';
2
+ import type { QuotaResponse } from '../types.js';
3
+ /**
4
+ * Requests quota information for a mailbox.
5
+ *
6
+ * @param connection - IMAP connection instance
7
+ * @param path - Mailbox path to query quota for
8
+ * @returns Quota information object, false if QUOTA not supported or on failure, or undefined if preconditions not met
9
+ */
10
+ export default function quota(connection: ImapFlow, path: string | string[]): Promise<QuotaResponse | false | undefined>;
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = quota;
4
+ const tools_js_1 = require("../tools.js");
5
+ /**
6
+ * Requests quota information for a mailbox.
7
+ *
8
+ * @param connection - IMAP connection instance
9
+ * @param path - Mailbox path to query quota for
10
+ * @returns Quota information object, false if QUOTA not supported or on failure, or undefined if preconditions not met
11
+ */
12
+ async function quota(connection, path) {
13
+ if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !path) {
14
+ // nothing to do here
15
+ return;
16
+ }
17
+ if (!connection.capabilities.has('QUOTA')) {
18
+ return false;
19
+ }
20
+ path = (0, tools_js_1.normalizePath)(connection, path);
21
+ let map = { path };
22
+ // Parse a QUOTA response. The resource list uses a repeating triplet pattern (i % 3):
23
+ // position 0: resource name (e.g., "STORAGE", "MESSAGE")
24
+ // position 1: current usage
25
+ // position 2: limit
26
+ // Storage values are in KB on the wire; multiply by 1024 to report bytes.
27
+ let processQuotaResponse = (untagged) => {
28
+ let attributes = untagged.attributes && untagged.attributes[1];
29
+ if (!attributes || !Array.isArray(attributes) || !attributes.length) {
30
+ return false;
31
+ }
32
+ let key = false;
33
+ attributes.forEach((attribute, i) => {
34
+ const position = i % 3;
35
+ if (position === 0) {
36
+ key = attribute && typeof attribute.value === 'string' ? attribute.value.toLowerCase() : false;
37
+ return;
38
+ }
39
+ if (!key) {
40
+ return;
41
+ }
42
+ // isNaN() also passes '1e5', ' 12 ' and 'Infinity', none of which is a usable octet count
43
+ let value = (0, tools_js_1.parseUintValue)(attribute && attribute.value);
44
+ if (value === false) {
45
+ return;
46
+ }
47
+ // Resource names are server-controlled. This object is returned to the caller, so it
48
+ // keeps a normal prototype and unsafe names are dropped instead; the fixed fields
49
+ // must keep their values too.
50
+ if ((0, tools_js_1.isUnsafeKey)(key) || key === 'path' || key === 'quotaroot') {
51
+ return;
52
+ }
53
+ if (!map[key]) {
54
+ map[key] = {};
55
+ }
56
+ // Storage quota is reported in KB by IMAP; convert to bytes for consistency
57
+ const multiplier = key === 'storage' ? 1024 : 1;
58
+ if (position === 1) {
59
+ map[key].usage = value * multiplier;
60
+ }
61
+ else if (position === 2) {
62
+ map[key].limit = value * multiplier;
63
+ // Calculate usage percentage for convenient display
64
+ if (map[key].limit) {
65
+ map[key].status = Math.round(((map[key].usage || 0) / map[key].limit) * 100) + '%';
66
+ }
67
+ }
68
+ });
69
+ };
70
+ let quotaFound = false;
71
+ let response;
72
+ try {
73
+ // Two-step quota lookup: GETQUOTAROOT identifies the quota root for a mailbox,
74
+ // and the server usually sends the QUOTA response inline. Some servers only
75
+ // send the root name and require a separate GETQUOTA command.
76
+ response = await connection.exec('GETQUOTAROOT', [{ type: 'ATOM', value: (0, tools_js_1.encodePath)(connection, path) }], {
77
+ untagged: {
78
+ // QUOTAROOT response tells us which quota root applies to this mailbox.
79
+ // A mailbox may have zero or one quota root.
80
+ QUOTAROOT: async (untagged) => {
81
+ let quotaRoot = untagged.attributes && untagged.attributes[1] && typeof untagged.attributes[1].value === 'string'
82
+ ? untagged.attributes[1].value
83
+ : false;
84
+ if (quotaRoot) {
85
+ map.quotaRoot = quotaRoot;
86
+ }
87
+ },
88
+ // QUOTA response provides the actual resource usage and limits
89
+ QUOTA: async (untagged) => {
90
+ quotaFound = true;
91
+ processQuotaResponse(untagged);
92
+ }
93
+ }
94
+ });
95
+ response.next();
96
+ // Fallback: if we got a quota root but no QUOTA response inline,
97
+ // explicitly request quota for that root.
98
+ if (map.quotaRoot && !quotaFound) {
99
+ response = await connection.exec('GETQUOTA', [{ type: 'ATOM', value: map.quotaRoot }], {
100
+ untagged: {
101
+ QUOTA: async (untagged) => {
102
+ processQuotaResponse(untagged);
103
+ }
104
+ }
105
+ });
106
+ // Release the parser: without this the connection stalls, because the reader loop
107
+ // waits for the response to be handed back before parsing any further input.
108
+ response.next();
109
+ }
110
+ return map;
111
+ }
112
+ catch (err) {
113
+ await (0, tools_js_1.enhanceCommandError)(err);
114
+ connection.log.warn({ err, cid: connection.id });
115
+ return false;
116
+ }
117
+ }
118
+ module.exports = exports.default;
119
+ Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
@@ -0,0 +1,12 @@
1
+ import type { ImapFlow } from '../imap-flow.js';
2
+ import type { MailboxRenameResponse } from '../types.js';
3
+ /**
4
+ * Renames an existing mailbox.
5
+ *
6
+ * @param connection - IMAP connection instance
7
+ * @param path - Current mailbox path
8
+ * @param newPath - New mailbox path
9
+ * @returns Object with old and new paths, or undefined if preconditions not met
10
+ * @throws If the RENAME command fails
11
+ */
12
+ export default function rename(connection: ImapFlow, path: string | string[], newPath: string | string[]): Promise<MailboxRenameResponse | undefined>;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = rename;
4
+ const tools_js_1 = require("../tools.js");
5
+ /**
6
+ * Renames an existing mailbox.
7
+ *
8
+ * @param connection - IMAP connection instance
9
+ * @param path - Current mailbox path
10
+ * @param newPath - New mailbox path
11
+ * @returns Object with old and new paths, or undefined if preconditions not met
12
+ * @throws If the RENAME command fails
13
+ */
14
+ async function rename(connection, path, newPath) {
15
+ if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
16
+ // nothing to do here
17
+ return;
18
+ }
19
+ // Normalize both paths (resolve special names, apply namespace prefix) and encode
20
+ // them for the IMAP wire format (modified UTF-7 for non-ASCII characters).
21
+ path = (0, tools_js_1.normalizePath)(connection, path);
22
+ newPath = (0, tools_js_1.normalizePath)(connection, newPath);
23
+ // Must close/deselect the mailbox before renaming if it's currently selected,
24
+ // as IMAP servers will not rename an active mailbox.
25
+ if (connection.state === connection.states.SELECTED && connection.mailbox.path === path) {
26
+ await connection.run('CLOSE');
27
+ }
28
+ let response;
29
+ try {
30
+ let map = {
31
+ path,
32
+ newPath
33
+ };
34
+ response = await connection.exec('RENAME', [
35
+ { type: 'ATOM', value: (0, tools_js_1.encodePath)(connection, path) },
36
+ { type: 'ATOM', value: (0, tools_js_1.encodePath)(connection, newPath) }
37
+ ]);
38
+ response.next();
39
+ return map;
40
+ }
41
+ catch (err) {
42
+ await (0, tools_js_1.enhanceCommandError)(err);
43
+ connection.log.warn({ err, cid: connection.id });
44
+ throw err;
45
+ }
46
+ }
47
+ module.exports = exports.default;
48
+ Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
@@ -0,0 +1,15 @@
1
+ import type { ImapFlow } from '../imap-flow.js';
2
+ import type { ESearchResult, SearchObject, SearchOptions } from '../types.js';
3
+ /**
4
+ * Searches for messages matching the specified criteria.
5
+ *
6
+ * @param connection - IMAP connection instance
7
+ * @param query - Search query object, or true/empty object to match all messages
8
+ * @param options - Search options
9
+ * @param options.uid - If true, use UID SEARCH instead of SEARCH
10
+ * @param options.returnOptions - ESEARCH RETURN options. When present AND the
11
+ * server advertises ESEARCH capability, triggers ESEARCH and returns an ESearchResult.
12
+ * Items are strings ('MIN','MAX','COUNT','ALL') or objects ({ partial: '1:100' }).
13
+ * When server lacks ESEARCH, falls back to plain SEARCH and returns number[].
14
+ */
15
+ export default function search(connection: ImapFlow, query: SearchObject | boolean | null | undefined, options?: SearchOptions | undefined): Promise<number[] | ESearchResult | false>;