Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes bug that new line is not working in workflow reminder emails #3452

Merged
merged 9 commits into from
Jul 21, 2022
32 changes: 20 additions & 12 deletions apps/web/ee/lib/workflows/reminders/emailReminderManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import client from "@sendgrid/client";
import sgMail from "@sendgrid/mail";

import dayjs from "@calcom/dayjs";
import { sendWorkflowReminderEmail } from "@calcom/emails";
import prisma from "@calcom/prisma";
import { BookingInfo, timeUnitLowerCase } from "@ee/lib/workflows/reminders/smsReminderManager";
import emailReminderTemplate from "@ee/lib/workflows/reminders/templates/emailReminderTemplate";
Expand Down Expand Up @@ -60,11 +59,17 @@ export const scheduleEmailReminder = async (
const attendeeName = action === WorkflowActions.EMAIL_HOST ? evt.attendees[0].name : evt.organizer.name;
const timeZone = action === WorkflowActions.EMAIL_HOST ? evt.organizer.timeZone : evt.attendees[0].timeZone;

let emailContent = {
emailSubject,
emailBody: {
text: emailBody,
html: `<body style="white-space: pre-wrap;">${emailBody}</body>`,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

necessary so line breaks from custom templates work

},
};

switch (template) {
case WorkflowTemplates.REMINDER:
const emailTemplate = emailReminderTemplate(startTime, evt.title, timeZone, attendeeName, name);
emailSubject = emailTemplate.subject;
emailBody = emailTemplate.body;
emailContent = emailReminderTemplate(startTime, evt.title, timeZone, attendeeName, name);
break;
}

Expand All @@ -73,7 +78,14 @@ export const scheduleEmailReminder = async (
triggerEvent === WorkflowTriggerEvents.EVENT_CANCELLED
) {
try {
await sendWorkflowReminderEmail(evt, sendTo, emailSubject, emailBody);
await sgMail.send({
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove sendWorkflowReminderEmail as it is not needed and emails were sent from the organizer instead of hello@cal.com

to: sendTo,
from: senderEmail,
subject: emailContent.emailSubject,
text: emailContent.emailBody.text,
html: emailContent.emailBody.html,
batchId: batchIdResponse[1].batch_id,
});
} catch (error) {
console.log("Error sending Email");
}
Expand All @@ -88,13 +100,9 @@ export const scheduleEmailReminder = async (
await sgMail.send({
to: sendTo,
from: senderEmail,
subject: emailSubject,
content: [
{
type: "text/html",
value: emailBody,
},
],
subject: emailContent.emailSubject,
text: emailContent.emailBody.text,
html: emailContent.emailBody.html,
batchId: batchIdResponse[1].batch_id,
sendAt: scheduledDate.unix(),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,25 @@ const emailReminderTemplate = (
attendee: string,
name: string
) => {
const templateSubject = `Reminder: ${eventName} at ${dayjs(startTime)
const emailSubject = `Reminder: ${eventName} on ${dayjs(startTime)
.tz(timeZone)
.format("YYYY MMM D h:mmA")}`;
.format("YYYY MMM D")} at ${dayjs(startTime).tz(timeZone).format("h:mmA")} ${timeZone}.`;

const templateBody = `Hi ${name},\n\nThis is a reminder that your meeting (${eventName}) with ${attendee} is on ${dayjs(
const templateBodyText = `Hi ${name}, this is a reminder that your meeting (${eventName}) with ${attendee} is on ${dayjs(
startTime
)
.tz(timeZone)
.format("YYYY MMM D")} at ${dayjs(startTime).tz(timeZone).format("h:mmA")} ${timeZone}.`;

const emailContent = { subject: templateSubject, body: templateBody };
const templateBodyHtml = `<body>Hi ${name},<br><br>This is a reminder that your meeting (${eventName}) with ${attendee} is on ${dayjs(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in html format so line breaks are actually working

startTime
)
.tz(timeZone)
.format("YYYY MMM D")} at ${dayjs(startTime).tz(timeZone).format("h:mmA")} ${timeZone}.<body>`;

const emailBody = { text: templateBodyText, html: templateBodyHtml };

return emailContent;
return { emailSubject, emailBody };
};

export default emailReminderTemplate;
27 changes: 13 additions & 14 deletions apps/web/ee/pages/api/cron/workflows/scheduleEmailReminders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
? 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
Expand All @@ -92,9 +87,17 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
? reminder.booking?.attendees[0].timeZone
: reminder.booking?.user?.timeZone;

let emailContent = {
emailSubject: reminder.workflowStep.emailSubject || "",
emailBody: {
text: reminder.workflowStep.reminderBody || "",
html: `<body style="white-space: pre-wrap;">${reminder.workflowStep.reminderBody || ""}</body>`,
},
};

switch (reminder.workflowStep.template) {
case WorkflowTemplates.REMINDER:
emailTemplate = emailReminderTemplate(
emailContent = emailReminderTemplate(
reminder.booking?.startTime.toISOString() || "",
reminder.booking?.eventType?.title || "",
timeZone || "",
Expand All @@ -103,17 +106,13 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
);
break;
}
if (emailTemplate.subject.length > 0 && emailTemplate.body.length > 0 && sendTo) {
if (emailContent.emailSubject.length > 0 && emailContent.emailBody.text.length > 0 && sendTo) {
await sgMail.send({
to: sendTo,
from: senderEmail,
subject: emailTemplate.subject,
content: [
{
type: "text/html",
value: emailTemplate.body,
},
],
subject: emailContent.emailSubject,
text: emailContent.emailBody.text,
html: emailContent.emailBody.html,
batchId: batchIdResponse[1].batch_id,
sendAt: dayjs(reminder.scheduledDate).unix(),
});
Expand Down
13 changes: 0 additions & 13 deletions packages/emails/email-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import AttendeeRescheduledEmail from "./templates/attendee-rescheduled-email";
import AttendeeScheduledEmail from "./templates/attendee-scheduled-email";
import BrokenIntegrationEmail from "./templates/broken-integration-email";
import FeedbackEmail, { Feedback } from "./templates/feedback-email";
import WorkflowReminderEmail from "./templates/workflow-reminder-email";
import ForgotPasswordEmail, { PasswordReset } from "./templates/forgot-password-email";
import OrganizerCancelledEmail from "./templates/organizer-cancelled-email";
import OrganizerLocationChangeEmail from "./templates/organizer-location-change-email";
Expand All @@ -21,7 +20,6 @@ import OrganizerRequestRescheduleEmail from "./templates/organizer-request-resch
import OrganizerRescheduledEmail from "./templates/organizer-rescheduled-email";
import OrganizerScheduledEmail from "./templates/organizer-scheduled-email";
import TeamInviteEmail, { TeamInvite } from "./templates/team-invite-email";
import { BookingInfo } from "@calcom/web/ee/lib/workflows/reminders/smsReminderManager";

export const sendScheduledEmails = async (calEvent: CalendarEvent) => {
const emailsToSend: Promise<unknown>[] = [];
Expand Down Expand Up @@ -329,14 +327,3 @@ export const sendBrokenIntegrationEmail = async (evt: CalendarEvent, type: "vide
}
});
};

export const sendWorkflowReminderEmail = async (evt: BookingInfo, sendTo: string, emailSubject: string, emailBody: string) => {
await new Promise((resolve, reject) => {
try {
const workflowReminderEmail = new WorkflowReminderEmail(evt, sendTo, emailSubject, emailBody);
resolve(workflowReminderEmail.sendEmail());
} catch (e) {
reject(console.error("WorkflowReminderEmail.sendEmail failed", e));
}
});
}
34 changes: 0 additions & 34 deletions packages/emails/templates/workflow-reminder-email.ts

This file was deleted.

32 changes: 16 additions & 16 deletions packages/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ generator zod {
}

enum SchedulingType {
ROUND_ROBIN @map("roundRobin")
COLLECTIVE @map("collective")
ROUND_ROBIN @map("roundRobin")
COLLECTIVE @map("collective")
}

enum PeriodType {
UNLIMITED @map("unlimited")
ROLLING @map("rolling")
RANGE @map("range")
UNLIMITED @map("unlimited")
ROLLING @map("rolling")
RANGE @map("range")
}

model EventType {
Expand Down Expand Up @@ -253,10 +253,10 @@ model Attendee {
}

enum BookingStatus {
CANCELLED @map("cancelled")
ACCEPTED @map("accepted")
REJECTED @map("rejected")
PENDING @map("pending")
CANCELLED @map("cancelled")
ACCEPTED @map("accepted")
REJECTED @map("rejected")
PENDING @map("pending")
}

model DailyEventReference {
Expand Down Expand Up @@ -335,10 +335,10 @@ model SelectedCalendar {
}

enum EventTypeCustomInputType {
TEXT @map("text")
TEXTLONG @map("textLong")
NUMBER @map("number")
BOOL @map("bool")
TEXT @map("text")
TEXTLONG @map("textLong")
NUMBER @map("number")
BOOL @map("bool")
}

model EventTypeCustomInput {
Expand Down Expand Up @@ -575,9 +575,9 @@ model WorkflowsOnEventTypes {
}

enum TimeUnit {
DAY @map("day")
HOUR @map("hour")
MINUTE @map("minute")
DAY @map("day")
HOUR @map("hour")
MINUTE @map("minute")
}

model WorkflowReminder {
Expand Down