zele 0.3.16 → 0.3.20

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 (90) hide show
  1. package/README.md +155 -36
  2. package/dist/api-utils.d.ts +14 -0
  3. package/dist/api-utils.js +20 -0
  4. package/dist/api-utils.js.map +1 -1
  5. package/dist/auth.d.ts +71 -9
  6. package/dist/auth.js +186 -10
  7. package/dist/auth.js.map +1 -1
  8. package/dist/cli-types.d.ts +4 -0
  9. package/dist/cli-types.js +6 -0
  10. package/dist/cli-types.js.map +1 -0
  11. package/dist/cli.js +1 -5
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/attachment.d.ts +2 -2
  14. package/dist/commands/attachment.js +2 -0
  15. package/dist/commands/attachment.js.map +1 -1
  16. package/dist/commands/auth-cmd.d.ts +2 -2
  17. package/dist/commands/auth-cmd.js +104 -6
  18. package/dist/commands/auth-cmd.js.map +1 -1
  19. package/dist/commands/calendar.d.ts +2 -2
  20. package/dist/commands/calendar.js.map +1 -1
  21. package/dist/commands/draft.d.ts +2 -2
  22. package/dist/commands/draft.js +58 -4
  23. package/dist/commands/draft.js.map +1 -1
  24. package/dist/commands/filter.d.ts +2 -2
  25. package/dist/commands/filter.js +7 -2
  26. package/dist/commands/filter.js.map +1 -1
  27. package/dist/commands/label.d.ts +2 -2
  28. package/dist/commands/label.js +19 -9
  29. package/dist/commands/label.js.map +1 -1
  30. package/dist/commands/mail-actions.d.ts +2 -2
  31. package/dist/commands/mail-actions.js +290 -1
  32. package/dist/commands/mail-actions.js.map +1 -1
  33. package/dist/commands/mail.d.ts +2 -2
  34. package/dist/commands/mail.js +90 -23
  35. package/dist/commands/mail.js.map +1 -1
  36. package/dist/commands/profile.d.ts +2 -2
  37. package/dist/commands/profile.js +25 -18
  38. package/dist/commands/profile.js.map +1 -1
  39. package/dist/commands/watch.d.ts +2 -2
  40. package/dist/commands/watch.js.map +1 -1
  41. package/dist/db.js +24 -0
  42. package/dist/db.js.map +1 -1
  43. package/dist/generated/internal/class.js +2 -2
  44. package/dist/generated/internal/class.js.map +1 -1
  45. package/dist/generated/internal/prismaNamespace.d.ts +2 -0
  46. package/dist/generated/internal/prismaNamespace.js +2 -0
  47. package/dist/generated/internal/prismaNamespace.js.map +1 -1
  48. package/dist/generated/internal/prismaNamespaceBrowser.d.ts +2 -0
  49. package/dist/generated/internal/prismaNamespaceBrowser.js +2 -0
  50. package/dist/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  51. package/dist/generated/models/Account.d.ts +97 -1
  52. package/dist/gmail-client.d.ts +73 -3
  53. package/dist/gmail-client.js +165 -5
  54. package/dist/gmail-client.js.map +1 -1
  55. package/dist/imap-smtp-client.d.ts +306 -0
  56. package/dist/imap-smtp-client.js +1349 -0
  57. package/dist/imap-smtp-client.js.map +1 -0
  58. package/dist/mail-tui.js.map +1 -1
  59. package/dist/unsubscribe.d.ts +76 -0
  60. package/dist/unsubscribe.js +224 -0
  61. package/dist/unsubscribe.js.map +1 -0
  62. package/package.json +6 -3
  63. package/schema.prisma +7 -5
  64. package/skills/zele/SKILL.md +26 -96
  65. package/src/api-utils.ts +20 -0
  66. package/src/auth.ts +282 -14
  67. package/src/cli-types.ts +8 -0
  68. package/src/cli.ts +2 -7
  69. package/src/commands/attachment.ts +3 -2
  70. package/src/commands/auth-cmd.ts +114 -8
  71. package/src/commands/calendar.ts +2 -2
  72. package/src/commands/draft.ts +65 -6
  73. package/src/commands/filter.ts +11 -5
  74. package/src/commands/label.ts +24 -13
  75. package/src/commands/mail-actions.ts +317 -5
  76. package/src/commands/mail.ts +97 -25
  77. package/src/commands/profile.ts +29 -19
  78. package/src/commands/watch.ts +2 -2
  79. package/src/db.ts +28 -0
  80. package/src/generated/internal/class.ts +2 -2
  81. package/src/generated/internal/prismaNamespace.ts +2 -0
  82. package/src/generated/internal/prismaNamespaceBrowser.ts +2 -0
  83. package/src/generated/models/Account.ts +97 -1
  84. package/src/gmail-client.test.ts +155 -2
  85. package/src/gmail-client.ts +258 -6
  86. package/src/imap-smtp-client.ts +1560 -0
  87. package/src/mail-tui.tsx +2 -1
  88. package/src/schema.sql +2 -0
  89. package/src/unsubscribe.test.ts +487 -0
  90. package/src/unsubscribe.ts +255 -0
