diff --git a/apps/web/modules/ee/workflows/components/WorkflowStepContainer.tsx b/apps/web/modules/ee/workflows/components/WorkflowStepContainer.tsx
index 567ff9857f..41f8fcc432 100644
--- a/apps/web/modules/ee/workflows/components/WorkflowStepContainer.tsx
+++ b/apps/web/modules/ee/workflows/components/WorkflowStepContainer.tsx
@@ -1392,7 +1392,8 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
{form.formState?.errors?.steps[step.stepNumber - 1]?.reminderBody?.message || ""}
)}
- {isEmailSubjectNeeded && (
+ {isEmailSubjectNeeded &&
+ trigger !== WorkflowTriggerEvents.BOOKING_REQUESTED && (
({
prisma: {},
}));
+vi.mock("@calcom/emails/lib/generateIcsString", () => ({
+ default: vi.fn().mockReturnValue("mock-ics-content"),
+}));
+
const mockWorkflowReminderRepository: Pick = {
findByIdIncludeStepAndWorkflow: vi.fn(),
};
@@ -499,4 +503,83 @@ describe("EmailWorkflowService", () => {
).rejects.toThrow("Either evt or formData must be provided");
});
});
+
+ describe("generateEmailPayloadForEvtWorkflow - ICS attachment", () => {
+ const mockBookingInfo = {
+ uid: "booking-123",
+ bookerUrl: "https://cal.com",
+ title: "Test Meeting",
+ startTime: "2024-12-01T10:00:00Z",
+ endTime: "2024-12-01T11:00:00Z",
+ organizer: {
+ name: "Organizer Name",
+ email: "organizer@example.com",
+ timeZone: "UTC",
+ language: { locale: "en" },
+ timeFormat: "h:mma",
+ },
+ attendees: [
+ {
+ name: "Attendee Name",
+ email: "attendee@example.com",
+ timeZone: "UTC",
+ language: { locale: "en" },
+ },
+ ],
+ };
+
+ test("should NOT include ICS attachment for BOOKING_REQUESTED trigger even when includeCalendarEvent is true", async () => {
+ const result = await emailWorkflowService.generateEmailPayloadForEvtWorkflow({
+ evt: mockBookingInfo,
+ sendTo: ["attendee@example.com"],
+ hideBranding: false,
+ emailSubject: "Test Subject",
+ emailBody: "Test Body",
+ sender: "Cal.com",
+ action: WorkflowActions.EMAIL_ATTENDEE,
+ template: WorkflowTemplates.REMINDER,
+ includeCalendarEvent: true,
+ triggerEvent: WorkflowTriggerEvents.BOOKING_REQUESTED,
+ });
+
+ expect(result.attachments).toBeUndefined();
+ });
+
+ test("should include ICS attachment for BEFORE_EVENT trigger when includeCalendarEvent is true", async () => {
+ const result = await emailWorkflowService.generateEmailPayloadForEvtWorkflow({
+ evt: mockBookingInfo,
+ sendTo: ["attendee@example.com"],
+ hideBranding: false,
+ emailSubject: "Test Subject",
+ emailBody: "Test Body",
+ sender: "Cal.com",
+ action: WorkflowActions.EMAIL_ATTENDEE,
+ template: WorkflowTemplates.REMINDER,
+ includeCalendarEvent: true,
+ triggerEvent: WorkflowTriggerEvents.BEFORE_EVENT,
+ });
+
+ expect(result.attachments).toBeDefined();
+ expect(result.attachments).toHaveLength(1);
+ expect(result.attachments?.[0].filename).toBe("event.ics");
+ expect(result.attachments?.[0].contentType).toBe("text/calendar; charset=UTF-8; method=REQUEST");
+ });
+
+ test("should NOT include ICS attachment when includeCalendarEvent is false", async () => {
+ const result = await emailWorkflowService.generateEmailPayloadForEvtWorkflow({
+ evt: mockBookingInfo,
+ sendTo: ["attendee@example.com"],
+ hideBranding: false,
+ emailSubject: "Test Subject",
+ emailBody: "Test Body",
+ sender: "Cal.com",
+ action: WorkflowActions.EMAIL_ATTENDEE,
+ template: WorkflowTemplates.REMINDER,
+ includeCalendarEvent: false,
+ triggerEvent: WorkflowTriggerEvents.BEFORE_EVENT,
+ });
+
+ expect(result.attachments).toBeUndefined();
+ });
+ });
});
diff --git a/packages/features/ee/workflows/lib/service/EmailWorkflowService.ts b/packages/features/ee/workflows/lib/service/EmailWorkflowService.ts
index 1f199bfa08..7ca3caf829 100644
--- a/packages/features/ee/workflows/lib/service/EmailWorkflowService.ts
+++ b/packages/features/ee/workflows/lib/service/EmailWorkflowService.ts
@@ -455,7 +455,11 @@ export class EmailWorkflowService {
location: bookingMetadataSchema.parse(evt.metadata || {})?.videoCallUrl || evt.location,
};
- const attachments = includeCalendarEvent
+ const shouldIncludeCalendarEvent =
+ includeCalendarEvent &&
+ triggerEvent !== WorkflowTriggerEvents.BOOKING_REQUESTED;
+
+ const attachments = shouldIncludeCalendarEvent
? [
{
content: