import * as plugins from './smartimap.plugins.js'; export interface ImapClientConfig { host: string; port?: number; // Defaults to 993 if secure, else 143 secure?: boolean; // Defaults to true auth: { user: string; pass: string; }; mailbox?: string; // Defaults to 'INBOX' filter?: plugins.imapflow.SearchObject; // IMAP search criteria object } export type SmartImapMessage = plugins.mailparser.ParsedMail; export class ImapClient extends plugins.events.EventEmitter { private client: plugins.imapflow.ImapFlow; private mailbox: string; private filter: plugins.imapflow.SearchObject; private connected: boolean = false; private processing: boolean = false; private seenUids: Set = new Set(); constructor(private config: ImapClientConfig) { super(); this.mailbox = config.mailbox || 'INBOX'; this.filter = config.filter || { seen: false }; // Updated default filter this.client = new plugins.imapflow.ImapFlow({ host: config.host, port: config.port || (config.secure === false ? 143 : 993), secure: config.secure !== false, auth: config.auth, logger: false, // Set to console for debugging }); this.client.on('error', (error) => { this.emit('error', error); }); } public async connect(): Promise { try { await this.client.connect(); this.connected = true; await this.client.mailboxOpen(this.mailbox); // Removed { reopen: true } this.emit('connected'); this.setupIdle(); } catch (error) { this.emit('error', error); } } private async setupIdle(): Promise { this.client.on('exists', async () => { await this.fetchNewMessages(); }); // Initial fetch await this.fetchNewMessages(); } private async fetchNewMessages(): Promise { if (this.processing) return; this.processing = true; try { const searchResult = await this.client.search(this.filter); // Convert searchResult to a regular array const searchResultArray = Array.from(searchResult); const newUids = searchResultArray.filter((uid) => !this.seenUids.has(uid)); if (newUids.length === 0) { this.processing = false; return; } // Fetch messages for await (const message of this.client.fetch(newUids, { envelope: true, source: true })) { const parsed = await plugins.mailparser.simpleParser(message.source); this.emit('message', parsed); this.seenUids.add(message.uid); } } catch (error) { this.emit('error', error); } finally { this.processing = false; } } public setFilter(filter: plugins.imapflow.SearchObject): void { this.filter = filter; } public async disconnect(): Promise { if (this.connected) { await this.client.logout(); this.connected = false; this.emit('disconnected'); } } }