Files
mwitnessing/src/helpers/email.js
2024-04-27 16:49:54 +03:00

287 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// helper module to send emails with nodemailer
const fs = require("fs");
const path = require('path');
const { MailtrapClient } = require("mailtrap");
const nodemailer = require("nodemailer");
const CON = require("./const");
const CAL = require("./calendar");
const Handlebars = require('handlebars');
// const { google } = require("googleapis");
// const OAuth2 = google.auth.OAuth2;
const { Shift, Publisher, PrismaClient } = require("@prisma/client");
const { env } = require("../../next.config");
const SMTPTransport = require("nodemailer/lib/smtp-transport");
var transporter;
if (process.env.EMAIL_SERVICE.toLowerCase() === "mailtrap") {
transporter = nodemailer.createTransport({
host: process.env.MAILTRAP_HOST || "sandbox.smtp.mailtrap.io",
port: process.env.MAILTRAP_PORT || 2525,
auth: {
user: process.env.MAILTRAP_USER,
pass: process.env.MAILTRAP_PASS
}
});
}
else if (process.env.EMAIL_SERVICE.toLowerCase() === "gmail") {
transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL_GMAIL_USERNAME,
pass: process.env.EMAIL_GMAIL_APP_PASS
}
});
}
// ------------------ Email sending ------------------
var lastResult = null;
function setResult(result) {
lastResult = result;
}
exports.GetLastResult = function () {
return lastResult;
};
function normalizeEmailAddresses(to) {
let emails = [];
if (typeof to === 'string') {
// Handle CSV string by splitting into an array
if (to.includes(',')) emails = to.split(/\s*,\s*/);
else emails = [to]; // Handle single email string
} else if (Array.isArray(to)) {
emails = to.map(item => {
if (typeof item === 'string') return item;
if (item.name && item.email) return `"${item.name}" <${item.email}>`;
return JSON.stringify(item); // Handle unexpected object format
});
} else if (typeof to === 'object' && to.email) {
// Handle single object
emails = [`"${to.name}" <${to.email}>`];
} else {
// Fallback for other types
emails = [String(to)];
}
return emails; // Always returns an array
}
/// <summary>
/// Final email sending function.
/// </summary>
/// <param name="to">Email address or array of email addresses</param>
/// <param name="subject">Email subject</param>
/// <param name="text">Plain text version of the email</param>
/// <param name="html">HTML version of the email</param>
/// <param name="attachments">Array of attachment objects</param>
/// <returns>Promise</returns>
exports.SendEmail = async function (to, subject, text, html, attachments = []) {
let sender = process.env.EMAIL_SENDER || '"Специално Свидетелстване София" <sofia@mwitnessing.com>';
let emailAddresses = normalizeEmailAddresses(to)
const bypassEmailReccipients = process.env.EMAIL_BYPASS_TO || null;
if (bypassEmailReccipients !== null && bypassEmailReccipients.length > 0) {
emailAddresses = bypassEmailReccipients;
console.log("Emails bypassed. All mails sent to: " + emailAddresses);
}
const message = {
from: sender,
to: emailAddresses,
subject,
text,
html,
attachments
};
let result = await transporter
.sendMail(message)
.then(console.log)
.catch(console.error);
return result;
};
exports.SendEmailHandlebars = async function (to, templateName, model, attachments = []) {
try {
// Ensure the sender and mailtrapTestClient are correctly defined or imported
// Load and compile the main template
const mainTemplateSource = fs.readFileSync(path.join(process.cwd(), 'src', 'templates', 'emails', 'main.hbs'), 'utf8');
const mainTemplate = Handlebars.compile(mainTemplateSource);
// Dynamically load and compile the specified template
const templateSource = fs.readFileSync(path.join(process.cwd(), 'src', 'templates', 'emails', `${templateName}.hbs`), 'utf8');
// Extract subject and optional text version from the template source
const subjectMatch = templateSource.match(/{{!--\s*Subject:\s*(.*?)\s*--}}/);
const textMatch = templateSource.match(/{{!--\s*Text:\s*([\s\S]*?)\s*--}}/);
let subject = subjectMatch ? subjectMatch[1].trim() : 'ССОМ: Известие';
let textVersion = textMatch ? textMatch[1].trim() : null;
// Remove the subject and text annotations from the template source
const cleanTemplateSource = templateSource.replace(/{{!-- Subject: .* --}}/, '').replace(/{{!-- Text: [\s\S]*? --}}/, '');
// const cleanTemplateSource = templateSource
// .replace(/{{!--\s*Subject:.*?--}}\s*/, '')
// .replace(/{{!--\s*Text:.*?--}}\s*/, '');
// Compile the cleaned template
const template = Handlebars.compile(cleanTemplateSource);
// Render the specified template with the provided model
const templateHtml = template(model);
// Render the main template, inserting the specific template HTML
const html = mainTemplate({ body: templateHtml });
// Generate a plain text version if not explicitly provided
let text = textVersion || html.replace(/<[^>]*>?/gm, ''); // Simple regex to strip HTML tags. Might need refinement.
subject = Handlebars.compile(subject)(model);
text = Handlebars.compile(text)(model);
let results = this.SendEmail(to, subject, text, html, attachments);
return results;
} catch (error) {
console.error(error);
return new Error('Error sending email');
}
};
exports.SendEmail_NewShifts = async function (publisher, shifts) {
if (shifts.length === 0) return;
var date = new Date(shifts[0].startTime);
// Generate ICS calendar links for all shifts
const icsLink = CAL.GenerateICS(shifts);
// Prepare the shifts string
const shiftStr = shifts.map((s) => {
return `${CON.weekdaysBG[s.startTime.getDay()]} ${CON.GetDateFormat(s.startTime)} at ${s.cartEvent.location.name} from ${CON.GetTimeFormat(s.startTime)} to ${CON.GetTimeFormat(s.endTime)}`;
}).join("<br>");
// Define the model for the Handlebars template
const model = {
publisherFirstName: publisher.firstName,
publisherLastName: publisher.lastName,
month: CON.monthNamesBG[date.getMonth()],
shifts: shiftStr,
sentDate: new Date().toLocaleDateString() // Assuming you want to include the sent date in the email
};
await exports.SendEmailHandlebars(publisher.email, "newShifts", model,
[{
filename: "calendar.ics",
content: icsLink,
contentType: 'text/calendar' // Ensure this is correctly set for the ICS file
}]
).then(console.log).catch(console.error);
};
//----------------------- OLD -----------------------------
// exports.SendEmail_NewShifts = async function (publisher, shifts) {
// if (shifts.length == 0) return;
// var date = new Date(shifts[0].startTime);
// //generate ICS calendar links for all shifts
// const icsLink = CAL.GenerateICS(shifts);
// const shftStr = shifts
// .map((s) => {
// return ` ${CON.weekdaysBG[s.startTime.getDay()]
// } ${CON.GetDateFormat(s.startTime)} ${s.cartEvent.location.name
// } ${CON.GetTimeFormat(s.startTime)} - ${CON.GetTimeFormat(
// s.endTime
// )}`;
// })
// .join("\n");
// await client.send({
// from: sender,
// to: [
// {
// email: "dobromir.popov@gmail.com",//publisher.email,
// name: publisher.firstName + " " + publisher.lastName,
// },
// ],
// subject: "[CCC]: вашите смени през " + CON.monthNamesBG[date.getMonth()],
// text:
// "Здравей, " + publisher.firstName + " " + publisher.lastName + "!\n\n" +
// "Ти регистриран да получавате известия за нови смени на количка.\n" +
// `За месец ${CON.monthNamesBG[date.getMonth()]} имате следните смени:\n` +
// ` ${shftStr} \n\n\n` +
// "Поздрави,\n" +
// "Специално Свидетелстване София",
// attachments: [
// {
// filename: "calendar.ics",
// content_id: "calendar.ics",
// disposition: "inline",
// content: icsLink,
// },
// ],
// })
// .then(console.log, console.error, setResult);
// };
// // https://mailtrap.io/blog/sending-emails-with-nodemailer/
// exports.SendEmail_Example = async function (to) {
// const welcomeImage = fs.readFileSync(
// path.join(CON.contentPath, "welcome.png")
// );
// await client
// .send({
// category: "test",
// custom_variables: {
// hello: "world",
// year: 2022,
// anticipated: true,
// },
// from: sender,
// to: [{ email: to }],
// subject: "Hello from Mailtrap!",
// html: `<!doctype html>
// <html>
// <head>
// <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
// </head>
// <body style="font-family: sans-serif;">
// <div style="display: block; margin: auto; max-width: 600px;" class="main">
// <h1 style="font-size: 18px; font-weight: bold; margin-top: 20px">Congrats for sending test email with Mailtrap!</h1>
// <p>Inspect it using the tabs you see above and learn how this email can be improved.</p>
// <img alt="Inspect with Tabs" src="cid:welcome.png" style="width: 100%;">
// <p>Now send your email using our fake SMTP server and integration of your choice!</p>
// <p>Good luck! Hope it works.</p>
// </div>
// <!-- Example of invalid for email html/css, will be detected by Mailtrap: -->
// <style>
// .main { background-color: white; }
// a:hover { border-left-width: 1em; min-height: 2em; }
// </style>
// </body>
// </html>`,
// attachments: [
// {
// filename: "welcome.png",
// content_id: "welcome.png",
// disposition: "inline",
// content: welcomeImage,
// },
// ],
// })
// .then(console.log, console.error, setResult);
// };