imapkit 4.0.3 → 4.1.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 (485) hide show
  1. package/README.md +32 -19
  2. package/bin/imapkit.js +12 -16
  3. package/dist/cjs/addressparser.d.ts +21 -0
  4. package/dist/cjs/addressparser.js +277 -0
  5. package/dist/cjs/arguments.d.ts +31 -0
  6. package/{lib → dist/cjs}/arguments.js +9 -21
  7. package/dist/cjs/bodystructure.d.ts +25 -0
  8. package/dist/cjs/bodystructure.js +150 -0
  9. package/dist/cjs/cert.d.ts +2 -0
  10. package/dist/cjs/cert.js +7 -0
  11. package/dist/cjs/command-states.d.ts +36 -0
  12. package/dist/cjs/command-states.js +102 -0
  13. package/dist/cjs/commands/append.d.ts +88 -0
  14. package/dist/cjs/commands/append.js +299 -0
  15. package/dist/cjs/commands/capability.d.ts +2 -0
  16. package/dist/cjs/commands/capability.js +44 -0
  17. package/dist/cjs/commands/check.d.ts +2 -0
  18. package/dist/cjs/commands/check.js +28 -0
  19. package/dist/cjs/commands/close.d.ts +2 -0
  20. package/dist/cjs/commands/close.js +35 -0
  21. package/dist/cjs/commands/copy.d.ts +30 -0
  22. package/dist/cjs/commands/copy.js +107 -0
  23. package/dist/cjs/commands/create.d.ts +2 -0
  24. package/dist/cjs/commands/create.js +53 -0
  25. package/dist/cjs/commands/delete.d.ts +2 -0
  26. package/dist/cjs/commands/delete.js +63 -0
  27. package/dist/cjs/commands/examine.d.ts +2 -0
  28. package/dist/cjs/commands/examine.js +19 -0
  29. package/dist/cjs/commands/expunge.d.ts +2 -0
  30. package/dist/cjs/commands/expunge.js +32 -0
  31. package/dist/cjs/commands/fetch.d.ts +23 -0
  32. package/dist/cjs/commands/fetch.js +208 -0
  33. package/dist/cjs/commands/handlers/fetch.d.ts +12 -0
  34. package/dist/cjs/commands/handlers/fetch.js +195 -0
  35. package/dist/cjs/commands/handlers/flags.d.ts +17 -0
  36. package/dist/cjs/commands/handlers/flags.js +39 -0
  37. package/dist/cjs/commands/handlers/search.d.ts +85 -0
  38. package/dist/cjs/commands/handlers/search.js +504 -0
  39. package/dist/cjs/commands/handlers/status.d.ts +34 -0
  40. package/dist/cjs/commands/handlers/status.js +81 -0
  41. package/dist/cjs/commands/handlers/store.d.ts +3 -0
  42. package/dist/cjs/commands/handlers/store.js +117 -0
  43. package/dist/cjs/commands/index.d.ts +2 -0
  44. package/dist/cjs/commands/index.js +61 -0
  45. package/dist/cjs/commands/list.d.ts +2 -0
  46. package/dist/cjs/commands/list.js +86 -0
  47. package/dist/cjs/commands/login.d.ts +2 -0
  48. package/dist/cjs/commands/login.js +62 -0
  49. package/dist/cjs/commands/logout.d.ts +2 -0
  50. package/dist/cjs/commands/logout.js +40 -0
  51. package/dist/cjs/commands/lsub.d.ts +2 -0
  52. package/dist/cjs/commands/lsub.js +79 -0
  53. package/dist/cjs/commands/noop.d.ts +2 -0
  54. package/dist/cjs/commands/noop.js +28 -0
  55. package/dist/cjs/commands/rename.d.ts +2 -0
  56. package/dist/cjs/commands/rename.js +98 -0
  57. package/dist/cjs/commands/search.d.ts +10 -0
  58. package/dist/cjs/commands/search.js +71 -0
  59. package/dist/cjs/commands/select.d.ts +19 -0
  60. package/dist/cjs/commands/select.js +230 -0
  61. package/dist/cjs/commands/status.d.ts +2 -0
  62. package/dist/cjs/commands/status.js +57 -0
  63. package/dist/cjs/commands/store.d.ts +10 -0
  64. package/dist/cjs/commands/store.js +134 -0
  65. package/dist/cjs/commands/subscribe.d.ts +2 -0
  66. package/dist/cjs/commands/subscribe.js +51 -0
  67. package/dist/cjs/commands/uid-copy.d.ts +2 -0
  68. package/dist/cjs/commands/uid-copy.js +19 -0
  69. package/dist/cjs/commands/uid-fetch.d.ts +3 -0
  70. package/dist/cjs/commands/uid-fetch.js +17 -0
  71. package/dist/cjs/commands/uid-search.d.ts +3 -0
  72. package/dist/cjs/commands/uid-search.js +17 -0
  73. package/dist/cjs/commands/uid-store.d.ts +3 -0
  74. package/dist/cjs/commands/uid-store.js +17 -0
  75. package/dist/cjs/commands/unsubscribe.d.ts +2 -0
  76. package/dist/cjs/commands/unsubscribe.js +50 -0
  77. package/dist/cjs/dates.d.ts +64 -0
  78. package/dist/cjs/dates.js +124 -0
  79. package/dist/cjs/deflate-layer.d.ts +83 -0
  80. package/dist/cjs/deflate-layer.js +232 -0
  81. package/dist/cjs/encoded-words.d.ts +15 -0
  82. package/dist/cjs/encoded-words.js +85 -0
  83. package/dist/cjs/envelope.d.ts +33 -0
  84. package/dist/cjs/envelope.js +86 -0
  85. package/dist/cjs/esearch.d.ts +96 -0
  86. package/dist/cjs/esearch.js +190 -0
  87. package/dist/cjs/framing.d.ts +66 -0
  88. package/{lib → dist/cjs}/framing.js +9 -26
  89. package/dist/cjs/index.d.ts +9 -0
  90. package/dist/cjs/index.js +56 -0
  91. package/dist/cjs/list-extensions.d.ts +50 -0
  92. package/dist/cjs/list-extensions.js +35 -0
  93. package/dist/cjs/load-plugins.d.ts +21 -0
  94. package/dist/cjs/load-plugins.js +89 -0
  95. package/dist/cjs/mailbox-name.d.ts +26 -0
  96. package/dist/cjs/mailbox-name.js +127 -0
  97. package/dist/cjs/mimeparser.d.ts +137 -0
  98. package/dist/cjs/mimeparser.js +727 -0
  99. package/dist/cjs/mock-client.d.ts +39 -0
  100. package/dist/cjs/mock-client.js +236 -0
  101. package/dist/cjs/numbers.d.ts +28 -0
  102. package/dist/cjs/numbers.js +52 -0
  103. package/dist/cjs/package.json +3 -0
  104. package/dist/cjs/plugins/acl.d.ts +2 -0
  105. package/dist/cjs/plugins/acl.js +888 -0
  106. package/dist/cjs/plugins/appendlimit.d.ts +16 -0
  107. package/dist/cjs/plugins/appendlimit.js +87 -0
  108. package/dist/cjs/plugins/auth-plain.d.ts +2 -0
  109. package/dist/cjs/plugins/auth-plain.js +89 -0
  110. package/dist/cjs/plugins/binary.d.ts +30 -0
  111. package/dist/cjs/plugins/binary.js +247 -0
  112. package/dist/cjs/plugins/catenate.d.ts +14 -0
  113. package/dist/cjs/plugins/catenate.js +250 -0
  114. package/dist/cjs/plugins/compress.d.ts +7 -0
  115. package/dist/cjs/plugins/compress.js +79 -0
  116. package/dist/cjs/plugins/condstore.d.ts +5 -0
  117. package/dist/cjs/plugins/condstore.js +492 -0
  118. package/dist/cjs/plugins/context-search.d.ts +8 -0
  119. package/dist/cjs/plugins/context-search.js +304 -0
  120. package/dist/cjs/plugins/context-sort.d.ts +6 -0
  121. package/dist/cjs/plugins/context-sort.js +32 -0
  122. package/dist/cjs/plugins/create-special-use.d.ts +7 -0
  123. package/dist/cjs/plugins/create-special-use.js +101 -0
  124. package/dist/cjs/plugins/enable.d.ts +23 -0
  125. package/dist/cjs/plugins/enable.js +127 -0
  126. package/dist/cjs/plugins/esearch.d.ts +6 -0
  127. package/dist/cjs/plugins/esearch.js +142 -0
  128. package/dist/cjs/plugins/esort.d.ts +6 -0
  129. package/dist/cjs/plugins/esort.js +60 -0
  130. package/dist/cjs/plugins/id.d.ts +5 -0
  131. package/dist/cjs/plugins/id.js +123 -0
  132. package/dist/cjs/plugins/idle.d.ts +5 -0
  133. package/dist/cjs/plugins/idle.js +85 -0
  134. package/dist/cjs/plugins/imap4rev2.d.ts +6 -0
  135. package/dist/cjs/plugins/imap4rev2.js +184 -0
  136. package/dist/cjs/plugins/index.d.ts +2 -0
  137. package/dist/cjs/plugins/index.js +119 -0
  138. package/dist/cjs/plugins/list-extended.d.ts +2 -0
  139. package/dist/cjs/plugins/list-extended.js +235 -0
  140. package/dist/cjs/plugins/list-status.d.ts +6 -0
  141. package/dist/cjs/plugins/list-status.js +42 -0
  142. package/dist/cjs/plugins/literalminus.d.ts +8 -0
  143. package/dist/cjs/plugins/literalminus.js +32 -0
  144. package/dist/cjs/plugins/literalplus.d.ts +6 -0
  145. package/dist/cjs/plugins/literalplus.js +30 -0
  146. package/dist/cjs/plugins/logindisabled.d.ts +5 -0
  147. package/dist/cjs/plugins/logindisabled.js +54 -0
  148. package/dist/cjs/plugins/messagelimit.d.ts +19 -0
  149. package/dist/cjs/plugins/messagelimit.js +227 -0
  150. package/dist/cjs/plugins/metadata-server.d.ts +7 -0
  151. package/dist/cjs/plugins/metadata-server.js +24 -0
  152. package/dist/cjs/plugins/metadata.d.ts +11 -0
  153. package/dist/cjs/plugins/metadata.js +436 -0
  154. package/dist/cjs/plugins/move.d.ts +11 -0
  155. package/dist/cjs/plugins/move.js +96 -0
  156. package/dist/cjs/plugins/multiappend.d.ts +12 -0
  157. package/dist/cjs/plugins/multiappend.js +38 -0
  158. package/dist/cjs/plugins/multisearch.d.ts +6 -0
  159. package/dist/cjs/plugins/multisearch.js +263 -0
  160. package/dist/cjs/plugins/namespace.d.ts +5 -0
  161. package/dist/cjs/plugins/namespace.js +57 -0
  162. package/dist/cjs/plugins/notify.d.ts +2 -0
  163. package/dist/cjs/plugins/notify.js +628 -0
  164. package/dist/cjs/plugins/oauthbearer.d.ts +32 -0
  165. package/dist/cjs/plugins/oauthbearer.js +202 -0
  166. package/dist/cjs/plugins/objectid.d.ts +23 -0
  167. package/dist/cjs/plugins/objectid.js +221 -0
  168. package/dist/cjs/plugins/partial.d.ts +6 -0
  169. package/dist/cjs/plugins/partial.js +78 -0
  170. package/dist/cjs/plugins/preview.d.ts +31 -0
  171. package/dist/cjs/plugins/preview.js +378 -0
  172. package/dist/cjs/plugins/qresync.d.ts +11 -0
  173. package/dist/cjs/plugins/qresync.js +473 -0
  174. package/dist/cjs/plugins/quota.d.ts +18 -0
  175. package/dist/cjs/plugins/quota.js +254 -0
  176. package/dist/cjs/plugins/replace.d.ts +14 -0
  177. package/dist/cjs/plugins/replace.js +130 -0
  178. package/dist/cjs/plugins/sasl-ir.d.ts +5 -0
  179. package/dist/cjs/plugins/sasl-ir.js +24 -0
  180. package/dist/cjs/plugins/savedate.d.ts +17 -0
  181. package/dist/cjs/plugins/savedate.js +64 -0
  182. package/dist/cjs/plugins/savelimit.d.ts +10 -0
  183. package/dist/cjs/plugins/savelimit.js +30 -0
  184. package/dist/cjs/plugins/searchres.d.ts +6 -0
  185. package/dist/cjs/plugins/searchres.js +91 -0
  186. package/dist/cjs/plugins/sort-display.d.ts +11 -0
  187. package/dist/cjs/plugins/sort-display.js +37 -0
  188. package/dist/cjs/plugins/sort.d.ts +11 -0
  189. package/dist/cjs/plugins/sort.js +125 -0
  190. package/dist/cjs/plugins/special-use.d.ts +10 -0
  191. package/dist/cjs/plugins/special-use.js +95 -0
  192. package/dist/cjs/plugins/starttls.d.ts +5 -0
  193. package/dist/cjs/plugins/starttls.js +55 -0
  194. package/dist/cjs/plugins/status-size.d.ts +7 -0
  195. package/dist/cjs/plugins/status-size.js +30 -0
  196. package/dist/cjs/plugins/thread-orderedsubject.d.ts +11 -0
  197. package/dist/cjs/plugins/thread-orderedsubject.js +28 -0
  198. package/dist/cjs/plugins/thread-references.d.ts +11 -0
  199. package/dist/cjs/plugins/thread-references.js +28 -0
  200. package/dist/cjs/plugins/uidonly.d.ts +15 -0
  201. package/dist/cjs/plugins/uidonly.js +126 -0
  202. package/dist/cjs/plugins/uidplus.d.ts +15 -0
  203. package/dist/cjs/plugins/uidplus.js +119 -0
  204. package/dist/cjs/plugins/unauthenticate.d.ts +7 -0
  205. package/dist/cjs/plugins/unauthenticate.js +32 -0
  206. package/dist/cjs/plugins/unselect.d.ts +5 -0
  207. package/dist/cjs/plugins/unselect.js +36 -0
  208. package/dist/cjs/plugins/utf8-accept.d.ts +6 -0
  209. package/dist/cjs/plugins/utf8-accept.js +72 -0
  210. package/dist/cjs/plugins/x-gm-ext-1.d.ts +26 -0
  211. package/dist/cjs/plugins/x-gm-ext-1.js +422 -0
  212. package/dist/cjs/plugins/xoauth2.d.ts +2 -0
  213. package/dist/cjs/plugins/xoauth2.js +155 -0
  214. package/dist/cjs/plugins/xtoybird.d.ts +2 -0
  215. package/dist/cjs/plugins/xtoybird.js +236 -0
  216. package/dist/cjs/server.d.ts +876 -0
  217. package/dist/cjs/server.js +2597 -0
  218. package/dist/cjs/smtp-listener.d.ts +13 -0
  219. package/dist/cjs/smtp-listener.js +47 -0
  220. package/dist/cjs/sorting.d.ts +77 -0
  221. package/dist/cjs/sorting.js +290 -0
  222. package/dist/cjs/threading.d.ts +30 -0
  223. package/dist/cjs/threading.js +318 -0
  224. package/dist/cjs/types.d.ts +327 -0
  225. package/dist/cjs/types.js +3 -0
  226. package/dist/cjs/utf8-session.d.ts +17 -0
  227. package/dist/cjs/utf8-session.js +148 -0
  228. package/dist/cjs/vanished.d.ts +21 -0
  229. package/dist/cjs/vanished.js +55 -0
  230. package/dist/esm/addressparser.d.ts +21 -0
  231. package/{lib → dist/esm}/addressparser.js +102 -123
  232. package/dist/esm/arguments.d.ts +31 -0
  233. package/dist/esm/arguments.js +96 -0
  234. package/dist/esm/bodystructure.d.ts +25 -0
  235. package/{lib → dist/esm}/bodystructure.js +17 -33
  236. package/dist/esm/cert.d.ts +2 -0
  237. package/dist/esm/cert.js +4 -0
  238. package/dist/esm/command-states.d.ts +36 -0
  239. package/{lib → dist/esm}/command-states.js +4 -16
  240. package/dist/esm/commands/append.d.ts +88 -0
  241. package/{lib → dist/esm}/commands/append.js +47 -85
  242. package/dist/esm/commands/capability.d.ts +2 -0
  243. package/dist/esm/commands/capability.js +29 -0
  244. package/dist/esm/commands/check.d.ts +2 -0
  245. package/dist/esm/commands/check.js +13 -0
  246. package/dist/esm/commands/close.d.ts +2 -0
  247. package/dist/esm/commands/close.js +20 -0
  248. package/dist/esm/commands/copy.d.ts +30 -0
  249. package/{lib → dist/esm}/commands/copy.js +31 -55
  250. package/dist/esm/commands/create.d.ts +2 -0
  251. package/{lib → dist/esm}/commands/create.js +25 -39
  252. package/dist/esm/commands/delete.d.ts +2 -0
  253. package/{lib → dist/esm}/commands/delete.js +25 -41
  254. package/dist/esm/commands/examine.d.ts +2 -0
  255. package/dist/esm/commands/examine.js +4 -0
  256. package/dist/esm/commands/expunge.d.ts +2 -0
  257. package/dist/esm/commands/expunge.js +17 -0
  258. package/dist/esm/commands/fetch.d.ts +23 -0
  259. package/{lib → dist/esm}/commands/fetch.js +33 -74
  260. package/dist/esm/commands/handlers/fetch.d.ts +12 -0
  261. package/{lib → dist/esm}/commands/handlers/fetch.js +11 -42
  262. package/dist/esm/commands/handlers/flags.d.ts +17 -0
  263. package/{lib → dist/esm}/commands/handlers/flags.js +3 -11
  264. package/dist/esm/commands/handlers/search.d.ts +85 -0
  265. package/{lib → dist/esm}/commands/handlers/search.js +33 -71
  266. package/dist/esm/commands/handlers/status.d.ts +34 -0
  267. package/{lib → dist/esm}/commands/handlers/status.js +1 -9
  268. package/dist/esm/commands/handlers/store.d.ts +3 -0
  269. package/{lib → dist/esm}/commands/handlers/store.js +20 -44
  270. package/dist/esm/commands/index.d.ts +2 -0
  271. package/dist/esm/commands/index.js +55 -0
  272. package/dist/esm/commands/list.d.ts +2 -0
  273. package/dist/esm/commands/list.js +71 -0
  274. package/dist/esm/commands/login.d.ts +2 -0
  275. package/{lib → dist/esm}/commands/login.js +24 -44
  276. package/dist/esm/commands/logout.d.ts +2 -0
  277. package/dist/esm/commands/logout.js +25 -0
  278. package/dist/esm/commands/lsub.d.ts +2 -0
  279. package/dist/esm/commands/lsub.js +64 -0
  280. package/dist/esm/commands/noop.d.ts +2 -0
  281. package/dist/esm/commands/noop.js +13 -0
  282. package/dist/esm/commands/rename.d.ts +2 -0
  283. package/{lib → dist/esm}/commands/rename.js +32 -51
  284. package/dist/esm/commands/search.d.ts +10 -0
  285. package/dist/esm/commands/search.js +54 -0
  286. package/dist/esm/commands/select.d.ts +19 -0
  287. package/dist/esm/commands/select.js +214 -0
  288. package/dist/esm/commands/status.d.ts +2 -0
  289. package/{lib → dist/esm}/commands/status.js +18 -39
  290. package/dist/esm/commands/store.d.ts +10 -0
  291. package/{lib → dist/esm}/commands/store.js +39 -73
  292. package/dist/esm/commands/subscribe.d.ts +2 -0
  293. package/{lib → dist/esm}/commands/subscribe.js +22 -39
  294. package/dist/esm/commands/uid-copy.d.ts +2 -0
  295. package/dist/esm/commands/uid-copy.js +4 -0
  296. package/dist/esm/commands/uid-fetch.d.ts +3 -0
  297. package/dist/esm/commands/uid-fetch.js +3 -0
  298. package/dist/esm/commands/uid-search.d.ts +3 -0
  299. package/dist/esm/commands/uid-search.js +3 -0
  300. package/dist/esm/commands/uid-store.d.ts +3 -0
  301. package/dist/esm/commands/uid-store.js +3 -0
  302. package/dist/esm/commands/unsubscribe.d.ts +2 -0
  303. package/{lib → dist/esm}/commands/unsubscribe.js +22 -37
  304. package/dist/esm/dates.d.ts +64 -0
  305. package/{lib → dist/esm}/dates.js +6 -14
  306. package/dist/esm/deflate-layer.d.ts +83 -0
  307. package/{lib → dist/esm}/deflate-layer.js +9 -26
  308. package/dist/esm/encoded-words.d.ts +15 -0
  309. package/{lib → dist/esm}/encoded-words.js +9 -25
  310. package/dist/esm/envelope.d.ts +33 -0
  311. package/{lib → dist/esm}/envelope.js +8 -19
  312. package/dist/esm/esearch.d.ts +96 -0
  313. package/{lib → dist/esm}/esearch.js +12 -39
  314. package/dist/esm/framing.d.ts +66 -0
  315. package/dist/esm/framing.js +82 -0
  316. package/dist/esm/index.d.ts +9 -0
  317. package/dist/esm/index.js +6 -0
  318. package/dist/esm/list-extensions.d.ts +50 -0
  319. package/{lib → dist/esm}/list-extensions.js +1 -4
  320. package/dist/esm/load-plugins.d.ts +21 -0
  321. package/{lib → dist/esm}/load-plugins.js +9 -43
  322. package/dist/esm/mailbox-name.d.ts +26 -0
  323. package/{lib → dist/esm}/mailbox-name.js +5 -26
  324. package/dist/esm/mimeparser.d.ts +137 -0
  325. package/{lib → dist/esm}/mimeparser.js +74 -152
  326. package/dist/esm/mock-client.d.ts +39 -0
  327. package/{lib → dist/esm}/mock-client.js +26 -40
  328. package/dist/esm/numbers.d.ts +28 -0
  329. package/{lib → dist/esm}/numbers.js +1 -8
  330. package/dist/esm/package.json +3 -0
  331. package/dist/esm/plugins/acl.d.ts +2 -0
  332. package/{lib → dist/esm}/plugins/acl.js +146 -240
  333. package/dist/esm/plugins/appendlimit.d.ts +16 -0
  334. package/{lib → dist/esm}/plugins/appendlimit.js +5 -16
  335. package/dist/esm/plugins/auth-plain.d.ts +2 -0
  336. package/{lib → dist/esm}/plugins/auth-plain.js +11 -31
  337. package/dist/esm/plugins/binary.d.ts +30 -0
  338. package/{lib → dist/esm}/plugins/binary.js +17 -43
  339. package/dist/esm/plugins/catenate.d.ts +14 -0
  340. package/{lib → dist/esm}/plugins/catenate.js +19 -40
  341. package/dist/esm/plugins/compress.d.ts +7 -0
  342. package/dist/esm/plugins/compress.js +61 -0
  343. package/dist/esm/plugins/condstore.d.ts +5 -0
  344. package/{lib → dist/esm}/plugins/condstore.js +66 -152
  345. package/dist/esm/plugins/context-search.d.ts +8 -0
  346. package/{lib → dist/esm}/plugins/context-search.js +53 -88
  347. package/dist/esm/plugins/context-sort.d.ts +6 -0
  348. package/{lib → dist/esm}/plugins/context-sort.js +4 -9
  349. package/dist/esm/plugins/create-special-use.d.ts +7 -0
  350. package/{lib → dist/esm}/plugins/create-special-use.js +33 -55
  351. package/dist/esm/plugins/enable.d.ts +23 -0
  352. package/dist/esm/plugins/enable.js +111 -0
  353. package/dist/esm/plugins/esearch.d.ts +6 -0
  354. package/{lib → dist/esm}/plugins/esearch.js +13 -42
  355. package/dist/esm/plugins/esort.d.ts +6 -0
  356. package/{lib → dist/esm}/plugins/esort.js +7 -25
  357. package/dist/esm/plugins/id.d.ts +5 -0
  358. package/dist/esm/plugins/id.js +108 -0
  359. package/dist/esm/plugins/idle.d.ts +5 -0
  360. package/dist/esm/plugins/idle.js +70 -0
  361. package/dist/esm/plugins/imap4rev2.d.ts +6 -0
  362. package/{lib → dist/esm}/plugins/imap4rev2.js +24 -60
  363. package/dist/esm/plugins/index.d.ts +2 -0
  364. package/dist/esm/plugins/index.js +113 -0
  365. package/dist/esm/plugins/list-extended.d.ts +2 -0
  366. package/{lib → dist/esm}/plugins/list-extended.js +28 -66
  367. package/dist/esm/plugins/list-status.d.ts +6 -0
  368. package/{lib → dist/esm}/plugins/list-status.js +5 -12
  369. package/dist/esm/plugins/literalminus.d.ts +8 -0
  370. package/{lib → dist/esm}/plugins/literalminus.js +2 -5
  371. package/dist/esm/plugins/literalplus.d.ts +6 -0
  372. package/{lib → dist/esm}/plugins/literalplus.js +2 -5
  373. package/dist/esm/plugins/logindisabled.d.ts +5 -0
  374. package/dist/esm/plugins/logindisabled.js +39 -0
  375. package/dist/esm/plugins/messagelimit.d.ts +19 -0
  376. package/{lib → dist/esm}/plugins/messagelimit.js +18 -41
  377. package/dist/esm/plugins/metadata-server.d.ts +7 -0
  378. package/{lib → dist/esm}/plugins/metadata-server.js +3 -7
  379. package/dist/esm/plugins/metadata.d.ts +11 -0
  380. package/dist/esm/plugins/metadata.js +421 -0
  381. package/dist/esm/plugins/move.d.ts +11 -0
  382. package/{lib → dist/esm}/plugins/move.js +37 -66
  383. package/dist/esm/plugins/multiappend.d.ts +12 -0
  384. package/{lib → dist/esm}/plugins/multiappend.js +2 -5
  385. package/dist/esm/plugins/multisearch.d.ts +6 -0
  386. package/{lib → dist/esm}/plugins/multisearch.js +24 -48
  387. package/dist/esm/plugins/namespace.d.ts +5 -0
  388. package/dist/esm/plugins/namespace.js +42 -0
  389. package/dist/esm/plugins/notify.d.ts +2 -0
  390. package/{lib → dist/esm}/plugins/notify.js +90 -134
  391. package/dist/esm/plugins/oauthbearer.d.ts +32 -0
  392. package/{lib → dist/esm}/plugins/oauthbearer.js +18 -48
  393. package/dist/esm/plugins/objectid.d.ts +23 -0
  394. package/{lib → dist/esm}/plugins/objectid.js +21 -58
  395. package/dist/esm/plugins/partial.d.ts +6 -0
  396. package/{lib → dist/esm}/plugins/partial.js +7 -15
  397. package/dist/esm/plugins/preview.d.ts +31 -0
  398. package/{lib → dist/esm}/plugins/preview.js +28 -66
  399. package/dist/esm/plugins/qresync.d.ts +11 -0
  400. package/{lib → dist/esm}/plugins/qresync.js +64 -134
  401. package/dist/esm/plugins/quota.d.ts +18 -0
  402. package/{lib → dist/esm}/plugins/quota.js +89 -135
  403. package/dist/esm/plugins/replace.d.ts +14 -0
  404. package/{lib → dist/esm}/plugins/replace.js +21 -51
  405. package/dist/esm/plugins/sasl-ir.d.ts +5 -0
  406. package/{lib → dist/esm}/plugins/sasl-ir.js +3 -6
  407. package/dist/esm/plugins/savedate.d.ts +17 -0
  408. package/{lib → dist/esm}/plugins/savedate.js +5 -15
  409. package/dist/esm/plugins/savelimit.d.ts +10 -0
  410. package/{lib → dist/esm}/plugins/savelimit.js +3 -6
  411. package/dist/esm/plugins/searchres.d.ts +6 -0
  412. package/{lib → dist/esm}/plugins/searchres.js +13 -22
  413. package/dist/esm/plugins/sort-display.d.ts +11 -0
  414. package/{lib → dist/esm}/plugins/sort-display.js +6 -10
  415. package/dist/esm/plugins/sort.d.ts +11 -0
  416. package/{lib → dist/esm}/plugins/sort.js +24 -46
  417. package/dist/esm/plugins/special-use.d.ts +10 -0
  418. package/{lib → dist/esm}/plugins/special-use.js +9 -24
  419. package/dist/esm/plugins/starttls.d.ts +5 -0
  420. package/{lib → dist/esm}/plugins/starttls.js +20 -37
  421. package/dist/esm/plugins/status-size.d.ts +7 -0
  422. package/{lib → dist/esm}/plugins/status-size.js +4 -11
  423. package/dist/esm/plugins/thread-orderedsubject.d.ts +11 -0
  424. package/{lib → dist/esm}/plugins/thread-orderedsubject.js +3 -6
  425. package/dist/esm/plugins/thread-references.d.ts +11 -0
  426. package/{lib → dist/esm}/plugins/thread-references.js +3 -6
  427. package/dist/esm/plugins/uidonly.d.ts +15 -0
  428. package/{lib → dist/esm}/plugins/uidonly.js +11 -35
  429. package/dist/esm/plugins/uidplus.d.ts +15 -0
  430. package/{lib → dist/esm}/plugins/uidplus.js +25 -45
  431. package/dist/esm/plugins/unauthenticate.d.ts +7 -0
  432. package/dist/esm/plugins/unauthenticate.js +17 -0
  433. package/dist/esm/plugins/unselect.d.ts +5 -0
  434. package/dist/esm/plugins/unselect.js +21 -0
  435. package/dist/esm/plugins/utf8-accept.d.ts +6 -0
  436. package/{lib → dist/esm}/plugins/utf8-accept.js +10 -21
  437. package/dist/esm/plugins/x-gm-ext-1.d.ts +26 -0
  438. package/{lib → dist/esm}/plugins/x-gm-ext-1.js +48 -100
  439. package/dist/esm/plugins/xoauth2.d.ts +2 -0
  440. package/dist/esm/plugins/xoauth2.js +140 -0
  441. package/dist/esm/plugins/xtoybird.d.ts +2 -0
  442. package/dist/esm/plugins/xtoybird.js +218 -0
  443. package/dist/esm/server.d.ts +876 -0
  444. package/dist/esm/server.js +2543 -0
  445. package/dist/esm/smtp-listener.d.ts +13 -0
  446. package/{lib → dist/esm}/smtp-listener.js +5 -12
  447. package/dist/esm/sorting.d.ts +77 -0
  448. package/{lib → dist/esm}/sorting.js +40 -53
  449. package/dist/esm/threading.d.ts +30 -0
  450. package/{lib → dist/esm}/threading.js +29 -70
  451. package/dist/esm/types.d.ts +327 -0
  452. package/dist/esm/types.js +2 -0
  453. package/dist/esm/utf8-session.d.ts +17 -0
  454. package/{lib → dist/esm}/utf8-session.js +15 -25
  455. package/dist/esm/vanished.d.ts +21 -0
  456. package/{lib → dist/esm}/vanished.js +16 -21
  457. package/dist/plugin-help.json +298 -0
  458. package/package.json +54 -11
  459. package/lib/commands/capability.js +0 -47
  460. package/lib/commands/check.js +0 -21
  461. package/lib/commands/close.js +0 -30
  462. package/lib/commands/examine.js +0 -7
  463. package/lib/commands/expunge.js +0 -27
  464. package/lib/commands/list.js +0 -100
  465. package/lib/commands/logout.js +0 -41
  466. package/lib/commands/lsub.js +0 -87
  467. package/lib/commands/noop.js +0 -21
  468. package/lib/commands/search.js +0 -76
  469. package/lib/commands/select.js +0 -289
  470. package/lib/commands/uid copy.js +0 -7
  471. package/lib/commands/uid fetch.js +0 -5
  472. package/lib/commands/uid search.js +0 -5
  473. package/lib/commands/uid store.js +0 -5
  474. package/lib/plugins/compress.js +0 -76
  475. package/lib/plugins/enable.js +0 -155
  476. package/lib/plugins/id.js +0 -138
  477. package/lib/plugins/idle.js +0 -105
  478. package/lib/plugins/logindisabled.js +0 -50
  479. package/lib/plugins/metadata.js +0 -475
  480. package/lib/plugins/namespace.js +0 -67
  481. package/lib/plugins/unauthenticate.js +0 -28
  482. package/lib/plugins/unselect.js +0 -36
  483. package/lib/plugins/xoauth2.js +0 -188
  484. package/lib/plugins/xtoybird.js +0 -282
  485. package/lib/server.js +0 -2880