@@ -0,0 +1,306 @@
1
+ import { AuthError, ApiError, UnsupportedError, EmptyThreadError, NotFoundError } from './api-utils.js';
2
+ import type { AccountId, ImapSmtpCredentials } from './auth.js';
3
+ import type { ThreadListResult, ThreadResult, ParsedMessage, WatchEvent, Sender } from './gmail-client.js';
4
+ export declare class ImapSmtpClient {
5
+ private imapCreds;
6
+ private smtpCreds;
7
+ private account;
8
+ private smtpTransporter;
9
+ constructor({ credentials, account }: {
10
+ credentials: ImapSmtpCredentials;
11
+ account: AccountId;
12
+ });
13
+ private createImapClient;
14
+ /**
15
+ * Resolve a zele folder name (inbox, sent, trash, etc.) to the actual IMAP
16
+ * mailbox path by checking RFC 6154 specialUse attributes first, then
17
+ * falling back to common mailbox name variants.
18
+ */
19
+ private resolveMailboxPath;
20
+ /** Run an IMAP operation with auto-connect/logout.
21
+ * The entire callback is wrapped in imapBoundary so any IMAP error
22
+ * (getMailboxLock, search, fetch, etc.) becomes an error value. */
23
+ private withImap;
24
+ private getSmtpTransporter;
25
+ listThreads({ query, folder, maxResults, labelIds, pageToken, }?: {
26
+ query?: string;
27
+ folder?: string;
28
+ maxResults?: number;
29
+ labelIds?: string[];
30
+ pageToken?: string;
31
+ }): Promise<ThreadListResult | AuthError | ApiError>;
32
+ getThread({ threadId }: {
33
+ threadId: string;
34
+ }): Promise<ThreadResult>;
35
+ getMessage({ messageId }: {
36
+ messageId: string;
37
+ }): Promise<ParsedMessage | AuthError | ApiError>;
38
+ getRawMessage({ messageId }: {
39
+ messageId: string;
40
+ }): Promise<string | NotFoundError | AuthError | ApiError>;
41
+ sendMessage({ to, subject, body, cc, bcc, inReplyTo, references, attachments, }: {
42
+ to: Array<{
43
+ name?: string;
44
+ email: string;
45
+ }>;
46
+ subject: string;
47
+ body: string;
48
+ cc?: Array<{
49
+ name?: string;
50
+ email: string;
51
+ }>;
52
+ bcc?: Array<{
53
+ name?: string;
54
+ email: string;
55
+ }>;
56
+ threadId?: string;
57
+ inReplyTo?: string;
58
+ references?: string;
59
+ attachments?: Array<{
60
+ filename: string;
61
+ mimeType: string;
62
+ content: Buffer;
63
+ }>;
64
+ fromEmail?: string;
65
+ }): Promise<{
66
+ id: string;
67
+ threadId: string;
68
+ labelIds: string[];
69
+ } | UnsupportedError | AuthError | ApiError>;
70
+ replyToThread({ threadId, body, replyAll, cc, fromEmail, }: {
71
+ threadId: string;
72
+ body: string;
73
+ replyAll?: boolean;
74
+ cc?: Array<{
75
+ email: string;
76
+ }>;
77
+ fromEmail?: string;
78
+ }): Promise<EmptyThreadError | UnsupportedError | AuthError | ApiError | {
79
+ id: string;
80
+ threadId: string;
81
+ labelIds: string[];
82
+ }>;
83
+ forwardThread({ threadId, to, body, fromEmail, }: {
84
+ threadId: string;
85
+ to: Array<{
86
+ email: string;
87
+ }>;
88
+ body?: string;
89
+ fromEmail?: string;
90
+ }): Promise<EmptyThreadError | UnsupportedError | AuthError | ApiError | {
91
+ id: string;
92
+ threadId: string;
93
+ labelIds: string[];
94
+ }>;
95
+ star({ threadIds }: {
96
+ threadIds: string[];
97
+ }): Promise<void | AuthError | ApiError>;
98
+ unstar({ threadIds }: {
99
+ threadIds: string[];
100
+ }): Promise<void | AuthError | ApiError>;
101
+ markAsRead({ threadIds }: {
102
+ threadIds: string[];
103
+ }): Promise<void | AuthError | ApiError>;
104
+ markAsUnread({ threadIds }: {
105
+ threadIds: string[];
106
+ }): Promise<void | AuthError | ApiError>;
107
+ trash({ threadId }: {
108
+ threadId: string;
109
+ }): Promise<void | AuthError | ApiError>;
110
+ untrash({ threadId }: {
111
+ threadId: string;
112
+ }): Promise<void | AuthError | ApiError>;
113
+ archive({ threadIds }: {
114
+ threadIds: string[];
115
+ }): Promise<void | AuthError | ApiError>;
116
+ markAsSpam({ threadIds }: {
117
+ threadIds: string[];
118
+ }): Promise<void | AuthError | ApiError>;
119
+ unmarkSpam({ threadIds }: {
120
+ threadIds: string[];
121
+ }): Promise<void | AuthError | ApiError>;
122
+ trashAllSpam(): Promise<{
123
+ count: number;
124
+ } | AuthError | ApiError>;
125
+ listLabels(): Promise<UnsupportedError>;
126
+ modifyLabels(_opts: {
127
+ threadIds: string[];
128
+ addLabelIds: string[];
129
+ removeLabelIds: string[];
130
+ }): Promise<UnsupportedError>;
131
+ getProfile(): Promise<{
132
+ emailAddress: string;
133
+ messagesTotal: number;
134
+ threadsTotal: number;
135
+ historyId: string;
136
+ } | AuthError | ApiError>;
137
+ getEmailAliases(): Promise<Array<{
138
+ email: string;
139
+ name?: string;
140
+ primary: boolean;
141
+ }> | AuthError | ApiError>;
142
+ getAttachment({ messageId, attachmentId }: {
143
+ messageId: string;
144
+ attachmentId: string;
145
+ }): Promise<string | NotFoundError | AuthError | ApiError>;
146
+ watchInbox({ folder, intervalMs, query, once, }?: {
147
+ folder?: string;
148
+ intervalMs?: number;
149
+ query?: string;
150
+ once?: boolean;
151
+ }): AsyncGenerator<WatchEvent>;
152
+ listDrafts({ query, maxResults, pageToken, }?: {
153
+ query?: string;
154
+ maxResults?: number;
155
+ pageToken?: string;
156
+ }): Promise<{
157
+ drafts: Array<{
158
+ id: string;
159
+ subject: string;
160
+ to: string[];
161
+ date: string;
162
+ }>;
163
+ nextPageToken: string | null;
164
+ } | AuthError | ApiError>;
165
+ createDraft({ to, subject, body, cc, bcc, threadId, fromEmail, }: {
166
+ to: Array<{
167
+ name?: string;
168
+ email: string;
169
+ }>;
170
+ subject: string;
171
+ body: string;
172
+ cc?: Array<{
173
+ name?: string;
174
+ email: string;
175
+ }>;
176
+ bcc?: Array<{
177
+ name?: string;
178
+ email: string;
179
+ }>;
180
+ threadId?: string;
181
+ fromEmail?: string;
182
+ attachments?: Array<{
183
+ filename: string;
184
+ mimeType: string;
185
+ content: Buffer;
186
+ }>;
187
+ }): Promise<{
188
+ id: string;
189
+ message: {
190
+ id: string;
191
+ };
192
+ threadId: string;
193
+ }>;
194
+ getDraft({ draftId }: {
195
+ draftId: string;
196
+ }): Promise<{
197
+ id: string;
198
+ message: ParsedMessage;
199
+ to: Sender[];
200
+ cc: Sender[];
201
+ bcc: Sender[];
202
+ }>;
203
+ sendDraft({ draftId }: {
204
+ draftId: string;
205
+ }): Promise<AuthError | ApiError | UnsupportedError | {
206
+ id: string;
207
+ threadId: string;
208
+ labelIds: string[];
209
+ }>;
210
+ deleteDraft({ draftId }: {
211
+ draftId: string;
212
+ }): Promise<void | AuthError | ApiError>;
213
+ /**
214
+ * Update an existing draft. IMAP has no native update — we delete the old
215
+ * draft and APPEND a new message to the Drafts folder.
216
+ */
217
+ updateDraft({ draftId, to, subject, body, cc, bcc, fromEmail, }: {
218
+ draftId: string;
219
+ to: Array<{
220
+ name?: string;
221
+ email: string;
222
+ }>;
223
+ subject: string;
224
+ body: string;
225
+ cc?: Array<{
226
+ name?: string;
227
+ email: string;
228
+ }>;
229
+ bcc?: Array<{
230
+ name?: string;
231
+ email: string;
232
+ }>;
233
+ threadId?: string;
234
+ fromEmail?: string;
235
+ attachments?: Array<{
236
+ filename: string;
237
+ mimeType: string;
238
+ content: Buffer;
239
+ }>;
240
+ }): Promise<AuthError | ApiError | {
241
+ id: string;
242
+ message: {
243
+ id: string;
244
+ };
245
+ threadId: string;
246
+ }>;
247
+ /**
248
+ * Create a draft reply to a thread. Resolves reply-to, reply-all CCs,
249
+ * and sets In-Reply-To/References headers, then appends to Drafts.
250
+ */
251
+ createDraftReply({ threadId, body, replyAll, cc, fromEmail, }: {
252
+ threadId: string;
253
+ body: string;
254
+ replyAll?: boolean;
255
+ cc?: Array<{
256
+ email: string;
257
+ }>;
258
+ fromEmail?: string;
259
+ }): Promise<EmptyThreadError | AuthError | ApiError | {
260
+ id: string;
261
+ message: {
262
+ id: string;
263
+ };
264
+ threadId: string;
265
+ }>;
266
+ /**
267
+ * Create a draft forwarding a thread. Builds the forwarded-message body
268
+ * and appends to Drafts folder.
269
+ */
270
+ createDraftForward({ threadId, to, body, fromEmail, }: {
271
+ threadId: string;
272
+ to: Array<{
273
+ email: string;
274
+ }>;
275
+ body?: string;
276
+ fromEmail?: string;
277
+ }): Promise<EmptyThreadError | AuthError | ApiError | {
278
+ id: string;
279
+ message: {
280
+ id: string;
281
+ };
282
+ threadId: string;
283
+ }>;
284
+ listFolders(): Promise<Array<{
285
+ name: string;
286
+ path: string;
287
+ specialUse?: string;
288
+ flags: string[];
289
+ }> | AuthError | ApiError>;
290
+ invalidateThreads(_threadIds: string[]): Promise<void>;
291
+ invalidateThread(_threadId: string): Promise<void>;
292
+ /** Modify IMAP flags on messages. Groups by folder for efficiency. */
293
+ private modifyFlags;
294
+ /** Check if a message has attachments from its bodyStructure. */
295
+ private hasAttachments;
296
+ /** Parse an imapflow FetchMessageObject into our ParsedMessage type. */
297
+ private parseImapMessage;
298
+ /** Extract body text from raw RFC 2822 source. */
299
+ private extractBodyFromSource;
300
+ private parseBody;
301
+ private parseMultipart;
302
+ private decodeTransferEncoding;
303
+ private getHeader;
304
+ /** Recursively collect attachment metadata from bodyStructure. */
305
+ private collectAttachments;
306
+ }