@wirecat/mail-cli 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/CHANGELOG.md +149 -0
  2. package/README.md +48 -13
  3. package/dist/bin/mail.js +2 -2
  4. package/dist/bundle/{all-profiles-GR5JXYEQ.js → all-profiles-SI67TKZM.js} +9 -9
  5. package/dist/bundle/{anthropic-REBXE65F.js → anthropic-DALMLC3Y.js} +6 -6
  6. package/dist/bundle/{app-server-QJ7ICQXZ.js → app-server-XOH327Z2.js} +46 -46
  7. package/dist/bundle/{bun-WAX4QHW5.js → bun-ORL67CJ6.js} +2 -2
  8. package/dist/bundle/{bun-sqlite-5S7TQ4SG.js → bun-sqlite-DGXFNFHI.js} +5 -5
  9. package/dist/bundle/{chunk-ZD3WUGR2.js → chunk-23IEVVL2.js} +4 -4
  10. package/dist/bundle/{chunk-B5WSIWY5.js → chunk-2M4K7HYR.js} +17 -17
  11. package/dist/bundle/{chunk-IWDOGGMY.js → chunk-35KD2CI2.js} +501 -301
  12. package/dist/bundle/{chunk-7A7BHABA.js → chunk-3GZK5GTU.js} +1 -1
  13. package/dist/bundle/{chunk-JJBQPA7D.js → chunk-3TYEJRMZ.js} +4 -4
  14. package/dist/bundle/{chunk-M6BDHZON.js → chunk-45KA5667.js} +26 -13
  15. package/dist/bundle/{chunk-LOA4X6JW.js → chunk-4NYWHINR.js} +6 -6
  16. package/dist/bundle/{dist-KJOAJ6NF.js → chunk-4ULY3GDL.js} +16 -116
  17. package/dist/bundle/{chunk-2FXVBCA3.js → chunk-5BSEGMNE.js} +4 -4
  18. package/dist/bundle/{chunk-HCMUGUAG.js → chunk-5JEYIHS6.js} +3 -3
  19. package/dist/bundle/{chunk-QXOSGGKS.js → chunk-6LK7KTWB.js} +1 -1
  20. package/dist/bundle/{chunk-ESNNQA7D.js → chunk-6RMMAUUW.js} +28 -28
  21. package/dist/bundle/{chunk-VXAZZGXE.js → chunk-6XNPXAJU.js} +33 -27
  22. package/dist/bundle/{chunk-5INWLYBD.js → chunk-73OJJGZE.js} +14 -3
  23. package/dist/bundle/{chunk-4XJ4AM3K.js → chunk-7K6KJWTO.js} +12 -12
  24. package/dist/bundle/{chunk-KIDF77MA.js → chunk-AP7V256W.js} +1 -1
  25. package/dist/bundle/{chunk-4BMNP2FT.js → chunk-BEMLGWY4.js} +1 -1
  26. package/dist/bundle/{chunk-BFJV4FWJ.js → chunk-BGUMGCUY.js} +2 -2
  27. package/dist/bundle/{chunk-5BVIWP3S.js → chunk-BM445GYF.js} +2 -2
  28. package/dist/bundle/{chunk-F3NYA4KN.js → chunk-CAKBG5FC.js} +6 -6
  29. package/dist/bundle/{chunk-EB3R2PV3.js → chunk-DKQWTQVY.js} +23 -23
  30. package/dist/bundle/{chunk-6TY3DGCC.js → chunk-DXGMPMFP.js} +4 -4
  31. package/dist/bundle/{chunk-LFRHIXCF.js → chunk-E3DRM6YP.js} +3 -3
  32. package/dist/bundle/{chunk-FSUNGHRI.js → chunk-EYT33MM3.js} +47 -46
  33. package/dist/bundle/{chunk-DXDQOZ2P.js → chunk-FPOGVDLS.js} +2 -2
  34. package/dist/bundle/{chunk-S677WGOQ.js → chunk-FTFNWGIR.js} +8 -8
  35. package/dist/bundle/{chunk-TI6VBZKJ.js → chunk-FUB3X25H.js} +4 -4
  36. package/dist/bundle/{chunk-7JCRQX56.js → chunk-GJUUTUK4.js} +8 -8
  37. package/dist/bundle/{chunk-BLS5YG77.js → chunk-HFJNEXU7.js} +2 -2
  38. package/dist/bundle/{chunk-YKPBC3NL.js → chunk-HV3EIYX4.js} +1 -1
  39. package/dist/bundle/{chunk-EL554DV2.js → chunk-IYZHM3ZN.js} +3 -3
  40. package/dist/bundle/{chunk-6EO7GVYJ.js → chunk-JFMUI4H6.js} +1 -1
  41. package/dist/bundle/{chunk-2YQNBIDQ.js → chunk-LZ5J3UXD.js} +4 -4
  42. package/dist/bundle/{chunk-WNCCYHRV.js → chunk-M2JCUVCJ.js} +116 -95
  43. package/dist/bundle/{chunk-7F3NDIYL.js → chunk-MCJ7LKYR.js} +6 -6
  44. package/dist/bundle/{chunk-VDAIJM5L.js → chunk-MHQKHWCJ.js} +88 -34
  45. package/dist/bundle/{chunk-SQ7KOBRA.js → chunk-MMXMVGA6.js} +10 -8
  46. package/dist/bundle/{chunk-AFCGOZR7.js → chunk-NNIXREJH.js} +7 -7
  47. package/dist/bundle/{chunk-LQ37ALDJ.js → chunk-NXJLC2WK.js} +8 -8
  48. package/dist/bundle/{chunk-6GE3EADU.js → chunk-OHTR4WFO.js} +2 -2
  49. package/dist/bundle/{chunk-PJCTWPJB.js → chunk-PDL4UREY.js} +8 -8
  50. package/dist/bundle/{chunk-J3QXTBD2.js → chunk-Q2C3VMSU.js} +20 -18
  51. package/dist/bundle/{chunk-SWJAG5IE.js → chunk-Q44AYEOB.js} +2 -2
  52. package/dist/bundle/{chunk-P7P5MNAU.js → chunk-QZBT6BOU.js} +1 -1
  53. package/dist/bundle/{chunk-IBYTYIYO.js → chunk-R5MML3FC.js} +61 -54
  54. package/dist/bundle/{chunk-CEAANMJ2.js → chunk-RQVWZBW3.js} +3 -3
  55. package/dist/bundle/{chunk-5CXAH4Y6.js → chunk-S4YUR4S3.js} +656 -572
  56. package/dist/bundle/{chunk-QX7RCLRS.js → chunk-SQLCCKEL.js} +1 -1
  57. package/dist/bundle/chunk-U6UJ3HRS.js +58 -0
  58. package/dist/bundle/{chunk-YRGBZZUW.js → chunk-V4TDG4KF.js} +14 -14
  59. package/dist/bundle/{chunk-5FK6RD4M.js → chunk-VBOMKZ4E.js} +73 -57
  60. package/dist/bundle/{chunk-MQUJEQTU.js → chunk-VKPWP3AK.js} +2 -2
  61. package/dist/bundle/{chunk-7XNPSIWD.js → chunk-VNJMO5F6.js} +2 -2
  62. package/dist/bundle/{chunk-MMDCL42A.js → chunk-VSHJWTX5.js} +12 -6
  63. package/dist/bundle/{chunk-2MRECWJZ.js → chunk-XQJWMBDY.js} +6 -6
  64. package/dist/bundle/{chunk-2U4IANVV.js → chunk-ZKCNMW7G.js} +2 -2
  65. package/dist/bundle/{chunk-LNS27BTB.js → chunk-ZKZABB4K.js} +3 -3
  66. package/dist/bundle/{chunk-WNI5BZFB.js → chunk-ZNGQ3NZ4.js} +9 -9
  67. package/dist/bundle/command-contract-CB5BII3S.js +34 -0
  68. package/dist/bundle/{decode-D7BDVIVB.js → decode-KOBURZIQ.js} +5 -5
  69. package/dist/bundle/{dispatch-EUKKT3PD.js → dispatch-GDAH4JHS.js} +8 -8
  70. package/dist/bundle/dist-T7HMT675.js +134 -0
  71. package/dist/bundle/{echarts-IVRX7XHP.js → echarts-LEWTQO6H.js} +2 -2
  72. package/dist/bundle/{embed-X527RBTG.js → embed-PUFE4BSQ.js} +6 -6
  73. package/dist/bundle/{embedder-F4PSJS6S.js → embedder-3G4BQQ6X.js} +9 -9
  74. package/dist/bundle/{failure-OAIC5VAP.js → failure-6COJAO7T.js} +2 -2
  75. package/dist/bundle/{first-run-M5CIX6NA.js → first-run-FLXOC53U.js} +11 -11
  76. package/dist/bundle/first-screen-VUZEDSQW.js +32 -0
  77. package/dist/bundle/{instructions-UX36BT5F.js → instructions-HGSXDCBT.js} +1 -1
  78. package/dist/bundle/mail.js +12 -11
  79. package/dist/bundle/{mcp-L7SRVDRN.js → mcp-GAPDLFWA.js} +2 -2
  80. package/dist/bundle/{node-OXT7WE2T.js → node-5Z7PS4F5.js} +2 -2
  81. package/dist/bundle/{node-sqlite-X2PSEHA4.js → node-sqlite-OAW7APIX.js} +5 -5
  82. package/dist/bundle/{oauth-MYK4BSYN.js → oauth-ZFZWPAJN.js} +7 -7
  83. package/dist/bundle/{open-GONIP2DH.js → open-ZQMBZVH4.js} +4 -4
  84. package/dist/bundle/{openai-YJFNUOQT.js → openai-XT2RIXAK.js} +14 -14
  85. package/dist/bundle/{process-7IEUUSRK.js → process-VVEQIHPE.js} +1 -1
  86. package/dist/bundle/{program-Q73TTG3E.js → program-RD3BBDNY.js} +21470 -7075
  87. package/dist/bundle/{prompt-SKQ72KN7.js → prompt-PU7GE4Z4.js} +5 -5
  88. package/dist/bundle/{recognize-GC7CU2DB.js → recognize-AG4A3KUK.js} +4 -4
  89. package/dist/bundle/{remote-UEXFZP2I.js → remote-D6TQ6T7F.js} +7 -7
  90. package/dist/bundle/{rerank-2U2NDEZP.js → rerank-GO24HJPF.js} +7 -7
  91. package/dist/bundle/{serve-OOGKFEWL.js → serve-WCHJAH6G.js} +9 -9
  92. package/dist/bundle/server-5KJJ3D6P.js +63 -0
  93. package/dist/bundle/{server-FZ3LFQTF.js → server-CAVNBG3P.js} +38 -38
  94. package/dist/bundle/{sqlite-runtime-GIQSW6LJ.js → sqlite-runtime-ANXC4AW2.js} +5 -5
  95. package/dist/bundle/{state-EMFXPQVZ.js → state-EGJ66A62.js} +6 -6
  96. package/dist/bundle/{store-BDU4UPNK.js → store-OON7FCMQ.js} +15 -15
  97. package/dist/bundle/{store-LDI62AUG.js → store-SBFA444C.js} +13 -13
  98. package/dist/bundle/store-maintenance-command-UEOJLYMJ.js +52 -0
  99. package/dist/commands/attachments.d.ts +3 -0
  100. package/dist/commands/attachments.d.ts.map +1 -0
  101. package/dist/commands/attachments.js +97 -0
  102. package/dist/commands/attachments.js.map +1 -0
  103. package/dist/commands/context.d.ts +21 -6
  104. package/dist/commands/context.d.ts.map +1 -1
  105. package/dist/commands/context.js +58 -7
  106. package/dist/commands/context.js.map +1 -1
  107. package/dist/commands/drafts-send.d.ts +7 -0
  108. package/dist/commands/drafts-send.d.ts.map +1 -0
  109. package/dist/commands/drafts-send.js +58 -0
  110. package/dist/commands/drafts-send.js.map +1 -0
  111. package/dist/commands/drafts.d.ts +3 -0
  112. package/dist/commands/drafts.d.ts.map +1 -0
  113. package/dist/commands/drafts.js +243 -0
  114. package/dist/commands/drafts.js.map +1 -0
  115. package/dist/commands/export.d.ts +3 -0
  116. package/dist/commands/export.d.ts.map +1 -0
  117. package/dist/commands/export.js +278 -0
  118. package/dist/commands/export.js.map +1 -0
  119. package/dist/commands/folders.d.ts.map +1 -1
  120. package/dist/commands/folders.js +120 -2
  121. package/dist/commands/folders.js.map +1 -1
  122. package/dist/commands/messages.d.ts +25 -0
  123. package/dist/commands/messages.d.ts.map +1 -0
  124. package/dist/commands/messages.js +506 -0
  125. package/dist/commands/messages.js.map +1 -0
  126. package/dist/commands/read.d.ts +4 -1
  127. package/dist/commands/read.d.ts.map +1 -1
  128. package/dist/commands/read.js +14 -3
  129. package/dist/commands/read.js.map +1 -1
  130. package/dist/commands/rules.d.ts +3 -0
  131. package/dist/commands/rules.d.ts.map +1 -0
  132. package/dist/commands/rules.js +292 -0
  133. package/dist/commands/rules.js.map +1 -0
  134. package/dist/commands/send.d.ts +39 -0
  135. package/dist/commands/send.d.ts.map +1 -0
  136. package/dist/commands/send.js +309 -0
  137. package/dist/commands/send.js.map +1 -0
  138. package/dist/commands/server-search.d.ts +8 -0
  139. package/dist/commands/server-search.d.ts.map +1 -0
  140. package/dist/commands/server-search.js +38 -0
  141. package/dist/commands/server-search.js.map +1 -0
  142. package/dist/commands/session-start.d.ts.map +1 -1
  143. package/dist/commands/session-start.js +107 -10
  144. package/dist/commands/session-start.js.map +1 -1
  145. package/dist/commands/session.d.ts.map +1 -1
  146. package/dist/commands/session.js +72 -9
  147. package/dist/commands/session.js.map +1 -1
  148. package/dist/commands/stats.d.ts +3 -0
  149. package/dist/commands/stats.d.ts.map +1 -0
  150. package/dist/commands/stats.js +89 -0
  151. package/dist/commands/stats.js.map +1 -0
  152. package/dist/commands/status.js +2 -2
  153. package/dist/commands/status.js.map +1 -1
  154. package/dist/commands/sync.d.ts +6 -0
  155. package/dist/commands/sync.d.ts.map +1 -1
  156. package/dist/commands/sync.js +28 -20
  157. package/dist/commands/sync.js.map +1 -1
  158. package/dist/commands/tags.d.ts +3 -0
  159. package/dist/commands/tags.d.ts.map +1 -0
  160. package/dist/commands/tags.js +144 -0
  161. package/dist/commands/tags.js.map +1 -0
  162. package/dist/config.d.ts +15 -0
  163. package/dist/config.d.ts.map +1 -1
  164. package/dist/config.js +52 -1
  165. package/dist/config.js.map +1 -1
  166. package/dist/export/format.d.ts +19 -0
  167. package/dist/export/format.d.ts.map +1 -0
  168. package/dist/export/format.js +40 -0
  169. package/dist/export/format.js.map +1 -0
  170. package/dist/export/journal.d.ts +32 -0
  171. package/dist/export/journal.d.ts.map +1 -0
  172. package/dist/export/journal.js +84 -0
  173. package/dist/export/journal.js.map +1 -0
  174. package/dist/export/write.d.ts +14 -0
  175. package/dist/export/write.d.ts.map +1 -0
  176. package/dist/export/write.js +42 -0
  177. package/dist/export/write.js.map +1 -0
  178. package/dist/identity.d.ts.map +1 -1
  179. package/dist/identity.js +3 -0
  180. package/dist/identity.js.map +1 -1
  181. package/dist/mail/backend.d.ts +104 -2
  182. package/dist/mail/backend.d.ts.map +1 -1
  183. package/dist/mail/backend.js +4 -1
  184. package/dist/mail/backend.js.map +1 -1
  185. package/dist/mail/changes.d.ts +91 -0
  186. package/dist/mail/changes.d.ts.map +1 -0
  187. package/dist/mail/changes.js +198 -0
  188. package/dist/mail/changes.js.map +1 -0
  189. package/dist/mail/cleanup.d.ts +41 -0
  190. package/dist/mail/cleanup.d.ts.map +1 -0
  191. package/dist/mail/cleanup.js +119 -0
  192. package/dist/mail/cleanup.js.map +1 -0
  193. package/dist/mail/compose.d.ts +73 -0
  194. package/dist/mail/compose.d.ts.map +1 -0
  195. package/dist/mail/compose.js +110 -0
  196. package/dist/mail/compose.js.map +1 -0
  197. package/dist/mail/doctor.d.ts +67 -0
  198. package/dist/mail/doctor.d.ts.map +1 -0
  199. package/dist/mail/doctor.js +115 -0
  200. package/dist/mail/doctor.js.map +1 -0
  201. package/dist/mail/drafts.d.ts +54 -0
  202. package/dist/mail/drafts.d.ts.map +1 -0
  203. package/dist/mail/drafts.js +104 -0
  204. package/dist/mail/drafts.js.map +1 -0
  205. package/dist/mail/imap/connection.d.ts +13 -3
  206. package/dist/mail/imap/connection.d.ts.map +1 -1
  207. package/dist/mail/imap/connection.js +87 -18
  208. package/dist/mail/imap/connection.js.map +1 -1
  209. package/dist/mail/imap/index.d.ts +3 -3
  210. package/dist/mail/imap/index.d.ts.map +1 -1
  211. package/dist/mail/imap/index.js +14 -4
  212. package/dist/mail/imap/index.js.map +1 -1
  213. package/dist/mail/imap/messages.d.ts +5 -6
  214. package/dist/mail/imap/messages.d.ts.map +1 -1
  215. package/dist/mail/imap/messages.js +14 -28
  216. package/dist/mail/imap/messages.js.map +1 -1
  217. package/dist/mail/imap/read.d.ts.map +1 -1
  218. package/dist/mail/imap/read.js +27 -13
  219. package/dist/mail/imap/read.js.map +1 -1
  220. package/dist/mail/imap/search.d.ts +14 -0
  221. package/dist/mail/imap/search.d.ts.map +1 -0
  222. package/dist/mail/imap/search.js +55 -0
  223. package/dist/mail/imap/search.js.map +1 -0
  224. package/dist/mail/imap/write.d.ts +5 -0
  225. package/dist/mail/imap/write.d.ts.map +1 -0
  226. package/dist/mail/imap/write.js +93 -0
  227. package/dist/mail/imap/write.js.map +1 -0
  228. package/dist/mail/organise.d.ts +116 -0
  229. package/dist/mail/organise.d.ts.map +1 -0
  230. package/dist/mail/organise.js +531 -0
  231. package/dist/mail/organise.js.map +1 -0
  232. package/dist/mail/rethread.d.ts +1 -2
  233. package/dist/mail/rethread.d.ts.map +1 -1
  234. package/dist/mail/rethread.js +8 -3
  235. package/dist/mail/rethread.js.map +1 -1
  236. package/dist/mail/rules/apply.d.ts +40 -0
  237. package/dist/mail/rules/apply.d.ts.map +1 -0
  238. package/dist/mail/rules/apply.js +114 -0
  239. package/dist/mail/rules/apply.js.map +1 -0
  240. package/dist/mail/rules/file.d.ts +9 -0
  241. package/dist/mail/rules/file.d.ts.map +1 -0
  242. package/dist/mail/rules/file.js +51 -0
  243. package/dist/mail/rules/file.js.map +1 -0
  244. package/dist/mail/rules/filters.d.ts +11 -0
  245. package/dist/mail/rules/filters.d.ts.map +1 -0
  246. package/dist/mail/rules/filters.js +150 -0
  247. package/dist/mail/rules/filters.js.map +1 -0
  248. package/dist/mail/rules/folders.d.ts +11 -0
  249. package/dist/mail/rules/folders.d.ts.map +1 -0
  250. package/dist/mail/rules/folders.js +17 -0
  251. package/dist/mail/rules/folders.js.map +1 -0
  252. package/dist/mail/rules/query.d.ts +15 -0
  253. package/dist/mail/rules/query.d.ts.map +1 -0
  254. package/dist/mail/rules/query.js +103 -0
  255. package/dist/mail/rules/query.js.map +1 -0
  256. package/dist/mail/rules/store.d.ts +9 -0
  257. package/dist/mail/rules/store.d.ts.map +1 -0
  258. package/dist/mail/rules/store.js +17 -0
  259. package/dist/mail/rules/store.js.map +1 -0
  260. package/dist/mail/save.d.ts +9 -0
  261. package/dist/mail/save.d.ts.map +1 -0
  262. package/dist/mail/save.js +50 -0
  263. package/dist/mail/save.js.map +1 -0
  264. package/dist/mail/send.d.ts +67 -0
  265. package/dist/mail/send.d.ts.map +1 -0
  266. package/dist/mail/send.js +173 -0
  267. package/dist/mail/send.js.map +1 -0
  268. package/dist/mail/smtp.d.ts +4 -0
  269. package/dist/mail/smtp.d.ts.map +1 -0
  270. package/dist/mail/smtp.js +133 -0
  271. package/dist/mail/smtp.js.map +1 -0
  272. package/dist/oauth.d.ts +74 -0
  273. package/dist/oauth.d.ts.map +1 -0
  274. package/dist/oauth.js +230 -0
  275. package/dist/oauth.js.map +1 -0
  276. package/dist/program.d.ts.map +1 -1
  277. package/dist/program.js +26 -4
  278. package/dist/program.js.map +1 -1
  279. package/dist/providers.d.ts +96 -9
  280. package/dist/providers.d.ts.map +1 -1
  281. package/dist/providers.js +69 -16
  282. package/dist/providers.js.map +1 -1
  283. package/dist/reasons.d.ts +9 -0
  284. package/dist/reasons.d.ts.map +1 -0
  285. package/dist/reasons.js +27 -0
  286. package/dist/reasons.js.map +1 -0
  287. package/dist/version.d.ts +1 -1
  288. package/dist/version.js +1 -1
  289. package/package.json +7 -5
  290. package/skills/mail-cli/SKILL.md +30 -3
  291. package/dist/bundle/chunk-YD5WV757.js +0 -27
  292. package/dist/bundle/command-contract-GPUED3GT.js +0 -34
  293. package/dist/bundle/first-screen-M7MT776O.js +0 -32
  294. package/dist/bundle/server-4JMHDHZ7.js +0 -63
  295. package/dist/bundle/store-maintenance-command-OFRPORN2.js +0 -52
  296. /package/dist/bundle/{chunk-NPGVOZVK.js → chunk-WJWLHLQ7.js} +0 -0
