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,628 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = notifyPlugin;
7
+ const command_states_js_1 = require("../command-states.js");
8
+ const fetch_js_1 = require("../commands/fetch.js");
9
+ const fetch_js_2 = __importDefault(require("../commands/handlers/fetch.js"));
10
+ const status_js_1 = require("../commands/handlers/status.js");
11
+ const search_js_1 = require("../commands/handlers/search.js");
12
+ const arguments_js_1 = require("../arguments.js");
13
+ /**
14
+ * @help Adds NOTIFY [RFC5465] capability. Events: MessageNew (with
15
+ * @help fetch attributes for the selected mailbox), MessageExpunge,
16
+ * @help FlagChange, MailboxName, SubscriptionChange, and with METADATA
17
+ * @help MailboxMetadataChange and ServerMetadataChange.
18
+ * @help server.notifyOverflow([connection]) sends
19
+ * @help "* OK [NOTIFICATIONOVERFLOW]" and turns NOTIFY off
20
+ *
21
+ * NOTIFY: https://www.rfc-editor.org/rfc/rfc5465
22
+ *
23
+ * Additional commands:
24
+ * - NOTIFY SET [STATUS] event-groups, NOTIFY NONE
25
+ *
26
+ * After the first NOTIFY command the session gets only the events it asked for (RFC 5465 section 3.1),
27
+ * also between commands. Events caused by the session itself are not reported (section 5), the
28
+ * responses of its own commands are sent as usual. Fetch attributes of MessageNew never set \Seen,
29
+ * clients SHOULD NOT use such attributes anyway (section 5.2).
30
+ */
31
+ // RFC 5465 section 8, canonical names by upper case name
32
+ const MESSAGE_EVENTS = ['MessageNew', 'MessageExpunge', 'FlagChange', 'AnnotationChange'];
33
+ const EVENT_NAMES = new Map(MESSAGE_EVENTS.concat(['MailboxName', 'SubscriptionChange', 'MailboxMetadataChange', 'ServerMetadataChange']).map(name => [name.toUpperCase(), name]));
34
+ const SELECTED_FILTERS = ['SELECTED', 'SELECTED-DELAYED'];
35
+ const OTHER_FILTERS = ['INBOXES', 'PERSONAL', 'SUBSCRIBED', 'SUBTREE', 'MAILBOXES'];
36
+ // fetch items whose arguments are checked with a dry run when NOTIFY SET is parsed
37
+ const SECTION_ITEMS = ['BODY', 'BODY.PEEK', 'BINARY', 'BINARY.PEEK', 'BINARY.SIZE'];
38
+ function notifyPlugin(server) {
39
+ server.registerCapability('NOTIFY');
40
+ // NOTIFY needs the authenticated state, UNAUTHENTICATE clears the settings
41
+ const isActive = (connection) => !!connection.notifyState;
42
+ // RFC 5465 sections 5.6 and 5.7: the metadata events are supported (and REQUIRED) with METADATA or METADATA-SERVER
43
+ const getSupportedEvents = () => {
44
+ const supported = ['MessageNew', 'MessageExpunge', 'FlagChange', 'MailboxName', 'SubscriptionChange'];
45
+ if (server.capabilities.METADATA) {
46
+ supported.push('MailboxMetadataChange');
47
+ }
48
+ if (server.capabilities.METADATA || server.capabilities['METADATA-SERVER']) {
49
+ supported.push('ServerMetadataChange');
50
+ }
51
+ return supported;
52
+ };
53
+ // Access checks, RFC 5465 section 3.1 and section 5: every event needs the "l" and "r" rights
54
+ const hasRights = (connection, mailbox, letters, acl) => {
55
+ const rights = server.acl && server.acl.getRights(connection, mailbox, acl);
56
+ return !rights || [...letters].every(letter => rights.has(letter));
57
+ };
58
+ const canList = (connection, mailbox, acl) => hasRights(connection, mailbox, 'l', acl);
59
+ const canRead = (connection, mailbox, acl) => hasRights(connection, mailbox, 'lr', acl);
60
+ const normalizePath = (path) => (path.toUpperCase() === 'INBOX' ? 'INBOX' : path);
61
+ /**
62
+ * Checks if an event group of NOTIFY SET covers a mailbox name (RFC 5465 section 6)
63
+ *
64
+ * @param {Object} group Parsed event group
65
+ * @param {String} path Storage name
66
+ * @param {Object} [mailbox] Mailbox object, if the mailbox exists
67
+ * @param {Boolean} [subscription] true for a subscription change, the subscribed filter covers both states
68
+ */
69
+ const covers = (group, path, mailbox, subscription) => {
70
+ switch (group.filter) {
71
+ case 'INBOXES':
72
+ // RFC 5465 section 6.3: a server that can not tell which mailboxes get mail treats it as "personal"
73
+ // falls through
74
+ case 'PERSONAL':
75
+ return server.isPersonal(path);
76
+ case 'SUBSCRIBED':
77
+ // RFC 5465 section 6.4: the list is reevaluated when subscriptions change
78
+ return !!subscription || !!(mailbox && mailbox.subscribed);
79
+ case 'SUBTREE':
80
+ return group.paths.indexOf(path) >= 0 || group.prefixes.some((prefix) => path.substr(0, prefix.length) === prefix);
81
+ case 'MAILBOXES':
82
+ // RFC 5465 section 6.6: no wildcard expansion
83
+ return group.paths.indexOf(path) >= 0;
84
+ }
85
+ return false;
86
+ };
87
+ /**
88
+ * Lists the events a session asked for on a mailbox other than the selected one. Several groups
89
+ * can cover the same mailbox (RFC 5465 section 6), message events for the selected mailbox only
90
+ * come from SELECTED or SELECTED-DELAYED (section 3.1)
91
+ *
92
+ * @return {Set} event names
93
+ */
94
+ const getEvents = (connection, path, mailbox, subscription) => {
95
+ const events = new Set();
96
+ connection.notifyState.groups.forEach(group => {
97
+ if (covers(group, path, mailbox, subscription)) {
98
+ group.events.forEach(event => events.add(event));
99
+ }
100
+ });
101
+ if (mailbox && mailbox === connection.selectedMailbox) {
102
+ MESSAGE_EVENTS.forEach(event => events.delete(event));
103
+ }
104
+ return events;
105
+ };
106
+ // RFC 5465 section 6.1.2: with SELECTED-DELAYED an expunge waits for a command that allows it
107
+ const isHeld = (connection) => !!(connection.notifyState.selected && connection.notifyState.selected.delayed) && !connection.directNotifications && connection.hasPendingExpunge();
108
+ /**
109
+ * Sends the queued notifications of a session that is between commands (RFC 5465 section 3.1: the
110
+ * client listens all the time). During a command they wait for its tagged response
111
+ */
112
+ const flush = (connection) => {
113
+ if (!connection.socket || !connection.notificationQueue.length || connection._runningCommand || !isActive(connection) || isHeld(connection)) {
114
+ return;
115
+ }
116
+ connection.processNotifications();
117
+ };
118
+ // the events of one command go out together, e.g. several expunges as one VANISHED response (QRESYNC)
119
+ const scheduleFlush = (connection) => {
120
+ if (!connection.notifyFlushPending) {
121
+ connection.notifyFlushPending = true;
122
+ setImmediate(() => {
123
+ connection.notifyFlushPending = false;
124
+ flush(connection);
125
+ });
126
+ }
127
+ };
128
+ /**
129
+ * Sends an event response about another mailbox or about the server
130
+ *
131
+ * @param {Object} connection IMAP connection
132
+ * @param {Object} response Untagged response
133
+ */
134
+ const deliver = (connection, event) => {
135
+ const response = event;
136
+ response.tag = '*';
137
+ response.notification = true;
138
+ if (!connection._runningCommand && isHeld(connection)) {
139
+ // this does not change message sequence numbers, so it does not have to wait for the expunge
140
+ connection.send(response, 'NOTIFY EVENT');
141
+ return;
142
+ }
143
+ connection.notificationQueue.push(response);
144
+ scheduleFlush(connection);
145
+ };
146
+ // the sessions that use NOTIFY, other than the one that caused a change (RFC 5465 section 5: SHOULD omit)
147
+ const listeners = (origin) => [...server.connections].filter(connection => connection !== origin && isActive(connection));
148
+ /**
149
+ * Builds an unsolicited STATUS response for a mailbox. With FlagChange the UNSEEN count is added
150
+ * when it changed since the session last heard of it (RFC 5465 section 5.1), with CONDSTORE (or
151
+ * QRESYNC) enabled HIGHESTMODSEQ as well (sections 5.1, 5.2 and 5.3)
152
+ *
153
+ * @return {Object|Boolean} response, or false if there is nothing to tell
154
+ */
155
+ const eventStatus = (connection, mailbox, items, events) => {
156
+ items = items.slice();
157
+ if (events.has('FlagChange')) {
158
+ const status = server.getStatus(mailbox);
159
+ const unseen = (status && status.unseen) || 0;
160
+ if (connection.notifyState.unseen.get(mailbox) !== unseen) {
161
+ connection.notifyState.unseen.set(mailbox, unseen);
162
+ items.push('UNSEEN');
163
+ }
164
+ }
165
+ if (server.condstore && server.condstore.isEnabled(connection)) {
166
+ items.push('HIGHESTMODSEQ');
167
+ }
168
+ if (!items.length) {
169
+ return false;
170
+ }
171
+ return (0, status_js_1.statusResponse)(connection, mailbox.path, mailbox, items);
172
+ };
173
+ // Reports a change of the messages of a mailbox that is not selected (RFC 5465 sections 5.1, 5.2 and 5.3)
174
+ const messageEvent = (mailbox, event, items, origin) => {
175
+ listeners(origin).forEach(connection => {
176
+ if (mailbox === connection.selectedMailbox || !canRead(connection, mailbox)) {
177
+ return;
178
+ }
179
+ const events = getEvents(connection, mailbox.path, mailbox);
180
+ if (!events.has(event)) {
181
+ return;
182
+ }
183
+ const response = eventStatus(connection, mailbox, event === 'FlagChange' && server.condstore && server.condstore.isEnabled(connection) ? ['UIDVALIDITY'] : items, events);
184
+ if (response) {
185
+ deliver(connection, response);
186
+ }
187
+ });
188
+ };
189
+ // Checks if any mailbox below a mailbox is visible to the session (RFC 3348 section 4)
190
+ const hasVisibleChildren = (connection, path) => server.hasDescendant(path, (child) => canList(connection, child) && child.flags.indexOf('\\NonExistent') < 0);
191
+ /**
192
+ * Builds an unsolicited LIST response with accurate attributes (RFC 5465 sections 5.4 and 5.5)
193
+ *
194
+ * @param {Object} connection IMAP connection
195
+ * @param {String} path Storage name
196
+ * @param {Object} [options] `{ oldPath, noAccess, exists }`, `exists: false` reports the name as \NonExistent
197
+ */
198
+ const listResponse = (connection, path, options) => {
199
+ options = options || {};
200
+ const mailbox = server.getMailbox(path);
201
+ const exists = options.exists !== false && !!mailbox && canList(connection, mailbox);
202
+ const flags = server.listAttributes(exists ? mailbox : null, {
203
+ exists,
204
+ subscribed: exists && mailbox.subscribed,
205
+ extra: options.noAccess ? ['\\NoAccess'] : [],
206
+ hasChildren: hasVisibleChildren(connection, path)
207
+ });
208
+ const attributes = [flags.map(flag => ({ type: 'ATOM', value: flag })), server.getSeparator(path), { type: 'MAILBOX', value: path }];
209
+ if (options.oldPath) {
210
+ // RFC 5465 section 5.4, the OLDNAME extended data item (mbox-list-extended)
211
+ attributes.push([{ type: 'STRING', value: 'OLDNAME' }, [{ type: 'STRING', value: connection.exportMailboxName(options.oldPath) }]]);
212
+ }
213
+ return { tag: '*', command: 'LIST', attributes };
214
+ };
215
+ // RFC 5465 section 5.4: a created or deleted mailbox and its direct parent are affected
216
+ const nameEvent = (connection, path, mailbox, exists) => {
217
+ [path, server.getParentPath(path)].forEach(name => {
218
+ if (!name) {
219
+ return;
220
+ }
221
+ const target = name === path ? mailbox : server.getMailbox(name);
222
+ if (getEvents(connection, name, target).has('MailboxName')) {
223
+ deliver(connection, listResponse(connection, name, name === path ? { exists } : {}));
224
+ }
225
+ });
226
+ };
227
+ // RFC 5465 section 5.1: with FlagChange the server MUST tell about UIDVALIDITY changes, a mailbox that
228
+ // gets a name that is watched has a new UIDVALIDITY
229
+ const uidvalidityEvent = (connection, mailbox) => {
230
+ if (mailbox !== connection.selectedMailbox && canRead(connection, mailbox) && getEvents(connection, mailbox.path, mailbox).has('FlagChange')) {
231
+ // the item list is not empty, so there is always a response
232
+ deliver(connection, eventStatus(connection, mailbox, ['MESSAGES', 'UIDNEXT', 'UIDVALIDITY'], new Set(['FlagChange'])));
233
+ }
234
+ };
235
+ server.on('mailbox', (change) => {
236
+ const mailbox = server.getMailbox(change.path);
237
+ listeners(change.origin).forEach(connection => {
238
+ switch (change.type) {
239
+ case 'create':
240
+ if (mailbox && canList(connection, mailbox)) {
241
+ nameEvent(connection, change.path, mailbox, true);
242
+ uidvalidityEvent(connection, mailbox);
243
+ }
244
+ break;
245
+ case 'delete':
246
+ if (change.mailbox && canList(connection, change.mailbox)) {
247
+ nameEvent(connection, change.path, mailbox, !!mailbox);
248
+ }
249
+ break;
250
+ case 'rename':
251
+ // RFC 5465 section 5.4: one LIST response for the new name, none for the children
252
+ if (mailbox && canList(connection, mailbox)) {
253
+ const events = getEvents(connection, change.path, mailbox);
254
+ // a rename always has the old name
255
+ getEvents(connection, change.oldPath).forEach(event => events.add(event));
256
+ if (events.has('MailboxName')) {
257
+ deliver(connection, listResponse(connection, change.path, { oldPath: change.oldPath }));
258
+ }
259
+ uidvalidityEvent(connection, mailbox);
260
+ }
261
+ break;
262
+ case 'subscribe':
263
+ case 'unsubscribe':
264
+ // RFC 5465 section 5.5
265
+ if (mailbox && canList(connection, mailbox) && getEvents(connection, change.path, mailbox, true).has('SubscriptionChange')) {
266
+ deliver(connection, listResponse(connection, change.path));
267
+ }
268
+ break;
269
+ }
270
+ });
271
+ });
272
+ // RFC 5465 section 5.4: granting or revoking the "l" right counts as creating or deleting the mailbox. Section 5.9:
273
+ // monitoring stops without the rights and starts again when they are granted, \NoAccess tells about the "r" right
274
+ server.on('acl', (mailbox, previous) => {
275
+ listeners(null).forEach(connection => {
276
+ const before = { list: canList(connection, mailbox, previous), read: canRead(connection, mailbox, previous) };
277
+ const after = { list: canList(connection, mailbox), read: canRead(connection, mailbox) };
278
+ if (before.list !== after.list) {
279
+ nameEvent(connection, mailbox.path, mailbox, after.list);
280
+ }
281
+ else if (after.list && before.read !== after.read) {
282
+ const events = getEvents(connection, mailbox.path, mailbox);
283
+ if (MESSAGE_EVENTS.some(event => events.has(event))) {
284
+ deliver(connection, listResponse(connection, mailbox.path, { noAccess: !after.read }));
285
+ }
286
+ }
287
+ });
288
+ });
289
+ server.on('expunge', (mailbox, messages, origin) => messageEvent(mailbox, 'MessageExpunge', ['MESSAGES', 'UIDNEXT'], origin));
290
+ server.on('notify', (notification) => {
291
+ const command = notification.command || {};
292
+ const mailbox = typeof notification.mailbox === 'string' ? server.getMailbox(notification.mailbox) : notification.mailbox;
293
+ if (mailbox && command.flagUpdate) {
294
+ messageEvent(mailbox, 'FlagChange', [], notification.origin);
295
+ }
296
+ else if (mailbox && command.message && (0, arguments_js_1.isAtom)(command.attributes && command.attributes[1], 'EXISTS')) {
297
+ messageEvent(mailbox, 'MessageNew', ['MESSAGES', 'UIDNEXT'], notification.origin);
298
+ }
299
+ else if (command.command === 'METADATA' && command.attributes && command.attributes[0]) {
300
+ // RFC 5465 sections 5.6 and 5.7: METADATA responses without ENABLE METADATA
301
+ const path = command.attributes[0].value;
302
+ const target = path === '' ? null : server.getMailbox(path);
303
+ listeners(notification.origin).forEach(connection => {
304
+ let wanted;
305
+ if (path === '') {
306
+ wanted = connection.notifyState.groups.some(group => group.events.has('ServerMetadataChange'));
307
+ }
308
+ else {
309
+ wanted = !!target && canRead(connection, target) && getEvents(connection, path, target).has('MailboxMetadataChange');
310
+ }
311
+ if (wanted) {
312
+ notification.notifyHandled = notification.notifyHandled || new Set();
313
+ notification.notifyHandled.add(connection);
314
+ deliver(connection, Object.assign({}, command));
315
+ }
316
+ });
317
+ }
318
+ });
319
+ // a METADATA response that NOTIFY sent already does not go out again for ENABLE METADATA
320
+ server.notifyFilters.push((connection, notification) => !(notification.notifyHandled && notification.notifyHandled.has(connection)));
321
+ // Which message event a notification for the selected mailbox is
322
+ const selectedEvent = (command) => {
323
+ if (command.flagUpdate) {
324
+ return 'FlagChange';
325
+ }
326
+ const type = command.attributes && command.attributes[1];
327
+ if ((0, arguments_js_1.isAtom)(type, 'EXPUNGE')) {
328
+ return 'MessageExpunge';
329
+ }
330
+ if ((0, arguments_js_1.isAtom)(type, 'EXISTS')) {
331
+ // the EXISTS after expunges carries a snapshot, the one of a new message the message
332
+ return command.message ? 'MessageNew' : 'MessageExpunge';
333
+ }
334
+ return false;
335
+ };
336
+ // Builds the FETCH response for a new message in the selected mailbox (RFC 5465 section 5.2)
337
+ const newMessageFetch = (connection, items, sequence, message) => {
338
+ const params = items.map(item => Object.assign({}, item));
339
+ let data;
340
+ try {
341
+ data = (0, fetch_js_1.fetchResponse)(connection, message, params);
342
+ }
343
+ catch {
344
+ // the items were checked by NOTIFY SET, a failure here leaves out the FETCH response
345
+ return false;
346
+ }
347
+ // the message goes with the response for output handlers (UIDONLY reports its UID). Not as `message`, that
348
+ // marks an EXPUNGE notification
349
+ return { tag: '*', notification: true, attributes: [sequence, { type: 'ATOM', value: 'FETCH' }, data], fetchedMessage: message };
350
+ };
351
+ server.connectionHandlers.push((connection) => {
352
+ connection.notifyState = null;
353
+ const queueNotification = connection.queueNotification;
354
+ connection.queueNotification = function (command, notification) {
355
+ const event = notification && notification.mailbox && selectedEvent(command);
356
+ if (!isActive(this) || !event || notification.origin === this) {
357
+ // responses to the own commands of the session are not NOTIFY events
358
+ return queueNotification.call(this, command, notification);
359
+ }
360
+ const selected = this.notifyState.selected;
361
+ // notifications about the selected mailbox
362
+ if (!selected || !selected.events.has(event) || !canRead(this, this.selectedMailbox)) {
363
+ // RFC 5465 section 3.1: without SELECTED or SELECTED-DELAYED (or without the event) the client
364
+ // does not want to hear about it
365
+ return;
366
+ }
367
+ this.notificationQueue.push(command);
368
+ if (event === 'MessageNew' && selected.fetch) {
369
+ // the EXISTS response gives the sequence number of the new message
370
+ const fetch = newMessageFetch(this, selected.fetch, command.attributes[0], command.message);
371
+ if (fetch) {
372
+ this.notificationQueue.push(fetch);
373
+ }
374
+ }
375
+ scheduleFlush(this);
376
+ };
377
+ });
378
+ // RFC 8437 section 4.1: UNAUTHENTICATE forgets the NOTIFY settings
379
+ server.resetHandlers.push((connection) => {
380
+ connection.notifyState = null;
381
+ });
382
+ // notifications held back during a command (FETCH, STORE, SEARCH) go out once it completed
383
+ server.outputHandlers.push((connection, response) => {
384
+ if (response.tag !== '*' && !response.notification && isActive(connection) && connection.notificationQueue.length) {
385
+ scheduleFlush(connection);
386
+ }
387
+ });
388
+ /**
389
+ * RFC 5465 section 5.8: disables notifications for a session (or all sessions that use NOTIFY),
390
+ * which get an untagged OK [NOTIFICATIONOVERFLOW] and behave as after NOTIFY NONE
391
+ *
392
+ * @param {Object} [target] IMAP connection, all sessions if not set
393
+ */
394
+ server.notifyOverflow = (target) => {
395
+ listeners(null)
396
+ .filter(connection => !target || connection === target)
397
+ .forEach(connection => {
398
+ connection.notifyState = { selected: null, groups: [], unseen: new WeakMap() };
399
+ deliver(connection, {
400
+ command: 'OK',
401
+ attributes: [
402
+ { type: 'SECTION', section: [{ type: 'ATOM', value: 'NOTIFICATIONOVERFLOW' }] },
403
+ { type: 'TEXT', value: 'Too many notifications, NOTIFY is turned off' }
404
+ ]
405
+ });
406
+ });
407
+ };
408
+ /**
409
+ * Parses the fetch attributes of MessageNew (RFC 5465 section 8: "(" fetch-att *(SP fetch-att) ")")
410
+ *
411
+ * @param {Object} connection IMAP connection
412
+ * @param {Array} list Parsed list
413
+ * @return {Array} fetch items
414
+ */
415
+ const parseFetchAtts = (connection, list) => {
416
+ if (!list.length) {
417
+ throw (0, search_js_1.badError)('MessageNew expects a list of fetch attributes');
418
+ }
419
+ return list.map(item => {
420
+ const key = (0, arguments_js_1.isAtom)(item) && item.value.toUpperCase();
421
+ // macros like ALL are not fetch-att values
422
+ if (!key || !(server.fetchHandlers[key] || fetch_js_2.default[key])) {
423
+ throw (0, search_js_1.badError)('Invalid fetch attribute for MessageNew');
424
+ }
425
+ if ((item.section || item.partial) && SECTION_ITEMS.indexOf(key) >= 0) {
426
+ // check the section and the partial range against a message
427
+ const params = [Object.assign({}, item)];
428
+ try {
429
+ // a dry run against a minimal message, the section items only look at its source
430
+ (0, fetch_js_1.fetchResponse)(connection, { raw: 'Subject: test\r\n\r\nTest\r\n', flags: [], uid: 1 }, params);
431
+ }
432
+ catch (err) {
433
+ throw (0, search_js_1.badError)(err.message);
434
+ }
435
+ }
436
+ return item;
437
+ });
438
+ };
439
+ /**
440
+ * Parses the events of an event group (RFC 5465 section 8: events = ( "(" event *(SP event) ")" ) / "NONE")
441
+ *
442
+ * @param {Object} connection IMAP connection
443
+ * @param {Object|Array} value Parsed events
444
+ * @param {Boolean} selected true for SELECTED and SELECTED-DELAYED
445
+ * @param {Array} unknown Collects the unknown event names
446
+ * @return {Object} `{ events, fetch }`
447
+ */
448
+ const parseEvents = (connection, value, selected, unknown) => {
449
+ const events = new Set();
450
+ let fetch = null;
451
+ if ((0, arguments_js_1.isAtom)(value, 'NONE')) {
452
+ return { events, fetch };
453
+ }
454
+ if (!Array.isArray(value) || !value.length) {
455
+ throw (0, search_js_1.badError)('Expecting a list of events or NONE');
456
+ }
457
+ for (let i = 0; i < value.length; i++) {
458
+ const item = value[i];
459
+ if (!(0, arguments_js_1.isAtom)(item) || item.section || item.partial) {
460
+ throw (0, search_js_1.badError)('Invalid event');
461
+ }
462
+ const name = EVENT_NAMES.get(item.value.toUpperCase());
463
+ if (Array.isArray(value[i + 1]) && name === 'MessageNew') {
464
+ // the fetch-att list is only allowed for the selected mailbox (RFC 5465 section 8)
465
+ if (!selected) {
466
+ throw (0, search_js_1.badError)('Fetch attributes for MessageNew are only allowed with SELECTED or SELECTED-DELAYED');
467
+ }
468
+ fetch = parseFetchAtts(connection, value[++i]);
469
+ }
470
+ if (!name) {
471
+ // event-ext: an event this server does not know, NO [BADEVENT] once the syntax is checked
472
+ unknown.push(item.value);
473
+ continue;
474
+ }
475
+ if (selected && MESSAGE_EVENTS.indexOf(name) < 0) {
476
+ // RFC 5465 section 6.1
477
+ throw (0, search_js_1.badError)(name + ' can not be used with SELECTED or SELECTED-DELAYED');
478
+ }
479
+ events.add(name);
480
+ }
481
+ // RFC 5465 section 5
482
+ if (events.has('MessageNew') !== events.has('MessageExpunge')) {
483
+ throw (0, search_js_1.badError)('MessageNew and MessageExpunge must be used together');
484
+ }
485
+ if ((events.has('FlagChange') || events.has('AnnotationChange')) && !events.has('MessageNew')) {
486
+ throw (0, search_js_1.badError)('FlagChange and AnnotationChange require MessageNew and MessageExpunge');
487
+ }
488
+ return { events, fetch };
489
+ };
490
+ // one-or-more-mailbox = mailbox / many-mailboxes, the names are converted to storage names
491
+ const parseMailboxes = (connection, value) => {
492
+ const list = Array.isArray(value) ? value : [value];
493
+ if (!list.length || !list.every(arguments_js_1.isAstring)) {
494
+ throw (0, search_js_1.badError)('Expecting a mailbox name or a list of mailbox names');
495
+ }
496
+ return list.map(item => normalizePath(connection.importMailboxName(item.value)));
497
+ };
498
+ /**
499
+ * Parses the arguments of NOTIFY (RFC 5465 section 8)
500
+ *
501
+ * @return {Object} `{ state, status, unknown }`
502
+ */
503
+ const parseNotify = (connection, args) => {
504
+ // `unseen` holds the UNSEEN count each mailbox had in the last STATUS response the session got
505
+ const state = { selected: null, groups: [], unseen: new WeakMap() };
506
+ const unknown = [];
507
+ if ((0, arguments_js_1.isAtom)(args[0], 'NONE')) {
508
+ if (args.length !== 1) {
509
+ throw (0, search_js_1.badError)('NOTIFY NONE does not take any arguments');
510
+ }
511
+ return { state, status: false, unknown };
512
+ }
513
+ if (!(0, arguments_js_1.isAtom)(args[0], 'SET')) {
514
+ throw (0, search_js_1.badError)('NOTIFY expects SET or NONE');
515
+ }
516
+ const status = (0, arguments_js_1.isAtom)(args[1], 'STATUS');
517
+ const groups = args.slice(status ? 2 : 1);
518
+ if (!groups.length) {
519
+ throw (0, search_js_1.badError)('NOTIFY SET expects event groups');
520
+ }
521
+ groups.forEach(group => {
522
+ if (!Array.isArray(group) || !(0, arguments_js_1.isAtom)(group[0])) {
523
+ throw (0, search_js_1.badError)('Invalid event group');
524
+ }
525
+ const filter = group[0].value.toUpperCase();
526
+ if (SELECTED_FILTERS.indexOf(filter) >= 0) {
527
+ if (group.length !== 2) {
528
+ throw (0, search_js_1.badError)('Invalid event group');
529
+ }
530
+ if (state.selected) {
531
+ // RFC 5465 section 6.1
532
+ throw (0, search_js_1.badError)('Only one of SELECTED and SELECTED-DELAYED can be used');
533
+ }
534
+ state.selected = Object.assign({ delayed: filter === 'SELECTED-DELAYED' }, parseEvents(connection, group[1], true, unknown));
535
+ }
536
+ else if (OTHER_FILTERS.indexOf(filter) >= 0) {
537
+ const withNames = filter === 'SUBTREE' || filter === 'MAILBOXES';
538
+ if (group.length !== (withNames ? 3 : 2)) {
539
+ throw (0, search_js_1.badError)('Invalid event group');
540
+ }
541
+ const paths = withNames ? parseMailboxes(connection, group[1]) : [];
542
+ const { events } = parseEvents(connection, group[group.length - 1], false, unknown);
543
+ // the names below a SUBTREE root start with these
544
+ const prefixes = filter === 'SUBTREE' ? paths.map(root => root + server.getSeparator(root)) : [];
545
+ state.groups.push({ filter, paths, prefixes, events });
546
+ }
547
+ else {
548
+ throw (0, search_js_1.badError)('Unknown mailbox filter ' + group[0].value);
549
+ }
550
+ });
551
+ return { state, status, unknown };
552
+ };
553
+ // RFC 5465 section 3.1: the initial STATUS responses and the \NoAccess LIST responses of NOTIFY SET
554
+ const sendInitialResponses = (connection, status, parsed, data) => {
555
+ const paths = Object.keys(server.folderCache).sort((a, b) => (a === 'INBOX' ? -1 : b === 'INBOX' ? 1 : a.localeCompare(b)));
556
+ paths.forEach(path => {
557
+ const mailbox = server.folderCache[path];
558
+ if (mailbox === connection.selectedMailbox || mailbox.flags.some((flag) => /^\\(Noselect|NonExistent)$/i.test(flag))) {
559
+ return;
560
+ }
561
+ const events = getEvents(connection, path, mailbox);
562
+ if (!events.size || !canList(connection, mailbox)) {
563
+ return;
564
+ }
565
+ if (!canRead(connection, mailbox)) {
566
+ connection.send(listResponse(connection, path, { noAccess: true }), 'NOTIFY LIST', parsed, data);
567
+ return;
568
+ }
569
+ if (!status || !events.has('MessageNew')) {
570
+ return;
571
+ }
572
+ const items = ['MESSAGES', 'UIDNEXT', 'UIDVALIDITY'];
573
+ if (events.has('FlagChange')) {
574
+ items.push('UNSEEN');
575
+ const mailboxStatus = server.getStatus(mailbox);
576
+ connection.notifyState.unseen.set(mailbox, (mailboxStatus && mailboxStatus.unseen) || 0);
577
+ if (server.condstore) {
578
+ items.push('HIGHESTMODSEQ');
579
+ }
580
+ }
581
+ connection.send((0, status_js_1.statusResponse)(connection, path, mailbox, items), 'NOTIFY STATUS', parsed, data);
582
+ });
583
+ };
584
+ server.setCommandHandler('NOTIFY', (connection, parsed, data, callback) => {
585
+ let result;
586
+ try {
587
+ result = parseNotify(connection, parsed.attributes || []);
588
+ }
589
+ catch (err) {
590
+ connection.sendStatus(parsed, data, 'BAD', err.imapResponse === 'BAD' ? err.message : 'Invalid NOTIFY arguments');
591
+ return callback();
592
+ }
593
+ const supported = getSupportedEvents();
594
+ const used = [result.state.selected]
595
+ .concat(result.state.groups)
596
+ .filter((group) => !!group);
597
+ const unsupported = result.unknown.concat(...used.map(group => [...group.events].filter(event => supported.indexOf(event) < 0)));
598
+ if (unsupported.length) {
599
+ // RFC 5465 section 3.1: NO with BADEVENT, which MUST list all supported events
600
+ connection.send({
601
+ tag: parsed.tag,
602
+ command: 'NO',
603
+ attributes: [
604
+ { type: 'SECTION', section: [{ type: 'ATOM', value: 'BADEVENT' }, supported.map(event => ({ type: 'ATOM', value: event }))] },
605
+ { type: 'TEXT', value: 'Unsupported NOTIFY events' }
606
+ ]
607
+ }, 'NOTIFY FAILED', parsed, data);
608
+ return callback();
609
+ }
610
+ connection.notifyState = result.state;
611
+ sendInitialResponses(connection, result.status, parsed, data);
612
+ // the tagged response sends the changes of the selected mailbox, NOTIFY SET implies NOOP (section 3.1)
613
+ connection.sendStatus(parsed, data, 'OK', 'NOTIFY completed');
614
+ return callback();
615
+ }, { states: command_states_js_1.states.AUTHENTICATED });
616
+ }
617
+ {
618
+ const defaultExport = exports.default;
619
+ if (defaultExport && (typeof defaultExport === 'function' || typeof defaultExport === 'object')) {
620
+ for (const key of Object.keys(exports)) {
621
+ if (key !== 'default' && !(key in defaultExport)) {
622
+ defaultExport[key] = exports[key];
623
+ }
624
+ }
625
+ Object.defineProperty(defaultExport, 'default', { value: defaultExport, enumerable: false, writable: true, configurable: true });
626
+ module.exports = defaultExport;
627
+ }
628
+ }
@@ -0,0 +1,32 @@
1
+ import type { IMAPServer } from '../types.js';
2
+ /** A parsed OAUTHBEARER client response, see parseClientResponse() */
3
+ interface ClientResponse {
4
+ kvsepOnly?: boolean | undefined;
5
+ error?: string | undefined;
6
+ channelBinding?: boolean | undefined;
7
+ authzid?: string | false | undefined;
8
+ pairs?: Record<string, string> | undefined;
9
+ /** the user that the credentials log in, set by checkCredentials() */
10
+ username?: string | undefined;
11
+ }
12
+ /**
13
+ * Parses an OAUTHBEARER client response (RFC 7628 section 3.1)
14
+ *
15
+ * client-resp = (gs2-header kvsep *kvpair kvsep) / kvsep
16
+ * kvpair = key "=" value kvsep
17
+ * key = 1*(ALPHA)
18
+ * value = *(VCHAR / SP / HTAB / CR / LF)
19
+ *
20
+ * and its GS2 header (RFC 5801 section 4)
21
+ *
22
+ * gs2-header = [gs2-nonstd-flag ","] gs2-cb-flag "," [gs2-authzid] ","
23
+ * gs2-cb-flag = ("p=" cb-name) / "n" / "y"
24
+ * gs2-authzid = "a=" saslname
25
+ *
26
+ * @param {Buffer} input Decoded client response
27
+ * @return {Object} `{ kvsepOnly }`, `{ error }` when the response breaks the grammar, or
28
+ * `{ channelBinding, authzid, pairs }` where pairs maps keys to values
29
+ */
30
+ declare function parseClientResponse(input: Buffer): ClientResponse;
31
+ export default function oauthbearerPlugin(server: IMAPServer): void;
32
+ export { parseClientResponse };