From 399a23a52f57bd61b26d118e240e400793caec43 Mon Sep 17 00:00:00 2001 From: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Date: Thu, 22 Aug 2024 05:49:53 -0400 Subject: [PATCH] fix: Disable ICS file generation when destination calendar is Outlook (#16247) * Set the organizer in the organizer field * Create generateIcsFile * Add role enum and only disable for organizers * Move emails to generateIcsFile * Add new ics func to new emails * Fix tests * Type fix --------- Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> --- .../web/test/utils/bookingScenario/expects.ts | 20 ++++++-- .../office365calendar/lib/CalendarService.ts | 19 ++++--- packages/emails/lib/generateIcsFile.ts | 51 +++++++++++++++++++ packages/emails/lib/generateIcsString.ts | 6 ++- .../templates/attendee-add-guests-email.ts | 20 +++----- .../templates/attendee-cancelled-email.ts | 20 +++----- .../attendee-location-change-email.ts | 20 +++----- .../templates/attendee-rescheduled-email.ts | 20 +++----- .../templates/attendee-scheduled-email.ts | 24 ++++----- ...endee-was-requested-to-reschedule-email.ts | 22 ++++---- .../templates/organizer-add-guests-email.ts | 20 +++----- .../templates/organizer-cancelled-email.ts | 20 +++----- .../organizer-location-change-email.ts | 20 +++----- ...organizer-requested-to-reschedule-email.ts | 26 ++++------ .../templates/organizer-rescheduled-email.ts | 20 +++----- .../templates/organizer-scheduled-email.ts | 25 ++++----- .../test/fresh-booking.test.ts | 7 ++- 17 files changed, 191 insertions(+), 169 deletions(-) create mode 100644 packages/emails/lib/generateIcsFile.ts diff --git a/apps/web/test/utils/bookingScenario/expects.ts b/apps/web/test/utils/bookingScenario/expects.ts index 22030bd31c..3a5aefb68c 100644 --- a/apps/web/test/utils/bookingScenario/expects.ts +++ b/apps/web/test/utils/bookingScenario/expects.ts @@ -81,15 +81,24 @@ declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace jest { interface Matchers { - toHaveEmail(expectedEmail: ExpectedEmail, to: string): R; + toHaveEmail(expectedEmail: ExpectedEmail, to: string, subject?: string): R; } } } expect.extend({ - toHaveEmail(emails: Fixtures["emails"], expectedEmail: ExpectedEmail, to: string) { + toHaveEmail(emails: Fixtures["emails"], expectedEmail: ExpectedEmail, to: string, subject?: string) { const { isNot } = this; - const testEmail = emails.get().find((email) => email.to.includes(to)); + const testEmail = emails.get().find((email) => { + const filterConditions = [email.to.includes(to)]; + + if (subject) { + filterConditions.push(email.subject === subject); + } + + return filterConditions.every((condition) => condition); + }); + const emailsToLog = emails .get() .map((email) => ({ to: email.to, html: email.html, ics: email.icalEvent })); @@ -742,10 +751,12 @@ export function expectSuccessfulBookingRescheduledEmails({ export function expectAwaitingPaymentEmails({ emails, booker, + subject, }: { emails: Fixtures["emails"]; organizer: { email: string; name: string }; booker: { email: string; name: string }; + subject?: string; }) { expect(emails).toHaveEmail( { @@ -753,7 +764,8 @@ export function expectAwaitingPaymentEmails({ to: `${booker.name} <${booker.email}>`, noIcs: true, }, - `${booker.email}` + `${booker.email}`, + subject ); } diff --git a/packages/app-store/office365calendar/lib/CalendarService.ts b/packages/app-store/office365calendar/lib/CalendarService.ts index 465b278f4e..359a6ad14a 100644 --- a/packages/app-store/office365calendar/lib/CalendarService.ts +++ b/packages/app-store/office365calendar/lib/CalendarService.ts @@ -277,17 +277,16 @@ export default class Office365CalendarService implements Calendar { dateTime: dayjs(event.endTime).tz(event.organizer.timeZone).format("YYYY-MM-DDTHH:mm:ss"), timeZone: event.organizer.timeZone, }, - attendees: [ - // Add the calEvent organizer - { - emailAddress: { - address: event.destinationCalendar - ? event.destinationCalendar.find((cal) => cal.userId === event.organizer.id)?.externalId ?? - event.organizer.email - : event.organizer.email, - name: event.organizer.name, - }, + organizer: { + emailAddress: { + address: event.destinationCalendar + ? event.destinationCalendar.find((cal) => cal.userId === event.organizer.id)?.externalId ?? + event.organizer.email + : event.organizer.email, + name: event.organizer.name, }, + }, + attendees: [ ...event.attendees.map((attendee) => ({ emailAddress: { address: attendee.email, diff --git a/packages/emails/lib/generateIcsFile.ts b/packages/emails/lib/generateIcsFile.ts new file mode 100644 index 0000000000..cb63bbadfa --- /dev/null +++ b/packages/emails/lib/generateIcsFile.ts @@ -0,0 +1,51 @@ +import type { EventStatus } from "ics"; +import type { TFunction } from "next-i18next"; + +import type { CalendarEvent } from "@calcom/types/Calendar"; + +import generateIcsString from "./generateIcsString"; + +export enum GenerateIcsRole { + ATTENDEE = "attendee", + ORGANIZER = "organizer", +} + +export default function generateIcsFile({ + calEvent, + title, + subtitle, + role, + status, + t, + isRequestReschedule, +}: { + calEvent: CalendarEvent; + title: string; + subtitle: string; + role: GenerateIcsRole; + status: EventStatus; + t?: TFunction; + isRequestReschedule?: boolean; +}) { + // O365 deletes emails if the calendar event is selected. Currently no option to disable this on the web + if ( + role !== GenerateIcsRole.ATTENDEE && + calEvent.destinationCalendar && + calEvent.destinationCalendar[0].integration === "office365_calendar" + ) + return null; + + return { + filename: "event.ics", + content: generateIcsString({ + event: calEvent, + title, + subtitle, + role, + status, + t, + isRequestReschedule, + }), + method: "REQUEST", + }; +} diff --git a/packages/emails/lib/generateIcsString.ts b/packages/emails/lib/generateIcsString.ts index e369f55a45..59d2d35198 100644 --- a/packages/emails/lib/generateIcsString.ts +++ b/packages/emails/lib/generateIcsString.ts @@ -9,6 +9,8 @@ import { getWhen } from "@calcom/lib/CalEventParser"; import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser"; import type { CalendarEvent, Person } from "@calcom/types/Calendar"; +import { GenerateIcsRole } from "./generateIcsFile"; + export enum BookingAction { Create = "create", Cancel = "cancel", @@ -30,7 +32,7 @@ const generateIcsString = ({ title: string; subtitle: string; status: EventStatus; - role: "attendee" | "organizer"; + role: GenerateIcsRole; isRequestReschedule?: boolean; t?: TFunction; }) => { @@ -47,7 +49,7 @@ const generateIcsString = ({ const getTextBody = (title: string, subtitle: string): string => { let body: string; - if (isRequestReschedule && role === "attendee" && t) { + if (isRequestReschedule && role === GenerateIcsRole.ATTENDEE && t) { body = ` ${title} ${getWhen(event, t)} diff --git a/packages/emails/templates/attendee-add-guests-email.ts b/packages/emails/templates/attendee-add-guests-email.ts index 155989acbd..91db4da39d 100644 --- a/packages/emails/templates/attendee-add-guests-email.ts +++ b/packages/emails/templates/attendee-add-guests-email.ts @@ -1,21 +1,17 @@ import { renderEmail } from "../"; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import AttendeeScheduledEmail from "./attendee-scheduled-email"; export default class AttendeeAddGuestsEmail extends AttendeeScheduledEmail { protected async getNodeMailerPayload(): Promise> { return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.t("new_guests_added"), - subtitle: this.t("emailed_you_and_any_other_attendees"), - role: "attendee", - status: "CONFIRMED", - }), - method: "REQUEST", - }, + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.t("new_guests_added"), + subtitle: this.t("emailed_you_and_any_other_attendees"), + role: GenerateIcsRole.ATTENDEE, + status: "CONFIRMED", + }), to: `${this.attendee.name} <${this.attendee.email}>`, from: `${this.calEvent.organizer.name} <${this.getMailerOptions().from}>`, replyTo: this.calEvent.organizer.email, diff --git a/packages/emails/templates/attendee-cancelled-email.ts b/packages/emails/templates/attendee-cancelled-email.ts index 5a18b99dcd..a082a348f0 100644 --- a/packages/emails/templates/attendee-cancelled-email.ts +++ b/packages/emails/templates/attendee-cancelled-email.ts @@ -1,21 +1,17 @@ import { renderEmail } from "../"; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import AttendeeScheduledEmail from "./attendee-scheduled-email"; export default class AttendeeCancelledEmail extends AttendeeScheduledEmail { protected async getNodeMailerPayload(): Promise> { return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.t("event_request_cancelled"), - subtitle: this.t("emailed_you_and_any_other_attendees"), - status: "CANCELLED", - role: "attendee", - }), - method: "REQUEST", - }, + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.t("event_request_cancelled"), + subtitle: this.t("emailed_you_and_any_other_attendees"), + role: GenerateIcsRole.ATTENDEE, + status: "CANCELLED", + }), to: `${this.attendee.name} <${this.attendee.email}>`, from: `${this.calEvent.organizer.name} <${this.getMailerOptions().from}>`, replyTo: this.calEvent.organizer.email, diff --git a/packages/emails/templates/attendee-location-change-email.ts b/packages/emails/templates/attendee-location-change-email.ts index ad16431dc3..d23d7704de 100644 --- a/packages/emails/templates/attendee-location-change-email.ts +++ b/packages/emails/templates/attendee-location-change-email.ts @@ -1,21 +1,17 @@ import { renderEmail } from "../"; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import AttendeeScheduledEmail from "./attendee-scheduled-email"; export default class AttendeeLocationChangeEmail extends AttendeeScheduledEmail { protected async getNodeMailerPayload(): Promise> { return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.t("event_location_changed"), - subtitle: this.t("emailed_you_and_any_other_attendees"), - role: "attendee", - status: "CONFIRMED", - }), - method: "REQUEST", - }, + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.t("event_location_changed"), + subtitle: this.t("emailed_you_and_any_other_attendees"), + role: GenerateIcsRole.ATTENDEE, + status: "CONFIRMED", + }), to: `${this.attendee.name} <${this.attendee.email}>`, from: `${this.calEvent.organizer.name} <${this.getMailerOptions().from}>`, replyTo: this.calEvent.organizer.email, diff --git a/packages/emails/templates/attendee-rescheduled-email.ts b/packages/emails/templates/attendee-rescheduled-email.ts index 0ebceb096f..896cbabae8 100644 --- a/packages/emails/templates/attendee-rescheduled-email.ts +++ b/packages/emails/templates/attendee-rescheduled-email.ts @@ -1,21 +1,17 @@ import { renderEmail } from "../"; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import AttendeeScheduledEmail from "./attendee-scheduled-email"; export default class AttendeeRescheduledEmail extends AttendeeScheduledEmail { protected async getNodeMailerPayload(): Promise> { return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.t("event_type_has_been_rescheduled"), - subtitle: this.t("emailed_you_and_any_other_attendees"), - role: "attendee", - status: "CONFIRMED", - }), - method: "REQUEST", - }, + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.t("event_type_has_been_rescheduled"), + subtitle: this.t("emailed_you_and_any_other_attendees"), + role: GenerateIcsRole.ATTENDEE, + status: "CONFIRMED", + }), to: `${this.attendee.name} <${this.attendee.email}>`, from: `${this.calEvent.organizer.name} <${this.getMailerOptions().from}>`, replyTo: [...this.calEvent.attendees.map(({ email }) => email), this.calEvent.organizer.email], diff --git a/packages/emails/templates/attendee-scheduled-email.ts b/packages/emails/templates/attendee-scheduled-email.ts index 74311ee8cc..528a35dfb1 100644 --- a/packages/emails/templates/attendee-scheduled-email.ts +++ b/packages/emails/templates/attendee-scheduled-email.ts @@ -7,7 +7,7 @@ import { TimeFormat } from "@calcom/lib/timeFormat"; import type { CalendarEvent, Person } from "@calcom/types/Calendar"; import { renderEmail } from "../"; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import BaseEmail from "./_base-email"; export default class AttendeeScheduledEmail extends BaseEmail { @@ -33,19 +33,15 @@ export default class AttendeeScheduledEmail extends BaseEmail { const clonedCalEvent = cloneDeep(this.calEvent); return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.calEvent.recurringEvent?.count - ? this.t("your_event_has_been_scheduled_recurring") - : this.t("your_event_has_been_scheduled"), - role: "attendee", - subtitle: this.t("emailed_you_and_any_other_attendees"), - status: "CONFIRMED", - }), - method: "REQUEST", - }, + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.calEvent.recurringEvent?.count + ? this.t("your_event_has_been_scheduled_recurring") + : this.t("your_event_has_been_scheduled"), + role: GenerateIcsRole.ATTENDEE, + subtitle: this.t("emailed_you_and_any_other_attendees"), + status: "CONFIRMED", + }), to: `${this.attendee.name} <${this.attendee.email}>`, from: `${this.calEvent.organizer.name} <${this.getMailerOptions().from}>`, replyTo: [...this.calEvent.attendees.map(({ email }) => email), this.calEvent.organizer.email], diff --git a/packages/emails/templates/attendee-was-requested-to-reschedule-email.ts b/packages/emails/templates/attendee-was-requested-to-reschedule-email.ts index 579f46a947..4c7be20986 100644 --- a/packages/emails/templates/attendee-was-requested-to-reschedule-email.ts +++ b/packages/emails/templates/attendee-was-requested-to-reschedule-email.ts @@ -3,7 +3,7 @@ import { EMAIL_FROM_NAME } from "@calcom/lib/constants"; import type { CalendarEvent } from "@calcom/types/Calendar"; import { renderEmail } from ".."; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import OrganizerScheduledEmail from "./organizer-scheduled-email"; export default class AttendeeWasRequestedToRescheduleEmail extends OrganizerScheduledEmail { @@ -17,19 +17,15 @@ export default class AttendeeWasRequestedToRescheduleEmail extends OrganizerSche const toAddresses = [this.calEvent.attendees[0].email]; return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.t("request_reschedule_booking"), - subtitle: this.t("request_reschedule_subtitle", { - organizer: this.calEvent.organizer.name, - }), - role: "attendee", - status: "CANCELLED", + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.t("request_reschedule_booking"), + subtitle: this.t("request_reschedule_subtitle", { + organizer: this.calEvent.organizer.name, }), - method: "REQUEST", - }, + role: GenerateIcsRole.ATTENDEE, + status: "CANCELLED", + }), from: `${EMAIL_FROM_NAME} <${this.getMailerOptions().from}>`, to: toAddresses.join(","), subject: `${this.t("requested_to_reschedule_subject_attendee", { diff --git a/packages/emails/templates/organizer-add-guests-email.ts b/packages/emails/templates/organizer-add-guests-email.ts index 0a2a9d39b5..39ebcdf3ae 100644 --- a/packages/emails/templates/organizer-add-guests-email.ts +++ b/packages/emails/templates/organizer-add-guests-email.ts @@ -1,7 +1,7 @@ import { APP_NAME } from "@calcom/lib/constants"; import { renderEmail } from "../"; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import OrganizerScheduledEmail from "./organizer-scheduled-email"; export default class OrganizerAddGuestsEmail extends OrganizerScheduledEmail { @@ -9,17 +9,13 @@ export default class OrganizerAddGuestsEmail extends OrganizerScheduledEmail { const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email]; return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.t("new_guests_added"), - subtitle: this.t("emailed_you_and_any_other_attendees"), - role: "organizer", - status: "CONFIRMED", - }), - method: "REQUEST", - }, + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.t("new_guests_added"), + subtitle: this.t("emailed_you_and_any_other_attendees"), + role: GenerateIcsRole.ORGANIZER, + status: "CONFIRMED", + }), from: `${APP_NAME} <${this.getMailerOptions().from}>`, to: toAddresses.join(","), replyTo: [this.calEvent.organizer.email, ...this.calEvent.attendees.map(({ email }) => email)], diff --git a/packages/emails/templates/organizer-cancelled-email.ts b/packages/emails/templates/organizer-cancelled-email.ts index 8b3597ca6a..2990278d1c 100644 --- a/packages/emails/templates/organizer-cancelled-email.ts +++ b/packages/emails/templates/organizer-cancelled-email.ts @@ -1,7 +1,7 @@ import { EMAIL_FROM_NAME } from "@calcom/lib/constants"; import { renderEmail } from "../"; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import OrganizerScheduledEmail from "./organizer-scheduled-email"; export default class OrganizerCancelledEmail extends OrganizerScheduledEmail { @@ -9,17 +9,13 @@ export default class OrganizerCancelledEmail extends OrganizerScheduledEmail { const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email]; return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.t("event_request_cancelled"), - subtitle: this.t("emailed_you_and_any_other_attendees"), - status: "CANCELLED", - role: "organizer", - }), - method: "REQUEST", - }, + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.t("event_request_cancelled"), + subtitle: this.t("emailed_you_and_any_other_attendees"), + status: "CANCELLED", + role: GenerateIcsRole.ORGANIZER, + }), from: `${EMAIL_FROM_NAME} <${this.getMailerOptions().from}>`, to: toAddresses.join(","), subject: `${this.t("event_cancelled_subject", { diff --git a/packages/emails/templates/organizer-location-change-email.ts b/packages/emails/templates/organizer-location-change-email.ts index 9cfd14a544..6f2b7d8b8c 100644 --- a/packages/emails/templates/organizer-location-change-email.ts +++ b/packages/emails/templates/organizer-location-change-email.ts @@ -1,7 +1,7 @@ import { EMAIL_FROM_NAME } from "@calcom/lib/constants"; import { renderEmail } from "../"; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import OrganizerScheduledEmail from "./organizer-scheduled-email"; export default class OrganizerLocationChangeEmail extends OrganizerScheduledEmail { @@ -9,17 +9,13 @@ export default class OrganizerLocationChangeEmail extends OrganizerScheduledEmai const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email]; return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.t("event_location_changed"), - subtitle: this.t("emailed_you_and_any_other_attendees"), - role: "organizer", - status: "CONFIRMED", - }), - method: "REQUEST", - }, + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.t("event_location_changed"), + subtitle: this.t("emailed_you_and_any_other_attendees"), + role: GenerateIcsRole.ORGANIZER, + status: "CONFIRMED", + }), from: `${EMAIL_FROM_NAME} <${this.getMailerOptions().from}>`, to: toAddresses.join(","), replyTo: [this.calEvent.organizer.email, ...this.calEvent.attendees.map(({ email }) => email)], diff --git a/packages/emails/templates/organizer-requested-to-reschedule-email.ts b/packages/emails/templates/organizer-requested-to-reschedule-email.ts index 3c62aa6f02..be15708bb6 100644 --- a/packages/emails/templates/organizer-requested-to-reschedule-email.ts +++ b/packages/emails/templates/organizer-requested-to-reschedule-email.ts @@ -7,7 +7,7 @@ import { EMAIL_FROM_NAME } from "@calcom/lib/constants"; import type { CalendarEvent } from "@calcom/types/Calendar"; import { renderEmail } from ".."; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import OrganizerScheduledEmail from "./organizer-scheduled-email"; export default class OrganizerRequestedToRescheduleEmail extends OrganizerScheduledEmail { @@ -20,21 +20,17 @@ export default class OrganizerRequestedToRescheduleEmail extends OrganizerSchedu const toAddresses = [this.calEvent.organizer.email]; return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.t("request_reschedule_title_organizer", { - attendee: this.calEvent.attendees[0].name, - }), - subtitle: this.t("request_reschedule_subtitle_organizer", { - attendee: this.calEvent.attendees[0].name, - }), - role: "organizer", - status: "CANCELLED", + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.t("request_reschedule_title_organizer", { + attendee: this.calEvent.attendees[0].name, }), - method: "REQUEST", - }, + subtitle: this.t("request_reschedule_subtitle_organizer", { + attendee: this.calEvent.attendees[0].name, + }), + role: GenerateIcsRole.ORGANIZER, + status: "CANCELLED", + }), from: `${EMAIL_FROM_NAME} <${this.getMailerOptions().from}>`, to: toAddresses.join(","), subject: `${this.t("rescheduled_event_type_subject", { diff --git a/packages/emails/templates/organizer-rescheduled-email.ts b/packages/emails/templates/organizer-rescheduled-email.ts index 3b7013ac34..047d5151e4 100644 --- a/packages/emails/templates/organizer-rescheduled-email.ts +++ b/packages/emails/templates/organizer-rescheduled-email.ts @@ -1,7 +1,7 @@ import { EMAIL_FROM_NAME } from "@calcom/lib/constants"; import { renderEmail } from "../"; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile, { GenerateIcsRole } from "../lib/generateIcsFile"; import OrganizerScheduledEmail from "./organizer-scheduled-email"; export default class OrganizerRescheduledEmail extends OrganizerScheduledEmail { @@ -9,17 +9,13 @@ export default class OrganizerRescheduledEmail extends OrganizerScheduledEmail { const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email]; return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.t("event_type_has_been_rescheduled"), - subtitle: this.t("emailed_you_and_any_other_attendees"), - role: "organizer", - status: "CONFIRMED", - }), - method: "REQUEST", - }, + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.t("event_type_has_been_rescheduled"), + subtitle: this.t("emailed_you_and_any_other_attendees"), + role: GenerateIcsRole.ORGANIZER, + status: "CONFIRMED", + }), from: `${EMAIL_FROM_NAME} <${this.getMailerOptions().from}>`, to: toAddresses.join(","), replyTo: [this.calEvent.organizer.email, ...this.calEvent.attendees.map(({ email }) => email)], diff --git a/packages/emails/templates/organizer-scheduled-email.ts b/packages/emails/templates/organizer-scheduled-email.ts index 88465be6af..c7089c6637 100644 --- a/packages/emails/templates/organizer-scheduled-email.ts +++ b/packages/emails/templates/organizer-scheduled-email.ts @@ -8,7 +8,8 @@ import { TimeFormat } from "@calcom/lib/timeFormat"; import type { CalendarEvent, Person } from "@calcom/types/Calendar"; import { renderEmail } from "../"; -import generateIcsString from "../lib/generateIcsString"; +import generateIcsFile from "../lib/generateIcsFile"; +import { GenerateIcsRole } from "../lib/generateIcsFile"; import BaseEmail from "./_base-email"; export default class OrganizerScheduledEmail extends BaseEmail { @@ -31,19 +32,15 @@ export default class OrganizerScheduledEmail extends BaseEmail { const toAddresses = [this.teamMember?.email || this.calEvent.organizer.email]; return { - icalEvent: { - filename: "event.ics", - content: generateIcsString({ - event: this.calEvent, - title: this.calEvent.recurringEvent?.count - ? this.t("new_event_scheduled_recurring") - : this.t("new_event_scheduled"), - subtitle: this.t("emailed_you_and_any_other_attendees"), - role: "organizer", - status: "CONFIRMED", - }), - method: "REQUEST", - }, + icalEvent: generateIcsFile({ + calEvent: this.calEvent, + title: this.calEvent.recurringEvent?.count + ? this.t("new_event_scheduled_recurring") + : this.t("new_event_scheduled"), + subtitle: this.t("emailed_you_and_any_other_attendees"), + role: GenerateIcsRole.ORGANIZER, + status: "CONFIRMED", + }), from: `${EMAIL_FROM_NAME} <${this.getMailerOptions().from}>`, to: toAddresses.join(","), replyTo: [this.calEvent.organizer.email, ...this.calEvent.attendees.map(({ email }) => email)], diff --git a/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts b/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts index 5cba41c952..d8de18e1ec 100644 --- a/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts +++ b/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts @@ -2654,7 +2654,12 @@ describe("handleNewBooking", () => { expectWorkflowToBeNotTriggered({ emailsToReceive: [organizer.email], emails }); - expectAwaitingPaymentEmails({ organizer, booker, emails }); + expectAwaitingPaymentEmails({ + organizer, + booker, + emails, + subject: "complete_your_booking_subject", + }); expectBookingPaymentIntiatedWebhookToHaveBeenFired({ booker, organizer,