@@ -0,0 +1,473 @@
1
+ "use strict";
2
+ /**
3
+ * @help Adds QRESYNC [RFC7162] capability, loads CONDSTORE and ENABLE as well
4
+ * @help After ENABLE QRESYNC: SELECT/EXAMINE (QRESYNC (...)), UID FETCH (CHANGEDSINCE n VANISHED),
5
+ * @help and VANISHED responses instead of EXPUNGE
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.default = qresyncPlugin;
12
+ const fetch_js_1 = __importDefault(require("../commands/handlers/fetch.js"));
13
+ const vanished_js_1 = require("../vanished.js");
14
+ const numbers_js_1 = require("../numbers.js");
15
+ const arguments_js_1 = require("../arguments.js");
16
+ const enable_js_1 = require("./enable.js");
17
+ // commands that report expunged messages, their tagged OK carries the new HIGHESTMODSEQ (RFC 7162 sections 3.2.7
18
+ // and 3.2.9, RFC 6851 section 4.4). CLOSE MUST NOT (RFC 7162 section 3.2.8)
19
+ // REPLACE removes the replaced message as if with UID EXPUNGE (RFC 8508 section 4.5)
20
+ const EXPUNGING_COMMANDS = new Set(['EXPUNGE', 'UID EXPUNGE', 'MOVE', 'UID MOVE', 'REPLACE', 'UID REPLACE']);
21
+ function qresyncPlugin(server) {
22
+ server.registerCapability('QRESYNC');
23
+ (0, enable_js_1.registerEnable)(server, 'QRESYNC');
24
+ // RFC 8437 section 4.1: UNAUTHENTICATE ends what ENABLE QRESYNC enabled (the ENABLE plugin clears the list)
25
+ server.resetHandlers.push((connection) => {
26
+ connection.qresyncExpunged = false;
27
+ });
28
+ // mod-sequence each expunged message was removed with
29
+ const expungeModseq = new WeakMap();
30
+ const isQresync = (connection) => (0, enable_js_1.isEnabled)(connection, 'QRESYNC');
31
+ const { isEnabled: isCondstore, getHighestModseq } = server.condstore;
32
+ // Expunged UID ranges with their mod-sequences, oldest first (RFC 7162 section 5.3), and the mod-sequence after which
33
+ // all expunges are remembered. Messages missing from the initial storage were expunged at an unknown time
34
+ // before. The record belongs to one UIDVALIDITY, as nothing needs to be kept once it changes
35
+ const getExpunged = (mailbox, since) => {
36
+ if (!mailbox.qresyncExpunged || mailbox.qresyncExpunged.uidvalidity !== mailbox.uidvalidity) {
37
+ mailbox.qresyncExpunged = { uidvalidity: mailbox.uidvalidity, since: since || getHighestModseq(mailbox), list: [] };
38
+ }
39
+ return mailbox.qresyncExpunged;
40
+ };
41
+ // start remembering expunges for the mailboxes of the storage once their messages have mod-sequences
42
+ const indexFolders = server.indexFolders;
43
+ server.indexFolders = function (...args) {
44
+ const result = indexFolders.apply(this, args);
45
+ Object.keys(this.folderCache).forEach(path => getExpunged(this.folderCache[path]));
46
+ return result;
47
+ };
48
+ // CONDSTORE has already incremented HIGHESTMODSEQ for this removal, the expunged UIDs get that value
49
+ // (RFC 7162 section 3.2)
50
+ server.on('expunge', (mailbox, messages, connection) => {
51
+ const modseq = getHighestModseq(mailbox);
52
+ const list = getExpunged(mailbox, modseq - 1).list;
53
+ messages.forEach((message) => {
54
+ // consecutive UIDs expunged together are kept as one range, so the history stays small even in long test
55
+ // runs. It is never trimmed: the server keeps everything since it started (RFC 7162 section 5.3)
56
+ const last = list[list.length - 1];
57
+ if (last && last.modseq === modseq && last.to + 1 === message.uid) {
58
+ last.to = message.uid;
59
+ }
60
+ else {
61
+ list.push({ from: message.uid, to: message.uid, modseq });
62
+ }
63
+ expungeModseq.set(message, modseq);
64
+ });
65
+ if (connection) {
66
+ connection.qresyncExpunged = true;
67
+ }
68
+ });
69
+ /**
70
+ * Lists the UIDs of a set that were expunged after a mod-sequence (RFC 7162 sections 3.2.5.1 and 3.2.6)
71
+ *
72
+ * @param {Object} mailbox Mailbox object
73
+ * @param {Array} messages Messages of the mailbox as the session sees them, these are not reported
74
+ * @param {Array} ranges Ascending UID ranges as [from, to] pairs
75
+ * @param {Number} modseq Mod-sequence the client knows
76
+ * @param {Number} [knownUpTo] The client knows about all expunges up to this UID (message sequence match data)
77
+ * @return {String} sequence set of the UIDs, empty if there are none
78
+ */
79
+ const getVanished = (mailbox, messages, ranges, modseq, knownUpTo) => {
80
+ const { since, list } = getExpunged(mailbox);
81
+ let candidates;
82
+ if (modseq >= since) {
83
+ // all expunges after the client's mod-sequence are remembered. Message sequence match data only helps
84
+ // when they are not, so it is not used here (RFC 7162 section 5.3)
85
+ candidates = intersectRanges(mergeRanges(list.filter(entry => entry.modseq > modseq).map((entry) => [entry.from, entry.to])), ranges);
86
+ }
87
+ else {
88
+ // RFC 7162 section 3.2.6: for a mod-sequence older than the remembered expunges, the server MUST behave as
89
+ // if asked to report all expunged messages of the set: every UID below UIDNEXT that is not in the mailbox,
90
+ // except what the sequence match data shows the client knows
91
+ candidates = intersectRanges(ranges, [[(knownUpTo || 0) + 1, mailbox.uidnext - 1]]);
92
+ }
93
+ // messages the session still sees are left out, an expunge that the session has not been told about yet is
94
+ // reported with VANISHED without EARLIER
95
+ return subtractUids(candidates, messages)
96
+ .map(range => (range[0] === range[1] ? String(range[0]) : range[0] + ':' + range[1]))
97
+ .join(',');
98
+ };
99
+ const sendBad = (connection, parsed, data, callback, message) => {
100
+ connection.sendStatus(parsed, data, 'BAD', message, false, 'QRESYNC FAILED');
101
+ return callback();
102
+ };
103
+ // Wraps an existing command handler. Commands that are not available are left alone
104
+ const wrapHandler = (command, wrapper) => {
105
+ const prevHandler = server.getCommandHandler(command);
106
+ if (!prevHandler) {
107
+ return;
108
+ }
109
+ server.setCommandHandler(command, (connection, parsed, data, callback) => wrapper(prevHandler, connection, parsed, data, callback));
110
+ };
111
+ // RFC 7162 section 3.2.5: SELECT/EXAMINE mailbox (QRESYNC (uidvalidity mod-sequence-value [known-uids] [seq-match-data]))
112
+ const selectWrapper = (prevHandler, connection, parsed, data, callback) => {
113
+ const params = parsed.attributes && parsed.attributes[1];
114
+ const isQresyncParam = (param) => (0, arguments_js_1.isAtom)(param, 'QRESYNC');
115
+ const position = Array.isArray(params) ? params.findIndex(isQresyncParam) : -1;
116
+ if (position < 0) {
117
+ return prevHandler(connection, parsed, data, callback);
118
+ }
119
+ if (!isQresync(connection)) {
120
+ return sendBad(connection, parsed, data, callback, 'QRESYNC parameter requires ENABLE QRESYNC');
121
+ }
122
+ if (params.findLastIndex(isQresyncParam) !== position) {
123
+ return sendBad(connection, parsed, data, callback, 'QRESYNC parameter can be used only once');
124
+ }
125
+ let qresync;
126
+ try {
127
+ qresync = parseQresyncParam(params[position + 1]);
128
+ }
129
+ catch (err) {
130
+ return sendBad(connection, parsed, data, callback, err.message);
131
+ }
132
+ params.splice(position, 2);
133
+ if (!params.length) {
134
+ parsed.attributes.splice(1, 1);
135
+ }
136
+ parsed.qresync = qresync;
137
+ prevHandler(connection, parsed, data, callback);
138
+ };
139
+ wrapHandler('SELECT', selectWrapper);
140
+ wrapHandler('EXAMINE', selectWrapper);
141
+ // RFC 7162 section 3.2.6: the VANISHED UID FETCH modifier
142
+ const fetchWrapper = (isUid, prevHandler, connection, parsed, data, callback) => {
143
+ const modifiers = parsed.attributes && parsed.attributes[2];
144
+ const isVanished = (modifier) => (0, arguments_js_1.isAtom)(modifier, 'VANISHED');
145
+ const position = Array.isArray(modifiers) ? modifiers.findIndex(isVanished) : -1;
146
+ if (position < 0) {
147
+ return prevHandler(connection, parsed, data, callback);
148
+ }
149
+ if (!isUid) {
150
+ return sendBad(connection, parsed, data, callback, 'VANISHED is only allowed with UID FETCH');
151
+ }
152
+ if (!isQresync(connection)) {
153
+ return sendBad(connection, parsed, data, callback, 'VANISHED requires ENABLE QRESYNC');
154
+ }
155
+ if (modifiers.findLastIndex(isVanished) !== position) {
156
+ return sendBad(connection, parsed, data, callback, 'VANISHED can be used only once');
157
+ }
158
+ if (!modifiers.some((modifier) => (0, arguments_js_1.isAtom)(modifier, 'CHANGEDSINCE'))) {
159
+ return sendBad(connection, parsed, data, callback, 'VANISHED requires CHANGEDSINCE');
160
+ }
161
+ modifiers.splice(position, 1);
162
+ parsed.qresyncVanished = true;
163
+ prevHandler(connection, parsed, data, callback);
164
+ };
165
+ wrapHandler('FETCH', fetchWrapper.bind(null, false));
166
+ wrapHandler('UID FETCH', fetchWrapper.bind(null, true));
167
+ // RFC 7162 section 3.2.10: after ENABLE QRESYNC, expunges are reported with VANISHED instead of EXPUNGE.
168
+ // Consecutive EXPUNGE notifications become one VANISHED response
169
+ server.connectionHandlers.push((connection) => {
170
+ const prepareNotifications = connection.prepareNotifications;
171
+ connection.prepareNotifications = function (queue) {
172
+ queue = prepareNotifications.call(this, queue);
173
+ return isQresync(this) ? (0, vanished_js_1.toVanished)(queue) : queue;
174
+ };
175
+ });
176
+ // Sends a VANISHED (EARLIER) response, if there is anything to report
177
+ const sendVanishedEarlier = (connection, uids, parsed, data) => {
178
+ if (!uids) {
179
+ return;
180
+ }
181
+ connection.send({
182
+ tag: '*',
183
+ command: 'VANISHED',
184
+ attributes: [[{ type: 'ATOM', value: 'EARLIER' }], { type: 'SEQUENCE', value: uids }]
185
+ }, 'VANISHED EARLIER', parsed, data);
186
+ };
187
+ // RFC 7162 section 3.2.5.1: after SELECT/EXAMINE (QRESYNC), expunges and flag changes since the given mod-sequence
188
+ const sendQresyncChanges = (connection, parsed, data) => {
189
+ // only called with a mailbox selected
190
+ const mailbox = connection.selectedMailbox;
191
+ const qresync = parsed.qresync;
192
+ if (qresync.uidvalidity !== mailbox.uidvalidity) {
193
+ // RFC 7162 section 3.2.5: ignore the remaining parameters if UIDVALIDITY does not match
194
+ return;
195
+ }
196
+ // without known UIDs, the client is treated as if it sent 1:<UIDNEXT - 1>, nothing for an unused mailbox
197
+ const ranges = qresync.knownUids || (mailbox.uidnext > 1 ? [[1, mailbox.uidnext - 1]] : []);
198
+ // RFC 7162 section 3.2.5.2: the last pair of sequence number and UID that still match tells up to which
199
+ // UID the client knows about all expunges, the first pair that does not match ends the comparison
200
+ let knownUpTo = 0;
201
+ if (qresync.seqMatch) {
202
+ const uids = iterateRanges(qresync.seqMatch.uids);
203
+ for (const seq of iterateRanges(qresync.seqMatch.sequences)) {
204
+ const uid = uids.next().value;
205
+ const message = mailbox.messages[seq - 1];
206
+ if (!message || message.uid !== uid) {
207
+ break;
208
+ }
209
+ knownUpTo = uid;
210
+ }
211
+ }
212
+ // VANISHED (EARLIER) MUST come before the FETCH responses (RFC 7162 section 3.2.6)
213
+ sendVanishedEarlier(connection, getVanished(mailbox, mailbox.messages, ranges, qresync.modseq, knownUpTo), parsed, data);
214
+ const getFlags = server.fetchHandlers.FLAGS || fetch_js_1.default.FLAGS;
215
+ mailbox.messages.forEach((message, i) => {
216
+ if (message.MODSEQ <= qresync.modseq || !inRanges(ranges, message.uid)) {
217
+ return;
218
+ }
219
+ // flag changes MUST include the UID (RFC 7162 section 3.2.5.1)
220
+ connection.send({
221
+ tag: '*',
222
+ attributes: [
223
+ i + 1,
224
+ { type: 'ATOM', value: 'FETCH' },
225
+ [
226
+ { type: 'ATOM', value: 'UID' },
227
+ message.uid,
228
+ { type: 'ATOM', value: 'FLAGS' },
229
+ getFlags(connection, message, { type: 'ATOM', value: 'FLAGS' }),
230
+ { type: 'ATOM', value: 'MODSEQ' },
231
+ [message.MODSEQ]
232
+ ]
233
+ ]
234
+ }, 'QRESYNC FETCH', parsed, data, message);
235
+ });
236
+ };
237
+ const highestModseqCode = (modseq) => ({ type: 'SECTION', section: [{ type: 'ATOM', value: 'HIGHESTMODSEQ' }, modseq] });
238
+ server.outputHandlers.push((connection, response, description, parsed, data) => {
239
+ if (!parsed || !response || response.tag === '+') {
240
+ return;
241
+ }
242
+ const isTagged = response.tag !== '*' && response.tag === parsed.tag;
243
+ // UID FETCH (VANISHED): VANISHED (EARLIER) comes before the first FETCH response, or before the tagged OK
244
+ if (parsed.qresyncVanished && ((response.tag === '*' && description === 'UID FETCH') || (isTagged && response.command === 'OK'))) {
245
+ parsed.qresyncVanished = false;
246
+ // UID FETCH runs in the Selected state
247
+ const mailbox = connection.selectedMailbox;
248
+ const ranges = parseUidSet(parsed.attributes[0].value, mailbox.uidnext - 1);
249
+ if (ranges) {
250
+ sendVanishedEarlier(connection, getVanished(mailbox, connection.getSessionMessages(), ranges, parsed.changedsince), parsed, data);
251
+ }
252
+ return;
253
+ }
254
+ if (!isTagged) {
255
+ return;
256
+ }
257
+ if (parsed.qresync && response.command === 'OK' && (description === 'SELECT' || description === 'EXAMINE') && connection.selectedMailbox) {
258
+ sendQresyncChanges(connection, parsed, data);
259
+ return;
260
+ }
261
+ const expunged = connection.qresyncExpunged;
262
+ connection.qresyncExpunged = false;
263
+ // HIGHESTMODSEQ in the tagged OK once messages were expunged, RFC 7162 sections 3.2.7 and 3.2.9 require it
264
+ // with QRESYNC enabled, RFC 6851 section 4.4 for MOVE
265
+ if (expunged &&
266
+ response.command === 'OK' &&
267
+ EXPUNGING_COMMANDS.has(String(parsed.command).toUpperCase()) &&
268
+ connection.selectedMailbox &&
269
+ isCondstore(connection)) {
270
+ const hasCode = response.attributes && response.attributes[0] && response.attributes[0].type === 'SECTION';
271
+ if (!hasCode) {
272
+ response.attributes = [highestModseqCode(getHighestModseq(connection.selectedMailbox))].concat(response.attributes || []);
273
+ }
274
+ return;
275
+ }
276
+ // RFC 7162 section 3.2: while expunges are held back (FETCH, STORE, SEARCH), the client must not take a
277
+ // MODSEQ it got as the new HIGHESTMODSEQ, so tell it a value below the mod-sequence of the pending expunges
278
+ if (isCondstore(connection)) {
279
+ let lowest = 0;
280
+ connection.notificationQueue.forEach((notification) => {
281
+ const modseq = (0, vanished_js_1.isExpungeNotification)(notification) && notification.message && expungeModseq.get(notification.message);
282
+ if (modseq && (!lowest || modseq < lowest)) {
283
+ lowest = modseq;
284
+ }
285
+ });
286
+ if (lowest > 1) {
287
+ connection.send({
288
+ tag: '*',
289
+ command: 'OK',
290
+ attributes: [highestModseqCode(lowest - 1), { type: 'TEXT', value: 'Expunges not reported yet' }]
291
+ }, 'QRESYNC HIGHESTMODSEQ', parsed, data);
292
+ }
293
+ }
294
+ });
295
+ }
296
+ /**
297
+ * Parses a sequence set without "*" into [from, to] ranges as written
298
+ *
299
+ * @param {Object} value Parsed argument
300
+ * @param {String} name Name of the argument for the error message
301
+ * @return {Array} ranges
302
+ */
303
+ function parseSequenceSet(value, name) {
304
+ if (!value || Array.isArray(value) || ['ATOM', 'SEQUENCE'].indexOf(value.type) < 0 || !(0, numbers_js_1.isSequenceSet)(value.value, true)) {
305
+ throw new Error('Invalid QRESYNC ' + name + ', a sequence set without "*" expected');
306
+ }
307
+ return value.value.split(',').map((part) => {
308
+ const range = part.split(':').map(Number);
309
+ return [range[0], range.length > 1 ? range[1] : range[0]];
310
+ });
311
+ }
312
+ /**
313
+ * Parses the UID set of UID FETCH, "*" stands for the highest UID the mailbox may have used
314
+ *
315
+ * @param {String} value Sequence set
316
+ * @param {Number} star Value for "*"
317
+ * @return {Array|false} ranges ordered as [low, high], or false for other forms (e.g. "$" of SEARCHRES)
318
+ */
319
+ function parseUidSet(value, star) {
320
+ if (!/^[\d*:,]+$/.test(String(value))) {
321
+ return false;
322
+ }
323
+ return mergeRanges(String(value)
324
+ .split(',')
325
+ .map(part => part.split(':').map(number => (number === '*' ? star : Number(number)))));
326
+ }
327
+ // Intersection of two lists of ascending, non-overlapping ranges
328
+ function intersectRanges(a, b) {
329
+ const result = [];
330
+ let i = 0;
331
+ let j = 0;
332
+ while (i < a.length && j < b.length) {
333
+ const from = Math.max(a[i][0], b[j][0]);
334
+ const to = Math.min(a[i][1], b[j][1]);
335
+ if (from <= to) {
336
+ result.push([from, to]);
337
+ }
338
+ if (a[i][1] < b[j][1]) {
339
+ i++;
340
+ }
341
+ else {
342
+ j++;
343
+ }
344
+ }
345
+ return result;
346
+ }
347
+ // Removes the UIDs of messages (ordered by UID) from ascending ranges, walking both lists once
348
+ function subtractUids(ranges, messages) {
349
+ const result = [];
350
+ let i = 0;
351
+ ranges.forEach(([from, to]) => {
352
+ let next = from;
353
+ while (i < messages.length && messages[i].uid < from) {
354
+ i++;
355
+ }
356
+ for (; i < messages.length && messages[i].uid <= to; i++) {
357
+ if (messages[i].uid > next) {
358
+ result.push([next, messages[i].uid - 1]);
359
+ }
360
+ next = messages[i].uid + 1;
361
+ }
362
+ if (next <= to) {
363
+ result.push([next, to]);
364
+ }
365
+ });
366
+ return result;
367
+ }
368
+ /**
369
+ * Orders the ends of every range and merges overlapping or adjacent ranges, so that a UID is listed once
370
+ *
371
+ * @param {Array} ranges List of [from, to] or [number] ranges
372
+ * @return {Array} ascending [low, high] ranges
373
+ */
374
+ function mergeRanges(ranges) {
375
+ const sorted = ranges.map((range) => [Math.min(...range), Math.max(...range)]).sort((a, b) => a[0] - b[0]);
376
+ const result = [];
377
+ sorted.forEach(range => {
378
+ const last = result[result.length - 1];
379
+ if (last && range[0] <= last[1] + 1) {
380
+ last[1] = Math.max(last[1], range[1]);
381
+ }
382
+ else {
383
+ result.push(range);
384
+ }
385
+ });
386
+ return result;
387
+ }
388
+ // Lists the numbers of ascending ranges one by one
389
+ function* iterateRanges(ranges) {
390
+ for (const [from, to] of ranges) {
391
+ for (let i = from; i <= to; i++) {
392
+ yield i;
393
+ }
394
+ }
395
+ }
396
+ /**
397
+ * Checks that a sequence set lists its numbers in ascending order and counts them
398
+ */
399
+ function countAscending(ranges, name) {
400
+ let last = 0;
401
+ let count = 0;
402
+ ranges.forEach(([from, to]) => {
403
+ if (from > to || from <= last) {
404
+ throw new Error('Invalid QRESYNC ' + name + ', numbers must be in ascending order');
405
+ }
406
+ last = to;
407
+ count += to - from + 1;
408
+ });
409
+ return count;
410
+ }
411
+ /**
412
+ * Validates the value of the QRESYNC SELECT/EXAMINE parameter (RFC 7162 section 7):
413
+ * "(" uidvalidity SP mod-sequence-value [SP known-uids] [SP seq-match-data] ")"
414
+ *
415
+ * @param {Array} value Parsed parameter value
416
+ * @return {Object} `{ uidvalidity, modseq, knownUids, seqMatch }`
417
+ */
418
+ function parseQresyncParam(value) {
419
+ if (!Array.isArray(value) || value.length < 2 || value.length > 4) {
420
+ throw new Error('QRESYNC expects (uidvalidity modseq [known-uids] [(known-sequence-set known-uid-set)])');
421
+ }
422
+ const [uidvalidity, modseq] = value;
423
+ // uidvalidity = nz-number
424
+ if (!(0, arguments_js_1.isAtom)(uidvalidity) || !(0, numbers_js_1.isNzNumber)(uidvalidity.value)) {
425
+ throw new Error('Invalid QRESYNC uidvalidity, a non-zero number expected');
426
+ }
427
+ // mod-sequence-value = 1*DIGIT, 1 <= n <= 9,223,372,036,854,775,807
428
+ if (!(0, arguments_js_1.isAtom)(modseq) || !(0, numbers_js_1.isNumber)(modseq.value, numbers_js_1.MAX_NUMBER64) || BigInt(modseq.value) < 1n) {
429
+ throw new Error('Invalid QRESYNC mod-sequence, a positive number expected');
430
+ }
431
+ const result = {
432
+ uidvalidity: Number(uidvalidity.value),
433
+ modseq: Number(modseq.value),
434
+ knownUids: false,
435
+ seqMatch: false
436
+ };
437
+ const rest = value.slice(2);
438
+ if (rest.length && !Array.isArray(rest[0])) {
439
+ result.knownUids = mergeRanges(parseSequenceSet(rest.shift(), 'known-uids'));
440
+ }
441
+ if (rest.length) {
442
+ const seqMatch = rest.shift();
443
+ if (!Array.isArray(seqMatch) || seqMatch.length !== 2 || rest.length) {
444
+ throw new Error('Invalid QRESYNC parameters, (known-sequence-set known-uid-set) expected last');
445
+ }
446
+ // RFC 7162 section 3.2.5.2: both sets MUST be in ascending order, the Nth number of one matches the Nth of the other
447
+ const sequences = parseSequenceSet(seqMatch[0], 'known-sequence-set');
448
+ const uids = parseSequenceSet(seqMatch[1], 'known-uid-set');
449
+ const count = countAscending(sequences, 'known-sequence-set');
450
+ if (countAscending(uids, 'known-uid-set') !== count) {
451
+ throw new Error('Invalid QRESYNC sets, known-sequence-set and known-uid-set must have as many numbers');
452
+ }
453
+ result.seqMatch = { sequences, uids };
454
+ }
455
+ return result;
456
+ }
457
+ function inRanges(ranges, uid) {
458
+ return ranges.some(range => uid >= range[0] && uid <= range[1]);
459
+ }
460
+ // RFC 7162 section 3.2.3: a QRESYNC server implements CONDSTORE and ENABLE, these are loaded first
461
+ qresyncPlugin.requires = ['ENABLE', 'CONDSTORE'];
462
+ {
463
+ const defaultExport = exports.default;
464
+ if (defaultExport && (typeof defaultExport === 'function' || typeof defaultExport === 'object')) {
465
+ for (const key of Object.keys(exports)) {
466
+ if (key !== 'default' && !(key in defaultExport)) {
467
+ defaultExport[key] = exports[key];
468
+ }
469
+ }
470
+ Object.defineProperty(defaultExport, 'default', { value: defaultExport, enumerable: false, writable: true, configurable: true });
471
+ module.exports = defaultExport;
472
+ }
473
+ }
@@ -0,0 +1,18 @@
1
+ import type { IMAPServer } from '../types.js';
2
+ /**
3
+ * @help Adds QUOTA [RFC9208] capability with the STORAGE, MESSAGE and MAILBOX
4
+ * @help resources and SETQUOTA. All personal mailboxes share one quota root, set
5
+ * @help with the "quota" server option, eg. {"root": "User quota",
6
+ * @help "STORAGE": 10240, "MESSAGE": 1000, "MAILBOX": 100, "soft": false}.
7
+ * @help STORAGE is in units of 1024 octets. Hard limits make APPEND, COPY, MOVE
8
+ * @help and CREATE fail with NO [OVERQUOTA], soft limits only send a warning
9
+ *
10
+ * QUOTA: https://www.rfc-editor.org/rfc/rfc9208.txt
11
+ *
12
+ * Additional commands:
13
+ * - GETQUOTA, GETQUOTAROOT, SETQUOTA
14
+ *
15
+ * Additional STATUS items:
16
+ * - DELETED, DELETED-STORAGE
17
+ */
18
+ export default function quotaPlugin(server: IMAPServer): void;