@@ -0,0 +1,73 @@
1
+ export interface Person {
2
+ address: string;
3
+ name?: string;
4
+ }
5
+ /** `ann@example.com`, `Ann <ann@example.com>` or several split by commas; each address checked and lower-cased. */
6
+ export declare const peopleOf: (given: readonly string[], flag: string) => Person[];
7
+ /** The message a reply or forward is built from, read from its raw bytes on the server. */
8
+ export interface Original {
9
+ messageId?: string;
10
+ references: string[];
11
+ subject: string;
12
+ date?: string;
13
+ from?: Person;
14
+ replyTo: Person[];
15
+ to: Person[];
16
+ cc: Person[];
17
+ text: string;
18
+ }
19
+ export declare const originalOf: (raw: Uint8Array) => Promise<Original>;
20
+ /**
21
+ * Who a reply goes to: Reply-To, else the sender. Answering one's own message goes to its recipients instead.
22
+ * `all` adds the other recipients; the owner never receives a copy of their own reply.
23
+ */
24
+ export declare const replyPeople: (original: Original, owner: ReadonlySet<string>, all: boolean) => Person[];
25
+ /** The rest after a reply's `to`, for reply-all's Cc. */
26
+ export declare const replyCopies: (original: Original, owner: ReadonlySet<string>, to: readonly Person[]) => Person[];
27
+ export declare const replySubject: (subject: string) => string;
28
+ export declare const forwardSubject: (subject: string) => string;
29
+ /** RFC 5322 §3.6.4: the parent's References and its Message-ID; only the newest are kept on a long thread. */
30
+ export declare const referencesOf: (original: Original) => string[];
31
+ /** The text above the quote and every line of the original behind `> `, as plain-text mail clients quote. */
32
+ export declare const quoted: (text: string, original: Original) => string;
33
+ export interface Draft {
34
+ from: Person;
35
+ to: Person[];
36
+ cc: Person[];
37
+ bcc: Person[];
38
+ subject: string;
39
+ text: string;
40
+ messageId: string;
41
+ date: Date;
42
+ inReplyTo?: string;
43
+ references?: string[];
44
+ files: {
45
+ name: string;
46
+ path: string;
47
+ bytes: number;
48
+ }[];
49
+ /** Attachments already in memory: those of a draft that is being replaced. */
50
+ parts?: {
51
+ name: string;
52
+ mime: string | null;
53
+ bytes: Uint8Array;
54
+ }[];
55
+ /** A forwarded message, attached whole as `message/rfc822`. */
56
+ message?: {
57
+ name: string;
58
+ raw: Uint8Array;
59
+ };
60
+ }
61
+ /**
62
+ * The bytes that go out, without a Bcc line, and the copy for Sent, which keeps it so the owner sees who had one.
63
+ * Both carry the same Message-ID, so the copy is found by it.
64
+ */
65
+ export declare const build: (draft: Draft) => Promise<{
66
+ raw: Uint8Array;
67
+ copy: Uint8Array;
68
+ }>;
69
+ /** `<operation-id@domain>`: the same id on a retry with `--operation-id`, so Sent can tell whether it already went. */
70
+ export declare const messageIdFor: (operationId: string, from: string) => string;
71
+ /** The text says something is attached and nothing is: the mistake NeoMutt warns about. */
72
+ export declare const forgotAttachment: (text: string, attached: boolean) => boolean;
73
+ //# sourceMappingURL=compose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/mail/compose.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,mHAAmH;AACnH,eAAO,MAAM,QAAQ,UAAW,SAAS,MAAM,EAAE,QAAQ,MAAM,KAAG,MAAM,EAUrE,CAAA;AAOH,2FAA2F;AAC3F,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,EAAE,EAAE,MAAM,EAAE,CAAA;IACZ,EAAE,EAAE,MAAM,EAAE,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAID,eAAO,MAAM,UAAU,QAAe,UAAU,KAAG,OAAO,CAAC,QAAQ,CAkBlE,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,aAAc,QAAQ,SAAS,WAAW,CAAC,MAAM,CAAC,OAAO,OAAO,KAAG,MAAM,EAIhG,CAAA;AAED,yDAAyD;AACzD,eAAO,MAAM,WAAW,aAAc,QAAQ,SAAS,WAAW,CAAC,MAAM,CAAC,MAAM,SAAS,MAAM,EAAE,KAAG,MAAM,EACN,CAAA;AAKpG,eAAO,MAAM,YAAY,YAAa,MAAM,WAAqD,CAAA;AAEjG,eAAO,MAAM,cAAc,YAAa,MAAM,WAAkD,CAAA;AAEhG,8GAA8G;AAC9G,eAAO,MAAM,YAAY,aAAc,QAAQ,KAAG,MAAM,EACkC,CAAA;AAK1F,6GAA6G;AAC7G,eAAO,MAAM,MAAM,SAAU,MAAM,YAAY,QAAQ,KAAG,MAIzD,CAAA;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,EAAE,CAAA;IACZ,EAAE,EAAE,MAAM,EAAE,CAAA;IACZ,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACtD,8EAA8E;IAC9E,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,EAAE,CAAA;IAClE,+DAA+D;IAC/D,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,UAAU,CAAA;KAAE,CAAA;CAC5C;AAID;;;GAGG;AACH,eAAO,MAAM,KAAK,UAAiB,KAAK,KAAG,OAAO,CAAC;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAqCvF,CAAA;AAED,uHAAuH;AACvH,eAAO,MAAM,YAAY,gBAAiB,MAAM,QAAQ,MAAM,KAAG,MACgB,CAAA;AAEjF,2FAA2F;AAC3F,eAAO,MAAM,gBAAgB,SAAU,MAAM,YAAY,OAAO,KAAG,OACmB,CAAA"}
@@ -0,0 +1,110 @@
1
+ import { CliError } from "@wirecat/cli-base";
2
+ import { parseMail } from "@wirecat/cli-core/mail";
3
+ import addressparser from "nodemailer/lib/addressparser";
4
+ import MailComposer from "nodemailer/lib/mail-composer";
5
+ const EMAIL = /^[^\s@<>()",;:]+@[^\s@<>()",;:]+\.[^\s@<>()",;:]+$/u;
6
+ /** `ann@example.com`, `Ann <ann@example.com>` or several split by commas; each address checked and lower-cased. */
7
+ export const peopleOf = (given, flag) => given.flatMap((one) => addressparser(one, { flatten: true }).map(({ name, address }) => {
8
+ const clean = address.trim().toLowerCase();
9
+ if (!EMAIL.test(clean))
10
+ throw new CliError("validation_error", `${flag} takes email addresses; ${JSON.stringify(one)} holds none`, {
11
+ param: flag.replace(/^--/, ""),
12
+ });
13
+ return { address: clean, ...(name.trim() ? { name: name.trim() } : {}) };
14
+ }));
15
+ const unique = (people, without = new Set()) => {
16
+ const seen = new Set(without);
17
+ return people.filter(({ address }) => !seen.has(address) && seen.add(address) !== undefined);
18
+ };
19
+ const personOf = ({ email, name }) => ({ address: email, ...(name ? { name } : {}) });
20
+ export const originalOf = async (raw) => {
21
+ let mail;
22
+ try {
23
+ mail = await parseMail(raw, undefined, 0);
24
+ }
25
+ catch {
26
+ throw new CliError("invalid_response", "the original message on the server cannot be read");
27
+ }
28
+ return {
29
+ ...(mail.messageId ? { messageId: mail.messageId } : {}),
30
+ references: mail.references,
31
+ subject: mail.subject ?? "",
32
+ ...(mail.date ? { date: mail.date } : {}),
33
+ ...(mail.from ? { from: personOf(mail.from) } : {}),
34
+ replyTo: mail.replyTo.map(personOf),
35
+ to: mail.to.map(personOf),
36
+ cc: mail.cc.map(personOf),
37
+ text: mail.text,
38
+ };
39
+ };
40
+ /**
41
+ * Who a reply goes to: Reply-To, else the sender. Answering one's own message goes to its recipients instead.
42
+ * `all` adds the other recipients; the owner never receives a copy of their own reply.
43
+ */
44
+ export const replyPeople = (original, owner, all) => {
45
+ const mine = original.from !== undefined && owner.has(original.from.address);
46
+ const first = mine ? original.to : original.replyTo.length ? original.replyTo : original.from ? [original.from] : [];
47
+ return unique([...first, ...(all ? [...original.to, ...original.cc] : [])], owner);
48
+ };
49
+ /** The rest after a reply's `to`, for reply-all's Cc. */
50
+ export const replyCopies = (original, owner, to) => unique([...original.to, ...original.cc], new Set([...owner, ...to.map(({ address }) => address)]));
51
+ const prefixed = (subject, prefix, already) => already.test(subject.trim()) ? subject.trim() : `${prefix} ${subject.trim()}`.trim();
52
+ export const replySubject = (subject) => prefixed(subject, "Re:", /^(re|ha|aw|sv)\s*:/iu);
53
+ export const forwardSubject = (subject) => prefixed(subject, "Fwd:", /^(fwd?|fw)\s*:/iu);
54
+ /** RFC 5322 §3.6.4: the parent's References and its Message-ID; only the newest are kept on a long thread. */
55
+ export const referencesOf = (original) => [...original.references, ...(original.messageId ? [original.messageId] : [])].slice(-20);
56
+ const shown = (person) => person === undefined ? "someone" : person.name ? `${person.name} <${person.address}>` : person.address;
57
+ /** The text above the quote and every line of the original behind `> `, as plain-text mail clients quote. */
58
+ export const quoted = (text, original) => {
59
+ const when = original.date ? `On ${original.date}, ` : "";
60
+ const lines = original.text.split("\n").map((line) => (line.startsWith(">") ? `>${line}` : `> ${line}`));
61
+ return `${text.trimEnd()}\n\n${when}${shown(original.from)} wrote:\n${lines.join("\n")}\n`;
62
+ };
63
+ const header = (person) => (person.name ? { name: person.name, address: person.address } : person.address);
64
+ /**
65
+ * The bytes that go out, without a Bcc line, and the copy for Sent, which keeps it so the owner sees who had one.
66
+ * Both carry the same Message-ID, so the copy is found by it.
67
+ */
68
+ export const build = async (draft) => {
69
+ const options = {
70
+ from: header(draft.from),
71
+ to: draft.to.map(header),
72
+ ...(draft.cc.length ? { cc: draft.cc.map(header) } : {}),
73
+ ...(draft.bcc.length ? { bcc: draft.bcc.map(header) } : {}),
74
+ subject: draft.subject,
75
+ text: draft.text,
76
+ messageId: draft.messageId,
77
+ date: draft.date,
78
+ ...(draft.inReplyTo ? { inReplyTo: draft.inReplyTo } : {}),
79
+ ...(draft.references?.length ? { references: draft.references } : {}),
80
+ attachments: [
81
+ ...draft.files.map(({ name, path }) => ({ filename: name, path })),
82
+ ...(draft.parts ?? []).map(({ name, mime, bytes }) => ({
83
+ filename: name,
84
+ content: Buffer.from(bytes),
85
+ ...(mime ? { contentType: mime } : {}),
86
+ })),
87
+ ...(draft.message
88
+ ? [
89
+ {
90
+ filename: draft.message.name,
91
+ content: Buffer.from(draft.message.raw),
92
+ contentType: "message/rfc822",
93
+ contentDisposition: "attachment",
94
+ },
95
+ ]
96
+ : []),
97
+ ],
98
+ disableUrlAccess: true,
99
+ newline: "\r\n",
100
+ };
101
+ const sent = new MailComposer(options).compile();
102
+ const copy = new MailComposer(options).compile();
103
+ copy.keepBcc = true;
104
+ return { raw: new Uint8Array(await sent.build()), copy: new Uint8Array(await copy.build()) };
105
+ };
106
+ /** `<operation-id@domain>`: the same id on a retry with `--operation-id`, so Sent can tell whether it already went. */
107
+ export const messageIdFor = (operationId, from) => `<${operationId.replace(/[^\w.-]/g, "")}@${from.split("@")[1] ?? "localhost"}>`;
108
+ /** The text says something is attached and nothing is: the mistake NeoMutt warns about. */
109
+ export const forgotAttachment = (text, attached) => !attached && /\battach(ed|ment|ing)?\b|влож(ени|ил|ен)|прилага|прикреп/iu.test(text);
110
+ //# sourceMappingURL=compose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/mail/compose.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * What `doctor` reads of the change runs on disk, with no connection: a run that stopped part way, and Gmail Trash
3
+ * a run filled that Gmail empties within days. memo's doctor said this until the cleanup moved here (NEED-2111).
4
+ */
5
+ export declare const changesCheck: (env: NodeJS.ProcessEnv, now?: number) => {
6
+ fields: {
7
+ changes: {
8
+ runs: number;
9
+ unfinished: {
10
+ id: string;
11
+ account: string;
12
+ command: string;
13
+ started_at: string;
14
+ }[];
15
+ expiring: {
16
+ id: string;
17
+ account: string;
18
+ restorable_until: string | null;
19
+ in_trash: number;
20
+ }[];
21
+ };
22
+ };
23
+ notes: string[];
24
+ };
25
+ export declare const oauthCheck: (env: NodeJS.ProcessEnv, now?: number) => {
26
+ fields: {
27
+ oauth: {
28
+ profile: string;
29
+ provider: "google" | "microsoft";
30
+ client: "own" | "wirecat" | null;
31
+ signed_in_at: string | null;
32
+ sends: boolean | null;
33
+ testing_expiry_risk?: boolean | undefined;
34
+ }[];
35
+ };
36
+ notes: string[];
37
+ };
38
+ /** Every check doctor reads from disk, as one `local` hook. */
39
+ export declare const localChecks: (env: NodeJS.ProcessEnv) => {
40
+ fields: {
41
+ changes: {
42
+ runs: number;
43
+ unfinished: {
44
+ id: string;
45
+ account: string;
46
+ command: string;
47
+ started_at: string;
48
+ }[];
49
+ expiring: {
50
+ id: string;
51
+ account: string;
52
+ restorable_until: string | null;
53
+ in_trash: number;
54
+ }[];
55
+ };
56
+ oauth: {
57
+ profile: string;
58
+ provider: "google" | "microsoft";
59
+ client: "own" | "wirecat" | null;
60
+ signed_in_at: string | null;
61
+ sends: boolean | null;
62
+ testing_expiry_risk?: boolean | undefined;
63
+ }[];
64
+ };
65
+ notes: string[];
66
+ };
67
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/mail/doctor.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAS,MAAM,CAAC,UAAU;IAU/C,MAAM;QACJ,OAAO;YACL,IAAI;YACJ,UAAU;;;;;;YACV,QAAQ;;;;;;;;IAQZ,KAAK;CAaR,CAAA;AASD,eAAO,MAAM,UAAU,QAAS,MAAM,CAAC,UAAU;IA6B7C,MAAM;QAAI,KAAK;;;;;;;;;IACf,KAAK;CAqBR,CAAA;AAED,+DAA+D;AAC/D,eAAO,MAAM,WAAW,QAAS,MAAM,CAAC,UAAU;;;YAtF1C,IAAI;YACJ,UAAU;;;;;;YACV,QAAQ;;;;;;;;;;;;;;;;;CA8Ff,CAAA"}
@@ -0,0 +1,115 @@
1
+ import { configuration } from "../config.js";
2
+ import { IDENTITY } from "../identity.js";
3
+ import { GOOGLE_GUIDE, microsoftClient, OAUTH_GUIDE, sendScopeOf, signInRecords } from "../oauth.js";
4
+ import { providerFor } from "../providers.js";
5
+ import { runSummaries } from "./changes.js";
6
+ const DAY_MS = 86_400_000;
7
+ /** As memo's doctor warned: early enough to look at what a cleanup trashed before Gmail empties its Trash. */
8
+ const WARN_DAYS = 5;
9
+ /**
10
+ * What `doctor` reads of the change runs on disk, with no connection: a run that stopped part way, and Gmail Trash
11
+ * a run filled that Gmail empties within days. memo's doctor said this until the cleanup moved here (NEED-2111).
12
+ */
13
+ export const changesCheck = (env, now = Date.now()) => {
14
+ const runs = runSummaries(env);
15
+ const restore = (id, account) => `\`${IDENTITY.command} <profile of ${account}> messages restore --run ${id} --yes\``;
16
+ const unfinished = runs.filter(({ unfinished }) => unfinished);
17
+ const expiring = runs.filter(({ restorable_until, in_trash }) => {
18
+ const left = restorable_until === null ? 0 : Date.parse(restorable_until) - now;
19
+ return in_trash > 0 && left > 0 && left < WARN_DAYS * DAY_MS;
20
+ });
21
+ return {
22
+ fields: {
23
+ changes: {
24
+ runs: runs.length,
25
+ unfinished: unfinished.map(({ id, account, command, started_at }) => ({ id, account, command, started_at })),
26
+ expiring: expiring.map(({ id, account, restorable_until, in_trash }) => ({
27
+ id,
28
+ account,
29
+ restorable_until,
30
+ in_trash,
31
+ })),
32
+ },
33
+ },
34
+ notes: [
35
+ ...unfinished.map(({ id, account, command }) => `run ${id} of ${account} (${command}) stopped before the end; ${restore(id, account)} undoes what it did, ` +
36
+ "or run the command again to finish it"),
37
+ ...expiring.map(({ id, account, restorable_until, in_trash }) => `run ${id} of ${account} left ${in_trash} emails in Gmail's Trash, which Gmail empties at ${restorable_until}; ` +
38
+ `${restore(id, account)} brings them back before then`),
39
+ ],
40
+ };
41
+ };
42
+ /**
43
+ * Each OAuth profile from disk alone: the app it signs in with and what its last sign-in allowed. The tokens are in
44
+ * the keyring, which doctor never opens; `session status --check` proves one still works.
45
+ */
46
+ /** A Google app left in Testing ends its sign-ins after 7 days; from day 6 doctor says so. */
47
+ const TESTING_WARN_DAYS = 6;
48
+ export const oauthCheck = (env, now = Date.now()) => {
49
+ const { configuredProfiles } = configuration.resolveSettings({}, { env, needsProfile: false });
50
+ const records = signInRecords(env);
51
+ const profiles = configuredProfiles.flatMap((profile) => {
52
+ const { mailbox } = configuration.resolveSettings({ profile }, { env });
53
+ const kind = mailbox.address ? providerFor(mailbox.address, mailbox.host)?.oauth : undefined;
54
+ if (mailbox.auth !== "oauth" || !kind)
55
+ return [];
56
+ let client = "own";
57
+ if (kind === "microsoft")
58
+ try {
59
+ client = microsoftClient(mailbox).source;
60
+ }
61
+ catch {
62
+ client = null;
63
+ }
64
+ const record = records[profile];
65
+ const days = record ? Math.floor((now - Date.parse(record.signed_in_at)) / DAY_MS) : null;
66
+ return [
67
+ {
68
+ profile,
69
+ provider: kind,
70
+ client,
71
+ signed_in_at: record?.signed_in_at ?? null,
72
+ sends: record ? record.scopes.includes(sendScopeOf(kind)) : null,
73
+ ...(kind === "google" ? { testing_expiry_risk: days !== null && days >= TESTING_WARN_DAYS } : {}),
74
+ },
75
+ ];
76
+ });
77
+ const sign = (profile) => `\`${IDENTITY.command} ${profile} session start\``;
78
+ return {
79
+ fields: { oauth: profiles },
80
+ notes: profiles.flatMap(({ profile, client, signed_in_at, sends, ...rest }) => [
81
+ ...("testing_expiry_risk" in rest && rest.testing_expiry_risk
82
+ ? [
83
+ `profile ${profile} signed in to Google ${TESTING_WARN_DAYS}+ days ago: if your Google app is still in ` +
84
+ `Testing, Google ends the sign-in on day 7. Publish the app (${GOOGLE_GUIDE}), then ${sign(profile)}`,
85
+ ]
86
+ : []),
87
+ ...(client === null
88
+ ? [
89
+ `profile ${profile} has no Microsoft app to sign in with again: set one with ` +
90
+ `\`${IDENTITY.command} config set --defaults microsoft_client_id <id>\` (${OAUTH_GUIDE})`,
91
+ ]
92
+ : []),
93
+ ...(signed_in_at === null
94
+ ? [`profile ${profile} has no OAuth sign-in on record here; run ${sign(profile)}`]
95
+ : []),
96
+ ...(sends === false
97
+ ? [`profile ${profile} was not allowed to send at its last sign-in; ${sign(profile)} asks again`]
98
+ : []),
99
+ ]),
100
+ };
101
+ };
102
+ /** Every check doctor reads from disk, as one `local` hook. */
103
+ export const localChecks = (env) => {
104
+ const changes = changesCheck(env);
105
+ let oauth;
106
+ try {
107
+ oauth = oauthCheck(env);
108
+ }
109
+ catch {
110
+ // A config file doctor cannot read is reported as `config.issues` already.
111
+ oauth = { fields: { oauth: [] }, notes: [] };
112
+ }
113
+ return { fields: { ...changes.fields, ...oauth.fields }, notes: [...changes.notes, ...oauth.notes] };
114
+ };
115
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/mail/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACpG,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,MAAM,GAAG,UAAU,CAAA;AACzB,8GAA8G;AAC9G,MAAM,SAAS,GAAG,CAAC,CAAA;AAEnB;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAsB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE;IACvE,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;IAC9B,MAAM,OAAO,GAAG,CAAC,EAAU,EAAE,OAAe,EAAE,EAAE,CAC9C,KAAK,QAAQ,CAAC,OAAO,gBAAgB,OAAO,4BAA4B,EAAE,UAAU,CAAA;IACtF,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,CAAA;IAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC9D,MAAM,IAAI,GAAG,gBAAgB,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,GAAG,GAAG,CAAA;QAC/E,OAAO,QAAQ,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,SAAS,GAAG,MAAM,CAAA;IAC9D,CAAC,CAAC,CAAA;IACF,OAAO;QACL,MAAM,EAAE;YACN,OAAO,EAAE;gBACP,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;gBAC5G,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;oBACvE,EAAE;oBACF,OAAO;oBACP,gBAAgB;oBAChB,QAAQ;iBACT,CAAC,CAAC;aACJ;SACF;QACD,KAAK,EAAE;YACL,GAAG,UAAU,CAAC,GAAG,CACf,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAC3B,OAAO,EAAE,OAAO,OAAO,KAAK,OAAO,6BAA6B,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,uBAAuB;gBAC3G,uCAAuC,CAC1C;YACD,GAAG,QAAQ,CAAC,GAAG,CACb,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC9C,OAAO,EAAE,OAAO,OAAO,SAAS,QAAQ,oDAAoD,gBAAgB,IAAI;gBAChH,GAAG,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,+BAA+B,CACzD;SACF;KACF,CAAA;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,8FAA8F;AAC9F,MAAM,iBAAiB,GAAG,CAAC,CAAA;AAE3B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAsB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE;IACrE,MAAM,EAAE,kBAAkB,EAAE,GAAG,aAAa,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAA;IAC9F,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACtD,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,eAAe,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;QACvE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;QAC5F,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAA;QAChD,IAAI,MAAM,GAA6B,KAAK,CAAA;QAC5C,IAAI,IAAI,KAAK,WAAW;YACtB,IAAI,CAAC;gBACH,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,MAAM,CAAA;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,GAAG,IAAI,CAAA;YACf,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;QAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QACzF,OAAO;YACL;gBACE,OAAO;gBACP,QAAQ,EAAE,IAAI;gBACd,MAAM;gBACN,YAAY,EAAE,MAAM,EAAE,YAAY,IAAI,IAAI;gBAC1C,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;gBAChE,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAClG;SACF,CAAA;IACH,CAAC,CAAC,CAAA;IACF,MAAM,IAAI,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,KAAK,QAAQ,CAAC,OAAO,IAAI,OAAO,kBAAkB,CAAA;IACpF,OAAO;QACL,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE;QAC3B,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC;YAC7E,GAAG,CAAC,qBAAqB,IAAI,IAAI,IAAI,IAAI,CAAC,mBAAmB;gBAC3D,CAAC,CAAC;oBACE,WAAW,OAAO,wBAAwB,iBAAiB,6CAA6C;wBACtG,+DAA+D,YAAY,WAAW,IAAI,CAAC,OAAO,CAAC,EAAE;iBACxG;gBACH,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,MAAM,KAAK,IAAI;gBACjB,CAAC,CAAC;oBACE,WAAW,OAAO,4DAA4D;wBAC5E,KAAK,QAAQ,CAAC,OAAO,sDAAsD,WAAW,GAAG;iBAC5F;gBACH,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,YAAY,KAAK,IAAI;gBACvB,CAAC,CAAC,CAAC,WAAW,OAAO,6CAA6C,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAClF,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,KAAK,KAAK,KAAK;gBACjB,CAAC,CAAC,CAAC,WAAW,OAAO,iDAAiD,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;gBACjG,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;KACH,CAAA;AACH,CAAC,CAAA;AAED,+DAA+D;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAsB,EAAE,EAAE;IACpD,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;IACjC,IAAI,KAAoC,CAAA;IACxC,IAAI,CAAC;QACH,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;QAC3E,KAAK,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;IAC9C,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAA;AACtG,CAAC,CAAA"}
@@ -0,0 +1,54 @@
1
+ import type { Organise } from "../providers.js";
2
+ import type { FolderInfo, MailBackend } from "./backend.js";
3
+ import { type Draft as Outgoing, type Person } from "./compose.js";
4
+ /** `\Seen` too: a draft is the owner's own text, and a mail app shows an unseen one as new mail. */
5
+ export declare const DRAFT_FLAGS: readonly ["\\Draft", "\\Seen"];
6
+ export declare const draftsFolderOf: (folders: readonly FolderInfo[], organise: Organise) => string;
7
+ /** A draft is named by its Message-ID, which stays the same across its versions; the angle brackets are optional. */
8
+ export declare const draftIdOf: (given: string) => string;
9
+ export interface Draft {
10
+ id: string;
11
+ uid: number;
12
+ subject: string;
13
+ from: string | null;
14
+ to: string[];
15
+ cc: string[];
16
+ bcc: string[];
17
+ date: string | null;
18
+ in_reply_to: string | null;
19
+ attachments: {
20
+ name: string;
21
+ mime: string | null;
22
+ }[];
23
+ text: string;
24
+ }
25
+ /** A draft as the answer shows it, and what its next version carries over: thread, Bcc and attachments. */
26
+ export interface ReadDraft {
27
+ draft: Draft;
28
+ references: string[];
29
+ parts: NonNullable<Outgoing["parts"]>;
30
+ }
31
+ export declare const readDraft: (raw: Uint8Array, uid: number) => Promise<ReadDraft>;
32
+ type Reads = Pick<MailBackend, "search" | "fetchRaw">;
33
+ /** The newest drafts first, at most `limit`; read from the server, since the store holds Drafts only if it syncs it. */
34
+ export declare const listDrafts: (backend: Reads, folder: string, limit: number) => Promise<{
35
+ items: Draft[];
36
+ more: boolean;
37
+ }>;
38
+ /** The draft with this Message-ID now: its UID, the folder's UIDVALIDITY and what it holds. */
39
+ export declare const findDraft: (backend: Pick<MailBackend, "writes" | "fetchRaw">, folder: string, id: string) => Promise<{
40
+ uid: number;
41
+ validity: string;
42
+ read: ReadDraft;
43
+ }>;
44
+ export interface Changes {
45
+ to?: Person[];
46
+ cc?: Person[];
47
+ bcc?: Person[];
48
+ subject?: string;
49
+ text?: string;
50
+ }
51
+ /** The next version of a draft: each given field replaces the old one; the rest, its thread and its id stay. */
52
+ export declare const nextVersion: ({ draft, references, parts }: ReadDraft, given: Changes, owner: string) => Outgoing;
53
+ export {};
54
+ //# sourceMappingURL=drafts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drafts.d.ts","sourceRoot":"","sources":["../../src/mail/drafts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,KAAK,KAAK,IAAI,QAAQ,EAAE,KAAK,MAAM,EAAY,MAAM,cAAc,CAAA;AAE5E,oGAAoG;AACpG,eAAO,MAAM,WAAW,YAAI,SAAS,EAAE,QAAQ,CAAU,CAAA;AAEzD,eAAO,MAAM,cAAc,YAAa,SAAS,UAAU,EAAE,YAAY,QAAQ,KAAG,MAUnF,CAAA;AAED,qHAAqH;AACrH,eAAO,MAAM,SAAS,UAAW,MAAM,KAAG,MAKzC,CAAA;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,EAAE,EAAE,MAAM,EAAE,CAAA;IACZ,EAAE,EAAE,MAAM,EAAE,CAAA;IACZ,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,EAAE,CAAA;IACpD,IAAI,EAAE,MAAM,CAAA;CACb;AAeD,2GAA2G;AAC3G,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;CACtC;AAED,eAAO,MAAM,SAAS,QAAe,UAAU,OAAO,MAAM,KAAG,OAAO,CAAC,SAAS,CAuB/E,CAAA;AAED,KAAK,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAA;AAUrD,wHAAwH;AACxH,eAAO,MAAM,UAAU,YAAmB,KAAK,UAAU,MAAM,SAAS,MAAM;;;EAU7E,CAAA;AAED,+FAA+F;AAC/F,eAAO,MAAM,SAAS,YAAmB,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,UAAU,CAAC,UAAU,MAAM,MAAM,MAAM;;;;EAW5G,CAAA;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAA;IACb,EAAE,CAAC,EAAE,MAAM,EAAE,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,EAAE,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,gHAAgH;AAChH,eAAO,MAAM,WAAW,iCAAkC,SAAS,SAAS,OAAO,SAAS,MAAM,KAAG,QAgBpG,CAAA"}
@@ -0,0 +1,104 @@
1
+ import { CliError } from "@wirecat/cli-base";
2
+ import { parseMail } from "@wirecat/cli-core/mail";
3
+ import { peopleOf } from "./compose.js";
4
+ /** `\Seen` too: a draft is the owner's own text, and a mail app shows an unseen one as new mail. */
5
+ export const DRAFT_FLAGS = ["\\Draft", "\\Seen"];
6
+ export const draftsFolderOf = (folders, organise) => {
7
+ const found = folders.find(({ role }) => role === "drafts") ?? folders.find(({ path }) => organise.drafts.includes(path));
8
+ if (!found)
9
+ throw new CliError("provider_unavailable", "the mailbox has no Drafts folder this tool can find; folders list shows the folders", { reason: "mail.no-drafts" });
10
+ return found.path;
11
+ };
12
+ /** A draft is named by its Message-ID, which stays the same across its versions; the angle brackets are optional. */
13
+ export const draftIdOf = (given) => {
14
+ const bare = given.trim().replace(/^<|>$/g, "");
15
+ if (!/^[^\s<>]+@[^\s<>]+$/.test(bare))
16
+ throw new CliError("validation_error", `"${given}" is no draft id — drafts list shows them`, { param: "draft" });
17
+ return `<${bare}>`;
18
+ };
19
+ const dateOf = (raw) => {
20
+ const head = Buffer.from(raw)
21
+ .toString("latin1")
22
+ .split(/\r?\n\r?\n/)[0] ?? "";
23
+ const value = /^Date:[ \t]*(.+)$/im.exec(head)?.[1];
24
+ const at = value ? Date.parse(value) : Number.NaN;
25
+ return Number.isNaN(at) ? null : new Date(at).toISOString();
26
+ };
27
+ const shown = (people) => people.map(({ email, name }) => (name ? `${name} <${email}>` : email));
28
+ export const readDraft = async (raw, uid) => {
29
+ const parsed = await parseMail(raw, undefined, Number.POSITIVE_INFINITY);
30
+ const head = Buffer.from(raw)
31
+ .toString("latin1")
32
+ .split(/\r?\n\r?\n/)[0] ?? "";
33
+ return {
34
+ draft: {
35
+ id: (parsed.messageId ?? "").replace(/^<|>$/g, ""),
36
+ uid,
37
+ subject: parsed.subject ?? "",
38
+ from: parsed.from ? shown([parsed.from])[0] : null,
39
+ to: shown(parsed.to),
40
+ cc: shown(parsed.cc),
41
+ bcc: shown(parsed.bcc),
42
+ date: dateOf(raw),
43
+ in_reply_to: /^In-Reply-To:[ \t]*(<[^<>\s]+>)/im.exec(head)?.[1] ?? null,
44
+ attachments: parsed.attachments.map(({ name, mime }) => ({ name, mime })),
45
+ text: parsed.text,
46
+ },
47
+ references: parsed.references,
48
+ parts: parsed.attachments.flatMap(({ name, mime, bytes }) => (bytes ? [{ name, mime, bytes }] : [])),
49
+ };
50
+ };
51
+ const rawOf = async (backend, folder, uids) => {
52
+ const read = await backend.fetchRaw(uids.map((uid) => ({ uid: String(uid), receivedAt: "", folder })));
53
+ return read.map((one) => {
54
+ if (one instanceof Error)
55
+ throw one;
56
+ return one;
57
+ });
58
+ };
59
+ /** The newest drafts first, at most `limit`; read from the server, since the store holds Drafts only if it syncs it. */
60
+ export const listDrafts = async (backend, folder, limit) => {
61
+ if (!backend.search)
62
+ throw new CliError("provider_unavailable", "this mailbox cannot list a folder");
63
+ const { uids } = await backend.search(new Date(0), folder);
64
+ const newest = uids
65
+ .map(Number)
66
+ .sort((a, b) => b - a)
67
+ .slice(0, limit);
68
+ const raws = newest.length ? await rawOf(backend, folder, newest) : [];
69
+ const drafts = await Promise.all(raws.map((raw, at) => readDraft(raw, newest[at])));
70
+ return { items: drafts.map(({ draft }) => draft), more: uids.length > limit };
71
+ };
72
+ /** The draft with this Message-ID now: its UID, the folder's UIDVALIDITY and what it holds. */
73
+ export const findDraft = async (backend, folder, id) => {
74
+ const writes = backend.writes;
75
+ if (!writes)
76
+ throw new CliError("provider_unavailable", "this mailbox cannot be changed from here");
77
+ const { validity, uids } = await writes.locate(folder, { messageIds: [id] });
78
+ const uid = uids.get(id);
79
+ if (uid === undefined)
80
+ throw new CliError("not_found", `no draft ${id.replace(/^<|>$/g, "")} in ${folder}; drafts list shows them`, {
81
+ reason: "mail.draft-unknown",
82
+ });
83
+ const [raw] = await rawOf(backend, folder, [uid]);
84
+ return { uid, validity, read: await readDraft(raw, uid) };
85
+ };
86
+ /** The next version of a draft: each given field replaces the old one; the rest, its thread and its id stay. */
87
+ export const nextVersion = ({ draft, references, parts }, given, owner) => {
88
+ const people = (list, flag) => (list.length ? peopleOf(list, flag) : []);
89
+ return {
90
+ from: peopleOf([draft.from ?? owner], "from")[0],
91
+ to: given.to ?? people(draft.to, "--to"),
92
+ cc: given.cc ?? people(draft.cc, "--cc"),
93
+ bcc: given.bcc ?? people(draft.bcc, "--bcc"),
94
+ subject: given.subject ?? draft.subject,
95
+ text: given.text ?? draft.text,
96
+ messageId: `<${draft.id}>`,
97
+ date: new Date(),
98
+ ...(draft.in_reply_to ? { inReplyTo: draft.in_reply_to } : {}),
99
+ ...(references.length ? { references } : {}),
100
+ files: [],
101
+ parts,
102
+ };
103
+ };
104
+ //# sourceMappingURL=drafts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drafts.js","sourceRoot":"","sources":["../../src/mail/drafts.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { ImapFlow } from "imapflow";
2
- import type { MailEndpoint, RunBounds } from "../backend.js";
2
+ import type { MailCredential, MailEndpoint, RunBounds } from "../backend.js";
3
3
  /**
4
4
  * How the source spends a connection. The defaults come from measuring Yandex 360 (cli-testing,
5
5
  * performance/mail/yandex-imap-sync): a header FETCH takes 0.1 to 0.7 s per message and the time per message grows with
@@ -52,11 +52,21 @@ export interface Connections {
52
52
  /** `work` on a connection with no folder selected, retried like every read. */
53
53
  onServer<T>(work: (open: ImapFlow) => Promise<T>): Promise<T>;
54
54
  inFolder<T>(folder: string, work: Work<T>, expected?: string, slot?: number): Promise<T>;
55
+ /**
56
+ * `work` with `folder` selected for writing, sent once: a write that may have reached the server is not sent again.
57
+ * With `expected`, a folder whose UIDVALIDITY is not that is refused before anything is sent.
58
+ */
59
+ writeIn<T>(folder: string, work: Work<T>, expected?: string): Promise<T>;
60
+ /** `work` on a connection with no folder selected, sent once, for a change to the folders themselves. */
61
+ writeOnServer<T>(work: (open: ImapFlow) => Promise<T>): Promise<T>;
55
62
  /** Runs `work` over the batches on up to `connections` connections; the first failure stops the others. */
56
63
  spread<I, O, E = never>(folder: string, batches: I[], work: (open: ImapFlow, batch: I) => Promise<O>, expected: string | undefined, onError?: (error: unknown, batch: I) => E): Promise<(O | E)[]>;
57
64
  close(): Promise<void>;
58
65
  }
