@hyperbytes/wappler-imap-manager
Version:
IMAP eMail Management for Wappler
189 lines (157 loc) • 8.02 kB
JavaScript
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();
});
};