Files
bodyshop/server/email/sendemail.js

292 lines
8.5 KiB
JavaScript

const path = require("path");
require("dotenv").config({
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
});
const axios = require("axios");
const InstanceManager = require("../utils/instanceMgr").default;
const logger = require("../utils/logger");
const client = require("../graphql-client/graphql-client").client;
const queries = require("../graphql-client/queries");
const { isObject } = require("lodash");
const generateEmailTemplate = require("./generateTemplate");
const mailer = require("./mailer");
// Get the image from the URL and return it as a base64 string
const getImage = async (imageUrl) => {
let image = await axios.get(imageUrl, { responseType: "arraybuffer" });
let raw = Buffer.from(image.data).toString("base64");
return "data:" + image.headers["content-type"] + ";base64," + raw;
};
// Log the email in the database
const logEmail = async (req, email) => {
try {
await client.request(queries.INSERT_EMAIL_AUDIT, {
email: {
to: email.to,
cc: email.cc,
subject: email.subject,
bodyshopid: req.body.bodyshopid,
useremail: req.user.email,
contents: req.body.html,
jobid: req.body.jobid,
sesmessageid: email.messageId,
status: "Sent"
}
});
} catch (error) {
logger.log("email-log-error", "error", req?.user?.email, null, {
from: `${req.body.from.name} <${req.body.from.address}>`,
to: req?.body?.to,
cc: req?.body?.cc,
subject: req?.body?.subject,
email
// info,
});
}
};
const sendServerEmail = async ({ subject, text }) => {
if (process.env.NODE_ENV === undefined) return;
try {
mailer.sendMail(
{
from: InstanceManager({
imex: `ImEX Online API - ${process.env.NODE_ENV} <noreply@imex.online>`,
rome: `Rome Online API - ${process.env.NODE_ENV} <noreply@romeonline.io>`
}),
to: ["support@thinkimex.com"],
subject: subject,
text: text,
ses: {
// optional extra arguments for SendRawEmail
Tags: [
{
Name: "tag_name",
Value: "tag_value"
}
]
}
},
(err, info) => {
logger.log("server-email-failure", err ? "error" : "debug", null, null, { message: err || info });
}
);
} catch (error) {
logger.log("server-email-failure", "error", null, null, { error });
}
};
const sendTaskEmail = async ({ to, subject, type = "text", html, text, attachments }) => {
try {
mailer.sendMail(
{
from: InstanceManager({
imex: `ImEX Online <noreply@imex.online>`,
rome: `Rome Online <noreply@romeonline.io>`
}),
to: to,
subject: subject,
...(type === "text" ? { text } : { html }),
attachments: attachments || null
},
(err, info) => {
// (message, type, user, record, meta
logger.log("server-email", err ? "error" : "debug", null, null, { errorMessage: err?.message });
}
);
} catch (error) {
logger.log("server-email-failure", "error", null, null, { error });
}
};
// Send an email
const sendEmail = async (req, res) => {
logger.log("send-email", "DEBUG", req.user.email, null, {
from: `${req.body.from.name} <${req.body.from.address}>`,
replyTo: req.body.ReplyTo.Email,
to: req.body.to,
cc: req.body.cc,
subject: req.body.subject,
templateStrings: req.body.templateStrings
});
let downloadedMedia = [];
if (req.body.media && req.body.media.length > 0) {
downloadedMedia = await Promise.all(
req.body.media.map((m) => {
try {
return getImage(m);
} catch (error) {
logger.log("send-email-error", "ERROR", req.user.email, null, {
from: `${req.body.from.name} <${req.body.from.address}>`,
replyTo: req.body.ReplyTo.Email,
to: req.body.to,
cc: req.body.cc,
subject: req.body.subject,
templateStrings: req.body.templateStrings,
error
});
}
})
);
}
mailer.sendMail(
{
from: `${req.body.from.name} <${req.body.from.address}>`,
replyTo: req.body.ReplyTo.Email,
to: req.body.to,
cc: req.body.cc,
subject: req.body.subject,
attachments:
[
...((req.body.attachments &&
req.body.attachments.map((a) => {
return {
filename: a.filename,
path: a.path
};
})) ||
[]),
...downloadedMedia.map((a) => {
return {
path: a
};
})
] || null,
html: isObject(req.body?.templateStrings) ? generateEmailTemplate(req.body.templateStrings) : req.body.html,
ses: {
// optional extra arguments for SendRawEmail
Tags: [
{
Name: "tag_name",
Value: "tag_value"
}
]
}
},
(err, info) => {
if (info) {
logger.log("send-email-success", "DEBUG", req?.user?.email, null, {
from: `${req.body.from.name} <${req.body.from.address}>`,
replyTo: req.body.ReplyTo.Email,
to: req.body.to,
cc: req.body.cc,
subject: req.body.subject,
templateStrings: req.body.templateStrings
// info,
});
logEmail(req, {
to: req.body.to,
cc: req.body.cc,
subject: req.body.subject,
messageId: info.response
});
res.json({
success: true //response: info
});
} else {
logger.log("send-email-failure", "ERROR", req?.user?.email, null, {
from: `${req.body.from.name} <${req.body.from.address}>`,
replyTo: req.body.ReplyTo.Email,
to: req.body.to,
cc: req.body.cc,
subject: req.body.subject,
templateStrings: req.body.templateStrings,
error: err
});
logEmail(req, {
to: req.body.to,
cc: req.body.cc,
subject: req.body.subject,
bodyshopid: req.body.bodyshopid
});
res.status(500).json({ success: false, error: err });
}
}
);
};
// This will be called by an SNS event trigger
const emailBounce = async (req, res) => {
try {
const body = JSON.parse(req.body);
if (body.Type === "SubscriptionConfirmation") {
logger.log("SNS-message", "DEBUG", "api", null, {
body: req.body
});
}
const message = JSON.parse(body.Message);
if (message.notificationType === "Bounce") {
let replyTo, subject, messageId;
message.mail.headers.forEach((header) => {
if (header.name === "Reply-To") {
replyTo = header.value;
} else if (header.name === "Subject") {
subject = header.value;
}
});
messageId = message.mail.messageId;
if (
replyTo ===
InstanceManager({
imex: "noreply@imex.online",
rome: "noreply@romeonline.io"
})
) {
res.sendStatus(200);
return;
}
//If it's bounced, log it as bounced in audit log. Send an email to the user.
const result = await client.request(queries.UPDATE_EMAIL_AUDIT, {
sesid: messageId,
status: "Bounced",
context: message.bounce?.bouncedRecipients
});
mailer.sendMail(
{
from: InstanceMgr({
imex: `ImEX Online <noreply@imex.online>`,
rome: `Rome Online <noreply@romeonline.io>`
}),
to: replyTo,
//bcc: "patrick@snapt.ca",
subject: `${InstanceMgr({
imex: "ImEX Online",
rome: "Rome Online"
})} Bounced Email - RE: ${subject}`,
text: `${InstanceMgr({
imex: "ImEX Online",
rome: "Rome Online"
})} has tried to deliver an email with the subject: ${subject} to the intended recipients but encountered an error.
${body.bounce?.bouncedRecipients.map(
(r) =>
`Recipient: ${r.emailAddress} | Status: ${r.action} | Code: ${r.diagnosticCode}
`
)}
`
},
(err, info) => {
logger.log("sns-error", err ? "error" : "debug", "api", null, {
message: err ? JSON.stringify(error) : info
});
}
);
}
} catch (error) {
logger.log("sns-error", "ERROR", "api", null, {
error: JSON.stringify(error)
});
}
res.sendStatus(200);
};
module.exports = {
sendEmail,
sendServerEmail,
sendTaskEmail,
emailBounce
};