routes of update flags with imap

This commit is contained in:
grimhilt 2023-04-16 12:31:46 +02:00
parent 318748c984
commit 614f7d9802
6 changed files with 105 additions and 17 deletions

View File

@ -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 });
});
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}
}
getMailbox(mailboxId: number): Mailbox {
return this.boxes.find((box) => box.id === mailboxId);
}
}

View File

@ -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<void> {
return new Promise((resolve, reject) => {
this.imap.addFlags(source, flags, (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
removeFlag(source: string, flags: string[]): Promise<void> {
return new Promise((resolve, reject) => {
this.imap.delFlags(source, flags, (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
}

View File

@ -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();