UNPKG

@hyperbytes/wappler-imap-manager

Version:

IMAP eMail Management for Wappler

189 lines (157 loc) 8.02 kB
const Imap = require('imap'); exports.imapmailheaders = async function (options, name) { const IMAP_HOST = this.parseOptional(options.imap_host, '*', process.env.IMAP_HOST); const IMAP_PASSWORD = this.parseOptional(options.imap_password, '*', process.env.IMAP_PASSWORD); const IMAP_USER = this.parseOptional(options.imap_usesr, '*', process.env.IMAP_USER); const IMAP_PORT = this.parseOptional(options.imap_port, '*', process.env.IMAP_PORT); const imap_tlsstring = this.parseOptional(options.imap_tls, '*', process.env.IMAP_TLS).toLowerCase(); const IMAP_TLS = (imap_tlsstring == 'true'); const offset = this.parseOptional(options.offset, '*', 0); const payload = this.parseOptional(options.payload, '*', 25); const mailbox = this.parseOptional(options.mailbox, '*', 'INBOX'); return new Promise((resolve) => { const imap = new Imap({ user: IMAP_USER, password: IMAP_PASSWORD, host: IMAP_HOST, port: IMAP_PORT, tls: IMAP_TLS, tlsOptions: { rejectUnauthorized: process.env.IMAP_CERTIFICATE_OVERRIDE === '1' ? false : true } }); const messages = []; function openInbox(cb) { imap.openBox(mailbox, true, cb); } imap.once('ready', function () { openInbox(function (err, box) { if (err) { imap.end(); return resolve({ data: [], status: 401 }); } if (box.messages.total === 0) { imap.end(); return resolve({ data: [], status: 200 }); } const totalMessages = box.messages.total; let end = Math.max(totalMessages - (offset * payload), 1); let start = Math.max(end - payload, 1); if (start > end || start < 1) { imap.end(); return resolve({ data: [], status: 400 }); } const tofetch = `${start}:${end}`; const f = imap.seq.fetch(tofetch, { bodies: 'HEADER.FIELDS (FROM TO CC BCC SUBJECT DATE MESSAGE-ID RECEIVED)', struct: true, }); f.on('message', function (msg, seqno) { let messageData = { id: seqno, uid: null, headers: {}, flags: [], attachmentCount: 0, uidvalidity: box.uidvalidity, mailbox: mailbox }; msg.on('body', function (stream) { let buffer = ''; stream.on('data', function (chunk) { buffer += chunk.toString('utf8'); }); stream.once('end', function () { let headers = Imap.parseHeader(buffer); console.log("Extracted headers:", headers); if (headers.date) { headers.messagedate = new Intl.DateTimeFormat('en-GB', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'UTC', }).format(new Date(headers.date)); delete headers.Date; } else if (headers.received && headers.received.length > 0) { console.log("Checking Received headers for fallback date..."); const receivedTimestamps = headers.received.map(receivedHeader => { const match = receivedHeader.match(/\b(\w{3}, )?\d{1,2} \w{3} \d{4} \d{2}:\d{2}:\d{2} (\w+|\+\d{4})\b/); return match ? match[0] : null; }).filter(Boolean); if (receivedTimestamps.length > 0) { headers.messagedate = new Intl.DateTimeFormat('en-GB', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'UTC', }).format(new Date(receivedTimestamps[receivedTimestamps.length - 1])); } else { headers.messagedate = 'Unknown Date'; } } messageData.headers = { from: headers['from'], to: headers['to'], cc: headers['cc'] || [], bcc: headers['bcc'] || [], subject: headers['subject'], 'message-id': headers['message-id'], messagedate: headers.messagedate }; }); }); msg.once('attributes', function (attrs) { messageData.flags = attrs.flags; messageData.uid = attrs.uid; if (!messageData.headers.messagedate && attrs.date) { messageData.headers.messagedate = new Intl.DateTimeFormat('en-GB', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'UTC', }).format(new Date(attrs.date)); } if (attrs.struct) { function countAttachments(struct) { return struct.reduce((count, part) => { if (Array.isArray(part)) { return count + countAttachments(part); } return part.disposition && part.disposition.type.toLowerCase() === 'attachment' ? count + 1 : count; }, 0); } messageData.attachmentCount = countAttachments(attrs.struct); } }); msg.once('end', function () { console.log("Final message data before pushing:", messageData); messages.push(messageData); }); }); f.once('error', function () { resolve({ data: [], status: 400 }); }); f.once('end', function () { imap.end(); resolve({ data: messages.reverse(), status: 200 }); }); }); }); imap.once('error', function () { resolve({ data: [], status: 401 }); }); imap.once('end', function () { console.log('IMAP connection closed.'); }); imap.connect(); }); };