smartimap/ts/classes.imapclient.ts

105 lines
3.2 KiB
TypeScript
Raw Normal View History

2024-09-19 08:33:57 +00:00
import * as plugins from './smartimap.plugins.js';
export interface ImapClientConfig {
2024-09-19 08:33:57 +00:00
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 {
2024-09-19 08:33:57 +00:00
private client: plugins.imapflow.ImapFlow;
private mailbox: string;
private filter: plugins.imapflow.SearchObject;
private connected: boolean = false;
private processing: boolean = false;
private seenUids: Set<number> = new Set();
constructor(private config: ImapClientConfig) {
2024-09-19 08:33:57 +00:00
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<void> {
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<void> {
this.client.on('exists', async () => {
await this.fetchNewMessages();
});
// Initial fetch
await this.fetchNewMessages();
}
private async fetchNewMessages(): Promise<void> {
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<void> {
if (this.connected) {
await this.client.logout();
this.connected = false;
this.emit('disconnected');
}
}
}