59
- /** The connections of one source, opened on first use; the password never leaves this closure. */
60
- export declare const imapConnections: (endpoint: MailEndpoint, password: string, tuning?: ImapTuning) => Connections;
66
+ /**
67
+ * The connections of one source, opened on first use. Each login asks the credential, so a reconnect an hour later
68
+ * gets a refreshed token; the secret never leaves this closure.
69
+ */
70
+ export declare const imapConnections: (endpoint: MailEndpoint, credential: MailCredential, tuning?: ImapTuning) => Connections;
61
71
  export {};
62
72
  //# sourceMappingURL=connection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/mail/imap/connection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAG5D;;;;;;GAMG;AACH,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4GAA4G;IAC5G,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,0DAA0D;IAC1D,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;IACrD,8FAA8F;IAC9F,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3D,MAAM,CAAC,EAAE,MAAM,MAAM,CAAA;IACrB,qEAAqE;IACrE,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAA;CAC3D;AAED,eAAO,MAAM,aAAa;aACxB,QAAQ,EAAE,EAAE;aACZ,SAAS,EAAE,GAAG;aACd,SAAS,EAAE,EAAE;aACb,UAAU;aACV,WAAW,EAAE,CAAC;aACd,gBAAgB,EAAE,KAAM;aACxB,OAAO;iBAAI,WAAW,EAAE,IAAK;iBAAE,UAAU,EAAE,KAAM;;aACjD,WAAW,EAAE,CAAC;CACN,CAAA;AAOV,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;AAE/D,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,2GAA2G;IAC3G,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC7D,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACxF,2GAA2G;IAC3G,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,EACpB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,CAAC,EAAE,EACZ,IAAI,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAC9C,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,GACxC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAA;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,kGAAkG;AAClG,eAAO,MAAM,eAAe,aAAc,YAAY,YAAY,MAAM,WAAU,UAAU,KAAQ,WA4KnG,CAAA"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/mail/imap/connection.ts"],"names":[],"mappings":"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"}