@bobfrankston/iflow 1.0.2 → 1.0.4

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.
@@ -0,0 +1,42 @@
1
+ {
2
+ "folders": [
3
+ {
4
+ "path": "."
5
+ },
6
+ {
7
+ "path": "../imail"
8
+ },
9
+ {
10
+ "path": "../uinfo"
11
+ },
12
+ {
13
+ "path": "../mlconfig"
14
+ },
15
+ {
16
+ "path": "../config"
17
+ }
18
+ ],
19
+ "settings": {
20
+ "workbench.colorCustomizations": {
21
+ "activityBar.activeBackground": "#ebe835",
22
+ "activityBar.background": "#ebe835",
23
+ "activityBar.foreground": "#15202b",
24
+ "activityBar.inactiveForeground": "#15202b99",
25
+ "activityBarBadge.background": "#11aeab",
26
+ "activityBarBadge.foreground": "#e7e7e7",
27
+ "commandCenter.border": "#15202b99",
28
+ "sash.hoverBorder": "#ebe835",
29
+ "statusBar.background": "#d9d515",
30
+ "statusBar.foreground": "#15202b",
31
+ "statusBarItem.hoverBackground": "#aaa710",
32
+ "statusBarItem.remoteBackground": "#d9d515",
33
+ "statusBarItem.remoteForeground": "#15202b",
34
+ "titleBar.activeBackground": "#d9d515",
35
+ "titleBar.activeForeground": "#15202b",
36
+ "titleBar.inactiveBackground": "#d9d51599",
37
+ "titleBar.inactiveForeground": "#15202b99"
38
+ },
39
+ "peacock.color": "#d9d515",
40
+ "workbench.colorTheme": "Visual Studio 2019 Dark"
41
+ }
42
+ }
@@ -1,4 +1,4 @@
1
- import imapflow from 'imapflow';
1
+ import imapflow, { SearchObject } from 'imapflow';
2
2
  import { ImapClientConfig, FetchedMessage } from './types.js';
