summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/app.ts39
-rw-r--r--src/lib/email.ts57
-rw-r--r--src/lib/handlebars.ts27
-rwxr-xr-xsrc/routes.js568
-rw-r--r--src/routes/frontend.ts5
5 files changed, 302 insertions, 394 deletions
diff --git a/src/app.ts b/src/app.ts
index 0708081..85ee64e 100755
--- a/src/app.ts
+++ b/src/app.ts
@@ -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));
}