mail/back/mails/storeMessage.js
2023-03-29 16:34:30 +02:00

130 lines
4.8 KiB
JavaScript

const { getAddresseId } = require("../db/mail");
const { simpleParser } = require("mailparser");
const moment = require("moment");
const {
registerMessage,
registerMailbox_message,
saveHeader_fields,
saveAddress_fields,
registerBodypart,
saveBodypart,
saveSource,
} = require("../db/saveMessage");
const { getFieldId } = require("../db/mail");
const { logger } = require("../system/Logger");
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 todo
// 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) {
logger.warn("Fetch error: " + err);
});
f.once("end", function () {
// logger.log("Done fetching data of " + messageID); // todo
});
})
.catch((err) => {
logger.warn("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", "references"].includes(key)) {
// todo : "references" (array)
if (key == "references") return;
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";
let partType = "text/plain";
if (key == "html") {
partType = "text/html";
} else if (key == "textAsHtml") {
partType = "text/TexAsHtml";
}
saveBodypart(size, hash, parsed[key], "").then((bodypartId) => {
getFieldId(key).then((fieldId) => {
saveHeader_fields(messageId, fieldId, bodypartId, partType, undefined);
});
});
} else if (key == "attachments") {
// todo
} else if (["date", "messageId", "headers", "headerLines"].includes(key)) {
// messageId and date are already saved
// other field are not important and can be retrieved in source
return;
} else {
logger.warn("doesn't know key: " + key);
return;
}
});
return Promise.all(promises);
// todo when transfered
}
module.exports = {
saveMessage,
};
if (process.env["NODE_DEV"] == "TEST") {
module.exports = {
saveFromParsedData,
};
}