* 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>
140 lines
4.3 KiB
TypeScript
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 }),
|
|
});
|