Skip to content

fix(workflows): hide organizer email in workflow emails (#23392)#23525

Merged
volnei merged 1 commit into
calcom:mainfrom
harshjdhv:fix/hide-email-exposed-in-workflows
Sep 2, 2025
Merged

fix(workflows): hide organizer email in workflow emails (#23392)#23525
volnei merged 1 commit into
calcom:mainfrom
harshjdhv:fix/hide-email-exposed-in-workflows

Conversation

@harshjdhv

Copy link
Copy Markdown
Contributor

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.ts and scheduleEmailReminders.ts to conditionally use the SENDER_NAME constant whenever hideOrganizerEmail is true. This aligns workflow emails with regular booking emails, ensuring consistent privacy and preventing unintended exposure of organizer addresses.

  • Original: Workflow reminder email showed the organizer’s email in the sender field even with "Hide organizer's email" enabled.
  • Updated: Workflow reminder email now displays "Cal.com" (from SENDER_NAME) instead of the organizer’s email when the setting is enabled.

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code.
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox. → N/A
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

  1. Create an event type with "Hide organizer's email" enabled.
  2. Attach a workflow that sends email reminders.
  3. Book the event and check the workflow reminder email.
    • Expected behavior: The email should not show the organizer’s email address anywhere in the sender details.
  4. Repeat the same test with "Hide organizer's email" disabled.
    • Expected behavior: The email should show the organizer’s email address as usual.

Result: Consistent and privacy-respecting behavior across all workflow and booking emails.

Checklist

@vercel

vercel Bot commented Sep 2, 2025

Copy link
Copy Markdown

@jadhavharshh is attempting to deploy a commit to the cal Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Sep 2, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

The 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

Objective Addressed Explanation
Hide organizer email in workflow emails when eventType.hideOrganizerEmail is enabled (#23392)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes detected.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • CAL-23392: Entity not found: Issue - Could not find referenced Issue.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions Bot added emails area: emails, cancellation email, reschedule email, inbox, spam folder, not getting email Medium priority Created by Linear-GitHub Sync workflows area: workflows, automations 🐛 bug Something isn't working labels Sep 2, 2025
@graphite-app graphite-app Bot added the community Created by Linear-GitHub Sync label Sep 2, 2025
@graphite-app graphite-app Bot requested a review from a team September 2, 2025 19:58

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.email unconditionally. If hideOrganizerEmail is 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.email is included. Scrub it when hideOrganizerEmail is 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 undefined sender 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.

workflowStep may 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.findFirst only needs organizationId.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between 9b38ed6 and f7b85ca.

📒 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 use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/ee/workflows/api/scheduleEmailReminders.ts
  • packages/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.ts
  • packages/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.ts
  • packages/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 volnei left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM! @jadhavharshh thank you for your contribution!

@volnei volnei enabled auto-merge (squash) September 2, 2025 22:06
@volnei volnei merged commit 7f200df into calcom:main Sep 2, 2025
74 of 81 checks passed
@github-actions

github-actions Bot commented Sep 2, 2025

Copy link
Copy Markdown
Contributor

E2E results are ready!

@supalarry

Copy link
Copy Markdown
Contributor

@jadhavharshh thank you for the contribution!

One thing though. I am not sure this PR solves the issue - your code changes the sender name not email. I think that step.name is not email but just display name .e.g. Cal.com in screenshot below
Uploading Screenshot 2025-09-10 at 13.25.42.png…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 bug Something isn't working community Created by Linear-GitHub Sync emails area: emails, cancellation email, reschedule email, inbox, spam folder, not getting email Medium priority Created by Linear-GitHub Sync ready-for-e2e size/S workflows area: workflows, automations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

workflows (like reminders) should automatically hide host email from recipient when "hide organizer's email" is selected

3 participants