diff --git a/back/abl/Message-abl.ts b/back/abl/Message-abl.ts index 14a123f..6352114 100644 --- a/back/abl/Message-abl.ts +++ b/back/abl/Message-abl.ts @@ -1,15 +1,54 @@ import statusCode from "../utils/statusCodes"; import { Response } from "express"; +import { getMessageUid, getUserOfMailbox } from "../db/utils/mail"; +import emailManager from "../mails/EmailManager"; export default class Message { - static async addFlag(body, res: Response) { - console.log("hit") - res.status(statusCode.OK).send(); + const { mailboxId, messageId, flag } = body; + const uid = (await getMessageUid(messageId))[0]?.uid; + if (!uid) { + res.status(statusCode.NOT_FOUND).send({ error: "Message uid not found." }); + } + + const user = (await getUserOfMailbox(mailboxId))[0]?.user; + if (!user) { + res.status(statusCode.NOT_FOUND).send({ error: "Not account for this mailbox." }); + } + emailManager + .getImap(user) + .getMailbox(mailboxId) + .addFlag(uid.toString(), [flag]) + .then(() => { + res.status(statusCode.OK).send(); + }) + .catch((err) => { + console.log(err); + res.status(statusCode.METHOD_FAILURE).send({ error: err }); + }); } static async removeFlag(body, res: Response) { - console.log("hit") - res.status(statusCode.OK).send(); + const { mailboxId, messageId, flag } = body; + const uid = (await getMessageUid(messageId))[0]?.uid; + if (!uid) { + res.status(statusCode.NOT_FOUND).send({ error: "Message uid not found." }); + } + + const user = (await getUserOfMailbox(mailboxId))[0]?.user; + if (!user) { + res.status(statusCode.NOT_FOUND).send({ error: "Not account for this mailbox." }); + } + emailManager + .getImap(user) + .getMailbox(mailboxId) + .removeFlag(uid.toString(), [flag]) + .then(() => { + res.status(statusCode.OK).send(); + }) + .catch((err) => { + console.log(err); + res.status(statusCode.METHOD_FAILURE).send({ error: err }); + }); } } diff --git a/back/db/utils/mail.ts b/back/db/utils/mail.ts index 4feb221..d683d64 100644 --- a/back/db/utils/mail.ts +++ b/back/db/utils/mail.ts @@ -34,6 +34,12 @@ export async function getMessageIdOnUid(uid: number): Promise<{ message_id: numb return await execQueryAsync(query, values); } +export async function getMessageUid(messageId: number): Promise<{uid: number}[]> { + const query = `SELECT uid FROM mailbox_message WHERE message_id = ?`; + const values = [messageId]; + return await execQueryAsync(query, values); +} + export async function findRoomByOwner(ownerId: number): Promise<{ room_id: number }[]> { const query = `SELECT room_id FROM app_room WHERE owner_id = ?`; const values = [ownerId]; @@ -50,3 +56,15 @@ export async function getUserIdOfMailbox(boxId: number): Promise<{ user_id: numb const values = [boxId]; return await execQueryAsync(query, values); } + +export async function getUserOfMailbox(mailboxId: number): Promise<{ user: string }[]> { + const query = ` + SELECT address.email AS user + FROM mailbox + INNER JOIN app_account ON app_account.account_id = mailbox.account_id + INNER JOIN address on address.address_id = app_account.user_id + WHERE mailbox.mailbox_id = ? + `; + const values = [mailboxId]; + return await execQueryAsync(query, values); +} diff --git a/back/mails/EmailManager.ts b/back/mails/EmailManager.ts index 6a1a661..1b681b8 100644 --- a/back/mails/EmailManager.ts +++ b/back/mails/EmailManager.ts @@ -42,7 +42,11 @@ class EmailManager { } getSmtp(email: string): SmtpInstance | undefined { - return this.smtpInstances.find((instance) => instance.user == email); + return this.smtpInstances.find((instance) => instance.user === email); + } + + getImap(email: string): ImapInstance | undefined { + return this.imapInstances.find((instance) => instance.account.user === email); } } diff --git a/back/mails/imap/ImapInstance.ts b/back/mails/imap/ImapInstance.ts index 8afe950..323a53a 100644 --- a/back/mails/imap/ImapInstance.ts +++ b/back/mails/imap/ImapInstance.ts @@ -23,7 +23,7 @@ export class ImapInstance { this.boxes = []; /** - * IMAP + * IMAP init */ this.imap.once("ready", () => { logger.log("Imap connected for " + this.account.user); @@ -59,7 +59,7 @@ export class ImapInstance { getAllBox(boxes) { // ideally we should get the all box to get all messages - let allBox = ''; + let allBox = ""; Object.keys(boxes).forEach((key) => { if (key === "INBOX") return; if (allBox.includes("/")) return; // already found @@ -74,4 +74,8 @@ export class ImapInstance { if (!allBox.includes("/")) logger.warn("Did not find 'All' mailbox"); return allBox; } -} \ No newline at end of file + + getMailbox(mailboxId: number): Mailbox { + return this.boxes.find((box) => box.id === mailboxId); + } +} diff --git a/back/mails/imap/Mailbox.ts b/back/mails/imap/Mailbox.ts index 48e2d8f..2e42a3a 100644 --- a/back/mails/imap/Mailbox.ts +++ b/back/mails/imap/Mailbox.ts @@ -20,7 +20,7 @@ export default class Mailbox { msgToSync: number; syncing: boolean; - constructor(_imap, _boxId, _boxName) { + constructor(_imap: Imap, _boxId: number, _boxName: string) { this.imap = _imap; this.boxName = _boxName; this.id = _boxId; @@ -34,15 +34,15 @@ export default class Mailbox { // get mailbox from the database this.box = (await getMailbox(this.id))[0]; - const readOnly = true; - this.imap.openBox(this.boxName, readOnly, (err, box) => { + const isReadOnly = false; + this.imap.openBox(this.boxName, isReadOnly, (err, box) => { if (err) logger.err(err); // sync only if has new messages if (this.box.uidnext < box.uidnext) { this.sync(this.box.uidnext, box.uidnext); } else { - logger.log("Already up to date") + logger.log("Already up to date"); } // wait for new mails @@ -57,6 +57,7 @@ export default class Mailbox { }); this.imap.on("update", (seqno: number, info: ImapInfo) => { + logger.log(`Update message ${info.uid} with ${info.flags}`); const updateMsg = new updateMessage(info.uid, info.flags); updateMsg.updateFlags(); }); @@ -75,7 +76,6 @@ export default class Mailbox { f.on("message", (msg, seqno) => { msg.once("attributes", (attrs: AttrsWithEnvelope) => { - console.log(attrs.envelope); mails.push(attrs); promises.push(saveMessage(attrs, this.id, this.imap)); }); @@ -117,4 +117,28 @@ export default class Mailbox { } }); } + + addFlag(source: string, flags: string[]): Promise { + return new Promise((resolve, reject) => { + this.imap.addFlags(source, flags, (err) => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + } + + removeFlag(source: string, flags: string[]): Promise { + return new Promise((resolve, reject) => { + this.imap.delFlags(source, flags, (err) => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + } } diff --git a/back/server.ts b/back/server.ts index b1e1815..65b8148 100644 --- a/back/server.ts +++ b/back/server.ts @@ -1,8 +1,9 @@ import express from "express"; import cors from "cors"; const app = express(); -import ImapSync from "./mails/EmailManager"; import { execQueryAsync, execQuery } from "./db/db"; +import mailRouter from "./routes/mail"; +import emailManager from "./mails/EmailManager"; app.use(express.json()); app.use( @@ -13,8 +14,6 @@ app.use( app.use(cors()); app.listen(process.env.PORT || 5500); -import mailRouter from "./routes/mail"; -import emailManager from "./mails/EmailManager"; app.use("/api/mail", mailRouter); emailManager.init();