diff options
author | Gavin Mogan <git@gavinmogan.com> | 2025-04-23 15:06:54 -0700 |
---|---|---|
committer | Gavin Mogan <git@gavinmogan.com> | 2025-04-23 15:30:37 -0700 |
commit | aace2c7e6ccb6e74df83faac74c427d43bfaf79b (patch) | |
tree | 72853ba15eae2c1ec46afc0dbf62fe2c0b4550cf | |
parent | a9a33edbd90f8eb7a011ec839994fb07f084bd8b (diff) |
Fix ReferenceError: nodemailerTransporter is not defined
Part of https://github.com/lowercasename/gathio/pull/200 was migrating
more code to use the shared init email function, but all the local
usages of nodemailerTransporter were missed
-rwxr-xr-x | src/app.ts | 39 | ||||
-rw-r--r-- | src/lib/email.ts | 57 | ||||
-rw-r--r-- | src/lib/handlebars.ts | 27 | ||||
-rwxr-xr-x | src/routes.js | 568 | ||||
-rw-r--r-- | src/routes/frontend.ts | 5 |
5 files changed, 302 insertions, 394 deletions
@@ -15,16 +15,28 @@ import { activityPubContentType, alternateActivityPubContentType, } from "./lib/activitypub.js"; +import getConfig from "./lib/config.js"; const app = express(); +const config = getConfig(); -app.locals.sendEmails = initEmailService(); +initEmailService().then((sendEmails) => (app.locals.sendEmails = sendEmails)); // View engine // const hbsInstance = hbs.create({ defaultLayout: "main", partialsDir: ["views/partials/"], layoutsDir: "views/layouts/", + runtimeOptions: { + data: { + domain: config.general.domain, + contactEmail: config.general.email, + siteName: config.general.site_name, + mailService: config.general.mail_service, + siteLogo: config.general.email_logo_url, + isFederated: config.general.is_federated || true, + }, + }, helpers: { plural: function (number: number, text: string) { var singular = number === 1; @@ -46,6 +58,31 @@ const hbsInstance = hbs.create({ }, }, }); +app.locals.renderEmail = async function renderEmail( + template: string, + data: object +) { + const [html, text] = await Promise.all([ + hbsInstance.renderView( + `./views/emails/${template}Html.handlebars`, + { + cache: true, + layout: "email.handlebars", + ...data, + } + ), + hbsInstance.renderView( + `./views/emails/${template}Text.handlebars`, + { + cache: true, + layout: "email.handlebars", + ...data, + } + ), + ]); + return { html, text } +} + app.engine("handlebars", hbsInstance.engine); app.set("view engine", "handlebars"); app.set("hbsInstance", hbsInstance); diff --git a/src/lib/email.ts b/src/lib/email.ts index 7b7a7a1..e7243aa 100644 --- a/src/lib/email.ts +++ b/src/lib/email.ts @@ -1,10 +1,10 @@ -import { Request } from "express"; import sgMail from "@sendgrid/mail"; import nodemailer, { Transporter } from "nodemailer"; import { getConfig } from "./config.js"; import SMTPTransport from "nodemailer/lib/smtp-transport/index.js"; import { exitWithError } from "./process.js"; import { renderTemplate } from "./handlebars.js"; +import { ExpressHandlebars } from "express-handlebars"; const config = getConfig(); type EmailTemplate = @@ -36,10 +36,12 @@ export const initEmailService = async (): Promise<boolean> => { sgMail.setApiKey(config.sendgrid.api_key); console.log("Sendgrid is ready to send emails."); return true; - case "nodemailer": - let nodemailerTransporter:Transporter|undefined = undefined; + case "nodemailer": { + let nodemailerTransporter: Transporter | undefined = undefined; if (config.nodemailer?.smtp_url) { - nodemailerTransporter = nodemailer.createTransport(config.nodemailer?.smtp_url); + nodemailerTransporter = nodemailer.createTransport( + config.nodemailer?.smtp_url, + ); } else { if ( !config.nodemailer?.smtp_server || @@ -52,7 +54,7 @@ export const initEmailService = async (): Promise<boolean> => { const nodemailerConfig = { host: config.nodemailer?.smtp_server, port: Number(config.nodemailer?.smtp_port) || 587, - tls: { + tls: { // do not fail on invalid certs rejectUnauthorized: false, }, @@ -61,10 +63,11 @@ export const initEmailService = async (): Promise<boolean> => { if (config.nodemailer?.smtp_username) { nodemailerConfig.auth = { user: config.nodemailer?.smtp_username, - pass: config.nodemailer?.smtp_password + pass: config.nodemailer?.smtp_password, }; } - nodemailerTransporter = nodemailer.createTransport(nodemailerConfig); + nodemailerTransporter = + nodemailer.createTransport(nodemailerConfig); } const nodemailerVerified = await nodemailerTransporter.verify(); @@ -76,6 +79,7 @@ export const initEmailService = async (): Promise<boolean> => { "Error verifying Nodemailer transporter. Please check your Nodemailer configuration.", ); } + } case "none": default: console.warn( @@ -85,10 +89,34 @@ export const initEmailService = async (): Promise<boolean> => { } }; -export const sendEmail = async ( +export const sendTemplatedEmail = async ( + hbs: ExpressHandlebars, to: string, bcc: string, subject: string, + template: string, + data: object, +): Promise<boolean> => { + const [html, text] = await Promise.all([ + hbs.renderView(`./views/emails/${template}Html.handlebars`, { + cache: true, + layout: "email.handlebars", + ...data, + }), + hbs.renderView(`./views/emails/${template}Text.handlebars`, { + cache: true, + layout: "email.handlebars", + ...data, + }), + ]); + + return await sendEmail(to, bcc, subject, text, html); +}; + +export const sendEmail = async ( + to: string | string[], + bcc: string | string[] | undefined, + subject: string, text: string, html?: string, ): Promise<boolean> => { @@ -104,7 +132,7 @@ export const sendEmail = async ( html, }); return true; - } catch (e: any) { + } catch (e: Error) { if (e.response) { console.error(e.response.body); } else { @@ -114,9 +142,11 @@ export const sendEmail = async ( } case "nodemailer": try { - let nodemailerTransporter:Transporter|undefined = undefined; + let nodemailerTransporter: Transporter | undefined = undefined; if (config.nodemailer?.smtp_url) { - nodemailerTransporter = nodemailer.createTransport(config.nodemailer?.smtp_url); + nodemailerTransporter = nodemailer.createTransport( + config.nodemailer?.smtp_url, + ); } else { const nodemailerConfig = { host: config.nodemailer?.smtp_server, @@ -126,11 +156,12 @@ export const sendEmail = async ( if (config.nodemailer?.smtp_username) { nodemailerConfig.auth = { user: config.nodemailer?.smtp_username, - pass: config.nodemailer?.smtp_password + pass: config.nodemailer?.smtp_password, }; } - nodemailerTransporter = nodemailer.createTransport(nodemailerConfig); + nodemailerTransporter = + nodemailer.createTransport(nodemailerConfig); } await nodemailerTransporter.sendMail({ envelope: { diff --git a/src/lib/handlebars.ts b/src/lib/handlebars.ts index d5a8b6e..42f8010 100644 --- a/src/lib/handlebars.ts +++ b/src/lib/handlebars.ts @@ -1,4 +1,5 @@ import { Request } from "express"; +import { ExpressHandlebars } from "express-handlebars"; export const renderTemplate = async ( req: Request, @@ -21,3 +22,29 @@ export const renderTemplate = async ( ); }); }; + +export const renderEmail = async ( + hbsInstance: ExpressHandlebars, + templateName: string, + data: Record<string, unknown>, +): Promise<{ html: string, text: string }> => { + const [html, text] = await Promise.all([ + hbsInstance.renderView( + `./views/emails/${templateName}Html.handlebars`, + { + cache: true, + layout: "email.handlebars", + ...data, + } + ), + hbsInstance.renderView( + `./views/emails/${templateName}Text.handlebars`, + { + cache: true, + layout: "email.handlebars", + ...data, + } + ), + ]); + return { html, text } +} diff --git a/src/routes.js b/src/routes.js index e758e6b..f609f94 100755 --- a/src/routes.js +++ b/src/routes.js @@ -19,12 +19,13 @@ import { broadcastDeleteMessage, processInbox, } from "./activitypub.js"; +import { renderEmail } from "./lib/handlebars.js"; import Event from "./models/Event.js"; import EventGroup from "./models/EventGroup.js"; import path from "path"; import { activityPubContentType } from "./lib/activitypub.js"; import { hashString } from "./util/generator.js"; -import { initEmailService } from "./lib/email.js"; +import { initEmailService, sendEmail } from "./lib/email.js"; const config = getConfig(); const domain = config.general.domain; @@ -44,9 +45,7 @@ const nanoid = customAlphabet( const router = express.Router(); let sendEmails = false; -initEmailService().then((emailService) => { - sendEmails = emailService -}); +initEmailService().then((emailService) => (sendEmails = emailService)); router.use(fileUpload()); @@ -58,7 +57,10 @@ schedule.scheduleJob("59 23 * * *", function (fireDate) { return; } - const too_old = moment.tz("Etc/UTC").subtract(deleteAfterDays, "days").toDate(); + const too_old = moment + .tz("Etc/UTC") + .subtract(deleteAfterDays, "days") + .toDate(); console.log( "Old event deletion running! Deleting all events concluding before ", too_old, @@ -81,9 +83,9 @@ schedule.scheduleJob("59 23 * * *", function (fireDate) { "deleteOldEvents", "error", "Attempt to delete old event " + - id + - " failed with error: " + - err, + id + + " failed with error: " + + err, ); }); }; @@ -100,9 +102,9 @@ schedule.scheduleJob("59 23 * * *", function (fireDate) { "deleteOldEvents", "error", "Attempt to delete event image for old event " + - event.id + - " failed with error: " + - err, + event.id + + " failed with error: " + + err, ); } // Image removed @@ -149,9 +151,9 @@ schedule.scheduleJob("59 23 * * *", function (fireDate) { "deleteOldEvents", "error", "Attempt to delete old event " + - event.id + - " failed with error: " + - err, + event.id + + " failed with error: " + + err, ); }); @@ -204,9 +206,9 @@ router.post("/deleteimage/:eventID/:editToken", (req, res) => { "deleteEventImage", "error", "Attempt to delete event image for event " + - req.params.eventID + - " failed with error: " + - err, + req.params.eventID + + " failed with error: " + + err, ); } // Image removed @@ -227,9 +229,9 @@ router.post("/deleteimage/:eventID/:editToken", (req, res) => { "deleteEventImage", "error", "Attempt to delete event image for event " + - req.params.eventID + - " failed with error: " + - err, + req.params.eventID + + " failed with error: " + + err, ); }); }, @@ -271,9 +273,9 @@ router.post("/deleteevent/:eventID/:editToken", (req, res) => { "deleteEvent", "error", "Attempt to delete event " + - req.params.eventID + - " failed with error: " + - err, + req.params.eventID + + " failed with error: " + + err, ); } }, @@ -293,9 +295,9 @@ router.post("/deleteevent/:eventID/:editToken", (req, res) => { "deleteEvent", "error", "Attempt to delete event image for event " + - req.params.eventID + - " failed with error: " + - err, + req.params.eventID + + " failed with error: " + + err, ); } // Image removed @@ -303,8 +305,8 @@ router.post("/deleteevent/:eventID/:editToken", (req, res) => { "deleteEvent", "success", "Event " + - req.params.eventID + - " deleted", + req.params.eventID + + " deleted", ); }, ); @@ -316,63 +318,29 @@ router.post("/deleteevent/:eventID/:editToken", (req, res) => { // Send emails here otherwise they don't exist lol if (sendEmails) { - const attendeeEmails = event.attendees - .filter( + const attendeeEmails = event?.attendees?.filter( (o) => o.status === "attending" && o.email, ) - .map((o) => o.email); + .map((o) => o.email || '') || []; if (attendeeEmails.length) { console.log( "Sending emails to: " + - attendeeEmails, + attendeeEmails, ); - req.app.get("hbsInstance").renderView( - "./views/emails/deleteEvent/deleteEventHtml.handlebars", + renderEmail( + req.app.get("hbsInstance"), + "deleteEvent/deleteEvent", { - siteName, - siteLogo, - domain, - eventName: event.name, - cache: true, - layout: "email.handlebars", + eventName: event?.name, }, - function (err, html) { - const msg = { - to: attendeeEmails, - from: contactEmail, - subject: `${siteName}: ${event.name} was deleted`, - html, - }; - switch (mailService) { - case "sendgrid": - sgMail - .sendMultiple(msg) - .catch((e) => { - console.error( - e.toString(), - ); - res.status( - 500, - ).end(); - }); - break; - case "nodemailer": - nodemailerTransporter - .sendMail(msg) - .catch((e) => { - console.error( - e.toString(), - ); - res.status( - 500, - ).end(); - }); - break; - } - }, - ); + ).then( + ({ html, text }) => sendEmail(attendeeEmails, '', `${siteName}: ${event?.name} was deleted`, text, html) + ).catch((e) => { + console.error('error sending attendy email', e.toString()); + res.status(500).end(); + }); } else { console.log("Nothing to send!"); } @@ -381,15 +349,15 @@ router.post("/deleteevent/:eventID/:editToken", (req, res) => { .catch((err) => { res.send( "Sorry! Something went wrong (error deleting): " + - err, + err, ); addToLog( "deleteEvent", "error", "Attempt to delete event " + - req.params.eventID + - " failed with error: " + - err, + req.params.eventID + + " failed with error: " + + err, ); }); }, @@ -401,8 +369,8 @@ router.post("/deleteevent/:eventID/:editToken", (req, res) => { "deleteEvent", "error", "Attempt to delete event " + - req.params.eventID + - " failed with error: token does not match", + req.params.eventID + + " failed with error: token does not match", ); } }) @@ -412,9 +380,9 @@ router.post("/deleteevent/:eventID/:editToken", (req, res) => { "deleteEvent", "error", "Attempt to delete event " + - req.params.eventID + - " failed with error: " + - err, + req.params.eventID + + " failed with error: " + + err, ); }); }); @@ -447,9 +415,9 @@ router.post("/deleteeventgroup/:eventGroupID/:editToken", (req, res) => { "deleteEventGroup", "error", "Attempt to delete event group " + - req.params.eventGroupID + - " failed with error: " + - err, + req.params.eventGroupID + + " failed with error: " + + err, ); } }, @@ -469,9 +437,9 @@ router.post("/deleteeventgroup/:eventGroupID/:editToken", (req, res) => { "deleteEventGroup", "error", "Attempt to delete event image for event group " + - req.params.eventGroupID + - " failed with error: " + - err, + req.params.eventGroupID + + " failed with error: " + + err, ); } }, @@ -487,8 +455,8 @@ router.post("/deleteeventgroup/:eventGroupID/:editToken", (req, res) => { "deleteEventGroup", "success", "Event group " + - req.params.eventGroupID + - " deleted", + req.params.eventGroupID + + " deleted", ); res.writeHead(302, { Location: "/", @@ -498,30 +466,30 @@ router.post("/deleteeventgroup/:eventGroupID/:editToken", (req, res) => { .catch((err) => { res.send( "Sorry! Something went wrong (error deleting): " + - err, + err, ); addToLog( "deleteEventGroup", "error", "Attempt to delete event group " + - req.params.eventGroupID + - " failed with error: " + - err, + req.params.eventGroupID + + " failed with error: " + + err, ); }); }) .catch((err) => { res.send( "Sorry! Something went wrong (error deleting): " + - err, + err, ); addToLog( "deleteEventGroup", "error", "Attempt to delete event group " + - req.params.eventGroupID + - " failed with error: " + - err, + req.params.eventGroupID + + " failed with error: " + + err, ); }); } else { @@ -531,8 +499,8 @@ router.post("/deleteeventgroup/:eventGroupID/:editToken", (req, res) => { "deleteEventGroup", "error", "Attempt to delete event group " + - req.params.eventGroupID + - " failed with error: token does not match", + req.params.eventGroupID + + " failed with error: token does not match", ); } }) @@ -542,9 +510,9 @@ router.post("/deleteeventgroup/:eventGroupID/:editToken", (req, res) => { "deleteEventGroup", "error", "Attempt to delete event group " + - req.params.eventGroupID + - " failed with error: " + - err, + req.params.eventGroupID + + " failed with error: " + + err, ); }); }); @@ -562,9 +530,9 @@ router.post("/attendee/provision", async (req, res) => { "provisionEventAttendee", "error", "Attempt to provision attendee in event " + - req.query.eventID + - " failed with error: " + - e, + req.query.eventID + + " failed with error: " + + e, ); return res.sendStatus(500); }); @@ -580,9 +548,9 @@ router.post("/attendee/provision", async (req, res) => { "provisionEventAttendee", "error", "Attempt to provision attendee in event " + - req.query.eventID + - " failed with error: " + - e, + req.query.eventID + + " failed with error: " + + e, ); return res.sendStatus(500); }); @@ -618,9 +586,9 @@ router.post("/attendevent/:eventID", async (req, res) => { "attendEvent", "error", "Attempt to attend event " + - req.params.eventID + - " failed with error: " + - e, + req.params.eventID + + " failed with error: " + + e, ); return res.sendStatus(500); }); @@ -659,7 +627,9 @@ router.post("/attendevent/:eventID", async (req, res) => { "attendees.$.name": req.body.attendeeName, "attendees.$.email": req.body.attendeeEmail, "attendees.$.number": req.body.attendeeNumber, - "attendees.$.visibility": !!req.body.attendeeVisible ? "public" : "private", + "attendees.$.visibility": req.body.attendeeVisible + ? "public" + : "private", }, }, ) @@ -670,44 +640,23 @@ router.post("/attendevent/:eventID", async (req, res) => { "Attendee added to event " + req.params.eventID, ); if (sendEmails) { - if (req.body.attendeeEmail) { - req.app.get("hbsInstance").renderView( - "./views/emails/addEventAttendee/addEventAttendeeHtml.handlebars", + if (req.body.attendeeEmail) { + renderEmail( + req.app.get("hbsInstance"), + "addEventAttendee/addEventAttendee", { eventID: req.params.eventID, - siteName, - siteLogo, - domain, removalPassword: req.body.removalPassword, - removalPasswordHash: hashString(req.body.removalPassword), - cache: true, - layout: "email.handlebars", - }, - function (err, html) { - const msg = { - to: req.body.attendeeEmail, - from: contactEmail, - subject: `${siteName}: You're RSVPed to ${event.name}`, - html, - }; - switch (mailService) { - case "sendgrid": - sgMail.send(msg).catch((e) => { - console.error(e.toString()); - res.status(500).end(); - }); - break; - case "nodemailer": - nodemailerTransporter - .sendMail(msg) - .catch((e) => { - console.error(e.toString()); - res.status(500).end(); - }); - break; - } + removalPasswordHash: hashString( + req.body.removalPassword, + ), }, - ); + ).then( + ({ html, text }) => sendEmail(req.body.attendeeEmail, '', `${siteName}: You're RSVPed to ${event.name}`, text, html) + ).catch((e) => { + console.error('error sending addEventAttendee email', e.toString()); + res.status(500).end(); + }); } } res.redirect(`/${req.params.eventID}`); @@ -718,9 +667,9 @@ router.post("/attendevent/:eventID", async (req, res) => { "addEventAttendee", "error", "Attempt to add attendee to event " + - req.params.eventID + - " failed with error: " + - error, + req.params.eventID + + " failed with error: " + + error, ); }); }); @@ -750,40 +699,18 @@ router.get("/oneclickunattendevent/:eventID/:attendeeID", (req, res) => { if (sendEmails) { // currently this is never called because we don't have the email address if (req.body.attendeeEmail) { - req.app.get("hbsInstance").renderView( - "./views/emails/removeEventAttendee/removeEventAttendeeHtml.handlebars", + renderEmail( + req.app.get("hbsInstance"), + "removeEventAttendee/removeEventAttendee", { eventName: req.params.eventName, - siteName, - domain, - cache: true, - layout: "email.handlebars", }, - function (err, html) { - const msg = { - to: req.body.attendeeEmail, - from: contactEmail, - subject: `${siteName}: You have been removed from an event`, - html, - }; - switch (mailService) { - case "sendgrid": - sgMail.send(msg).catch((e) => { - console.error(e.toString()); - res.status(500).end(); - }); - break; - case "nodemailer": - nodemailerTransporter - .sendMail(msg) - .catch((e) => { - console.error(e.toString()); - res.status(500).end(); - }); - break; - } - }, - ); + ).then( + ({ html, text }) => sendEmail(req.body.attendeeEmail, '', `${siteName}: You have been removed from an event`, text, html) + ).catch((e) => { + console.error('error sending removeEventAttendeeHtml email', e.toString()); + res.status(500).end(); + }); } } res.writeHead(302, { @@ -797,9 +724,9 @@ router.get("/oneclickunattendevent/:eventID/:attendeeID", (req, res) => { "removeEventAttendee", "error", "Attempt to remove attendee by admin from event " + - req.params.eventID + - " failed with error: " + - err, + req.params.eventID + + " failed with error: " + + err, ); }); }); @@ -818,41 +745,18 @@ router.post("/removeattendee/:eventID/:attendeeID", (req, res) => { if (sendEmails) { // currently this is never called because we don't have the email address if (req.body.attendeeEmail) { - req.app.get("hbsInstance").renderView( - "./views/emails/removeEventAttendee/removeEventAttendeeHtml.handlebars", + renderEmail( + req.app.get("hbsInstance"), + "removeEventAttendee/removeEventAttendee", { eventName: req.params.eventName, - siteName, - siteLogo, - domain, - cache: true, - layout: "email.handlebars", - }, - function (err, html) { - const msg = { - to: req.body.attendeeEmail, - from: contactEmail, - subject: `${siteName}: You have been removed from an event`, - html, - }; - switch (mailService) { - case "sendgrid": - sgMail.send(msg).catch((e) => { - console.error(e.toString()); - res.status(500).end(); - }); - break; - case "nodemailer": - nodemailerTransporter - .sendMail(msg) - .catch((e) => { - console.error(e.toString()); - res.status(500).end(); - }); - break; - } }, - ); + ).then( + ({ html, text }) => sendEmail(req.body.attendeeEmail, '', `${siteName}: You have been removed from an event`, text, html) + ).catch((e) => { + console.error('error sending removeEventAttendeeHtml email', e.toString()); + res.status(500).end(); + }); } } res.writeHead(302, { @@ -866,9 +770,9 @@ router.post("/removeattendee/:eventID/:attendeeID", (req, res) => { "removeEventAttendee", "error", "Attempt to remove attendee by admin from event " + - req.params.eventID + - " failed with error: " + - err, + req.params.eventID + + " failed with error: " + + err, ); }); }); @@ -894,43 +798,20 @@ router.post("/subscribe/:eventGroupID", (req, res) => { eventGroup.subscribers.push(subscriber); eventGroup.save(); if (sendEmails) { - req.app.get("hbsInstance").renderView( - "./views/emails/subscribed/subscribedHtml.handlebars", + renderEmail( + req.app.get("hbsInstance"), + "subscribed/subscribed", { eventGroupName: eventGroup.name, eventGroupID: eventGroup.id, emailAddress: encodeURIComponent(subscriber.email), - siteName, - siteLogo, - domain, - cache: true, - layout: "email.handlebars", }, - function (err, html) { - const msg = { - to: subscriber.email, - from: contactEmail, - subject: `${siteName}: You have subscribed to an event group`, - html, - }; - switch (mailService) { - case "sendgrid": - sgMail.send(msg).catch((e) => { - console.error(e.toString()); - res.status(500).end(); - }); - break; - case "nodemailer": - nodemailerTransporter - .sendMail(msg) - .catch((e) => { - console.error(e.toString()); - res.status(500).end(); - }); - break; - } - }, - ); + ).then( + ({ html, text }) => sendEmail(subscriber.email, '', `${siteName}: You have subscribed to an event group`, text, html) + ).catch((e) => { + console.error('error sending removeEventAttendeeHtml email', e.toString()); + res.status(500).end(); + }); } return res.redirect(`/group/${eventGroup.id}`); }) @@ -939,11 +820,11 @@ router.post("/subscribe/:eventGroupID", (req, res) => { "addSubscription", "error", "Attempt to subscribe " + - req.body.emailAddress + - " to event group " + - req.params.eventGroupID + - " failed with error: " + - error, + req.body.emailAddress + + " to event group " + + req.params.eventGroupID + + " failed with error: " + + error, ); return res.sendStatus(500); }); @@ -970,11 +851,11 @@ router.get("/unsubscribe/:eventGroupID", (req, res) => { "removeSubscription", "error", "Attempt to unsubscribe " + - req.query.email + - " from event group " + - req.params.eventGroupID + - " failed with error: " + - error, + req.query.email + + " from event group " + + req.params.eventGroupID + + " failed with error: " + + error, ); return res.sendStatus(500); }); @@ -1028,58 +909,24 @@ router.post("/post/comment/:eventID", (req, res) => { (o) => o.status === "attending" && o.email, ) - .map((o) => o.email); + .map((o) => o.email || '') || []; if (attendeeEmails.length) { console.log( "Sending emails to: " + attendeeEmails, ); - req.app.get("hbsInstance").renderView( - "./views/emails/addEventComment/addEventCommentHtml.handlebars", + renderEmail( + req.app.get("hbsInstance"), + "addEventComment/addEventComment", { - siteName, - siteLogo, - domain, eventID: req.params.eventID, - commentAuthor: - req.body.commentAuthor, - cache: true, - layout: "email.handlebars", - }, - function (err, html) { - const msg = { - to: attendeeEmails, - from: contactEmail, - subject: `${siteName}: New comment in ${event.name}`, - html, - }; - switch (mailService) { - case "sendgrid": - sgMail - .sendMultiple(msg) - .catch((e) => { - console.error( - e.toString(), - ); - res.status( - 500, - ).end(); - }); - break; - case "nodemailer": - nodemailerTransporter - .sendMail(msg) - .catch((e) => { - console.error( - e.toString(), - ); - res.status( - 500, - ).end(); - }); - break; - } + commentAuthor: req.body.commentAuthor, }, - ); + ).then( + ({ html, text }) => sendEmail(attendeeEmails, '', `${siteName}: New comment in ${event.name}`, text, html) + ).catch((e) => { + console.error('error sending removeEventAttendeeHtml email', e.toString()); + res.status(500).end(); + }); } else { console.log("Nothing to send!"); } @@ -1097,9 +944,9 @@ router.post("/post/comment/:eventID", (req, res) => { "addEventComment", "error", "Attempt to add comment to event " + - req.params.eventID + - " failed with error: " + - err, + req.params.eventID + + " failed with error: " + + err, ); }); }, @@ -1130,9 +977,9 @@ router.post("/post/reply/:eventID/:commentID", (req, res) => { "addEventReply", "success", "Reply added to comment " + - commentID + - " in event " + - req.params.eventID, + commentID + + " in event " + + req.params.eventID, ); // broadcast an identical message to all followers, will show in their home timeline const guidObject = crypto.randomBytes(16).toString("hex"); @@ -1157,57 +1004,24 @@ router.post("/post/reply/:eventID/:commentID", (req, res) => { (o) => o.status === "attending" && o.email, ) - .map((o) => o.email); + .map((o) => o.email || '') || []; if (attendeeEmails.length) { console.log( "Sending emails to: " + attendeeEmails, ); - req.app.get("hbsInstance").renderView( - "./views/emails/addEventComment/addEventCommentHtml.handlebars", + renderEmail( + req.app.get("hbsInstance"), + "addEventComment/addEventComment", { - siteName, - siteLogo, - domain, eventID: req.params.eventID, commentAuthor: req.body.replyAuthor, - cache: true, - layout: "email.handlebars", }, - function (err, html) { - const msg = { - to: attendeeEmails, - from: contactEmail, - subject: `${siteName}: New comment in ${event.name}`, - html, - }; - switch (mailService) { - case "sendgrid": - sgMail - .sendMultiple(msg) - .catch((e) => { - console.error( - e.toString(), - ); - res.status( - 500, - ).end(); - }); - break; - case "nodemailer": - nodemailerTransporter - .sendMail(msg) - .catch((e) => { - console.error( - e.toString(), - ); - res.status( - 500, - ).end(); - }); - break; - } - }, - ); + ).then( + ({ html, text }) => sendEmail(attendeeEmails, '', `${siteName}: New comment in ${event.name}`, text, html) + ).catch((e) => { + console.error('error sending removeEventAttendeeHtml email', e.toString()); + res.status(500).end(); + }); } else { console.log("Nothing to send!"); } @@ -1225,11 +1039,11 @@ router.post("/post/reply/:eventID/:commentID", (req, res) => { "addEventReply", "error", "Attempt to add reply to comment " + - commentID + - " in event " + - req.params.eventID + - " failed with error: " + - err, + commentID + + " in event " + + req.params.eventID + + " failed with error: " + + err, ); }); }, @@ -1265,17 +1079,17 @@ router.post("/deletecomment/:eventID/:commentID/:editToken", (req, res) => { .catch((err) => { res.send( "Sorry! Something went wrong (error deleting): " + - err, + err, ); addToLog( "deleteComment", "error", "Attempt to delete comment " + - req.params.commentID + - "from event " + - req.params.eventID + - " failed with error: " + - err, + req.params.commentID + + "from event " + + req.params.eventID + + " failed with error: " + + err, ); }); } else { @@ -1285,10 +1099,10 @@ router.post("/deletecomment/:eventID/:commentID/:editToken", (req, res) => { "deleteComment", "error", "Attempt to delete comment " + - req.params.commentID + - "from event " + - req.params.eventID + - " failed with error: token does not match", + req.params.commentID + + "from event " + + req.params.eventID + + " failed with error: token does not match", ); } }) @@ -1298,11 +1112,11 @@ router.post("/deletecomment/:eventID/:commentID/:editToken", (req, res) => { "deleteComment", "error", "Attempt to delete comment " + - req.params.commentID + - "from event " + - req.params.eventID + - " failed with error: " + - err, + req.params.commentID + + "from event " + + req.params.eventID + + " failed with error: " + + err, ); }); }); diff --git a/src/routes/frontend.ts b/src/routes/frontend.ts index 14bb779..1b95763 100644 --- a/src/routes/frontend.ts +++ b/src/routes/frontend.ts @@ -1,5 +1,4 @@ import { Router, Request, Response } from "express"; -import fs from "fs"; import moment from "moment-timezone"; import { marked } from "marked"; import { markdownToSanitizedHTML, renderPlain } from "../util/markdown.js"; @@ -25,7 +24,7 @@ const router = Router(); // Add config middleware to all routes router.use(getConfigMiddleware); -router.get("/", (_: Request, res: Response) => { +router.get("/", (_, res) => { if (res.locals.config?.general.show_public_event_list) { return res.redirect("/events"); } @@ -44,7 +43,7 @@ router.get("/about", (_: Request, res: Response) => { }); }); -router.get("/new", (req: Request, res: Response) => { +router.get("/new", (_: Request, res: Response) => { if (res.locals.config?.general.creator_email_addresses?.length) { return res.render("createEventMagicLink", frontendConfig(res)); } |