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
@@ -1,13 +1,10 @@
1
- 'use strict';
2
-
3
- const { states } = require('../command-states');
4
- const { normalizeSystemFlag, checkSystemFlags } = require('../commands/handlers/flags');
5
- const builtinStoreHandlers = require('../commands/handlers/store');
6
- const { getListExtensions } = require('../list-extensions');
7
- const { beginSelect } = require('../commands/select');
8
- const { getPendingTarget } = require('../commands/append');
9
- const { isAstring } = require('../arguments');
10
-
1
+ import { states } from '../command-states.js';
2
+ import { normalizeSystemFlag, checkSystemFlags } from '../commands/handlers/flags.js';
3
+ import builtinStoreHandlers from '../commands/handlers/store.js';
4
+ import { getListExtensions } from '../list-extensions.js';
5
+ import { beginSelect } from '../commands/select.js';
6
+ import { getPendingTarget } from '../commands/append.js';
7
+ import { isAstring } from '../arguments.js';
11
8
  /**
12
9
  * @help Adds ACL [RFC4314] capability with RIGHTS=texk
13
10
  * @help The owner (server option "aclOwner", default "testuser")
@@ -26,7 +23,6 @@ const { isAstring } = require('../arguments');
26
23
  *
27
24
  * Users other than the owner can only do what their rights allow (RFC 4314 section 4).
28
25
  */
29
-
30
26
  // RFC 4314 section 2.1, in the order they are listed in responses
31
27
  const RIGHTS = 'lrswipkxtea';
32
28
  const ALL_RIGHTS = new Set(RIGHTS);
@@ -41,7 +37,6 @@ const FLAG_RIGHTS = ['s', 'w', 't'];
41
37
  // RFC 4314 section 4: MYRIGHTS needs any of these
42
38
  const ANY_RIGHTS = ['l', 'r', 'i', 'k', 'x', 'a'];
43
39
  const STORE_ITEMS = ['FLAGS', '+FLAGS', '-FLAGS', 'FLAGS.SILENT', '+FLAGS.SILENT', '-FLAGS.SILENT'];
44
-
45
40
  /**
46
41
  * Formats an astring for a response. The compiler sends an ATOM value that is not a valid atom as a
47
42
  * quoted string or a literal, only a leading "\\" (allowed for flags) and NIL have to be kept away from it
@@ -55,7 +50,6 @@ function astring(value) {
55
50
  // an atom NIL would read back as NIL, not as an identifier
56
51
  return value && value.charAt(0) !== '\\' && !/^NIL$/i.test(value) ? { type: 'ATOM', value } : value;
57
52
  }
58
-
59
53
  /**
60
54
  * Creates an error that is answered with BAD
61
55
  *
@@ -67,7 +61,6 @@ function badInput(message) {
67
61
  err.imapResponse = 'BAD';
68
62
  return err;
69
63
  }
70
-
71
64
  /**
72
65
  * Parses a rights string, the virtual "c" and "d" rights are expanded (RFC 4314 section 2.1.1)
73
66
  *
@@ -80,17 +73,19 @@ function parseRights(value) {
80
73
  for (const chr of value) {
81
74
  if (ALL_RIGHTS.has(chr)) {
82
75
  rights.add(chr);
83
- } else if (Object.hasOwn(VIRTUAL_RIGHTS, chr)) {
84
- VIRTUAL_RIGHTS[chr].split('').forEach(right => rights.add(right));
85
- } else if (/^[A-Z]$/.test(chr)) {
76
+ }
77
+ else if (Object.hasOwn(VIRTUAL_RIGHTS, chr)) {
78
+ VIRTUAL_RIGHTS[chr].split('').forEach((right) => rights.add(right));
79
+ }
80
+ else if (/^[A-Z]$/.test(chr)) {
86
81
  throw badInput('Uppercase rights are not allowed');
87
- } else {
82
+ }
83
+ else {
88
84
  throw badInput('The ' + (/^[\x21-\x7e]$/.test(chr) ? chr + ' ' : '') + 'right is not supported');
89
85
  }
90
86
  }
91
87
  return rights;
92
88
  }
93
-
94
89
  /**
95
90
  * Builds the attributes of an ACL, LISTRIGHTS or MYRIGHTS response. The mailbox name is a MAILBOX
96
91
  * attribute, so each session gets it in the form it uses (modified UTF-7, or UTF-8 after ENABLE
@@ -101,9 +96,8 @@ function parseRights(value) {
101
96
  * @return {Array} Response attributes
102
97
  */
103
98
  function mailboxResponse(mailbox, values) {
104
- return [{ type: 'MAILBOX', value: mailbox.path }].concat(values.map(astring));
99
+ return [{ type: 'MAILBOX', value: mailbox.path }].concat(values.map(value => astring(value)));
105
100
  }
106
-
107
101
  /**
108
102
  * Formats rights for ACL and MYRIGHTS responses. "c" and "d" are added when any of their
109
103
  * member rights is set (RFC 4314 section 2.1.1)
@@ -116,13 +110,12 @@ function formatRights(rights) {
116
110
  .filter(right => rights.has(right))
117
111
  .join('');
118
112
  Object.keys(VIRTUAL_RIGHTS).forEach(virtual => {
119
- if (VIRTUAL_RIGHTS[virtual].split('').some(right => rights.has(right))) {
113
+ if (VIRTUAL_RIGHTS[virtual].split('').some((right) => rights.has(right))) {
120
114
  result += virtual;
121
115
  }
122
116
  });
123
117
  return result;
124
118
  }
125
-
126
119
  /**
127
120
  * Checks an identifier argument. RFC 4314 section 3 asks for SASLprep, which is not implemented,
128
121
  * but an identifier that SASLprep would refuse (control characters, invalid UTF-8) or that is
@@ -145,16 +138,12 @@ function identifierError(identifier) {
145
138
  }
146
139
  return false;
147
140
  }
148
-
149
- module.exports = function (server) {
141
+ export default function aclPlugin(server) {
150
142
  server.registerCapability('ACL');
151
143
  // RFC 4314 section 5.1.1: the rights not defined in RFC 2086, MUST include "t", "e", "x" and "k"
152
144
  server.registerCapability('RIGHTS=texk');
153
-
154
145
  const owner = typeof server.options.aclOwner === 'string' ? server.options.aclOwner : 'testuser';
155
-
156
- const isOwner = connection => connection.username === owner;
157
-
146
+ const isOwner = (connection) => connection.username === owner;
158
147
  /**
159
148
  * Returns the ACL of a mailbox as a Map of identifier to a Set of rights. The ACL from the
160
149
  * storage (an object of identifier to rights string) is converted on first use
@@ -162,14 +151,15 @@ module.exports = function (server) {
162
151
  * @param {Object} mailbox Mailbox object
163
152
  * @return {Map}
164
153
  */
