468 lines
37 KiB
JavaScript
468 lines
37 KiB
JavaScript
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,
|
|
errorMessage: error?.message,
|
|
errorStack: error?.stack
|
|
// info,
|
|
});
|
|
}
|
|
};
|
|
|
|
const sendServerEmail = async ({ subject, text, to = [], attachments }) => {
|
|
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@imexsystems.ca", ...to],
|
|
subject: subject,
|
|
text: text,
|
|
attachments: attachments,
|
|
ses: {
|
|
// optional extra arguments for SendRawEmail
|
|
Tags: [
|
|
{
|
|
Name: "tag_name",
|
|
Value: "tag_value"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
// eslint-disable-next-line no-unused-vars
|
|
(err, info) => {
|
|
logger.log("server-email-send", err ? "error" : "debug", null, null, {
|
|
message: err?.message,
|
|
stack: err?.stack
|
|
});
|
|
}
|
|
);
|
|
} catch (error) {
|
|
logger.log("server-email-failure", "error", null, null, { message: error?.message, stack: error?.stack });
|
|
}
|
|
};
|
|
|
|
const sendMexicoBillingEmail = 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: ["mexico@rometech.zohodesk.com"],
|
|
subject: subject,
|
|
text: text,
|
|
ses: {
|
|
// optional extra arguments for SendRawEmail
|
|
Tags: [
|
|
{
|
|
Name: "tag_name",
|
|
Value: "tag_value"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
// eslint-disable-next-line no-unused-vars
|
|
(err, info) => {
|
|
logger.log("server-email-send", err ? "error" : "debug", null, null, {
|
|
message: err?.message,
|
|
stack: err?.stack
|
|
});
|
|
}
|
|
);
|
|
} catch (error) {
|
|
logger.log("server-email-failure", "error", null, null, { message: error?.message, stack: error?.stack });
|
|
}
|
|
};
|
|
|
|
const sendWelcomeEmail = async ({ to, resetLink, dateLine, features, bcc }) => {
|
|
try {
|
|
await mailer.sendMail({
|
|
from: InstanceManager({
|
|
imex: `ImEX Online <noreply@imex.online>`,
|
|
rome: `Rome Online <noreply@romeonline.io>`
|
|
}),
|
|
to,
|
|
bcc,
|
|
subject: InstanceManager({
|
|
imex: "Welcome to the ImEX Online platform.",
|
|
rome: "Welcome to the Rome Online platform."
|
|
}),
|
|
html: generateEmailTemplate({
|
|
header: InstanceManager({
|
|
imex: "Welcome to the ImEX Online platform.",
|
|
rome: "Welcome to the Rome Online platform."
|
|
}),
|
|
subHeader: `Your ${InstanceManager({
|
|
imex: features?.allAccess ? "ImEX Online" : "ImEX Lite",
|
|
rome: features?.allAccess ? "RO Manager" : "RO Basic"
|
|
})} shop setup has been completed, and this email will include all the information you need to begin.`,
|
|
body: `
|
|
<p style="color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 0 0 0 0px; Margin: 0 0 0 0px; line-height: 1.2; margin-bottom: 0px; Margin-bottom: 0px; font-size: 90%;">To finish setting up your account, visit this link and enter your desired password. <a href=${resetLink} style="color: #2199e8; text-decoration: none; font-weight: normal; padding: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%; line-height: 1.2;">Reset Password</a></p>
|
|
</td></tr>
|
|
</tbody></table></th>
|
|
</tr></tbody></table>
|
|
<table class="row" style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; padding: 0; width: 100%; position: relative; display: table;"><tbody style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; display: table-row-group;"><tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;">
|
|
<th class="small-12 large-12 columns first last" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; line-height: 1.2; margin: 0 auto; Margin: 0 auto; padding-bottom: 16px; width: 734px; padding-left: 8px; padding-right: 8px; border-collapse: collapse;"><table style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; width: 100%;">
|
|
<tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;"><td style="word-wrap: break-word; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin: 0; Margin: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; word-break: keep-all; -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; line-height: 1.2; border-collapse: collapse;">
|
|
<p style="color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 0 0 0 0px; Margin: 0 0 0 0px; line-height: 1.2; margin-bottom: 0px; Margin-bottom: 0px; font-size: 90%;">To access your ${InstanceManager(
|
|
{
|
|
imex: features.allAccess ? "ImEX Online" : "ImEX Lite",
|
|
rome: features.allAccess ? "RO Manager" : "RO Basic"
|
|
}
|
|
)} shop, visit <a href=${InstanceManager({
|
|
imex: "https://imex.online/",
|
|
rome: "https://romeonline.io/"
|
|
})} style="color: #2199e8; text-decoration: none; font-weight: normal; padding: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%; line-height: 1.2;">${InstanceManager(
|
|
{
|
|
imex: "imex.online",
|
|
rome: "romeonline.io"
|
|
}
|
|
)}</a>. Your username is your email, and your password is what you previously set up. Contact support for additional logins.</p>
|
|
</td></tr>
|
|
</tbody></table></th>
|
|
</tr></tbody></table>
|
|
${InstanceManager({
|
|
rome: `
|
|
<table class="row" style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; padding: 0; width: 100%; position: relative; display: table;"><tbody style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; display: table-row-group;"><tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;">
|
|
<th class="small-12 large-12 columns first last" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; line-height: 1.2; margin: 0 auto; Margin: 0 auto; padding-bottom: 16px; width: 734px; padding-left: 8px; padding-right: 8px; border-collapse: collapse;"><table style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; width: 100%;">
|
|
<tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;"><td style="word-wrap: break-word; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin: 0; Margin: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; word-break: keep-all; -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; line-height: 1.2; border-collapse: collapse;">
|
|
<p style="color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 0 0 0 0px; Margin: 0 0 0 0px; line-height: 1.2; margin-bottom: 0px; Margin-bottom: 0px; font-size: 90%;">To push estimates over from your estimating system, you must download the Web-Est EMS Unzipper & Rome Online Partner (Computers using Windows only). Here are some steps to help you get started.</p>
|
|
</td><tr>
|
|
<tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;"><td style="word-wrap: break-word; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin: 0; Margin: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; word-break: keep-all; -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; line-height: 1.2; border-collapse: collapse;">
|
|
<ul style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 1%; padding-left: 30px;">
|
|
<li style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%;">Download and set up the Web-Est EMS Unzipper - <a href="https://help.imex.online/en/article/how-to-set-up-the-ems-unzip-downloader-on-web-est-n9hbcv/" style="color: #2199e8; text-decoration: none; font-weight: normal; padding: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%; line-height: 1.2;">How to setup the EMS Unzip Downloader on Web-Est</a></li>
|
|
<li style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%;">Download and set up Rome Online Partner - <a href="https://help.imex.online/en/article/setting-up-the-rome-online-partner-1xsw8tb/" style="color: #2199e8; text-decoration: none; font-weight: normal; padding: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%; line-height: 1.2;">Setting up the Rome Online Partner</a></li>
|
|
</ul>
|
|
</td></tr>
|
|
</tbody></table></th>
|
|
</tr></tbody></table>
|
|
<table class="row" style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; padding: 0; width: 100%; position: relative; display: table;"><tbody style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; display: table-row-group;"><tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;">
|
|
<th class="small-12 large-12 columns first last" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; line-height: 1.2; margin: 0 auto; Margin: 0 auto; padding-bottom: 16px; width: 734px; padding-left: 8px; padding-right: 8px; border-collapse: collapse;"><table style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; width: 100%;">
|
|
<tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;"><td style="word-wrap: break-word; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin: 0; Margin: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; word-break: keep-all; -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; line-height: 1.2; border-collapse: collapse;">
|
|
<p style="color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 0 0 0 0px; Margin: 0 0 0 0px; line-height: 1.2; margin-bottom: 0px; Margin-bottom: 0px; font-size: 90%;">Once you successfully set up the partner, now it's time to do some initial in-product items: Please note, <b>an estimate must be exported from the estimating platform to use tours.</b></p>
|
|
</td><tr>
|
|
<tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;"><td style="word-wrap: break-word; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin: 0; Margin: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; word-break: keep-all; -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; line-height: 1.2; border-collapse: collapse;">
|
|
<ul style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 1%; padding-left: 30px;">
|
|
<li style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%;">Send estimate from Web-Est to RO Basic - <a href="https://help.imex.online/en/article/how-to-send-estimates-from-web-est-to-the-management-system-ox0h9a/" style="color: #2199e8; text-decoration: none; font-weight: normal; padding: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%; line-height: 1.2;">How to setup the EMS Unzip Downloader on Web-Est</a></li>
|
|
<li style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%;">Once completed, learn how to use RO Basic by accessing the tours at the bottom middle of the screen (labeled “Training Tours”). These walkthroughs will show you how to navigate from creating an RO to closing an RO - <a href="https://www.youtube.com/watch?v=gcbSe5med0I" style="color: #2199e8; text-decoration: none; font-weight: normal; padding: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%; line-height: 1.2;">ROME Collision Management Youtube Training Videos</a></li>
|
|
</ul>
|
|
</td></tr>
|
|
</tbody></table></th>
|
|
</tr></tbody></table>
|
|
<table class="row" style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; padding: 0; width: 100%; position: relative; display: table;"><tbody style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; display: table-row-group;"><tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;">
|
|
<th class="small-12 large-12 columns first last" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; line-height: 1.2; margin: 0 auto; Margin: 0 auto; padding-bottom: 16px; width: 734px; padding-left: 8px; padding-right: 8px; border-collapse: collapse;"><table style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; width: 100%;">
|
|
<tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;"><td style="word-wrap: break-word; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin: 0; Margin: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; word-break: keep-all; -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; line-height: 1.2; border-collapse: collapse;">
|
|
<p style="color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 0 0 0 0px; Margin: 0 0 0 0px; line-height: 1.2; margin-bottom: 0px; Margin-bottom: 0px; font-size: 90%;">If you need any assistance with setting up the programs, or if you want a dedicated Q&A session with one of our customer success specialists, schedule by clicking this link - <a href="https://rometech.zohobookings.com/#/PSAT" style="color: #2199e8; text-decoration: none; font-weight: normal; padding: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%; line-height: 1.2;">Rome Basic Training Booking</a></p>
|
|
</td></tr>
|
|
</tbody></table></th>
|
|
</tr></tbody></table>
|
|
<table class="row" style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; padding: 0; width: 100%; position: relative; display: table;"><tbody style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; display: table-row-group;"><tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;">
|
|
<th class="small-12 large-12 columns first last" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; line-height: 1.2; margin: 0 auto; Margin: 0 auto; padding-bottom: 16px; width: 734px; padding-left: 8px; padding-right: 8px; border-collapse: collapse;"><table style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; width: 100%;">
|
|
<tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;"><td style="word-wrap: break-word; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin: 0; Margin: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; word-break: keep-all; -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; line-height: 1.2; border-collapse: collapse;">
|
|
<p style="color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 0 0 0 0px; Margin: 0 0 0 0px; line-height: 1.2; margin-bottom: 0px; Margin-bottom: 0px; font-size: 90%;">If you have additional questions or need any support, feel free to use the RO Basic support chat (blue chat box located in the bottom right corner) or give us a call at <a href="tel:14103576700" style="color: #2199e8; text-decoration: none; font-weight: normal; padding: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%; line-height: 1.2;">(410) 357-6700</a>. We are here to help make your experience seamless!</p>
|
|
</td></tr>
|
|
</tbody></table></th>
|
|
</tr></tbody></table>
|
|
`
|
|
})}
|
|
<table class="row" style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; padding: 0; width: 100%; position: relative; display: table;"><tbody style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; display: table-row-group;"><tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;">
|
|
<th class="small-12 large-12 columns first last" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; line-height: 1.2; margin: 0 auto; Margin: 0 auto; padding-bottom: 16px; width: 734px; padding-left: 8px; padding-right: 8px; border-collapse: collapse;"><table style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; width: 100%;">
|
|
<tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;"><td style="word-wrap: break-word; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin: 0; Margin: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; word-break: keep-all; -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; line-height: 1.2; border-collapse: collapse;">
|
|
<p style="color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 0 0 0 0px; Margin: 0 0 0 0px; line-height: 1.2; margin-bottom: 0px; Margin-bottom: 0px; font-size: 90%;">In addition to the training tour, you can also book a live one-on-one demo to see exactly how our system can help streamline the repair process at your shop, schedule by clicking this link - <a href="https://outlook.office.com/bookwithme/user/0aa3ae2c6d59497d9f93fb72479848dc@imexsystems.ca/meetingtype/Qy7CsXl5MkuUJ0NRD7B1AA2?anonymous&ep=mlink" style="color: #2199e8; text-decoration: none; font-weight: normal; padding: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 90%; line-height: 1.2;">${InstanceManager(
|
|
{
|
|
imex: "ImEX Lite",
|
|
rome: "Rome Basic"
|
|
}
|
|
)} Demo Booking</a></p>
|
|
</td></tr>
|
|
</tbody></table></th>
|
|
</tr></tbody></table>
|
|
<table class="row" style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; padding: 0; width: 100%; position: relative; display: table;"><tbody style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; display: table-row-group;"><tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;">
|
|
<th class="small-12 large-12 columns first last" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; line-height: 1.2; margin: 0 auto; Margin: 0 auto; padding-bottom: 8px; width: 734px; padding-left: 0px; padding-right: 8px; border-collapse: collapse;"><table style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; width: 100%;">
|
|
<tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;"><td style="word-wrap: break-word; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin: 0; Margin: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; word-break: keep-all; -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; line-height: 1.2; border-collapse: collapse;">
|
|
<p style="color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 0 0 0 0px; Margin: 0 0 0 0px; line-height: 1.2; margin-bottom: 0px; Margin-bottom: 0px; font-size: 90%;">Thanks,</p>
|
|
</td></tr>
|
|
</tbody></table></th>
|
|
</tr></tbody></table>
|
|
<table class="row" style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; padding: 0; width: 100%; position: relative; display: table;"><tbody style="font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; display: table-row-group;"><tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;">
|
|
<th class="small-12 large-12 columns first last" style="word-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; line-height: 1.2; margin: 0 auto; Margin: 0 auto; padding-bottom: 8px; width: 734px; padding-left: 0px; padding-right: 8px; border-collapse: collapse;"><table style="border-spacing: 0; border-collapse: collapse; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; width: 100%;">
|
|
<tr style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; vertical-align: top; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif;"><td style="word-wrap: break-word; vertical-align: top; color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin: 0; Margin: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; font-size: 15px; word-break: keep-all; -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; line-height: 1.2; border-collapse: collapse;">
|
|
<p style="color: #0a0a0a; font-weight: normal; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; text-align: left; font-family: 'Montserrat', 'Montserrat Alternates', sans-serif; margin: 0 0 0 0px; Margin: 0 0 0 0px; line-height: 1.2; margin-bottom: 0px; Margin-bottom: 0px; font-size: 90%;">The ${InstanceManager(
|
|
{
|
|
imex: "ImEX Online",
|
|
rome: "Rome Online"
|
|
}
|
|
)} Team</p>
|
|
`,
|
|
dateLine
|
|
})
|
|
});
|
|
} 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
|
|
},
|
|
// eslint-disable-next-line no-unused-vars
|
|
(err, info) => {
|
|
// (message, type, user, record, meta
|
|
logger.log("server-email-send", err ? "error" : "debug", null, null, {
|
|
message: err?.message,
|
|
stack: err?.stack
|
|
});
|
|
}
|
|
);
|
|
} catch (error) {
|
|
logger.log("server-email-failure", "error", null, null, { message: error?.message, stack: error?.stack });
|
|
}
|
|
};
|
|
|
|
// 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,
|
|
errorMessage: error?.message,
|
|
errorStack: error?.stack
|
|
});
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
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
|
|
};
|
|
})
|
|
],
|
|
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,
|
|
errorMessage: err?.message,
|
|
errorStack: err?.stack
|
|
});
|
|
logEmail(req, {
|
|
to: req.body.to,
|
|
cc: req.body.cc,
|
|
subject: req.body.subject,
|
|
bodyshopid: req.body.bodyshopid
|
|
});
|
|
res.status(500).json({ success: false, errorMessage: err?.message, stack: err?.stack });
|
|
}
|
|
}
|
|
);
|
|
};
|
|
|
|
// 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.
|
|
await client.request(queries.UPDATE_EMAIL_AUDIT, {
|
|
sesid: messageId,
|
|
status: "Bounced",
|
|
context: message.bounce?.bouncedRecipients
|
|
});
|
|
mailer.sendMail(
|
|
{
|
|
from: InstanceManager({
|
|
imex: `ImEX Online <noreply@imex.online>`,
|
|
rome: `Rome Online <noreply@romeonline.io>`
|
|
}),
|
|
to: replyTo,
|
|
//bcc: "patrick@snapt.ca",
|
|
subject: `${InstanceManager({
|
|
imex: "ImEX Online",
|
|
rome: "Rome Online"
|
|
})} Bounced Email - RE: ${subject}`,
|
|
text: `${InstanceManager({
|
|
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}
|
|
`
|
|
)}
|
|
`
|
|
},
|
|
// eslint-disable-next-line no-unused-vars
|
|
(err, info) => {
|
|
logger.log("sns-error", err ? "error" : "debug", "api", null, {
|
|
errorMessage: err?.message,
|
|
errorStack: err?.stack
|
|
});
|
|
}
|
|
);
|
|
}
|
|
} catch (error) {
|
|
logger.log("sns-error", "ERROR", "api", null, {
|
|
errorMessage: error?.message,
|
|
errorStack: error?.stack
|
|
});
|
|
}
|
|
res.sendStatus(200);
|
|
};
|
|
|
|
module.exports = {
|
|
sendEmail,
|
|
sendServerEmail,
|
|
sendMexicoBillingEmail,
|
|
sendTaskEmail,
|
|
emailBounce,
|
|
sendWelcomeEmail
|
|
};
|