const { getAddresseId } = require("../db/mail"); const { DEBUG } = require("../utils/debug"); const { simpleParser } = require("mailparser"); const moment = require("moment"); const fs = require("fs"); const { registerMessage, registerMailbox_message, saveHeader_fields, saveAddress_fields, registerBodypart, saveBodypart, saveSource, } = require("../db/saveMessage"); const { getFieldId } = require("../db/mail"); function saveMessage(attrs, mailboxId, imap) { const envelope = attrs.envelope; const ts = moment(new Date(envelope.date).getTime()).format("YYYY-MM-DD HH:mm:ss"); const rfc822size = attrs.size; const messageID = envelope.messageId; return new Promise((resolve, reject) => { registerMessage(ts, rfc822size, messageID) .then((messageId) => { const isSeen = attrs.flags.includes("Seen") ? 1 : 0; // todo verify const deleted = attrs.flags.includes("Deleted") ? 1 : 0; // todo verify registerMailbox_message(mailboxId, attrs.uid, messageId, attrs.modseq, isSeen, deleted); const f = imap.fetch(attrs.uid, { bodies: "" }); let buffer = ""; f.on("message", function (msg, seqno) { msg.on("body", function (stream, info) { stream.on("data", function (chunk) { buffer += chunk.toString("utf8"); }); stream.once("end", () => { // save raw data saveSource(messageId, buffer); // parse data simpleParser(buffer, async (err, parsed) => { saveFromParsedData(parsed, messageId) .then(() => { resolve(messageId); }) .catch((err) => { reject(err); }); }); }); }); }); f.once("error", function (err) { console.log("Fetch error: " + err); }); f.once("end", function () { DEBUG.log("Done fetching data of "+messageID); }); }) .catch((err) => { DEBUG.log("Unable to register message: " + err); reject(err); }); }); } async function saveFromParsedData(parsed, messageId) { const promises = []; Object.keys(parsed).forEach((key) => { if (["from", "to", "cc", "bcc", "replyTo"].includes(key)) { promises.push( // save address field getFieldId(key).then((fieldId) => { parsed[key].value.forEach((addr, nb) => { getAddresseId(addr.address, addr.name).then(async (addressId) => { await saveAddress_fields(messageId, fieldId, addressId, nb); }); }); }), ); } else if (["subject", "inReplyTo"].includes(key)) { // todo : "references" promises.push( getFieldId(key).then(async (fieldId) => { await saveHeader_fields(messageId, fieldId, undefined, undefined, parsed[key]); }), ); } else if (["html", "text", "textAsHtml"].includes(key)) { const hash = "0"; const size = "0"; // saveBodypart(size, hash, parsed[key], "").then((bodypartId) => { // getFieldId(key).then((fieldId) => { // saveHeader_fields( // messageId, // fieldId, // bodypartId, // undefined, // todo ? // undefined // ); // }); // }); } else if (key == "attachments") { // todo } else if (["date", "messageId", "headers", "headerLines"].includes(key)) { // messageId and date are already saved // other field are not improted and can be retrieved in source return; } else { DEBUG.log("doesn't know key: " + key); return; } }); return Promise.all(promises); // todo when transfered } module.exports = { saveMessage, };