166 lines
5.9 KiB
JavaScript
166 lines
5.9 KiB
JavaScript
const { getAddresseId } = require("../sql/mail");
|
|
const { DEBUG } = require("../utils/debug");
|
|
const { simpleParser } = require("mailparser");
|
|
|
|
const {
|
|
registerMessage,
|
|
registerMailbox_message,
|
|
saveHeader_fields,
|
|
saveAddress_fields,
|
|
registerBodypart,
|
|
saveBodypart
|
|
} = require("../sql/saveMessage");
|
|
const { getFieldId } = require("../sql/mail");
|
|
|
|
function saveMessage(attrs, mailboxId, imap) {
|
|
const envelope = attrs.envelope;
|
|
const timestamp = new Date(envelope.date).getTime();
|
|
const rfc822size = attrs.size;
|
|
|
|
registerMessage(timestamp, rfc822size, envelope.messageId).then(
|
|
(messageId) => {
|
|
const seen = 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,
|
|
seen,
|
|
deleted
|
|
);
|
|
|
|
const len = attrs.struct.length;
|
|
attrs.struct.forEach((part) => {
|
|
if (len > 1) part = part[0];
|
|
|
|
// todo should be recursive to take eveyraçpghyrue
|
|
// todo attachments
|
|
if (part?.type == "text") {
|
|
const registerType = `${part.type}/${part.subtype}`
|
|
const hash = "2"; // todo
|
|
const text = "1"; // todo
|
|
saveBodypart(part.size, hash, text, '').then((bodypartId) => {
|
|
registerBodypart(messageId, registerType, bodypartId, part.size, part.lines);
|
|
});
|
|
}
|
|
});
|
|
|
|
// const fetch = imap.fetch(uid, { bodies: ["HEADER", part.partID] });
|
|
|
|
// fetch.on("message", (msg) => {
|
|
// msg.on("body", (stream, info) => {
|
|
// simpleParser(stream, async (err, parsed) => {
|
|
// console.log(part.partID, parsed?.subject);
|
|
// });
|
|
// });
|
|
|
|
// msg.once("end", () => {
|
|
// console.log("Finished fetching message");
|
|
// });
|
|
// });
|
|
|
|
// fetch.once("error", (err) => {
|
|
// console.log(err);
|
|
// });
|
|
|
|
// fetch.once("end", () => {
|
|
// console.log("Done fetching all messages");
|
|
// });
|
|
// }
|
|
// });
|
|
|
|
// todo when transfered
|
|
//The part column records to which MIME part this header field belongs. It's empty for the main header (the one seen above) and nonempty when a multipart message has headers on each part.
|
|
const part = ''; // todo ^
|
|
const position = 2; // todo
|
|
// save envelope (header + from, to, subject, date, cc)
|
|
Object.keys(envelope).forEach(key => {
|
|
const newKey = keyNormalizer(key);
|
|
if (isHeader(newKey)) {
|
|
getFieldId(newKey).then((fieldId) => {
|
|
saveHeader_fields(messageId, part, position, fieldId, envelope[key]);
|
|
});
|
|
} else {
|
|
getFieldId(newKey).then((fieldId) => {
|
|
if (envelope[key]) {
|
|
envelope[key].forEach((elt, index) => {
|
|
getAddresseId(`${elt.mailbox}@${elt.host}`).then((addressId) => {
|
|
saveAddress_fields(messageId, part, position, fieldId, index, addressId);
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// todo check for different provider
|
|
if (envelope?.inReplyTo) {
|
|
`SELECT app_room_messages.room, app_room_messages.thread FROM app_room_messages INNER JOIN messages WHERE messages.messageID = '${envelope.inReplyTo}' AND app_room_messages.message = messages.id`;
|
|
// parent message is in a thread, so register this message only in a thread
|
|
if (thread) {
|
|
`INSERT IGNORE INTO app_room_messages (thread, message) VALUES('${thread}', '${messageId}')`;
|
|
// increment not read counter and lastUpdate is not read (both)
|
|
} else if (room) {
|
|
|
|
if (!isGroup) {
|
|
// check if create thread
|
|
} else {
|
|
// check if create new group and delete thread
|
|
}
|
|
} else {
|
|
|
|
}
|
|
}
|
|
/**
|
|
* if reply to then add to same group as previous and update type if necessary
|
|
* else add to sender group
|
|
*
|
|
*/
|
|
|
|
}
|
|
);
|
|
}
|
|
|
|
function findTextPart(struct) {
|
|
for (var i = 0, len = struct.length, r; i < len; ++i) {
|
|
if (Array.isArray(struct[i])) {
|
|
if (r = findTextPart(struct[i]))
|
|
return r;
|
|
} else if (struct[i].type === 'text'
|
|
&& (struct[i].subtype === 'plain'
|
|
|| struct[i].subtype === 'html'))
|
|
return [struct[i].partID, struct[i].type + '/' + struct[i].subtype];
|
|
}
|
|
}
|
|
|
|
function isHeader(key) {
|
|
switch (key) {
|
|
case "date":
|
|
case "subject":
|
|
case "messageId":
|
|
case "inReplyTo": // when transfer or reply to message
|
|
return true;
|
|
case "from":
|
|
case "sender":
|
|
case "replyTo":
|
|
case "to":
|
|
case "cc":
|
|
case "bcc":
|
|
return false;
|
|
default:
|
|
DEBUG.log("Unknown header key: " + key);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function keyNormalizer(key) {
|
|
// todo
|
|
return key;
|
|
}
|
|
|
|
module.exports = {
|
|
saveMessage,
|
|
};
|