reply message from thread and room
This commit is contained in:
parent
7ad22e55c1
commit
4799e477be
@ -1,6 +1,6 @@
|
|||||||
import { Response } from "express";
|
import { Response } from "express";
|
||||||
import { getAccounts, registerAccount } from "../db/api-db";
|
import { getAccounts, registerAccount } from "../db/api-db";
|
||||||
import { getAddresseId } from "../db/utils/mail";
|
import { getAddressId } from "../db/utils/mail";
|
||||||
import statusCodes from "../utils/statusCodes";
|
import statusCodes from "../utils/statusCodes";
|
||||||
|
|
||||||
export default class Account {
|
export default class Account {
|
||||||
@ -12,7 +12,7 @@ export default class Account {
|
|||||||
|
|
||||||
static async register(body, res: Response) {
|
static async register(body, res: Response) {
|
||||||
const { email, pwd, xoauth, xoauth2, host, port, tls } = body;
|
const { email, pwd, xoauth, xoauth2, host, port, tls } = body;
|
||||||
getAddresseId(email).then((addressId) => {
|
getAddressId(email).then((addressId) => {
|
||||||
registerAccount(addressId, pwd, xoauth, xoauth2, host, port, tls)
|
registerAccount(addressId, pwd, xoauth, xoauth2, host, port, tls)
|
||||||
.then((mailboxId) => {
|
.then((mailboxId) => {
|
||||||
res.status(statusCodes.OK).json({ id: mailboxId });
|
res.status(statusCodes.OK).json({ id: mailboxId });
|
||||||
|
@ -2,24 +2,58 @@ import statusCode from "../utils/statusCodes";
|
|||||||
import { Response } from "express";
|
import { Response } from "express";
|
||||||
import { RoomType } from "../mails/message/saveMessage";
|
import { RoomType } from "../mails/message/saveMessage";
|
||||||
import { getRoomType } from "../db/message/saveMessage-db";
|
import { getRoomType } from "../db/message/saveMessage-db";
|
||||||
import { getRoomOwner } from "../db/Room-db";
|
import { getLastMsgData, getRoomOwner } from "../db/Room-db";
|
||||||
import emailManager from "../mails/EmailManager";
|
import emailManager from "../mails/EmailManager";
|
||||||
import MailBuilder from "../mails/utils/mailBuilder";
|
import MailBuilder from "../mails/utils/mailBuilder";
|
||||||
|
import { getAddresses } from "../db/utils/mail";
|
||||||
|
|
||||||
|
function rmUserFromAddrs(addresses: { email: string }[], user: string) {
|
||||||
|
let index = addresses.findIndex((a) => a.email == user);
|
||||||
|
if (index != -1) {
|
||||||
|
addresses.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
export default class Room {
|
export default class Room {
|
||||||
// todo change name
|
// todo change name of reponse
|
||||||
static async response(body, res: Response) {
|
static async response(body, res: Response) {
|
||||||
const { user, roomId, text, html } = body;
|
const { user, roomId, text, html } = body;
|
||||||
console.log(body)
|
|
||||||
const roomType = (await getRoomType(roomId))[0].room_type;
|
const roomType = (await getRoomType(roomId))[0].room_type;
|
||||||
|
|
||||||
if (roomType === RoomType.DM) {
|
if (roomType === RoomType.DM) {
|
||||||
const ownerEmail = (await getRoomOwner(roomId))[0].email;
|
const ownerEmail = (await getRoomOwner(roomId))[0].email;
|
||||||
|
|
||||||
const mailBuilder = new MailBuilder();
|
const mailBuilder = new MailBuilder();
|
||||||
mailBuilder.from(user).to(ownerEmail).text(text).html(html);
|
mailBuilder.from(user).to(ownerEmail).text(text).html(html);
|
||||||
|
|
||||||
emailManager.getSmtp(user).sendMail(mailBuilder.message);
|
emailManager.getSmtp(user).sendMail(mailBuilder.message);
|
||||||
// send new msg to recipient of dm
|
res.status(statusCode.OK).send();
|
||||||
} else if (roomType === RoomType.GROUP || roomType === RoomType.THREAD) {
|
} else if (roomType === RoomType.GROUP || roomType === RoomType.THREAD) {
|
||||||
// get all cc and to from of previous message and add them
|
const lastMsgData = (await getLastMsgData(roomId))[0];
|
||||||
|
console.log(lastMsgData);
|
||||||
|
|
||||||
|
const mailBuilder = new MailBuilder();
|
||||||
|
mailBuilder.inReplySubject(lastMsgData.subject).inReplyTo(lastMsgData.messageID).text(text).html(html);
|
||||||
|
|
||||||
|
const from = await getAddresses(lastMsgData.fromA);
|
||||||
|
let to = lastMsgData.toA ? await getAddresses(lastMsgData.toA) : [];
|
||||||
|
let cc = lastMsgData.ccA ? await getAddresses(lastMsgData.ccA) : [];
|
||||||
|
|
||||||
|
// remove us from recipients
|
||||||
|
rmUserFromAddrs(to, user);
|
||||||
|
rmUserFromAddrs(from, user);
|
||||||
|
|
||||||
|
// add sender of previous as recipient if it is not us
|
||||||
|
if (from.findIndex((a) => a.email == user) == -1) {
|
||||||
|
to = to.concat(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
mailBuilder
|
||||||
|
.from(user)
|
||||||
|
.to(to.map((a) => a.email))
|
||||||
|
.cc(cc.map((a) => a.email));
|
||||||
|
|
||||||
|
emailManager.getSmtp(user).sendMail(mailBuilder.message);
|
||||||
|
res.status(statusCode.OK).send();
|
||||||
} else {
|
} else {
|
||||||
res.status(statusCode.FORBIDDEN).send({ error: "Cannot add a new message in a room or a channel." });
|
res.status(statusCode.FORBIDDEN).send({ error: "Cannot add a new message in a room or a channel." });
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { execQueryAsync } from "./db";
|
import { execQueryAsync } from "./db";
|
||||||
|
import { queryCcId, queryFromId, queryToId } from "./utils/addressQueries";
|
||||||
|
|
||||||
export async function getRoomOwner(roomId: number) {
|
export async function getRoomOwner(roomId: number) {
|
||||||
const query = `
|
const query = `
|
||||||
@ -10,3 +11,51 @@ export async function getRoomOwner(roomId: number) {
|
|||||||
const values = [roomId];
|
const values = [roomId];
|
||||||
return await execQueryAsync(query, values);
|
return await execQueryAsync(query, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getLastMsgData(roomId: number) {
|
||||||
|
|
||||||
|
const query = `
|
||||||
|
SELECT
|
||||||
|
msg.message_id AS id,
|
||||||
|
GROUP_CONCAT(fromT.address_id) AS fromA,
|
||||||
|
GROUP_CONCAT(toT.address_id) AS toA,
|
||||||
|
GROUP_CONCAT(ccT.address_id) AS ccA,
|
||||||
|
subjectT.value AS subject,
|
||||||
|
content.text AS content,
|
||||||
|
message.idate AS date,
|
||||||
|
message.messageID AS messageID
|
||||||
|
FROM app_room_message msg
|
||||||
|
|
||||||
|
${queryFromId} fromT ON msg.message_id = fromT.message_id
|
||||||
|
${queryToId} toT ON msg.message_id = toT.message_id
|
||||||
|
${queryCcId} ccT ON msg.message_id = ccT.message_id
|
||||||
|
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT header_field.message_id, header_field.value
|
||||||
|
FROM header_field
|
||||||
|
INNER JOIN field_name
|
||||||
|
WHERE
|
||||||
|
field_name.field_id = header_field.field_id AND
|
||||||
|
field_name.field_name = 'subject'
|
||||||
|
) subjectT ON msg.message_id = subjectT.message_id
|
||||||
|
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT bodypart.text, header_field.message_id FROM bodypart
|
||||||
|
INNER JOIN header_field
|
||||||
|
INNER JOIN field_name
|
||||||
|
WHERE
|
||||||
|
field_name.field_id = header_field.field_id AND
|
||||||
|
field_name.field_name = 'html' AND
|
||||||
|
bodypart.bodypart_id = header_field.bodypart_id
|
||||||
|
) content ON msg.message_id = content.message_id
|
||||||
|
|
||||||
|
INNER JOIN message ON message.message_id = msg.message_id
|
||||||
|
|
||||||
|
WHERE msg.room_id = ?
|
||||||
|
GROUP BY msg.message_id
|
||||||
|
ORDER BY message.idate DESC
|
||||||
|
LIMIT 1
|
||||||
|
`;
|
||||||
|
const values = [roomId];
|
||||||
|
return await execQueryAsync(query, values);
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { execQueryAsync, execQueryAsyncWithId } from "../db";
|
import { execQueryAsync, execQueryAsyncWithId } from "../db";
|
||||||
|
|
||||||
export async function getAddresseId(email: string, name?: string): Promise<number> {
|
export async function getAddressId(email: string, name?: string): Promise<number> {
|
||||||
const localpart = email.split("@")[0];
|
const localpart = email.split("@")[0];
|
||||||
const domain = email.split("@")[1];
|
const domain = email.split("@")[1];
|
||||||
const query = `INSERT INTO address
|
const query = `INSERT INTO address
|
||||||
@ -10,6 +10,12 @@ export async function getAddresseId(email: string, name?: string): Promise<numbe
|
|||||||
return await execQueryAsyncWithId(query, values);
|
return await execQueryAsyncWithId(query, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getAddresses(ids: number | number[]): Promise<{ id: number, email: string }[]> {
|
||||||
|
const query = `SELECT address_id AS id, email FROM address WHERE address_id IN (?)`;
|
||||||
|
const values = [ids];
|
||||||
|
return await execQueryAsync(query, values);
|
||||||
|
}
|
||||||
|
|
||||||
export async function getFieldId(field: string): Promise<number> {
|
export async function getFieldId(field: string): Promise<number> {
|
||||||
const query = `INSERT INTO field_name (field_name) VALUES (?) ON DUPLICATE KEY UPDATE field_id=LAST_INSERT_ID(field_id)`;
|
const query = `INSERT INTO field_name (field_name) VALUES (?) ON DUPLICATE KEY UPDATE field_id=LAST_INSERT_ID(field_id)`;
|
||||||
const values = [field];
|
const values = [field];
|
||||||
@ -22,7 +28,7 @@ export async function getFlagId(flag: string): Promise<number> {
|
|||||||
return await execQueryAsyncWithId(query, values);
|
return await execQueryAsyncWithId(query, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getMessageIdOnUid(uid: number): Promise<{message_id: number}[]> {
|
export async function getMessageIdOnUid(uid: number): Promise<{ message_id: number }[]> {
|
||||||
const query = `SELECT message_id FROM mailbox_message WHERE uid = ?`;
|
const query = `SELECT message_id FROM mailbox_message WHERE uid = ?`;
|
||||||
const values = [uid];
|
const values = [uid];
|
||||||
return await execQueryAsync(query, values);
|
return await execQueryAsync(query, values);
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
getThreadInfoOnId,
|
getThreadInfoOnId,
|
||||||
} from "../../db/message/saveMessage-db";
|
} from "../../db/message/saveMessage-db";
|
||||||
|
|
||||||
import { findRoomByOwner, getAddresseId, getUserIdOfMailbox } from "../../db/utils/mail";
|
import { findRoomByOwner, getAddressId, getUserIdOfMailbox } from "../../db/utils/mail";
|
||||||
import { nbMembers } from "../utils/envelopeUtils";
|
import { nbMembers } from "../utils/envelopeUtils";
|
||||||
import logger from "../../system/Logger";
|
import logger from "../../system/Logger";
|
||||||
import { Attrs, Envelope, User } from "../../interfaces/mail/attrs.interface";
|
import { Attrs, Envelope, User } from "../../interfaces/mail/attrs.interface";
|
||||||
@ -57,7 +57,7 @@ export default class RegisterMessageInApp {
|
|||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
if (this.envelope.from) {
|
if (this.envelope.from) {
|
||||||
this.ownerId = await getAddresseId(createAddress(this.envelope.from[0])); // todo use sender or from ?
|
this.ownerId = await getAddressId(createAddress(this.envelope.from[0])); // todo use sender or from ?
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Envelope must have a 'from' field");
|
throw new Error("Envelope must have a 'from' field");
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ export default class RegisterMessageInApp {
|
|||||||
if (this.isDm()) {
|
if (this.isDm()) {
|
||||||
// create or add new message to DM
|
// create or add new message to DM
|
||||||
if (!this.envelope.to) throw new Error("Who send a DM and put the recipient in cc ?");
|
if (!this.envelope.to) throw new Error("Who send a DM and put the recipient in cc ?");
|
||||||
const userTo = await getAddresseId(createAddress(this.envelope.to[0]));
|
const userTo = await getAddressId(createAddress(this.envelope.to[0]));
|
||||||
await this.createOrRegisterOnExistence(userTo, RoomType.DM);
|
await this.createOrRegisterOnExistence(userTo, RoomType.DM);
|
||||||
} else {
|
} else {
|
||||||
// it is not a reply and not a dm
|
// it is not a reply and not a dm
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { getAddresseId, getFlagId } from "../../db/utils/mail";
|
import { getAddressId, getFlagId } from "../../db/utils/mail";
|
||||||
import { EmailAddress, ParsedMail, simpleParser } from "mailparser";
|
import { EmailAddress, ParsedMail, simpleParser } from "mailparser";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import Imap from "imap";
|
import Imap from "imap";
|
||||||
@ -91,7 +91,7 @@ async function saveFromParsedData(parsed: ParsedMail, messageId: number) {
|
|||||||
// save address field
|
// save address field
|
||||||
getFieldId(key).then((fieldId) => {
|
getFieldId(key).then((fieldId) => {
|
||||||
parsed[key].value.forEach((addr: EmailAddress, nb: number) => {
|
parsed[key].value.forEach((addr: EmailAddress, nb: number) => {
|
||||||
getAddresseId(addr.address, addr.name).then(async (addressId) => {
|
getAddressId(addr.address, addr.name).then(async (addressId) => {
|
||||||
await saveAddress_fields(messageId, fieldId, addressId, nb);
|
await saveAddress_fields(messageId, fieldId, addressId, nb);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -43,4 +43,10 @@ export default class MailBuilder {
|
|||||||
this.message.inReplyTo = messageID;
|
this.message.inReplyTo = messageID;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inReplySubject(originSubject: string): MailBuilder {
|
||||||
|
// todo concate if multiple ?
|
||||||
|
this.message.subject = "RE: " + originSubject;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ const boxId = 1;
|
|||||||
jest.mock("../../db/utils/mail", () => {
|
jest.mock("../../db/utils/mail", () => {
|
||||||
return {
|
return {
|
||||||
findRoomByOwner: jest.fn(),
|
findRoomByOwner: jest.fn(),
|
||||||
getAddresseId: jest.fn(),
|
getAddressId: jest.fn(),
|
||||||
getUserIdOfMailbox: jest.fn(),
|
getUserIdOfMailbox: jest.fn(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -38,7 +38,7 @@ jest.mock("../../db/message/saveMessage-db", () => {
|
|||||||
getThreadInfoOnId: jest.fn(),
|
getThreadInfoOnId: jest.fn(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
import { getAddresseId, getUserIdOfMailbox, findRoomByOwner } from "../../db/utils/mail";
|
import { getAddressId, getUserIdOfMailbox, findRoomByOwner } from "../../db/utils/mail";
|
||||||
import {
|
import {
|
||||||
createRoom,
|
createRoom,
|
||||||
registerMessageInRoom,
|
registerMessageInRoom,
|
||||||
@ -69,7 +69,7 @@ import { AttrsWithEnvelopeTest, createReplyWithSameMembers } from "../test-utils
|
|||||||
// if only me reply -> channel
|
// if only me reply -> channel
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
mocked(getAddresseId).mockImplementation(db.getAddresseId);
|
mocked(getAddressId).mockImplementation(db.getAddressId);
|
||||||
mocked(getUserIdOfMailbox).mockImplementation(db.getUserIdOfMailbox);
|
mocked(getUserIdOfMailbox).mockImplementation(db.getUserIdOfMailbox);
|
||||||
mocked(findRoomByOwner).mockImplementation(db.findRoomByOwner);
|
mocked(findRoomByOwner).mockImplementation(db.findRoomByOwner);
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ export default class saveMessageDatabase {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
getAddresseId = (email: string, name?: string): Promise<number> => {
|
getAddressId = (email: string, name?: string): Promise<number> => {
|
||||||
const match = this.users.find((user) => user.user.mailbox + "@" + user.user.host == email);
|
const match = this.users.find((user) => user.user.mailbox + "@" + user.user.host == email);
|
||||||
return new Promise((resolve, reject) => resolve(match?.id));
|
return new Promise((resolve, reject) => resolve(match?.id));
|
||||||
};
|
};
|
||||||
|
@ -30,6 +30,8 @@ const send = () => {
|
|||||||
html: htmlContent,
|
html: htmlContent,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// todo subject input when dm of group...
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
Loading…
Reference in New Issue
Block a user