// 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 }, pool: true, // use pooled connection rateLimit: true, // enable to make sure we are limiting maxConnections: 1, // set limit to 1 connection only maxMessages: 2 // send 2 emails per second }); } 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 } /** * Final email sending function. * * @param {string|string[]} to - Email address or array of email addresses. * @param {string} subject - Email subject. * @param {string} text - Plain text version of the email. * @param {string} html - HTML version of the email. * @param {Object[]} [attachments=[]] - Array of attachment objects. * @returns {Promise} - A promise that resolves when the email is sent. */ exports.SendEmail = async function (to, subject, text, html, attachments = []) { let sender = process.env.EMAIL_SENDER || '"Специално Свидетелстване София" '; 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); Handlebars.logger.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("
"); // 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: ` // // // // // //
//

Congrats for sending test email with Mailtrap!

//

Inspect it using the tabs you see above and learn how this email can be improved.

// Inspect with Tabs //

Now send your email using our fake SMTP server and integration of your choice!

//

Good luck! Hope it works.

//
// // // // `, // attachments: [ // { // filename: "welcome.png", // content_id: "welcome.png", // disposition: "inline", // content: welcomeImage, // }, // ], // }) // .then(console.log, console.error, setResult); // };