165
- const getAcl = mailbox => {
154
+ const getAcl = (mailbox) => {
166
155
  if (!(mailbox.acl instanceof Map)) {
167
156
  const acl = new Map();
168
157
  const source = mailbox.acl && typeof mailbox.acl === 'object' ? mailbox.acl : {};
169
158
  Object.keys(source).forEach(identifier => {
170
159
  try {
171
160
  acl.set(identifier, parseRights(String(source[identifier])));
172
- } catch (err) {
161
+ }
162
+ catch (err) {
173
163
  // not a client error, so this is answered with NO [SERVERBUG]
174
164
  throw new Error('Invalid ACL in storage for ' + mailbox.path + ': ' + err.message, { cause: err });
175
165
  }
@@ -178,7 +168,6 @@ module.exports = function (server) {
178
168
  }
179
169
  return mailbox.acl;
180
170
  };
181
-
182
171
  /**
183
172
  * Returns the rights a user has on a mailbox. The owner has all rights, other users get the
184
173
  * union of the rights of their own identifier and "anyone", minus the negative rights of
@@ -197,14 +186,12 @@ module.exports = function (server) {
197
186
  acl = acl || getAcl(mailbox);
198
187
  const identifiers = ['anyone'].concat(typeof username === 'string' && username ? username : []);
199
188
  const rights = new Set();
200
- identifiers.forEach(identifier => (acl.get(identifier) || []).forEach(right => rights.add(right)));
201
- identifiers.forEach(identifier => (acl.get('-' + identifier) || []).forEach(right => rights.delete(right)));
189
+ identifiers.forEach(identifier => (acl.get(identifier) || []).forEach((right) => rights.add(right)));
190
+ identifiers.forEach(identifier => (acl.get('-' + identifier) || []).forEach((right) => rights.delete(right)));
202
191
  return rights;
203
192
  };
204
-
205
193
  // for plugins that report only what a user may see (e.g. NOTIFY)
206
194
  server.acl = { getRights, isOwner };
207
-
208
195
  // Tells plugins that the ACL of a mailbox changed, with an `acl` event `(mailbox, previousAcl)`
209
196
  const changeAcl = (mailbox, change) => {
210
197
  const acl = getAcl(mailbox);
@@ -212,7 +199,6 @@ module.exports = function (server) {
212
199
  change(acl);
213
200
  server.emit('acl', mailbox, previous);
214
201
  };
215
-
216
202
  // CATENATE (RFC 4469 section 5): reading a message through an IMAP URL needs the "r" right, a
217
203
  // mailbox without "l" is reported like one that does not exist (RFC 4314 section 6)
218
204
  server.urlAccessChecks.push((connection, mailbox) => {
@@ -222,20 +208,17 @@ module.exports = function (server) {
222
208
  }
223
209
  return false;
224
210
  });
225
-
226
211
  // MULTISEARCH (RFC 7377 section 2.2): searching needs "r", and "l" for a mailbox that the client did not name.
227
212
  // Other mailboxes are left out without an error
228
213
  server.searchAccessChecks.push((connection, mailbox, named) => {
229
214
  const rights = getRights(connection, mailbox);
230
215
  return rights.has('r') && (named || rights.has('l'));
231
216
  });
232
-
233
217
  // Rights on the selected mailbox are taken when it is selected (RFC 4314 section 5.1.1 allows caching
234
218
  // them), so the FLAGS and PERMANENTFLAGS a session got stay correct until the next SELECT
235
- const getSelectedRights = connection => connection.aclRights || ALL_RIGHTS;
236
-
219
+ const getSelectedRights = (connection) => connection.aclRights || ALL_RIGHTS;
237
220
  // RFC 4314 section 4: "t" for \Deleted, "s" for \Seen and "w" for all other flags
238
- const flagRight = flag => {
221
+ const flagRight = (flag) => {
239
222
  flag = normalizeSystemFlag(flag);
240
223
  if (flag === '\\Deleted') {
241
224
  return 't';
@@ -245,24 +228,19 @@ module.exports = function (server) {
245
228
  }
246
229
  return 'w';
247
230
  };
248
-
249
- const flagValue = flag => (typeof flag === 'string' ? flag : String((flag && flag.value) || ''));
250
-
231
+ // flags are strings or parsed atoms
232
+ const flagValue = (flag) => (typeof flag === 'string' ? flag : String((flag && flag.value) || ''));
251
233
  const canSetFlag = (rights, flag) => rights.has(flagRight(flagValue(flag)));
252
-
253
234
  const mailboxArgument = (parsed, position) => {
254
235
  const attr = (parsed.attributes || [])[position];
255
236
  return isAstring(attr) ? attr.value : false;
256
237
  };
257
-
258
238
  // the mailbox named by an argument, false if there is no such mailbox or the argument is invalid
259
239
  const argumentMailbox = (parsed, position) => {
260
240
  const name = mailboxArgument(parsed, position);
261
241
  return (name !== false && server.getMailbox(name)) || false;
262
242
  };
263
-
264
243
  const sendNoPerm = (connection, parsed, data, description) => connection.sendStatus(parsed, data, 'NO', 'Permission denied', 'NOPERM', description);
265
-
266
244
  /**
267
245
  * Refuses a command for lack of rights. Without the "l" right the user gets the same error
268
246
  * as for a mailbox that does not exist, so the existence of the mailbox is not disclosed
@@ -271,20 +249,21 @@ module.exports = function (server) {
271
249
  const sendDenied = (connection, parsed, data, rights, description, notFound) => {
272
250
  if (rights.has('l')) {
273
251
  sendNoPerm(connection, parsed, data, description);
274
- } else if (notFound === 'TRYCREATE') {
252
+ }
253
+ else if (notFound === 'TRYCREATE') {
275
254
  connection.sendStatus(parsed, data, 'NO', 'Target mailbox does not exist', 'TRYCREATE', description);
276
- } else {
255
+ }
256
+ else {
277
257
  connection.sendStatus(parsed, data, 'NO', 'Mailbox does not exist', 'NONEXISTENT', description);
278
258
  }
279
259
  };
280
-
281
260
  /**
282
261
  * Finds the nearest existing parent of a mailbox name (RFC 4314 section 4, CREATE)
283
262
  *
284
263
  * @param {String} path Mailbox path
285
264
  * @return {Object|Boolean} parent mailbox or false if there is none
286
265
  */
287
- const getParent = path => {
266
+ const getParent = (path) => {
288
267
  for (let parent = server.getParentPath(path); parent; parent = server.getParentPath(parent)) {
289
268
  const mailbox = server.getMailbox(parent);
290
269
  if (mailbox) {
@@ -293,7 +272,6 @@ module.exports = function (server) {
293
272
  }
294
273
  return false;
295
274
  };
296
-
297
275
  // Checks for the ACL commands, true if the command can go ahead
298
276
  const checkAclCommand = (connection, parsed, data, mailbox, isAllowed) => {
299
277
  if (!mailbox) {
@@ -302,14 +280,12 @@ module.exports = function (server) {
302
280
  }
303
281
  const rights = getRights(connection, mailbox);
304
282
  if (!isAllowed(rights)) {
305
- sendDenied(connection, parsed, data, rights, false);
283
+ sendDenied(connection, parsed, data, rights);
306
284
  return false;
307
285
  }
308
286
  return true;
309
287
  };
310
-
311
- const hasAdmin = rights => rights.has('a');
312
-
288
+ const hasAdmin = (rights) => rights.has('a');
313
289
  /**
314
290
  * Validates the arguments of an ACL command: `count` astrings, the first one a mailbox name and
315
291
  * the second one (if any) an identifier
@@ -335,7 +311,6 @@ module.exports = function (server) {
335
311
  }
336
312
  return true;
337
313
  };
338
-
339
314
  // RFC 4314 section 2: an implementation MAY force rights to always be granted to an identifier
340
315
  const refuseOwnerIdentifier = (connection, parsed, data) => {
341
316
  const identifier = parsed.attributes[1].value;
@@ -345,28 +320,17 @@ module.exports = function (server) {
345
320
  connection.sendStatus(parsed, data, 'NO', 'Rights of the mailbox owner can not be changed', 'CANNOT');
346
321
  return true;
347
322
  };
348
-
349
323
  const aclCommand = (count, handler) => (connection, parsed, data, callback) => {
350
324
  if (checkArguments(connection, parsed, data, count)) {
351
325
  handler(connection, parsed, data, server.getMailbox(parsed.attributes[0].value));
352
326
  }
353
327
  callback();
354
328
  };
355
-
356
329
  const aclOptions = { states: states.AUTHENTICATED, mailboxArguments: [0] };
357
330
  // RFC 4314 section 7: identifier and mod-rights are astrings
358
331
  const identifierOptions = Object.assign({ astringArguments: [1] }, aclOptions);
359
-
360
332
  // RFC 4314 section 3.8: myrights-data = "MYRIGHTS" SP mailbox SP rights
361
- const sendMyRights = (connection, mailbox, parsed, data) =>
362
- connection.send(
363
- { tag: '*', command: 'MYRIGHTS', attributes: mailboxResponse(mailbox, [formatRights(getRights(connection, mailbox))]) },
364
- 'MYRIGHTS',
365
- parsed,
366
- data,
367
- mailbox
368
- );
369
-
333
+ const sendMyRights = (connection, mailbox, parsed, data) => connection.send({ tag: '*', command: 'MYRIGHTS', attributes: mailboxResponse(mailbox, [formatRights(getRights(connection, mailbox))]) }, 'MYRIGHTS', parsed, data, mailbox);
370
334
  // RFC 8440 section 3: the MYRIGHTS return option of an extended LIST. The registry is shared with
371
335
  // LIST-EXTENDED, which accepts the option only when it is loaded, in any load order
372
336
  const listExtensions = getListExtensions(server);
@@ -380,107 +344,81 @@ module.exports = function (server) {
380
344
  }
381
345
  }
382
346
  };
383
-
384
347
  // RFC 4314 section 3.1
385
- server.setCommandHandler(
386
- 'SETACL',
387
- aclCommand(3, (connection, parsed, data, mailbox) => {
388
- const identifier = parsed.attributes[1].value;
389
- const modification = parsed.attributes[2].value;
390
- const mode = /^[+-]/.test(modification) ? modification.charAt(0) : '';
391
-
392
- // an unrecognized right MUST cause BAD, before anything else is checked
393
- const rights = parseRights(modification.substr(mode.length));
394
-
395
- if (!checkAclCommand(connection, parsed, data, mailbox, hasAdmin) || refuseOwnerIdentifier(connection, parsed, data)) {
396
- return;
397
- }
398
-
399
- changeAcl(mailbox, acl => {
400
- const current = new Set(acl.get(identifier) || []);
401
- if (mode === '+') {
402
- rights.forEach(right => current.add(right));
403
- } else if (mode === '-') {
404
- rights.forEach(right => current.delete(right));
405
- }
406
- const updated = mode ? current : rights;
407
- if (updated.size) {
408
- acl.set(identifier, updated);
409
- } else {
410
- acl.delete(identifier);
411
- }
412
- });
413
- connection.sendStatus(parsed, data, 'OK', 'Setacl complete');
414
- }),
415
- Object.assign({ astringArguments: [1, 2] }, aclOptions)
416
- );
417
-
418
- // RFC 4314 section 3.2
419
- server.setCommandHandler(
420
- 'DELETEACL',
421
- aclCommand(2, (connection, parsed, data, mailbox) => {
422
- if (!checkAclCommand(connection, parsed, data, mailbox, hasAdmin) || refuseOwnerIdentifier(connection, parsed, data)) {
423
- return;
348
+ server.setCommandHandler('SETACL', aclCommand(3, (connection, parsed, data, mailbox) => {
349
+ const identifier = parsed.attributes[1].value;
350
+ const modification = parsed.attributes[2].value;
351
+ const mode = /^[+-]/.test(modification) ? modification.charAt(0) : '';
352
+ // an unrecognized right MUST cause BAD, before anything else is checked
353
+ const rights = parseRights(modification.substr(mode.length));
354
+ if (!checkAclCommand(connection, parsed, data, mailbox, hasAdmin) || refuseOwnerIdentifier(connection, parsed, data)) {
355
+ return;
356
+ }
357
+ changeAcl(mailbox, acl => {
358
+ const current = new Set(acl.get(identifier) || []);
359
+ if (mode === '+') {
360
+ rights.forEach(right => current.add(right));
424
361
  }
425
- changeAcl(mailbox, acl => acl.delete(parsed.attributes[1].value));
426
- connection.sendStatus(parsed, data, 'OK', 'Deleteacl complete');
427
- }),
428
- identifierOptions
429
- );
430
-
431
- // RFC 4314 sections 3.3 and 3.6
432
- server.setCommandHandler(
433
- 'GETACL',
434
- aclCommand(1, (connection, parsed, data, mailbox) => {
435
- if (!checkAclCommand(connection, parsed, data, mailbox, hasAdmin)) {
436
- return;
362
+ else if (mode === '-') {
363
+ rights.forEach(right => current.delete(right));
437
364
  }
438
- const attributes = [owner, formatRights(ALL_RIGHTS)];
439
- getAcl(mailbox).forEach((rights, identifier) => {
440
- attributes.push(identifier, formatRights(rights));
441
- });
442
- connection.send({ tag: '*', command: 'ACL', attributes: mailboxResponse(mailbox, attributes) }, 'ACL', parsed, data, mailbox);
443
- connection.sendStatus(parsed, data, 'OK', 'Getacl complete');
444
- }),
445
- aclOptions
446
- );
447
-
448
- // RFC 4314 sections 3.4 and 3.7
449
- server.setCommandHandler(
450
- 'LISTRIGHTS',
451
- aclCommand(2, (connection, parsed, data, mailbox) => {
452
- if (!checkAclCommand(connection, parsed, data, mailbox, hasAdmin)) {
453
- return;
365
+ const updated = mode ? current : rights;
366
+ if (updated.size) {
367
+ acl.set(identifier, updated);
454
368
  }
455
- // the identifier is sent back in the same form as the client used
456
- const identifier = parsed.attributes[1].value;
457
- let attributes;
458
- if (identifier === owner) {
459
- // the owner always has every right, nothing is optional
460
- attributes = [identifier, formatRights(ALL_RIGHTS)];
461
- } else {
462
- // nothing is granted always, every right can be granted on its own, including the virtual ones
463
- attributes = [identifier, ''].concat(RIGHTS.split(''), Object.keys(VIRTUAL_RIGHTS));
369
+ else {
370
+ acl.delete(identifier);
464
371
  }
465
- connection.send({ tag: '*', command: 'LISTRIGHTS', attributes: mailboxResponse(mailbox, attributes) }, 'LISTRIGHTS', parsed, data, mailbox);
466
- connection.sendStatus(parsed, data, 'OK', 'Listrights complete');
467
- }),
468
- identifierOptions
469
- );
470
-
372
+ });
373
+ connection.sendStatus(parsed, data, 'OK', 'Setacl complete');
374
+ }), Object.assign({ astringArguments: [1, 2] }, aclOptions));
375
+ // RFC 4314 section 3.2
376
+ server.setCommandHandler('DELETEACL', aclCommand(2, (connection, parsed, data, mailbox) => {
377
+ if (!checkAclCommand(connection, parsed, data, mailbox, hasAdmin) || refuseOwnerIdentifier(connection, parsed, data)) {
378
+ return;
379
+ }
380
+ changeAcl(mailbox, acl => acl.delete(parsed.attributes[1].value));
381
+ connection.sendStatus(parsed, data, 'OK', 'Deleteacl complete');
382
+ }), identifierOptions);
383
+ // RFC 4314 sections 3.3 and 3.6
384
+ server.setCommandHandler('GETACL', aclCommand(1, (connection, parsed, data, mailbox) => {
385
+ if (!checkAclCommand(connection, parsed, data, mailbox, hasAdmin)) {
386
+ return;
387
+ }
388
+ const attributes = [owner, formatRights(ALL_RIGHTS)];
389
+ getAcl(mailbox).forEach((rights, identifier) => {
390
+ attributes.push(identifier, formatRights(rights));
391
+ });
392
+ connection.send({ tag: '*', command: 'ACL', attributes: mailboxResponse(mailbox, attributes) }, 'ACL', parsed, data, mailbox);
393
+ connection.sendStatus(parsed, data, 'OK', 'Getacl complete');
394
+ }), aclOptions);
395
+ // RFC 4314 sections 3.4 and 3.7
396
+ server.setCommandHandler('LISTRIGHTS', aclCommand(2, (connection, parsed, data, mailbox) => {
397
+ if (!checkAclCommand(connection, parsed, data, mailbox, hasAdmin)) {
398
+ return;
399
+ }
400
+ // the identifier is sent back in the same form as the client used
401
+ const identifier = parsed.attributes[1].value;
402
+ let attributes;
403
+ if (identifier === owner) {
404
+ // the owner always has every right, nothing is optional
405
+ attributes = [identifier, formatRights(ALL_RIGHTS)];
406
+ }
407
+ else {
408
+ // nothing is granted always, every right can be granted on its own, including the virtual ones
409
+ attributes = [identifier, ''].concat(RIGHTS.split(''), Object.keys(VIRTUAL_RIGHTS));
410
+ }
411
+ connection.send({ tag: '*', command: 'LISTRIGHTS', attributes: mailboxResponse(mailbox, attributes) }, 'LISTRIGHTS', parsed, data, mailbox);
412
+ connection.sendStatus(parsed, data, 'OK', 'Listrights complete');
413
+ }), identifierOptions);
471
414
  // RFC 4314 sections 3.5 and 3.8
472
- server.setCommandHandler(
473
- 'MYRIGHTS',
474
- aclCommand(1, (connection, parsed, data, mailbox) => {
475
- if (!checkAclCommand(connection, parsed, data, mailbox, rights => ANY_RIGHTS.some(right => rights.has(right)))) {
476
- return;
477
- }
478
- sendMyRights(connection, mailbox, parsed, data);
479
- connection.sendStatus(parsed, data, 'OK', 'Myrights complete');
480
- }),
481
- aclOptions
482
- );
483
-
415
+ server.setCommandHandler('MYRIGHTS', aclCommand(1, (connection, parsed, data, mailbox) => {
416
+ if (!checkAclCommand(connection, parsed, data, mailbox, (rights) => ANY_RIGHTS.some(right => rights.has(right)))) {
417
+ return;
418
+ }
419
+ sendMyRights(connection, mailbox, parsed, data);
420
+ connection.sendStatus(parsed, data, 'OK', 'Myrights complete');
421
+ }), aclOptions);
484
422
  // Enforcement (RFC 4314 section 4). Commands are wrapped once every plugin is loaded, so that
485
423
  // the commands of every plugin (MOVE, UID EXPUNGE, ...) are covered whatever the load order is
486
424
  const wrappers = {};
@@ -499,7 +437,6 @@ module.exports = function (server) {
499
437
  });
500
438
  }
501
439
  });
502
-
503
440
  // Return options of an extended LIST (LIST-STATUS, LIST-MYRIGHTS) add responses for the listed
504
441
  // mailboxes, so they skip the mailboxes that are not listed for the user. STATUS also needs "r"
505
442
  // (RFC 5819 section 2: the STATUS response MUST NOT be returned if the mailbox can not be selected)
@@ -520,7 +457,6 @@ module.exports = function (server) {
520
457
  }
521
458
  };
522
459
  });
523
-
524
460
  // RFC 4314 section 4: STORE changes only the flags the user has rights for
525
461
  STORE_ITEMS.forEach(item => {
526
462
  const prevHandler = server.storeHandlers[item] || builtinStoreHandlers[item];
@@ -531,8 +467,8 @@ module.exports = function (server) {
531
467
  }
532
468
  flags = [].concat(flags);
533
469
  // invalid flags are still refused with BAD, even if the user could not set them anyway
534
- flags.forEach(flag => checkSystemFlags(connection, normalizeSystemFlag(flagValue(flag))));
535
- let allowed = flags.filter(flag => canSetFlag(rights, flag));
470
+ flags.forEach((flag) => checkSystemFlags(connection, normalizeSystemFlag(flagValue(flag))));
471
+ let allowed = flags.filter((flag) => canSetFlag(rights, flag));
536
472
  if (item.charAt(0) !== '+' && item.charAt(0) !== '-') {
537
473
  // replacing the flags keeps the ones the user can not change
538
474
  allowed = message.flags.filter(flag => !canSetFlag(rights, flag)).concat(allowed);
@@ -541,9 +477,7 @@ module.exports = function (server) {
541
477
  };
542
478
  });
543
479
  };
544
-
545
480
  server.once('pluginsLoaded', wrapCommands);
546
-
547
481
  const selectWrapper = (prevHandler, connection, parsed, data, callback) => {
548
482
  const mailbox = argumentMailbox(parsed, 0);
549
483
  if (!mailbox) {
@@ -567,31 +501,25 @@ module.exports = function (server) {
567
501
  };
568
502
  wrappers.SELECT = selectWrapper;
569
503
  wrappers.EXAMINE = selectWrapper;
570
-
571
504
  // Checks that the user has a right on the mailbox named by an argument. Unknown mailboxes and
572
505
  // invalid arguments are left to the command handler
573
506
  const hasMailboxRight = (right, position, notFound) => (connection, parsed, data) => {
574
507
  const mailbox = argumentMailbox(parsed, position);
575
508
  const rights = mailbox && getRights(connection, mailbox);
576
509
  if (rights && !rights.has(right)) {
577
- sendDenied(connection, parsed, data, rights, false, notFound);
510
+ sendDenied(connection, parsed, data, rights, undefined, notFound);
578
511
  return false;
579
512
  }
580
513
  return true;
581
514
  };
582
-
583
515
  const requireRight = (right, position, notFound) => {
584
516
  const check = hasMailboxRight(right, position, notFound);
585
- return (prevHandler, connection, parsed, data, callback) =>
586
- check(connection, parsed, data) ? prevHandler(connection, parsed, data, callback) : callback();
517
+ return (prevHandler, connection, parsed, data, callback) => check(connection, parsed, data) ? prevHandler(connection, parsed, data, callback) : callback();
587
518
  };
588
-
589
519
  wrappers.STATUS = requireRight('r', 0);
590
520
  // SUBSCRIBE checks that the mailbox exists, so it needs "l". UNSUBSCRIBE needs no rights
591
521
  wrappers.SUBSCRIBE = requireRight('l', 0);
592
-
593
522
  wrappers.DELETE = requireRight('x', 0);
594
-
595
523
  // CREATE needs "k" on the nearest existing parent, a mailbox at the top level can not be created
596
524
  const checkCreateRight = (connection, parsed, data, path) => {
597
525
  const parent = getParent(path);
@@ -601,7 +529,6 @@ module.exports = function (server) {
601
529
  }
602
530
  return true;
603
531
  };
604
-
605
532
  wrappers.CREATE = (prevHandler, connection, parsed, data, callback) => {
606
533
  const name = mailboxArgument(parsed, 0);
607
534
  if (name !== false && !checkCreateRight(connection, parsed, data, name)) {
@@ -609,7 +536,6 @@ module.exports = function (server) {
609
536
  }
610
537
  return prevHandler(connection, parsed, data, callback);
611
538
  };
612
-
613
539
  // RENAME needs "x" on the mailbox and "k" on the new parent
614
540
  const hasRenameRight = hasMailboxRight('x', 0);
615
541
  wrappers.RENAME = (prevHandler, connection, parsed, data, callback) => {
@@ -622,7 +548,6 @@ module.exports = function (server) {
622
548
  }
623
549
  return prevHandler(connection, parsed, data, callback);
624
550
  };
625
-
626
551
  // APPEND needs "i", and only the flags the user has rights for are stored
627
552
  wrappers.APPEND = (prevHandler, connection, parsed, data, callback) => {
628
553
  const mailbox = argumentMailbox(parsed, 0);
@@ -635,18 +560,18 @@ module.exports = function (server) {
635
560
  return callback();
636
561
  }
637
562
  const flags = parsed.attributes[1];
638
- if (Array.isArray(flags) && flags.every(flag => flag && flag.type === 'ATOM')) {
563
+ if (Array.isArray(flags) && flags.every((flag) => flag && flag.type === 'ATOM')) {
639
564
  try {
640
- flags.forEach(flag => checkSystemFlags(connection, normalizeSystemFlag(flag.value)));
565
+ flags.forEach((flag) => checkSystemFlags(connection, normalizeSystemFlag(flag.value)));
641
566
  // the server MUST NOT fail APPEND for flags the user can not set
642
- parsed.attributes[1] = flags.filter(flag => canSetFlag(rights, flag));
643
- } catch {
567
+ parsed.attributes[1] = flags.filter((flag) => canSetFlag(rights, flag));
568
+ }
569
+ catch {
644
570
  // invalid flags are refused with BAD by the APPEND handler
645
571
  }
646
572
  }
647
573
  return prevHandler(connection, parsed, data, callback);
648
574
  };
649
-
650
575
  // the refusal for a target mailbox without "i", see sendDenied
651
576
  const insertRefusal = (connection, mailbox) => {
652
577
  const rights = mailbox ? getRights(connection, mailbox) : false;
@@ -657,11 +582,10 @@ module.exports = function (server) {
657
582
  ? { command: 'NO', code: 'NOPERM', text: 'Permission denied' }
658
583
  : { command: 'NO', code: 'TRYCREATE', text: 'Target mailbox does not exist' };
659
584
  };
660
-
661
585
  // COPY and MOVE need "i" on the target, MOVE also needs what UID STORE \Deleted and UID EXPUNGE
662
586
  // need on the source, "t" and "e" (RFC 6851 section 4.2)
663
587
  const requireInsert = requireRight('i', 1, 'TRYCREATE');
664
- const copyWrapper = isMove => (prevHandler, connection, parsed, data, callback) => {
588
+ const copyWrapper = (isMove) => (prevHandler, connection, parsed, data, callback) => {
665
589
  const command = parsed.command.toUpperCase();
666
590
  if (isMove && !connection.readOnly) {
667
591
  const rights = getSelectedRights(connection);
@@ -676,7 +600,6 @@ module.exports = function (server) {
676
600
  wrappers['UID COPY'] = copyWrapper(false);
677
601
  wrappers.MOVE = copyWrapper(true);
678
602
  wrappers['UID MOVE'] = copyWrapper(true);
679
-
680
603
  // RFC 8508 section 4.1: REPLACE needs the rights of UID STORE (\Deleted, "t") and UID EXPUNGE ("e") on the
681
604
  // selected mailbox, and of APPEND ("i") on the target. A read-only session is refused by the command handler
682
605
  const replaceRefusal = (connection, mailbox) => {
@@ -696,7 +619,6 @@ module.exports = function (server) {
696
619
  };
697
620
  wrappers.REPLACE = replaceWrapper;
698
621
  wrappers['UID REPLACE'] = replaceWrapper;
699
-
700
622
  // The message literal of APPEND and REPLACE is refused before it is sent when the user may not add messages to the
701
623
  // target, with the same answer as after the literal. A mailbox the user can not see ("l") is refused like a
702
624
  // missing one, which the core literal filter refuses before the literal too, so the transcripts do not tell
@@ -712,11 +634,10 @@ module.exports = function (server) {
712
634
  }
713
635
  return command === 'APPEND' ? insertRefusal(connection, mailbox) : replaceRefusal(connection, mailbox);
714
636
  });
715
-
716
637
  // RFC 5464 section 3.3: mailbox annotations need "l" and any of "r", "s", "w", "i" or "p". Server
717
638
  // annotations (the empty mailbox name) are not covered by mailbox ACLs
718
639
  const METADATA_RIGHTS = ['r', 's', 'w', 'i', 'p'];
719
- const canUseMetadata = rights => rights.has('l') && METADATA_RIGHTS.some(right => rights.has(right));
640
+ const canUseMetadata = (rights) => rights.has('l') && METADATA_RIGHTS.some(right => rights.has(right));
720
641
  const metadataWrapper = (prevHandler, connection, parsed, data, callback) => {
721
642
  const args = parsed.attributes || [];
722
643
  // GETMETADATA takes its options before the mailbox name (RFC 5464 errata 2785)
@@ -725,7 +646,7 @@ module.exports = function (server) {
725
646
  if (mailbox && mailboxArgument(parsed, position) !== '') {
726
647
  const rights = getRights(connection, mailbox);
727
648
  if (!canUseMetadata(rights)) {
728
- sendDenied(connection, parsed, data, rights, false);
649
+ sendDenied(connection, parsed, data, rights);
729
650
  return callback();
730
651
  }
731
652
  }
@@ -733,7 +654,6 @@ module.exports = function (server) {
733
654
  };
734
655
  wrappers.GETMETADATA = metadataWrapper;
735
656
  wrappers.SETMETADATA = metadataWrapper;
736
-
737
657
  // Unsolicited METADATA responses (RFC 5464 section 4.4.2) only go to sessions that could read the
738
658
  // annotations of the mailbox. Server annotations have an empty mailbox name
739
659
  server.notifyFilters.push((connection, notification) => {
@@ -746,7 +666,6 @@ module.exports = function (server) {
746
666
  const mailbox = typeof path === 'string' && path !== '' && server.getMailbox(path);
747
667
  return !mailbox || canUseMetadata(getRights(connection, mailbox));
748
668
  });
749
-
750
669
  // RFC 9208 section 6: GETQUOTA needs no rights. GETQUOTAROOT needs "r" for the MESSAGE and STORAGE
751
670
  // resources, which tell about the messages of the mailbox, only MAILBOX needs no right. Without "r"
752
671
  // (or for a mailbox that does not exist, so nothing is disclosed) the QUOTA responses only list MAILBOX
@@ -757,7 +676,6 @@ module.exports = function (server) {
757
676
  }
758
677
  return prevHandler(connection, parsed, data, callback);
759
678
  };
760
-
761
679
  // RFC 9208 section 6: SETQUOTA needs "a". The quota root is not a mailbox, so the user needs "a" on
762
680
  // every mailbox the quota root applies to (all personal mailboxes)
763
681
  wrappers.SETQUOTA = (prevHandler, connection, parsed, data, callback) => {
@@ -774,7 +692,6 @@ module.exports = function (server) {
774
692
  }
775
693
  return prevHandler(connection, parsed, data, callback);
776
694
  };
777
-
778
695
  // EXPUNGE needs "e". In a read-only session the command handler refuses it already
779
696
  const expungeWrapper = (prevHandler, connection, parsed, data, callback) => {
780
697
  if (!connection.readOnly && !getSelectedRights(connection).has('e')) {
@@ -785,13 +702,11 @@ module.exports = function (server) {
785
702
  };
786
703
  wrappers.EXPUNGE = expungeWrapper;
787
704
  wrappers['UID EXPUNGE'] = expungeWrapper;
788
-
789
705
  // UNAUTHENTICATE (RFC 8437): rights of the previous user must not stay with the session
790
- server.resetHandlers.push(connection => {
706
+ server.resetHandlers.push((connection) => {
791
707
  connection.aclRights = null;
792
708
  });
793
-
794
- server.connectionHandlers.push(connection => {
709
+ server.connectionHandlers.push((connection) => {
795
710
  // A FETCH that implies setting \Seen MUST NOT set it without "s", and without "e" CLOSE MUST
796
711
  // close the mailbox without expunging (RFC 4314 section 4)
797
712
  const canSetSeen = connection.canSetSeen;
@@ -799,7 +714,6 @@ module.exports = function (server) {
799
714
  connection.canSetSeen = () => canSetSeen.call(connection) && getSelectedRights(connection).has('s');
800
715
  connection.canExpunge = () => canExpunge.call(connection) && getSelectedRights(connection).has('e');
801
716
  });
802
-
803
717
  // STORE needs the right of at least one of the flags it changes, it SHOULD NOT fail otherwise.
804
718
  // The flags themselves are filtered by the store handlers
805
719
  const storeWrapper = (prevHandler, connection, parsed, data, callback) => {
@@ -821,14 +735,16 @@ module.exports = function (server) {
821
735
  const flags = [].concat(args[args.length - 1] || []);
822
736
  try {
823
737
  flags.forEach(flag => checkSystemFlags(connection, normalizeSystemFlag(flagValue(flag))));
824
- } catch {
738
+ }
739
+ catch {
825
740
  // invalid flags are refused with BAD by the STORE handler
826
741
  return prevHandler(connection, parsed, data, callback);
827
742
  }
828
743
  let allowed;
829
744
  if (item.charAt(0) === '+' || item.charAt(0) === '-') {
830
745
  allowed = !flags.length || flags.some(flag => canSetFlag(rights, flag));
831
- } else {
746
+ }
747
+ else {
832
748
  // replacing the flags changes every flag the user has rights for
833
749
  allowed = FLAG_RIGHTS.some(right => rights.has(right));
834
750
  }
@@ -840,28 +756,21 @@ module.exports = function (server) {
840
756
  };
841
757
  wrappers.STORE = storeWrapper;
842
758
  wrappers['UID STORE'] = storeWrapper;
843
-
844
759
  // Checks if an extended LIST command asks for the STATUS return option (RFC 5819)
845
- const hasStatusReturnOption = parsed => {
760
+ const hasStatusReturnOption = (parsed) => {
846
761
  const args = (parsed && parsed.attributes) || [];
847
- return args.some(
848
- (arg, i) =>
849
- arg &&
850
- arg.type === 'ATOM' &&
851
- /^RETURN$/i.test(arg.value) &&
852
- Array.isArray(args[i + 1]) &&
853
- args[i + 1].some(option => option && option.type === 'ATOM' && /^STATUS$/i.test(option.value))
854
- );
762
+ return args.some((arg, i) => arg &&
763
+ arg.type === 'ATOM' &&
764
+ /^RETURN$/i.test(arg.value) &&
765
+ Array.isArray(args[i + 1]) &&
766
+ args[i + 1].some((option) => option && option.type === 'ATOM' && /^STATUS$/i.test(option.value)));
855
767
  };
856
-
857
768
  // Checks if any mailbox below a mailbox is visible to the user
858
- const hasVisibleChildren = (connection, mailbox) => server.hasDescendant(mailbox.path, child => getRights(connection, child).has('l'));
859
-
769
+ const hasVisibleChildren = (connection, mailbox) => server.hasDescendant(mailbox.path, (child) => getRights(connection, child).has('l'));
860
770
  server.outputHandlers.push((connection, response, description, parsed, data, extra) => {
861
771
  if (isOwner(connection)) {
862
772
  return;
863
773
  }
864
-
865
774
  if ((description === 'LIST ITEM' || description === 'LSUB ITEM') && extra && extra.path) {
866
775
  // LIST and LSUB need "l", the mailbox is left out without it and never answered with NO
867
776
  if (!getRights(connection, extra).has('l')) {
@@ -873,20 +782,19 @@ module.exports = function (server) {
873
782
  return;
874
783
  }
875
784
  response.attributes[0] = flags.slice();
876
- const index = flags.findIndex(flag => flag && flag.value === '\\HasChildren');
785
+ const index = flags.findIndex((flag) => flag && flag.value === '\\HasChildren');
877
786
  if (index >= 0 && !hasVisibleChildren(connection, extra)) {
878
787
  // children that the user can not see do not count (RFC 3348 section 4)
879
788
  response.attributes[0][index] = { type: 'ATOM', value: '\\HasNoChildren' };
880
789
  }
881
790
  // RFC 5819 section 2: a mailbox that gets no STATUS response because it can not be selected
882
791
  // (no "r" right) MUST be listed with \Noselect
883
- const isSelectable = !flags.some(flag => flag && /^\\(Noselect|NonExistent)$/i.test(flag.value));
792
+ const isSelectable = !flags.some((flag) => flag && /^\\(Noselect|NonExistent)$/i.test(flag.value));
884
793
  if (isSelectable && hasStatusReturnOption(parsed) && !getRights(connection, extra).has('r')) {
885
794
  response.attributes[0].push({ type: 'ATOM', value: '\\Noselect' });
886
795
  }
887
796
  return;
888
797
  }
889
-
890
798
  if (description === 'QUOTA' && parsed && parsed.aclQuotaMailboxOnly && Array.isArray(response.attributes[1])) {
891
799
  // quota-resource = resource-name SP resource-usage SP resource-limit
892
800
  const list = response.attributes[1];
@@ -899,36 +807,35 @@ module.exports = function (server) {
899
807
  // quota-list needs at least one resource, so without a MAILBOX limit there is no QUOTA response
900
808
  if (filtered.length) {
901
809
  response.attributes[1] = filtered;
902
- } else {
810
+ }
811
+ else {
903
812
  response.skipResponse = true;
904
813
  }
905
814
  return;
906
815
  }
907
-
908
816
  if (description === 'SELECT PERMANENTFLAGS') {
909
817
  // RFC 4314 section 5.1.1: PERMANENTFLAGS MUST reflect the rights of the user
910
818
  const section = response.attributes[0] && response.attributes[0].section;
911
819
  const rights = getSelectedRights(connection);
912
820
  if (section && Array.isArray(section[1])) {
913
- section[1] = section[1].filter(flag => (flag.value === '\\*' ? rights.has('w') : canSetFlag(rights, flag)));
821
+ section[1] = section[1].filter((flag) => (flag.value === '\\*' ? rights.has('w') : canSetFlag(rights, flag)));
914
822
  }
915
823
  return;
916
824
  }
917
-
918
825
  if (extra && extra.targetUids && extra.mailbox && /^(UID )?(COPY|MOVE COPYUID)$/.test(description)) {
919
826
  // RFC 4314 section 4: the copies only keep the flags the user has rights for in the target
920
827
  const rights = getRights(connection, extra.mailbox);
921
828
  const uids = new Set(extra.targetUids);
922
- extra.mailbox.messages.forEach(message => {
829
+ extra.mailbox.messages.forEach((message) => {
923
830
  if (uids.has(message.uid)) {
924
- message.flags = message.flags.filter(flag => canSetFlag(rights, flag));
831
+ message.flags = message.flags.filter((flag) => canSetFlag(rights, flag));
925
832
  }
926
833
  });
927
834
  }
928
835
  });
929
-
930
836
  // The DELETE command MUST delete the ACL of the mailbox (RFC 4314 section 4), this matters when a
931
837
  // \Noselect placeholder stays for the children of the mailbox
838
+ // DELETE and CREATE are core commands, so the handlers exist
932
839
  const prevDelete = server.getCommandHandler('DELETE');
933
840
  server.setCommandHandler('DELETE', (connection, parsed, data, callback) => {
934
841
  const mailbox = argumentMailbox(parsed, 0);
@@ -940,7 +847,6 @@ module.exports = function (server) {
940
847
  callback();
941
848
  });
942
849
  });
943
-
944
850
  // A new mailbox inherits the ACL of its parent (RFC 4314 section 4, CREATE SHOULD)
945
851
  const prevCreate = server.getCommandHandler('CREATE');
946
852
  server.setCommandHandler('CREATE', (connection, parsed, data, callback) => {
@@ -950,15 +856,15 @@ module.exports = function (server) {
950
856
  .filter(path => !existing.has(path))
951
857
  .sort((a, b) => a.length - b.length)
952
858
  .forEach(path => {
953
- const parent = getParent(path);
954
- const mailbox = server.folderCache[path];
955
- if (parent && parent !== mailbox) {
956
- const acl = new Map();
957
- getAcl(parent).forEach((rights, identifier) => acl.set(identifier, new Set(rights)));
958
- mailbox.acl = acl;
959
- }
960
- });
859
+ const parent = getParent(path);
860
+ const mailbox = server.folderCache[path];
861
+ if (parent && parent !== mailbox) {
862
+ const acl = new Map();
863
+ getAcl(parent).forEach((rights, identifier) => acl.set(identifier, new Set(rights)));
864
+ mailbox.acl = acl;
865
+ }
866
+ });
961
867
  callback();
962
868
  });
963
869
  });
964
- };
870
+ }