initial
This commit is contained in:
103
ts/classes.smartimap.ts
Normal file
103
ts/classes.smartimap.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import * as plugins from './smartimap.plugins.js';
|
||||
|
||||
export interface SmartImapConfig {
|
||||
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 class SmartImap 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<number> = new Set();
|
||||
|
||||
constructor(private config: SmartImapConfig) {
|
||||
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');
|
||||
}
|
||||
}
|
||||
}
|
1
ts/index.ts
Normal file
1
ts/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './classes.smartimap.js';
|
15
ts/smartimap.plugins.ts
Normal file
15
ts/smartimap.plugins.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// node native
|
||||
import * as events from 'events';
|
||||
|
||||
export {
|
||||
events,
|
||||
}
|
||||
|
||||
// third party
|
||||
import * as mailparser from 'mailparser';
|
||||
import * as imapflow from 'imapflow';
|
||||
|
||||
export {
|
||||
mailparser,
|
||||
imapflow,
|
||||
}
|
Reference in New Issue
Block a user