Added E-Mail Sending Features
This commit is contained in:
@@ -1,11 +1,115 @@
|
|||||||
import { FastifyInstance } from "fastify";
|
import nodemailer from "nodemailer"
|
||||||
import {createInvoicePDF} from "../utils/pdf";
|
|
||||||
import {useNextNumberRangeNumber} from "../utils/functions";
|
|
||||||
import {sendMailAsUser} from "../utils/emailengine";
|
|
||||||
import {subtle} from "node:crypto";
|
|
||||||
|
|
||||||
|
import { FastifyInstance } from "fastify";
|
||||||
|
import {sendMailAsUser} from "../utils/emailengine";
|
||||||
|
import {encrypt, decrypt} from "../utils/crypt"
|
||||||
|
import {secrets} from "../utils/secrets";
|
||||||
export default async function emailAsUserRoutes(server: FastifyInstance) {
|
export default async function emailAsUserRoutes(server: FastifyInstance) {
|
||||||
server.post("/emailasuser/send", async (req, reply) => {
|
|
||||||
|
// Create E-Mail Account
|
||||||
|
server.post("/email/accounts/", async (req, reply) => {
|
||||||
|
if (!req.user?.tenant_id) {
|
||||||
|
return reply.code(400).send({ error: "No tenant selected" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = req.body as Record<string, any>;
|
||||||
|
|
||||||
|
let createData = {
|
||||||
|
user_id: req.user.user_id,
|
||||||
|
email_encrypted: encrypt(body.email),
|
||||||
|
password_encrypted: encrypt(body.password),
|
||||||
|
tenant_id: req.user.tenant_id,
|
||||||
|
smtp_host_encrypted: encrypt(body.smtp_host),
|
||||||
|
smtp_port: body.smtp_port,
|
||||||
|
smtp_ssl: body.smtp_ssl,
|
||||||
|
type: "mail",
|
||||||
|
imap_host_encrypted: encrypt(body.imap_host),
|
||||||
|
imap_port: body.imap_port,
|
||||||
|
imap_ssl: body.imap_ssl,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const { data, error } = await server.supabase
|
||||||
|
.from("user_credentials")
|
||||||
|
.insert(createData)
|
||||||
|
.select("*")
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return reply.code(400).send({ error: error.message });
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
|
||||||
|
server.get("/email/accounts/:id?", async (req, reply) => {
|
||||||
|
if (!req.user?.tenant_id) {
|
||||||
|
return reply.code(400).send({ error: "No tenant selected" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id } = req.params as { id: string };
|
||||||
|
|
||||||
|
if(id) {
|
||||||
|
let returnData = {}
|
||||||
|
// @ts-ignore
|
||||||
|
const { data, error } = await server.supabase
|
||||||
|
.from("user_credentials")
|
||||||
|
.select("id, email_encrypted, smtp_host_encrypted, smtp_port, smtp_ssl, imap_host_encrypted, imap_port, imap_ssl, user_id, tenant_id")
|
||||||
|
.eq("id", id)
|
||||||
|
.eq("tenant_id", req.user.tenant_id)
|
||||||
|
.eq("type", "mail")
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (error || !data) {
|
||||||
|
return reply.code(404).send({ error: "Not found" });
|
||||||
|
} else {
|
||||||
|
Object.keys(data).forEach((key) => {
|
||||||
|
if(key.includes("encrypted")){
|
||||||
|
returnData[key.substring(0,key.length-10)] = decrypt(data[key])
|
||||||
|
} else {
|
||||||
|
returnData[key] = data[key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const { data, error } = await server.supabase
|
||||||
|
.from("user_credentials")
|
||||||
|
.select("id, email_encrypted, user_id, tenant_id")
|
||||||
|
.eq("tenant_id", req.user.tenant_id)
|
||||||
|
.eq("type", "mail")
|
||||||
|
|
||||||
|
let accounts = []
|
||||||
|
data.forEach(item => {
|
||||||
|
let temp = {}
|
||||||
|
Object.keys(item).forEach((key) => {
|
||||||
|
if(key.includes("encrypted")){
|
||||||
|
temp[key.substring(0,key.length-10)] = decrypt(item[key])
|
||||||
|
} else {
|
||||||
|
temp[key] = item[key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
accounts.push(temp)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return accounts
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return returnData;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
server.post("/email/send", async (req, reply) => {
|
||||||
const body = req.body as {
|
const body = req.body as {
|
||||||
to: string
|
to: string
|
||||||
cc?: string
|
cc?: string
|
||||||
@@ -18,10 +122,60 @@ export default async function emailAsUserRoutes(server: FastifyInstance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
reply.send(await sendMailAsUser(body.to,body.subject,body.html,body.text,body.account,body.cc,body.bcc,body.attachments))
|
|
||||||
|
let accountData = {}
|
||||||
|
// @ts-ignore
|
||||||
|
const { data, error } = await server.supabase
|
||||||
|
.from("user_credentials")
|
||||||
|
.select("id, email_encrypted,password_encrypted, smtp_host_encrypted, smtp_port, smtp_ssl, user_id, tenant_id")
|
||||||
|
.eq("id", body.account)
|
||||||
|
.eq("tenant_id", req.user.tenant_id)
|
||||||
|
.eq("type", "mail")
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (error || !data) {
|
||||||
|
return reply.code(404).send({ error: "Not found" });
|
||||||
|
} else {
|
||||||
|
Object.keys(data).forEach((key) => {
|
||||||
|
if(key.includes("encrypted")){
|
||||||
|
accountData[key.substring(0,key.length-10)] = decrypt(data[key])
|
||||||
|
} else {
|
||||||
|
accountData[key] = data[key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const transporter = nodemailer.createTransport({
|
||||||
|
host: accountData.smtp_host,
|
||||||
|
port: accountData.smtp_port,
|
||||||
|
secure: accountData.smtp_ssl,
|
||||||
|
auth: {
|
||||||
|
user: accountData.email,
|
||||||
|
pass: accountData.password,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const info = await transporter.sendMail({
|
||||||
|
from: accountData.email,
|
||||||
|
to: body.to,
|
||||||
|
cc: body.cc ? body.cc : undefined,
|
||||||
|
bcc: body.bcc ? body.bcc : undefined,
|
||||||
|
subject: body.subject,
|
||||||
|
html: body.html ? body.html : undefined,
|
||||||
|
text: body.text,
|
||||||
|
attachments: body.attachments ? body.attachments : undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
if(info.response.includes("OK")){
|
||||||
|
reply.send({success: true})
|
||||||
|
}{
|
||||||
|
reply.status(500)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err)
|
|
||||||
reply.code(500).send({ error: "Failed to send E-Mail as User" })
|
reply.code(500).send({ error: "Failed to send E-Mail as User" })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user