imapkit 4.0.2 → 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 +34 -75
  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,61 @@
1
+ import { states } from '../command-states.js';
2
+ import DeflateLayer from '../deflate-layer.js';
3
+ /**
4
+ * @help Adds COMPRESS=DEFLATE [RFC4978] capability
5
+ * @help Raw DEFLATE in both directions after the tagged OK,
6
+ * @help every burst of responses ends with a sync flush
7
+ */
8
+ export default function compressPlugin(server) {
9
+ server.registerCapability('COMPRESS=DEFLATE');
10
+ const isActive = (connection) => connection.transport instanceof DeflateLayer && connection.transport.active;
11
+ // RFC 8437 section 4.1: after UNAUTHENTICATE the server ends its compression after the CRLF of
12
+ // the OK, and the client after the CRLF of the command, so anything it compressed later is dropped
13
+ server.resetHandlers.push((connection) => {
14
+ if (isActive(connection)) {
15
+ connection.discardInput();
16
+ connection.transport.endInput();
17
+ connection.transport.end();
18
+ }
19
+ });
20
+ server.setCommandHandler('COMPRESS', (connection, parsed, data, callback) => {
21
+ const args = parsed.attributes || [];
22
+ // RFC 4978 section 5: compress = "COMPRESS" SP algorithm, algorithm = "DEFLATE"
23
+ if (args.length !== 1 || !args[0] || args[0].type !== 'ATOM') {
24
+ connection.sendStatus(parsed, data, 'BAD', 'COMPRESS expects a compression mechanism');
25
+ return callback();
26
+ }
27
+ if (args[0].value.toUpperCase() !== 'DEFLATE') {
28
+ connection.sendStatus(parsed, data, 'BAD', 'Unknown compression mechanism');
29
+ return callback();
30
+ }
31
+ // RFC 4978 section 3: BAD if COMPRESS is already active, NO is for compression by another
32
+ // layer, such as TLS, which ImapKit never negotiates. Dovecot answers NO here
33
+ if (isActive(connection)) {
34
+ connection.sendStatus(parsed, data, 'BAD', 'DEFLATE active via COMPRESS', 'COMPRESSIONACTIVE');
35
+ return callback();
36
+ }
37
+ connection.sendStatus(parsed, data, 'OK', 'DEFLATE active');
38
+ if (connection.transport) {
39
+ // the layer of an earlier session, it passes data on as is since UNAUTHENTICATE
40
+ connection.transport.destroy();
41
+ }
42
+ // compression starts right after the CRLF of the tagged OK
43
+ connection.transport = new DeflateLayer({
44
+ // the layer writes only Buffers to the server, strings come from the clients that share it
45
+ writeRaw: (chunk) => connection.writeRaw(chunk),
46
+ onData: (chunk) => connection.onData(chunk),
47
+ onError: (err) => {
48
+ // the input can not be decompressed, so there is nothing left to talk about
49
+ if (connection.options.debug) {
50
+ console.log('COMPRESS error: %s', err.message);
51
+ }
52
+ connection.sendStatus({ tag: '*' }, null, 'BYE', 'Invalid compressed data', false, 'COMPRESS ERROR');
53
+ connection.end();
54
+ }
55
+ });
56
+ return callback();
57
+ },
58
+ // RFC 4978 section 3: the client MUST NOT send further commands until it has seen the result of COMPRESS.
59
+ // Those commands would be uncompressed, and after an OK the server expects compressed input
60
+ { states: states.AUTHENTICATED, noPipelining: true });
61
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @help Adds CONDSTORE [RFC7162] capability
3
+ */
4
+ import type { IMAPServer } from '../types.js';
5
+ export default function condstorePlugin(server: IMAPServer): void;
@@ -1,68 +1,51 @@
1
- 'use strict';
2
-
3
1
  /**
4
2
  * @help Adds CONDSTORE [RFC7162] capability
5
3
  */
6
-
7
- const { macros: FETCH_MACROS } = require('../commands/fetch');
8
- const { badError } = require('../commands/handlers/search');
9
- const { INVALID_KEYWORD_CHAR } = require('../commands/handlers/flags');
10
- const { MAX_NUMBER64, isNumber } = require('../numbers');
11
- const { registerEnable, isEnabled: isExtensionEnabled } = require('./enable');
12
-
13
- module.exports = function (server) {
4
+ import { macros as FETCH_MACROS } from '../commands/fetch.js';
5
+ import { badError } from '../commands/handlers/search.js';
6
+ import { INVALID_KEYWORD_CHAR } from '../commands/handlers/flags.js';
7
+ import { MAX_NUMBER64, isNumber } from '../numbers.js';
8
+ import { registerEnable, isEnabled as isExtensionEnabled } from './enable.js';
9
+ export default function condstorePlugin(server) {
14
10
  // Register capability, always usable
15
11
  server.registerCapability('CONDSTORE');
16
-
17
12
  registerEnable(server, 'CONDSTORE');
18
-
19
13
  // HIGHESTMODSEQ must be a positive number, even for an empty mailbox
20
- const getHighestModseq = mailbox => Math.max(Number(mailbox.HIGHESTMODSEQ) || 0, 1);
21
-
22
- const bumpModseq = mailbox => {
14
+ const getHighestModseq = (mailbox) => Math.max(Number(mailbox.HIGHESTMODSEQ) || 0, 1);
15
+ const bumpModseq = (mailbox) => {
23
16
  mailbox.HIGHESTMODSEQ = getHighestModseq(mailbox) + 1;
24
17
  return mailbox.HIGHESTMODSEQ;
25
18
  };
26
-
27
19
  // RFC 8437 section 4.1: after UNAUTHENTICATE the session behaves as if no CONDSTORE enabling command was issued
28
- server.resetHandlers.push(connection => {
20
+ server.resetHandlers.push((connection) => {
29
21
  connection.condstoreEnabled = false;
30
22
  });
31
-
32
23
  // ENABLE QRESYNC is a CONDSTORE enabling command as well (RFC 7162 section 3.2.3)
33
- const isEnabled = connection => !!connection.condstoreEnabled || isExtensionEnabled(connection, 'CONDSTORE') || isExtensionEnabled(connection, 'QRESYNC');
34
-
24
+ const isEnabled = (connection) => !!connection.condstoreEnabled || isExtensionEnabled(connection, 'CONDSTORE') || isExtensionEnabled(connection, 'QRESYNC');
35
25
  // shared with QRESYNC, which builds on CONDSTORE
36
26
  server.condstore = { isEnabled, getHighestModseq };
37
-
38
27
  const sendHighestModseq = (connection, mailbox, parsed, data) => {
39
- connection.send(
40
- {
41
- tag: '*',
42
- command: 'OK',
43
- attributes: [
44
- {
45
- type: 'SECTION',
46
- section: [
47
- {
48
- type: 'ATOM',
49
- value: 'HIGHESTMODSEQ'
50
- },
51
- getHighestModseq(mailbox)
52
- ]
53
- },
54
- {
55
- type: 'TEXT',
56
- value: 'Highest'
57
- }
58
- ]
59
- },
60
- 'CONDSTORE INFO',
61
- parsed,
62
- data
63
- );
28
+ connection.send({
29
+ tag: '*',
30
+ command: 'OK',
31
+ attributes: [
32
+ {
33
+ type: 'SECTION',
34
+ section: [
35
+ {
36
+ type: 'ATOM',
37
+ value: 'HIGHESTMODSEQ'
38
+ },
39
+ getHighestModseq(mailbox)
40
+ ]
41
+ },
42
+ {
43
+ type: 'TEXT',
44
+ value: 'Highest'
45
+ }
46
+ ]
47
+ }, 'CONDSTORE INFO', parsed, data);
64
48
  };
65
-
66
49
  // Marks the session as CONDSTORE aware. The first CONDSTORE enabling command
67
50
  // issued with a mailbox selected reports HIGHESTMODSEQ for that mailbox
68
51
  const enableCondstore = (connection, parsed, data) => {
@@ -75,7 +58,6 @@ module.exports = function (server) {
75
58
  sendHighestModseq(connection, connection.selectedMailbox, parsed, data);
76
59
  }
77
60
  };
78
-
79
61
  // Set modseq values when a message is created or initialized
80
62
  server.messageHandlers.push((server, message, mailbox) => {
81
63
  const modseq = Number(message.MODSEQ);
@@ -83,24 +65,21 @@ module.exports = function (server) {
83
65
  // keep the value from storage
84
66
  message.MODSEQ = modseq;
85
67
  mailbox.HIGHESTMODSEQ = Math.max(getHighestModseq(mailbox), modseq);
86
- } else {
68
+ }
69
+ else {
87
70
  message.MODSEQ = bumpModseq(mailbox);
88
71
  }
89
72
  });
90
-
91
73
  // Expunging messages (EXPUNGE, UID EXPUNGE, CLOSE, MOVE) changes the mailbox, all messages removed
92
74
  // at once share the incremented mod-sequence (RFC 7162 section 3.2)
93
75
  server.on('expunge', mailbox => {
94
76
  bumpModseq(mailbox);
95
77
  });
96
-
97
78
  // RFC 7162 section 3.2.11: SELECT or EXAMINE closes the selected mailbox, a CONDSTORE server marks
98
79
  // where the responses for the new mailbox start
99
80
  server.closedChecks.push(() => true);
100
-
101
81
  server.allowedStatus.push('HIGHESTMODSEQ');
102
82
  server.statusHandlers.HIGHESTMODSEQ = (connection, mailbox) => getHighestModseq(mailbox);
103
-
104
83
  // Wraps an existing command handler. Commands that are not available are left alone
105
84
  const wrapHandler = (command, wrapper) => {
106
85
  const prevHandler = server.getCommandHandler(command);
@@ -109,17 +88,13 @@ module.exports = function (server) {
109
88
  }
110
89
  server.setCommandHandler(command, (connection, parsed, data, callback) => wrapper(prevHandler, connection, parsed, data, callback));
111
90
  };
112
-
113
91
  const sendBad = (connection, parsed, data, callback, message) => {
114
92
  connection.sendStatus(parsed, data, 'BAD', message, false, 'CONDSTORE FAILED');
115
93
  return callback();
116
94
  };
117
-
118
95
  // RFC 7162 section 7: chgsince-fetch-mod = "CHANGEDSINCE" SP mod-sequence-value (1 or more), store-modifier =/
119
96
  // "UNCHANGEDSINCE" SP mod-sequence-valzer (0 or more). Both are 1*DIGIT, so not a quoted string, up to 63 bits
120
- const isValidModseq = (value, allowZero) =>
121
- !!value && value.type === 'ATOM' && isNumber(value.value, MAX_NUMBER64) && (allowZero || BigInt(value.value) > 0n);
122
-
97
+ const isValidModseq = (value, allowZero) => !!value && value.type === 'ATOM' && isNumber(value.value, MAX_NUMBER64) && (allowZero || BigInt(value.value) > 0n);
123
98
  const selectWrapper = (prevHandler, connection, parsed, data, callback) => {
124
99
  if (hasCondstoreOption(parsed.attributes && parsed.attributes[1], parsed.attributes, 1)) {
125
100
  // SELECT and EXAMINE always report HIGHESTMODSEQ, so no need to send it here
@@ -128,10 +103,8 @@ module.exports = function (server) {
128
103
  }
129
104
  prevHandler(connection, parsed, data, callback);
130
105
  };
131
-
132
106
  wrapHandler('SELECT', selectWrapper);
133
107
  wrapHandler('EXAMINE', selectWrapper);
134
-
135
108
  wrapHandler('STATUS', (prevHandler, connection, parsed, data, callback) => {
136
109
  const items = parsed.attributes && parsed.attributes[1];
137
110
  if (Array.isArray(items) && items.some(item => item && item.type === 'ATOM' && String(item.value).toUpperCase() === 'HIGHESTMODSEQ')) {
@@ -139,13 +112,11 @@ module.exports = function (server) {
139
112
  }
140
113
  prevHandler(connection, parsed, data, callback);
141
114
  });
142
-
143
115
  const fetchWrapper = (prevHandler, connection, parsed, data, callback) => {
144
116
  // RFC 4466 2.4: fetch-modifiers are the last argument, a single fetch-att may take arguments of its own
145
117
  const attributes = parsed.attributes || [];
146
118
  const index = Math.max(attributes.length - 1, 2);
147
119
  const changedsince = getCondstoreValue(attributes[index], 'CHANGEDSINCE', attributes, index);
148
-
149
120
  if (changedsince) {
150
121
  if (!isValidModseq(changedsince)) {
151
122
  return sendBad(connection, parsed, data, callback, 'Invalid syntax for CHANGEDSINCE, number expected');
@@ -154,20 +125,15 @@ module.exports = function (server) {
154
125
  // CHANGEDSINCE implicitly adds the MODSEQ data item
155
126
  addModseqItem(parsed);
156
127
  }
157
-
158
128
  if (changedsince || hasModseqItem(parsed)) {
159
129
  enableCondstore(connection, parsed, data);
160
130
  }
161
-
162
131
  prevHandler(connection, parsed, data, callback);
163
132
  };
164
-
165
133
  wrapHandler('FETCH', fetchWrapper);
166
134
  wrapHandler('UID FETCH', fetchWrapper);
167
-
168
135
  const storeWrapper = (prevHandler, connection, parsed, data, callback) => {
169
136
  const unchangedsince = getCondstoreValue(parsed.attributes && parsed.attributes[1], 'UNCHANGEDSINCE', parsed.attributes, 1);
170
-
171
137
  if (unchangedsince) {
172
138
  if (!isValidModseq(unchangedsince, true)) {
173
139
  return sendBad(connection, parsed, data, callback, 'Invalid syntax for UNCHANGEDSINCE, number expected');
@@ -175,7 +141,6 @@ module.exports = function (server) {
175
141
  parsed.unchangedsince = Number(unchangedsince.value);
176
142
  enableCondstore(connection, parsed, data);
177
143
  }
178
-
179
144
  // Per command state for tracking changed messages
180
145
  parsed.condstoreStore = {
181
146
  isUid: (parsed.command || '').toUpperCase() === 'UID STORE',
@@ -183,32 +148,24 @@ module.exports = function (server) {
183
148
  modified: [],
184
149
  done: false
185
150
  };
186
-
187
151
  prevHandler(connection, parsed, data, callback);
188
152
  };
189
-
190
153
  wrapHandler('STORE', storeWrapper);
191
154
  wrapHandler('UID STORE', storeWrapper);
192
-
193
155
  // RFC 7162 section 3.1.5: MODSEQ [<entry-name> <entry-type-req>] <mod-sequence-valzer>. Mod-sequences
194
156
  // are not stored per flag, so the entry name and type are checked but otherwise ignored
195
157
  const searchModseq = (connection, message, index, ...args) => message.MODSEQ >= args[args.length - 1];
196
- searchModseq.argumentTypes = list =>
197
- typeof list[0] === 'string' && /^\d+$/.test(list[0]) ? [parseModseqValzer] : [parseEntryName, parseEntryType, parseModseqValzer];
158
+ searchModseq.argumentTypes = (list) => typeof list[0] === 'string' && /^\d+$/.test(list[0]) ? [parseModseqValzer] : [parseEntryName, parseEntryType, parseModseqValzer];
198
159
  server.searchHandlers.MODSEQ = searchModseq;
199
-
200
160
  // highest mod-sequence of a list of messages
201
- const highestModseq = messages => messages.reduce((highest, message) => Math.max(highest, message.MODSEQ), 0);
202
-
161
+ const highestModseq = (messages) => messages.reduce((highest, message) => Math.max(highest, message.MODSEQ), 0);
203
162
  server.fetchHandlers.MODSEQ = function (connection, message) {
204
163
  return [message.MODSEQ]; // Must be a list
205
164
  };
206
-
207
165
  server.fetchFilters.push((connection, message, parsed, index) => {
208
166
  if ('changedsince' in parsed && !(parsed.changedsince < message.MODSEQ)) {
209
167
  return false;
210
168
  }
211
-
212
169
  // remember \Seen state, FETCH might set it implicitly
213
170
  if (!parsed.condstoreFetch) {
214
171
  parsed.condstoreFetch = new Map();
@@ -217,51 +174,43 @@ module.exports = function (server) {
217
174
  message,
218
175
  seen: message.flags.indexOf('\\Seen') >= 0
219
176
  });
220
-
221
177
  return true;
222
178
  });
223
-
224
179
  server.storeFilters.push((connection, message, parsed, index) => {
225
180
  const state = parsed.condstoreStore;
226
181
  if (!state) {
227
182
  return true;
228
183
  }
229
-
230
184
  if ('unchangedsince' in parsed && message.MODSEQ > parsed.unchangedsince) {
231
185
  // failed the UNCHANGEDSINCE test, reported with the MODIFIED response code
232
186
  state.modified.push(state.isUid ? message.uid : index);
233
187
  return false;
234
188
  }
235
-
236
189
  state.messages.set(message, {
237
190
  index,
238
191
  before: snapshot(message),
239
192
  bumped: false,
240
193
  reported: false
241
194
  });
242
-
243
195
  return true;
244
196
  });
245
-
246
197
  // Bumps MODSEQ if the message metadata was changed by the current STORE
247
198
  const checkStored = (connection, message, entry) => {
248
199
  if (!entry.bumped && snapshot(message) !== entry.before) {
249
200
  entry.bumped = true;
201
+ // STORE runs in the Selected state
250
202
  message.MODSEQ = bumpModseq(connection.selectedMailbox);
251
203
  }
252
204
  };
253
-
254
205
  server.outputHandlers.push((connection, response, description, parsed, data, extra) => {
255
206
  // Flag changes made by another session (RFC 7162 section 3.1), these are not responses to a command
256
207
  if (description === 'FLAG NOTIFICATION' && response && extra && isEnabled(connection)) {
257
208
  setModseqValue(response.attributes[2], extra.MODSEQ);
258
209
  return;
259
210
  }
260
-
261
211
  if (!parsed || !response) {
262
212
  return;
263
213
  }
264
-
265
214
  // Untagged FETCH responses caused by STORE
266
215
  if (description === 'FLAG UPDATE' && parsed.condstoreStore && extra && parsed.condstoreStore.messages.has(extra)) {
267
216
  const entry = parsed.condstoreStore.messages.get(extra);
@@ -273,10 +222,10 @@ module.exports = function (server) {
273
222
  }
274
223
  return;
275
224
  }
276
-
277
225
  // SEARCH, ESEARCH, SORT or THREAD with the MODSEQ search key, a CONDSTORE enabling command (RFC 7162 section 3.1).
278
226
  // `extra.list` holds the messages the response is about
279
- const isSearch = ['SEARCH', 'SORT', 'THREAD'].includes(response.command) && [response.command, 'UID ' + response.command].includes(description);
227
+ const isSearch = ['SEARCH', 'SORT', 'THREAD'].includes(response.command) &&
228
+ [response.command, 'UID ' + response.command].includes(description);
280
229
  if ((isSearch || description === 'ESEARCH') && response.tag === '*' && extra && extra.keys && extra.keys.has('MODSEQ')) {
281
230
  enableCondstore(connection, parsed, data);
282
231
  // RFC 7162 section 3.1.9: THREAD responses are unchanged
@@ -288,16 +237,13 @@ module.exports = function (server) {
288
237
  }
289
238
  return;
290
239
  }
291
-
292
240
  // Untagged FETCH responses of FETCH, check for implicitly set \Seen
293
- if (
294
- response.tag === '*' &&
241
+ if (response.tag === '*' &&
295
242
  parsed.condstoreFetch &&
296
243
  response.attributes &&
297
244
  response.attributes[1] &&
298
245
  response.attributes[1].value === 'FETCH' &&
299
- parsed.condstoreFetch.has(response.attributes[0])
300
- ) {
246
+ parsed.condstoreFetch.has(response.attributes[0])) {
301
247
  const entry = parsed.condstoreFetch.get(response.attributes[0]);
302
248
  const message = entry.message;
303
249
  let changed = false;
@@ -316,12 +262,10 @@ module.exports = function (server) {
316
262
  }
317
263
  return;
318
264
  }
319
-
320
265
  // Tagged response of STORE
321
266
  if (response.tag === parsed.tag && parsed.condstoreStore && !parsed.condstoreStore.done) {
322
267
  const state = parsed.condstoreStore;
323
268
  state.done = true;
324
-
325
269
  state.messages.forEach((entry, message) => {
326
270
  checkStored(connection, message, entry);
327
271
  // .SILENT stores send no FETCH responses, CONDSTORE aware clients still need the new MODSEQ values
@@ -335,26 +279,19 @@ module.exports = function (server) {
335
279
  ];
336
280
  // RFC 7162 section 3.1: UID and MODSEQ in every untagged FETCH caused by STORE
337
281
  attributes.unshift({ type: 'ATOM', value: 'UID' }, message.uid);
338
- connection.send(
339
- {
340
- tag: '*',
341
- attributes: [
342
- entry.index,
343
- {
344
- type: 'ATOM',
345
- value: 'FETCH'
346
- },
347
- attributes
348
- ]
349
- },
350
- 'CONDSTORE MODSEQ UPDATE',
351
- parsed,
352
- data,
353
- message
354
- );
282
+ connection.send({
283
+ tag: '*',
284
+ attributes: [
285
+ entry.index,
286
+ {
287
+ type: 'ATOM',
288
+ value: 'FETCH'
289
+ },
290
+ attributes
291
+ ]
292
+ }, 'CONDSTORE MODSEQ UPDATE', parsed, data, message);
355
293
  }
356
294
  });
357
-
358
295
  // RFC 7162 section 3.1.3 example 11: MODIFIED can also go with the tagged NO of a STORE on expunged messages
359
296
  // (RFC 2180 section 4.2.3), it replaces EXPUNGEISSUED there since a response has only one response code
360
297
  if ((response.command === 'OK' || response.command === 'NO') && state.modified.length) {
@@ -372,11 +309,10 @@ module.exports = function (server) {
372
309
  }
373
310
  ]
374
311
  }
375
- ].concat((response.attributes || []).filter(attr => response.command === 'OK' || !attr || attr.type !== 'SECTION'));
312
+ ].concat((response.attributes || []).filter((attr) => response.command === 'OK' || !attr || attr.type !== 'SECTION'));
376
313
  }
377
314
  return;
378
315
  }
379
-
380
316
  if (description === 'ENABLED' && Array.isArray(extra) && extra.indexOf('CONDSTORE') >= 0) {
381
317
  // ENABLE CONDSTORE was issued
382
318
  if (!connection.condstoreEnabled) {
@@ -387,13 +323,11 @@ module.exports = function (server) {
387
323
  }
388
324
  return;
389
325
  }
390
-
391
326
  if (description === 'ENABLE' && parsed.condstoreReportHighest && connection.selectedMailbox) {
392
327
  parsed.condstoreReportHighest = false;
393
328
  sendHighestModseq(connection, connection.selectedMailbox, parsed, data);
394
329
  return;
395
330
  }
396
-
397
331
  // Add CONDSTORE info to SELECT and EXAMINE
398
332
  if ((description === 'EXAMINE' || description === 'SELECT') && response.tag === parsed.tag && connection.selectedMailbox) {
399
333
  // (CONDSTORE) option was used, show notice
@@ -404,17 +338,16 @@ module.exports = function (server) {
404
338
  type: 'TEXT',
405
339
  value: 'CONDSTORE is now enabled'
406
340
  });
407
- } else {
341
+ }
342
+ else {
408
343
  last.value += ', CONDSTORE is now enabled';
409
344
  }
410
345
  }
411
-
412
346
  // Send untagged info about highest modseq
413
347
  sendHighestModseq(connection, connection.selectedMailbox, parsed, data);
414
348
  }
415
349
  });
416
- };
417
-
350
+ }
418
351
  // RFC 7162 section 7: mod-sequence-valzer = "0" / mod-sequence-value. Dovecot also accepts values above 63 bits
419
352
  function parseModseqValzer(value) {
420
353
  if (!isNumber(value, MAX_NUMBER64)) {
@@ -422,7 +355,6 @@ function parseModseqValzer(value) {
422
355
  }
423
356
  return Number(value);
424
357
  }
425
-
426
358
  // RFC 7162 section 7: entry-flag-name = DQUOTE "/flags/" attr-flag DQUOTE, attr-flag is a flag without "\Recent"
427
359
  function parseEntryName(value) {
428
360
  const match = value.match(/^\/flags\/(\\?)(.+)$/i);
@@ -431,7 +363,6 @@ function parseEntryName(value) {
431
363
  }
432
364
  return value;
433
365
  }
434
-
435
366
  // RFC 7162 section 7: entry-type-req = "priv" / "shared" / "all"
436
367
  function parseEntryType(value) {
437
368
  if (!['PRIV', 'SHARED', 'ALL'].includes(value.toUpperCase())) {
@@ -439,12 +370,10 @@ function parseEntryType(value) {
439
370
  }
440
371
  return value;
441
372
  }
442
-
443
373
  // Serialized message metadata, used to detect changes
444
374
  function snapshot(message) {
445
375
  return JSON.stringify([message.flags || [], message['X-GM-LABELS'] || []]);
446
376
  }
447
-
448
377
  function findItem(list, name) {
449
378
  if (!Array.isArray(list)) {
450
379
  return -1;
@@ -456,7 +385,6 @@ function findItem(list, name) {
456
385
  }
457
386
  return -1;
458
387
  }
459
-
460
388
  // Sets or adds the MODSEQ value in a FETCH response attribute list
461
389
  function setModseqValue(list, modseq) {
462
390
  if (!Array.isArray(list)) {
@@ -465,39 +393,30 @@ function setModseqValue(list, modseq) {
465
393
  const pos = findItem(list, 'MODSEQ');
466
394
  if (pos >= 0) {
467
395
  list[pos + 1] = [modseq];
468
- } else {
469
- list.push(
470
- {
471
- type: 'ATOM',
472
- value: 'MODSEQ'
473
- },
474
- [modseq]
475
- );
396
+ }
397
+ else {
398
+ list.push({
399
+ type: 'ATOM',
400
+ value: 'MODSEQ'
401
+ }, [modseq]);
476
402
  }
477
403
  }
478
-
479
404
  // Adds the UID to a FETCH response attribute list unless it is there already
480
405
  function setUidValue(list, uid) {
481
406
  if (Array.isArray(list) && findItem(list, 'UID') < 0) {
482
- list.push(
483
- {
484
- type: 'ATOM',
485
- value: 'UID'
486
- },
487
- uid
488
- );
407
+ list.push({
408
+ type: 'ATOM',
409
+ value: 'UID'
410
+ }, uid);
489
411
  }
490
412
  }
491
-
492
413
  function isModseqAtom(item) {
493
414
  return !!item && item.type === 'ATOM' && String(item.value).toUpperCase() === 'MODSEQ';
494
415
  }
495
-
496
416
  function hasModseqItem(parsed) {
497
417
  const items = parsed.attributes && parsed.attributes[1];
498
418
  return Array.isArray(items) ? items.some(isModseqAtom) : isModseqAtom(items);
499
419
  }
500
-
501
420
  // Adds MODSEQ to the list of FETCH data items, unless it is already there
502
421
  function addModseqItem(parsed) {
503
422
  if (!parsed.attributes || !parsed.attributes[1] || hasModseqItem(parsed)) {
@@ -508,14 +427,13 @@ function addModseqItem(parsed) {
508
427
  const name = String(items.value).toUpperCase();
509
428
  const macro = items.type === 'ATOM' && Object.hasOwn(FETCH_MACROS, name) && FETCH_MACROS[name];
510
429
  // a single fetch-att keeps the arguments that follow it, eg. RFC 8970 PREVIEW (LAZY)
511
- items = macro ? macro.map(value => ({ type: 'ATOM', value })) : [items].concat(parsed.attributes.splice(2));
430
+ items = macro ? macro.map((value) => ({ type: 'ATOM', value })) : [items].concat(parsed.attributes.splice(2));
512
431
  }
513
432
  parsed.attributes[1] = items.concat({
514
433
  type: 'ATOM',
515
434
  value: 'MODSEQ'
516
435
  });
517
436
  }
518
-
519
437
  function hasCondstoreOption(attributes, parent, index) {
520
438
  if (!attributes) {
521
439
  return false;
@@ -529,7 +447,6 @@ function hasCondstoreOption(attributes, parent, index) {
529
447
  break;
530
448
  }
531
449
  }
532
-
533
450
  // remove parameter if no other memebers were left
534
451
  if (!attributes.length) {
535
452
  parent.splice(index, 1);
@@ -537,7 +454,6 @@ function hasCondstoreOption(attributes, parent, index) {
537
454
  }
538
455
  return !!condstoreOption;
539
456
  }
540
-
541
457
  function getCondstoreValue(attributes, name, parent, index) {
542
458
  if (!attributes) {
543
459
  return false;
@@ -552,12 +468,10 @@ function getCondstoreValue(attributes, name, parent, index) {
552
468
  break;
553
469
  }
554
470
  }
555
-
556
471
  // remove parameter if no other memebers were left
557
472
  if (!attributes.length) {
558
473
  parent.splice(index, 1);
559
474
  }
560
475
  }
561
-
562
476
  return condstoreValue;
563
477
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @help Adds CONTEXT=SEARCH [RFC5267] capability, loads ESEARCH as well
3
+ * @help SEARCH RETURN (UPDATE) sends ADDTO and REMOVEFROM updates as the result changes, until CANCELUPDATE or the mailbox is closed
4
+ * @help SEARCH RETURN (PARTIAL 1:100) returns a window of the results, the CONTEXT hint is accepted and ignored
5
+ * @help Server option "maxSearchContexts" (default 10) limits the updating contexts of a session, above it NOUPDATE is sent
6
+ */
7
+ import type { IMAPServer } from '../types.js';
8
+ export default function contextSearchPlugin(server: IMAPServer): void;