fix(workflows): hide organizer email in workflow emails (#23392)#23525
Conversation
|
@jadhavharshh is attempting to deploy a commit to the cal Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughThe changes update email sender handling for workflow reminder emails. In scheduleEmailReminders.ts, three sending paths now conditionally set the sender to SENDER_NAME when reminder.booking?.eventType?.hideOrganizerEmail is true; otherwise they use the existing workflow step sender. replyTo remains included only when hideOrganizerEmail is false. In emailReminderManager.ts, similar logic is applied: sender is set to SENDER_NAME when evt.hideOrganizerEmail is true; otherwise it uses the provided sender. Both files import SENDER_NAME from @calcom/lib/constants. Assessment against linked issues
Assessment against linked issues: Out-of-scope changesNo out-of-scope changes detected. Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/features/ee/workflows/lib/reminders/emailReminderManager.ts (1)
243-266: ICS attachment may still leak organizer email when hiding is enabled.The ICS payload uses
emailEvent.organizer.emailunconditionally. IfhideOrganizerEmailis true, the organizer email can still appear in the .ics. Scrub it before generating the ICS.Apply this diff:
@@ - const attachments = includeCalendarEvent + const attachments = includeCalendarEvent ? [ { content: Buffer.from( - generateIcsString({ - event: emailEvent, - status, - }) || "" + generateIcsString({ + event: + (evt.eventType?.hideOrganizerEmail ?? evt.hideOrganizerEmail ?? false) + ? { ...emailEvent, organizer: { ...emailEvent.organizer, email: undefined } } + : emailEvent, + status, + }) || "" ).toString("base64"),packages/features/ee/workflows/api/scheduleEmailReminders.ts (1)
343-356: ICS attachment can reveal organizer email despite hidden setting.When attaching the ICS,
event.organizer.emailis included. Scrub it whenhideOrganizerEmailis true.Apply this diff:
- attachments: reminder.workflowStep.includeCalendarEvent + attachments: reminder.workflowStep.includeCalendarEvent ? [ { - content: Buffer.from(generateIcsString({ event, status: "CONFIRMED" }) || "").toString( - "base64" - ), + content: Buffer.from( + generateIcsString({ + event: reminder.booking?.eventType?.hideOrganizerEmail + ? { ...event, organizer: { ...event.organizer, email: undefined } } + : event, + status: "CONFIRMED", + }) || "" + ).toString("base64"),
🧹 Nitpick comments (5)
packages/features/ee/workflows/api/scheduleEmailReminders.ts (5)
356-359: Provide a default sender when workflowStep.sender is absent.Avoid
undefinedsender in edge cases.Apply this diff:
- sender: reminder.booking?.eventType?.hideOrganizerEmail - ? SENDER_NAME - : reminder.workflowStep.sender, + sender: reminder.booking?.eventType?.hideOrganizerEmail + ? SENDER_NAME + : (reminder.workflowStep.sender ?? SENDER_NAME),
447-450: Default sender for mandatory reminders.
workflowStepmay be null for mandatory reminders; ensure a safe fallback.Apply this diff:
- sender: reminder.booking?.eventType?.hideOrganizerEmail - ? SENDER_NAME - : reminder.workflowStep?.sender, + sender: reminder.booking?.eventType?.hideOrganizerEmail + ? SENDER_NAME + : (reminder.workflowStep?.sender ?? SENDER_NAME),
340-365: Minor: factor hide flag once per block for readability.Optional clean-up to reduce repetition.
Apply this diff:
- const mailData = { + const hide = !!reminder.booking?.eventType?.hideOrganizerEmail; + const mailData = { subject: emailContent.emailSubject, to: Array.isArray(sendTo) ? sendTo : [sendTo], html: emailContent.emailBody, @@ - sender: reminder.booking?.eventType?.hideOrganizerEmail + sender: hide ? SENDER_NAME - : (reminder.workflowStep.sender ?? SENDER_NAME), - ...(!reminder.booking?.eventType?.hideOrganizerEmail && { + : (reminder.workflowStep.sender ?? SENDER_NAME), + ...(!hide && { replyTo: reminder.booking?.eventType?.customReplyToEmail ?? reminder.booking?.userPrimaryEmail ?? reminder.booking.user?.email, }), };
444-456: Minor: same readability improvement for mandatory path.Apply this diff:
- const mailData = { + const hide = !!reminder.booking?.eventType?.hideOrganizerEmail; + const mailData = { subject: emailContent.emailSubject, to: [sendTo], html: emailContent.emailBody, - sender: reminder.booking?.eventType?.hideOrganizerEmail + sender: hide ? SENDER_NAME : (reminder.workflowStep?.sender ?? SENDER_NAME), - ...(!reminder.booking?.eventType?.hideOrganizerEmail && { + ...(!hide && { replyTo: reminder.booking?.eventType?.customReplyToEmail || reminder.booking?.userPrimaryEmail || reminder.booking.user?.email, }), };
176-186: Optional: narrow Prisma selection to required fields.
profile.findFirstonly needsorganizationId.Apply this diff:
- const organizerOrganizationProfile = await prisma.profile.findFirst({ - where: { - userId: reminder.booking.user?.id, - }, - }); + const organizerOrganizationProfile = await prisma.profile.findFirst({ + where: { userId: reminder.booking.user?.id }, + select: { organizationId: true }, + });
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
packages/features/ee/workflows/api/scheduleEmailReminders.ts(3 hunks)packages/features/ee/workflows/lib/reminders/emailReminderManager.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/features/ee/workflows/api/scheduleEmailReminders.tspackages/features/ee/workflows/lib/reminders/emailReminderManager.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
packages/features/ee/workflows/api/scheduleEmailReminders.tspackages/features/ee/workflows/lib/reminders/emailReminderManager.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
packages/features/ee/workflows/api/scheduleEmailReminders.tspackages/features/ee/workflows/lib/reminders/emailReminderManager.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: anglerfishlyy
PR: calcom/cal.com#0
File: :0-0
Timestamp: 2025-08-27T16:39:38.156Z
Learning: anglerfishlyy successfully implemented CAL-3076 email invitation feature for Cal.com team event-types in PR #23312. The feature allows inviting people via email directly from assignment flow, with automatic team invitation if email doesn't belong to existing team member. Implementation includes Host type modifications (userId?: number, email?: string, isPending?: boolean), CheckedTeamSelect component updates with CreatableSelect, TRPC schema validation with zod email validation, and integration with existing teamInvite system.
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/features/ee/workflows/components/WorkflowStepContainer.tsx:641-649
Timestamp: 2025-08-26T20:09:17.089Z
Learning: In packages/features/ee/workflows/components/WorkflowStepContainer.tsx, Cal.AI actions are intentionally filtered out/hidden for organization workflows when props.isOrganization is true. This restriction is by design per maintainer Udit-takkar in PR #22995, despite the broader goal of enabling Cal.AI self-serve.
🧬 Code graph analysis (2)
packages/features/ee/workflows/api/scheduleEmailReminders.ts (1)
packages/lib/constants.ts (1)
SENDER_NAME(31-31)
packages/features/ee/workflows/lib/reminders/emailReminderManager.ts (1)
packages/lib/constants.ts (1)
SENDER_NAME(31-31)
🔇 Additional comments (3)
packages/features/ee/workflows/lib/reminders/emailReminderManager.ts (1)
9-9: Importing SENDER_NAME looks good.packages/features/ee/workflows/api/scheduleEmailReminders.ts (2)
11-11: Importing SENDER_NAME is correct.
499-507: Limit ICS generation to expected callsites
ICS generation is only invoked in two locations—packages/features/ee/workflows/api/scheduleEmailReminders.ts (line 346) and packages/features/ee/workflows/lib/reminders/emailReminderManager.ts (line 255); no other calls to generateIcsString were found.
volnei
left a comment
There was a problem hiding this comment.
LGTM! @jadhavharshh thank you for your contribution!
E2E results are ready! |
…)" This reverts commit 7f200df.
What does this PR do?
This PR ensures that workflow emails (such as reminders) fully respect the "Hide organizer's email" setting.
Previously, organizer emails could still be exposed in the sender field of workflow emails even when the setting was enabled.
The fix updates both
emailReminderManager.tsandscheduleEmailReminders.tsto conditionally use theSENDER_NAMEconstant wheneverhideOrganizerEmailis true. This aligns workflow emails with regular booking emails, ensuring consistent privacy and preventing unintended exposure of organizer addresses.SENDER_NAME) instead of the organizer’s email when the setting is enabled.Mandatory Tasks (DO NOT REMOVE)
How should this be tested?
Result: Consistent and privacy-respecting behavior across all workflow and booking emails.
Checklist