Files
calendar/apps/web/ee/pages/api/cron/workflows/scheduleEmailReminders.ts
T
75b817531e Fixes timezone in reminder templates (workflows) (#3376)
* fix time zone in reminder template

* fix timezone in email subject

* add missing timezone

* fix date in sms reminder template

* use organizer time zone if message send to host

* fix build error

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
2022-07-14 19:05:01 -04:00

140 lines
4.3 KiB
TypeScript

/* Schedule any workflow reminder that falls within 72 hours for email */
import { WorkflowActions, WorkflowTemplates, WorkflowMethods } from "@prisma/client";
import client from "@sendgrid/client";
import sgMail from "@sendgrid/mail";
import type { NextApiRequest, NextApiResponse } from "next";
import dayjs from "@calcom/dayjs";
import { defaultHandler } from "@calcom/lib/server";
import emailReminderTemplate from "@ee/lib/workflows/reminders/templates/emailReminderTemplate";
import prisma from "@lib/prisma";
const sendgridAPIKey = process.env.SENDGRID_API_KEY as string;
const senderEmail = process.env.SENDGRID_EMAIL as string;
sgMail.setApiKey(sendgridAPIKey);
async function handler(req: NextApiRequest, res: NextApiResponse) {
const apiKey = req.headers.authorization || req.query.apiKey;
if (process.env.CRON_API_KEY !== apiKey) {
res.status(401).json({ message: "Not authenticated" });
return;
}
if (!process.env.SENDGRID_API_KEY || !process.env.SENDGRID_EMAIL) {
res.status(405).json({ message: "No SendGrid API key or email" });
return;
}
const batchIdResponse = await client.request({
url: "/v3/mail/batch",
method: "POST",
});
//delete all scheduled email reminders where scheduled is past current date
await prisma.workflowReminder.deleteMany({
where: {
method: WorkflowMethods.EMAIL,
scheduledDate: {
lte: dayjs().toISOString(),
},
},
});
//find all unscheduled Email reminders
const unscheduledReminders = await prisma.workflowReminder.findMany({
where: {
method: WorkflowMethods.EMAIL,
scheduled: false,
},
include: {
workflowStep: true,
booking: {
include: {
eventType: true,
user: true,
attendees: true,
},
},
},
});
if (!unscheduledReminders.length) res.json({ ok: true });
const dateInSeventyTwoHours = dayjs().add(72, "hour");
unscheduledReminders.forEach(async (reminder) => {
if (dayjs(reminder.scheduledDate).isBefore(dateInSeventyTwoHours)) {
try {
const sendTo =
reminder.workflowStep.action === WorkflowActions.EMAIL_HOST
? reminder.booking?.user?.email
: reminder.booking?.attendees[0].email;
let emailTemplate = {
subject: reminder.workflowStep.emailSubject || "",
body: reminder.workflowStep.reminderBody || "",
};
const name =
reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
? reminder.booking?.attendees[0].name
: reminder.booking?.user?.name;
const attendeeName =
reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
? reminder.booking?.user?.name
: reminder.booking?.attendees[0].name;
const timeZone =
reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
? reminder.booking?.attendees[0].timeZone
: reminder.booking?.user?.timeZone;
switch (reminder.workflowStep.template) {
case WorkflowTemplates.REMINDER:
emailTemplate = emailReminderTemplate(
reminder.booking?.startTime.toISOString() || "",
reminder.booking?.eventType?.title || "",
timeZone || "",
attendeeName || "",
name || ""
);
break;
}
if (emailTemplate.subject.length > 0 && emailTemplate.body.length > 0 && sendTo) {
await sgMail.send({
to: sendTo,
from: senderEmail,
subject: emailTemplate.subject,
content: [
{
type: "text/html",
value: emailTemplate.body,
},
],
batchId: batchIdResponse[1].batch_id,
sendAt: dayjs(reminder.scheduledDate).unix(),
});
}
await prisma.workflowReminder.updateMany({
where: {
id: reminder.id,
},
data: {
scheduled: true,
referenceId: batchIdResponse[1].batch_id,
},
});
} catch (error) {
console.log(`Error scheduling Email with error ${error}`);
}
}
});
}
export default defaultHandler({
POST: Promise.resolve({ default: handler }),
});