mail/back/imap/storeMessage.js
2023-03-17 13:31:27 +01:00

124 lines
4.6 KiB
JavaScript

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,
};