3
3
  export interface iFetchOptions {
4
4
  source: boolean;
@@ -8,15 +8,68 @@ export declare class ImapClient {
8
8
  private config;
9
9
  private isDestroying;
10
10
  private connectionPromise;
11
+ private initialized;
12
+ private reconnectAttempts;
11
13
  constructor(cfg: ImapClientConfig);
12
14
  private init;
15
+ private getAuth;
13
16
  private handleReconnection;
14
17
  private cleanup;
15
18
  private withConnection;
16
19
  getMessagesCount(mailbox: string): Promise<number>;
20
+ /** Get all UIDs in a mailbox (lightweight — no message data fetched) */
21
+ getUids(mailbox: string): Promise<number[]>;
22
+ /**
23
+ * Search messages in a mailbox using IMAP SEARCH criteria.
24
+ * Returns UIDs of matching messages. Use fetchMessageByUid to get full content.
25
+ *
26
+ * @param mailbox Mailbox path (e.g., "INBOX")
27
+ * @param criteria imapflow SearchObject — supports from, to, subject, body,
28
+ * before/since dates, flags, size, header, boolean (or/not), and Gmail raw search (gmraw).
29
+ * See: https://imapflow.com/module-imapflow-ImapFlow.html#search
30
+ * @returns Array of matching UIDs
31
+ *
32
+ * @example
33
+ * // Text search in body
34
+ * await client.searchMessages("INBOX", { body: "meeting" });
35
+ * // From + date range
36
+ * await client.searchMessages("INBOX", { from: "bob", since: new Date("2026-01-01") });
37
+ * // Gmail native search
38
+ * await client.searchMessages("INBOX", { gmraw: "has:attachment from:alice" });
39
+ */
40
+ searchMessages(mailbox: string, criteria: SearchObject): Promise<number[]>;
17
41
  fetchMessageByDate(mailbox: string, start: Date | number, endingx?: Date | number, options?: iFetchOptions): Promise<FetchedMessage[]>;
18
42
  fetchMessages(mailbox: string, end: number, count: number, options?: iFetchOptions): Promise<FetchedMessage[]>;
43
+ /** Fetch messages with UID greater than sinceUid */
44
+ fetchMessagesSinceUid(mailbox: string, sinceUid: number, options?: iFetchOptions): Promise<FetchedMessage[]>;
45
+ /** Fetch a single message by UID, returning source by default */
46
+ fetchMessageByUid(mailbox: string, uid: number, options?: iFetchOptions): Promise<FetchedMessage | null>;
19
47
  moveMessage(msg: FetchedMessage, sourceMailbox: string, targetMailbox: string): Promise<void>;
48
+ /**
49
+ * Append a raw message to a mailbox
50
+ * @param mailbox Target mailbox path
51
+ * @param rawMessage Raw RFC822 message content
52
+ * @param flags Optional message flags (e.g., ['\\Seen', '\\Flagged'])
53
+ * @param internalDate Optional internal date for the message
54
+ */
55
+ appendMessage(mailbox: string, rawMessage: string | Buffer, flags?: string[], internalDate?: Date): Promise<false | imapflow.AppendResponseObject>;
56
+ /**
57
+ * Copy a message to another IMAP server/account
58
+ * @param msg Message to copy
59
+ * @param targetClient Target ImapClient (different server/account)
60
+ * @param targetMailbox Target mailbox on the destination server
61
+ * @param preserveFlags Whether to copy message flags (default: true)
62
+ */
63
+ copyMessageToServer(msg: FetchedMessage, targetClient: ImapClient, targetMailbox: string, preserveFlags?: boolean): Promise<void>;
64
+ /**
65
+ * Move a message to another IMAP server/account (copy then delete from source)
66
+ * @param msg Message to move
67
+ * @param sourceMailbox Source mailbox path
68
+ * @param targetClient Target ImapClient (different server/account)
69
+ * @param targetMailbox Target mailbox on the destination server
70
+ * @param preserveFlags Whether to copy message flags (default: true)
71
+ */
72
+ moveMessageToServer(msg: FetchedMessage, sourceMailbox: string, targetClient: ImapClient, targetMailbox: string, preserveFlags?: boolean): Promise<void>;
20
73
  getFolderList(): Promise<imapflow.ListResponse[]>;
21
74
  getFolderTree(): Promise<imapflow.ListTreeResponse>;
22
75
  getSpecialFolders(mailboxes: Awaited<ReturnType<ImapClient["getFolderList"]>>): {
@@ -29,6 +82,17 @@ export declare class ImapClient {
29
82
  junk: string;
30
83
  };
31
84
  createmailbox(folder: string[] | string): Promise<imapflow.MailboxCreateResponse>;
85
+ /** Add flags to a message by UID */
86
+ addFlags(mailbox: string, uid: number, flags: string[]): Promise<boolean>;
87
+ /** Remove flags from a message by UID */
88
+ removeFlags(mailbox: string, uid: number, flags: string[]): Promise<boolean>;
89
+ /** Get flags for a message by UID */
90
+ getFlags(mailbox: string, uid: number): Promise<string[]>;
91
+ /** Delete a message by UID from a mailbox */
92
+ deleteMessageByUid(mailbox: string, uid: number): Promise<void>;
93
+ /** Watch a mailbox for new messages via IMAP IDLE. Calls onNew when messages arrive.
94
+ * Returns a stop function to end the watch. */
95
+ watchMailbox(mailbox: string, onNew: (count: number) => void): Promise<() => void>;
32
96
  logout(): Promise<void>;
33
97
  connect(): Promise<void>;
34
98
  }
@@ -11,57 +11,80 @@ export class ImapClient {
11
11
  config;
12
12
  isDestroying = false;
13
13
  connectionPromise = null;
14
+ initialized;
15
+ reconnectAttempts = 0;
14
16
  constructor(cfg) {
15
17
  this.config = cfg;
16
- this.init();
18
+ if (!cfg.password && !cfg.tokenProvider) {
19
+ throw new Error('ImapClientConfig requires either password or tokenProvider');
20
+ }
21
+ this.initialized = this.init();
17
22
  }
18
- init() {
23
+ async init() {
24
+ const auth = await this.getAuth();
19
25
  this.client = new ImapFlow({
20
26
  host: this.config.server,
21
27
  port: this.config.port,
22
28
  secure: true,
23
- auth: {
24
- user: this.config.username,
25
- pass: this.config.password
26
- },
29
+ auth,
27
30
  logger: false, // Disable internal logging
31
+ tls: {
32
+ rejectUnauthorized: this.config.rejectUnauthorized !== false // Default to true (secure), but allow override
33
+ }
28
34
  });
29
35
  // Set up error handlers
30
36
  this.client.on('error', (err) => {
31
- console.error(`ImapFlow socket error: ${err.message}`);
37
+ console.error(`${new Date().toISOString()} ImapFlow socket error: ${err.message}`);
32
38
  if (!this.isDestroying) {
33
39
  this.handleReconnection();
34
40
  }
35
41
  });
36
42
  this.client.on('close', () => {
37
- console.error(`ImapFlow connection closed`);
43
+ console.error(`${new Date().toISOString()} ImapFlow connection closed`);
38
44
  if (!this.isDestroying) {
39
45
  this.handleReconnection();
40
46
  }
41
47
  });
42
48
  }
49
+ async getAuth() {
50
+ if (this.config.tokenProvider) {
51
+ const accessToken = await this.config.tokenProvider();
52
+ return { user: this.config.username, accessToken };
53
+ }
54
+ return { user: this.config.username, pass: this.config.password };
55
+ }
43
56
  async handleReconnection() {
44
57
  if (this.connectionPromise)
45
58
  return; // Already reconnecting
59
+ this.reconnectAttempts++;
60
+ const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts - 1), 30000); // Backoff: 1s, 2s, 4s, ... 30s max
46
61
  this.connectionPromise = new Promise(async (resolve) => {
47
62
  try {
48
- // Clean up old client
63
+ // Clean up old client listeners
49
64
  this.cleanup();
50
- // Wait before reconnecting
51
- await new Promise(r => setTimeout(r, 1000));
52
- // Reinitialize
53
- this.init();
65
+ // Force-close the underlying socket to stop repeated error events
66
+ try {
67
+ if (this.client) {
68
+ this.client.close();
69
+ }
70
+ }
71
+ catch { /* ignore close errors */ }
72
+ console.log(`${new Date().toISOString()} Reconnecting (attempt ${this.reconnectAttempts}, waiting ${delay}ms)...`);
73
+ await new Promise(r => setTimeout(r, delay));
74
+ // Reinitialize (re-fetches token if using OAuth)
75
+ await this.init();
54
76
  try {
55
77
  await this.client.connect();
56
- console.log('Reconnected successfully');
78
+ console.log(`${new Date().toISOString()} Reconnected successfully`);
79
+ this.reconnectAttempts = 0; // Reset on success
57
80
  }
58
81
  catch (err) {
59
- console.error('Reconnection failed, will retry:', err);
82
+ console.error(`${new Date().toISOString()} Reconnection failed: ${err.message}`);
60
83
  // Will trigger another reconnection attempt via error handler
61
84
  }
62
85
  }
63
86
  catch (err) {
64
- console.error('Error during reconnection process:', err);
87
+ console.error(`${new Date().toISOString()} Error during reconnection process: ${err.message}`);
65
88
  }
66
89
  finally {
67
90
  this.connectionPromise = null;
@@ -83,13 +106,15 @@ export class ImapClient {
83
106
  return await operation();
84
107
  }
85
108
  catch (err) {
86
- console.error(`Operation failed: ${err.message}`);
109
+ console.error(`${new Date().toISOString()} Operation failed: ${err.message}`);
87
110
  // Check if it's a connection-related error
88
111
  if (err.code === 'ECONNRESET' || err.code === 'ENOTFOUND' ||
89
112
  err.code === 'ETIMEDOUT' || err.code === 'ECONNREFUSED' ||
90
- err.message.includes('connection') || err.message.includes('socket')) {
113
+ err.code === 'CERT_HAS_EXPIRED' || err.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' ||
114
+ err.message.includes('connection') || err.message.includes('socket') ||
115
+ err.message.includes('certificate')) {
91
116
  if (!this.isDestroying) {
92
- console.log('Connection error detected, attempting reconnection...');
117
+ console.log(`${new Date().toISOString()} Connection error detected, attempting reconnection...`);
93
118
  await this.handleReconnection();
94
119
  // Retry the operation once after reconnection
95
120
  try {
@@ -97,7 +122,7 @@ export class ImapClient {
97
122
  return await operation();
98
123
  }
99
124
  catch (retryErr) {
100
- console.error(`Operation failed after reconnection: ${retryErr}`);
125
+ console.error(`${new Date().toISOString()} Operation failed after reconnection: ${retryErr}`);
101
126
  throw retryErr;
102
127
  }
103
128
  }
@@ -113,6 +138,55 @@ export class ImapClient {
113
138
  return status.messages;
114
139
  });
115
140
  }
141
+ /** Get all UIDs in a mailbox (lightweight — no message data fetched) */
142
+ async getUids(mailbox) {
143
+ try {
144
+ await this.connect();
145
+ await this.client.mailboxOpen(mailbox, { readOnly: true });
146
+ const uids = await this.client.search({ all: true }, { uid: true });
147
+ return uids;
148
+ }
149
+ catch (error) {
150
+ console.error(`Error getting UIDs: ${error.message}`);
151
+ throw error;
152
+ }
153
+ finally {
154
+ await this.client.mailboxClose();
155
+ }
156
+ }
157
+ /**
158
+ * Search messages in a mailbox using IMAP SEARCH criteria.
159
+ * Returns UIDs of matching messages. Use fetchMessageByUid to get full content.
160
+ *
161
+ * @param mailbox Mailbox path (e.g., "INBOX")
162
+ * @param criteria imapflow SearchObject — supports from, to, subject, body,
163
+ * before/since dates, flags, size, header, boolean (or/not), and Gmail raw search (gmraw).
164
+ * See: https://imapflow.com/module-imapflow-ImapFlow.html#search
165
+ * @returns Array of matching UIDs
166
+ *
167
+ * @example
168
+ * // Text search in body
169
+ * await client.searchMessages("INBOX", { body: "meeting" });
170
+ * // From + date range
171
+ * await client.searchMessages("INBOX", { from: "bob", since: new Date("2026-01-01") });
172
+ * // Gmail native search
173
+ * await client.searchMessages("INBOX", { gmraw: "has:attachment from:alice" });
174
+ */
175
+ async searchMessages(mailbox, criteria) {
176
+ try {
177
+ await this.connect();
178
+ await this.client.mailboxOpen(mailbox, { readOnly: true });
179
+ const uids = await this.client.search(criteria, { uid: true });
180
+ return uids;
181
+ }
182
+ catch (error) {
183
+ console.error(`Search error in ${mailbox}: ${error.message}`);
184
+ throw error;
185
+ }
186
+ finally {
187
+ await this.client.mailboxClose();
188
+ }
189
+ }
116
190
  async fetchMessageByDate(mailbox, start, endingx, options) {
117
191
  try {
118
192
  options = { ...defaultFetchOptions, ...options }; // Merge with default options
@@ -183,6 +257,61 @@ export class ImapClient {
183
257
  // await this.client.logout();
184
258
  }
185
259
  }
260
+ /** Fetch messages with UID greater than sinceUid */
261
+ async fetchMessagesSinceUid(mailbox, sinceUid, options) {
262
+ try {
263
+ options = { ...defaultFetchOptions, ...options };
264
+ await this.connect();
265
+ await this.client.mailboxOpen(mailbox, { readOnly: true });
266
+ // UID range: sinceUid+1:* means all UIDs after sinceUid
267
+ const range = `${sinceUid + 1}:*`;
268
+ const fetchQuery = {
269
+ uid: true,
270
+ envelope: true,
271
+ flags: true,
272
+ headers: true,
273
+ source: options.source
274
+ };
275
+ const messageObjects = await this.client.fetchAll(range, fetchQuery, { uid: true });
276
+ return messageObjects.map(msg => new FetchedMessage(msg));
277
+ }
278
+ catch (error) {
279
+ // "Nothing to fetch" just means no new messages
280
+ if (error.responseText?.includes("Nothing to fetch"))
281
+ return [];
282
+ console.error(`Error fetching messages since UID ${sinceUid}: ${error.message}`);
283
+ throw error;
284
+ }
285
+ finally {
286
+ await this.client.mailboxClose();
287
+ }
288
+ }
289
+ /** Fetch a single message by UID, returning source by default */
290
+ async fetchMessageByUid(mailbox, uid, options) {
291
+ try {
292
+ options = { ...defaultFetchOptions, ...options };
293
+ await this.connect();
294
+ await this.client.mailboxOpen(mailbox, { readOnly: true });
295
+ const fetchQuery = {
296
+ uid: true,
297
+ envelope: true,
298
+ flags: true,
299
+ headers: true,
300
+ source: options.source
301
+ };
302
+ const msg = await this.client.fetchOne(uid, fetchQuery, { uid: true });
303
+ if (!msg)
304
+ return null;
305
+ return new FetchedMessage(msg);
306
+ }
307
+ catch (error) {
308
+ console.error(`Error fetching message UID ${uid}: ${error.message}`);
309
+ throw error;
310
+ }
311
+ finally {
312
+ await this.client.mailboxClose();
313
+ }
314
+ }
186
315
  // async moveMessage(uid: number, sourceMailbox: string, targetMailbox: string) {
187
316
  async moveMessage(msg, sourceMailbox, targetMailbox) {
188
317
  try {
@@ -208,6 +337,82 @@ export class ImapClient {
208
337
  await this.client.mailboxClose();
209
338
  }
210
339
  }
340
+ /**
341
+ * Append a raw message to a mailbox
342
+ * @param mailbox Target mailbox path
343
+ * @param rawMessage Raw RFC822 message content
344
+ * @param flags Optional message flags (e.g., ['\\Seen', '\\Flagged'])
345
+ * @param internalDate Optional internal date for the message
346
+ */
347
+ async appendMessage(mailbox, rawMessage, flags, internalDate) {
348
+ try {
349
+ await this.connect();
350
+ const result = await this.client.append(mailbox, rawMessage, flags, internalDate);
351
+ return result;
352
+ }
353
+ catch (error) {
354
+ console.error(`Error appending message to ${mailbox}: ${error.message}`);
355
+ throw error;
356
+ }
357
+ }
358
+ /**
359
+ * Copy a message to another IMAP server/account
360
+ * @param msg Message to copy
361
+ * @param targetClient Target ImapClient (different server/account)
362
+ * @param targetMailbox Target mailbox on the destination server
363
+ * @param preserveFlags Whether to copy message flags (default: true)
364
+ */
365
+ async copyMessageToServer(msg, targetClient, targetMailbox, preserveFlags = true) {
366
+ try {
367
+ if (!msg.source) {
368
+ throw new Error('Message source is required for cross-server copy. Fetch with source: true');
369
+ }
370
+ // Prepare flags if preserving them
371
+ const flags = [];
372
+ if (preserveFlags) {
373
+ if (msg.flagged)
374
+ flags.push('\\Flagged');
375
+ if (msg.seen)
376
+ flags.push('\\Seen');
377
+ if (msg.answered)
378
+ flags.push('\\Answered');
379
+ if (msg.draft)
380
+ flags.push('\\Draft');
381
+ }
382
+ // Append to target server
383
+ const date = msg.internalDate instanceof Date ? msg.internalDate : undefined;
384
+ await targetClient.appendMessage(targetMailbox, msg.source, flags, date);
385
+ }
386
+ catch (error) {
387
+ console.error(`Error copying message to another server: ${error.message}`);
388
+ throw error;
389
+ }
390
+ }
391
+ /**
392
+ * Move a message to another IMAP server/account (copy then delete from source)
393
+ * @param msg Message to move
394
+ * @param sourceMailbox Source mailbox path
395
+ * @param targetClient Target ImapClient (different server/account)
396
+ * @param targetMailbox Target mailbox on the destination server
397
+ * @param preserveFlags Whether to copy message flags (default: true)
398
+ */
399
+ async moveMessageToServer(msg, sourceMailbox, targetClient, targetMailbox, preserveFlags = true) {
400
+ try {
401
+ // First copy to target
402
+ await this.copyMessageToServer(msg, targetClient, targetMailbox, preserveFlags);
403
+ // Then delete from source
404
+ await this.connect();
405
+ await this.client.mailboxOpen(sourceMailbox, { readOnly: false });
406
+ await this.client.messageDelete([msg.uid], { uid: true });
407
+ }
408
+ catch (error) {
409
+ console.error(`Error moving message to another server: ${error.message}`);
410
+ throw error;
411
+ }
412
+ finally {
413
+ await this.client.mailboxClose();
414
+ }
415
+ }
211
416
  async getFolderList() {
212
417
  return this.withConnection(async () => {
213
418
  return await this.client.list();
@@ -280,6 +485,88 @@ export class ImapClient {
280
485
  return info;
281
486
  });
282
487
  }
488
+ /** Add flags to a message by UID */
489
+ async addFlags(mailbox, uid, flags) {
490
+ try {
491
+ await this.connect();
492
+ await this.client.mailboxOpen(mailbox, { readOnly: false });
493
+ return await this.client.messageFlagsAdd([uid], flags, { uid: true });
494
+ }
495
+ catch (error) {
496
+ console.error(`Error adding flags to UID ${uid}: ${error.message}`);
497
+ throw error;
498
+ }
499
+ finally {
500
+ await this.client.mailboxClose();
501
+ }
502
+ }
503
+ /** Remove flags from a message by UID */
504
+ async removeFlags(mailbox, uid, flags) {
505
+ try {
506
+ await this.connect();
507
+ await this.client.mailboxOpen(mailbox, { readOnly: false });
508
+ return await this.client.messageFlagsRemove([uid], flags, { uid: true });
509
+ }
510
+ catch (error) {
511
+ console.error(`Error removing flags from UID ${uid}: ${error.message}`);
512
+ throw error;
513
+ }
514
+ finally {
515
+ await this.client.mailboxClose();
516
+ }
517
+ }
518
+ /** Get flags for a message by UID */
519
+ async getFlags(mailbox, uid) {
520
+ try {
521
+ await this.connect();
522
+ await this.client.mailboxOpen(mailbox, { readOnly: true });
523
+ const msg = await this.client.fetchOne(uid, { flags: true }, { uid: true });
524
+ if (!msg)
525
+ return [];
526
+ return [...msg.flags];
527
+ }
528
+ catch (error) {
529
+ console.error(`Error getting flags for UID ${uid}: ${error.message}`);
530
+ throw error;
531
+ }
532
+ finally {
533
+ await this.client.mailboxClose();
534
+ }
535
+ }
536
+ /** Delete a message by UID from a mailbox */
537
+ async deleteMessageByUid(mailbox, uid) {
538
+ try {
539
+ await this.connect();
540
+ await this.client.mailboxOpen(mailbox, { readOnly: false });
541
+ await this.client.messageDelete([uid], { uid: true });
542
+ }
543
+ catch (error) {
544
+ console.error(`Error deleting UID ${uid} from ${mailbox}: ${error.message}`);
545
+ throw error;
546
+ }
547
+ finally {
548
+ await this.client.mailboxClose();
549
+ }
550
+ }
551
+ /** Watch a mailbox for new messages via IMAP IDLE. Calls onNew when messages arrive.
552
+ * Returns a stop function to end the watch. */
553
+ async watchMailbox(mailbox, onNew) {
554
+ await this.connect();
555
+ await this.client.mailboxOpen(mailbox, { readOnly: true });
556
+ const handler = (data) => {
557
+ if (data.count > data.prevCount) {
558
+ onNew(data.count - data.prevCount);
559
+ }
560
+ };
561
+ this.client.on('exists', handler);
562
+ return async () => {
563
+ this.client.off('exists', handler);
564
+ try {
565
+ await this.client.mailboxClose();
566
+ }
567
+ catch { /* ignore */ }
568
+ };
569
+ }
283
570
  async logout() {
284
571
  this.isDestroying = true;
285
572
  this.cleanup();
@@ -293,6 +580,7 @@ export class ImapClient {
293
580
  }
294
581
  async connect() {
295
582
  try {
583
+ await this.initialized; // Ensure async init completed
296
584
  if (this.connectionPromise) {
297
585
  await this.connectionPromise;
298
586
  }
@@ -301,7 +589,7 @@ export class ImapClient {
301
589
  }
302
590
  }
303
591
  catch (err) {
304
- console.error(`Connection failed: ${err.message}`);
592
+ console.error(`${new Date().toISOString()} Connection failed: ${err.message}`);
305
593
  if (!this.isDestroying) {
306
594
  await this.handleReconnection();
307
595
  }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Gmail-specific IMAP support with OAuth authentication
3
+ */
4
+ import { ImapClientConfig } from './types.js';
5
+ export interface OAuthImapConfig {
6
+ username: string;
7
+ credentialsPath?: string;
8
+ tokenDirectory?: string;
9
+ }
10
+ /**
11
+ * Check if email address is Gmail
12
+ */
13
+ export declare function isGmailUser(username: string): boolean;
14
+ /**
15
+ * Check if a server is Gmail
16
+ */
17
+ export declare function isGmailServer(server: string): boolean;
18
+ /**
19
+ * Creates an ImapClientConfig with OAuth tokenProvider
20
+ * Auto-detects Gmail from @gmail.com email addresses
21
+ * Tokens stored in <tokenDirectory>/tokens/<sanitized-email>/token.json
22
+ *
23
+ * Credentials and tokens are stored in the iflow package directory by default
24
+ */
25
+ export declare function createImapConfig(config: OAuthImapConfig): ImapClientConfig;
26
+ /** @deprecated Use createImapConfig instead */
27
+ export declare const createGmailConfig: typeof createImapConfig;
28
+ /**
29
+ * Auto-configure IMAP client - detects Gmail and uses OAuth, otherwise uses password
30
+ * This is the main function to use - it handles all authentication logic internally
31
+ *
32
+ * @param config - Server configuration with username, password (optional for Gmail), server, port
33
+ * @returns ImapClientConfig ready to use with ImapClient
34
+ */
35
+ export declare function createAutoImapConfig(config: {
36
+ server: string;
37
+ port: number;
38
+ username: string;
39
+ password?: string;
40
+ verbose?: boolean;
41
+ rejectUnauthorized?: boolean;
42
+ }): ImapClientConfig;
43
+ //# sourceMappingURL=gmail.d.ts.map