Skip to content

feat: support custom email subject with booking field placeholders in…#29662

Open
sciencebanda09 wants to merge 4 commits into
calcom:mainfrom
sciencebanda09:fix/custom-field-placeholder-confirmation-email
Open

feat: support custom email subject with booking field placeholders in…#29662
sciencebanda09 wants to merge 4 commits into
calcom:mainfrom
sciencebanda09:fix/custom-field-placeholder-confirmation-email

Conversation

@sciencebanda09

Copy link
Copy Markdown

What does this PR do?

Fixes #29658

Implements custom confirmation email subject with {placeholder} support for booking fields. When an organizer sets a custom subject like Meeting with {company}, the attendee receives the email with the actual submitted value (e.g. Meeting with Acme Corp).

Changes

  • packages/prisma/zod-utils.ts — added confirmationEmailSubject field to EventTypeMetaDataSchema
  • packages/types/Calendar.d.ts — added customEmailSubject to CalendarEvent interface
  • packages/features/CalendarEventBuilder.ts — pass customEmailSubject through withEventType()
  • packages/features/bookings/lib/service/RegularBookingService.ts — read confirmationEmailSubject from event type metadata and pass it to the calendar event
  • packages/emails/templates/attendee-scheduled-email.ts — interpolate {fieldIdentifier} placeholders using attendee's booking responses
  • apps/web/modules/event-types/components/tabs/advanced/EventAdvancedTab.tsx — UI input field for organizers to set custom confirmation email subject

How was this tested?

  • Traced full data flow from zod schemaFormValuesUIRegularBookingServiceCalendarEventBuilderCalendarEventAttendeeScheduledEmail
  • Verified placeholder substitution logic handles string fields, name objects, and missing fields gracefully
  • Fallback to calEvent.title when no custom subject is set (no breaking change)

… confirmation email

- Add confirmationEmailSubject to EventTypeMetaDataSchema
- Add customEmailSubject field to CalendarEvent type
- Pass customEmailSubject from event type metadata through CalendarEventBuilder
- Interpolate {fieldIdentifier} placeholders in AttendeeScheduledEmail using booking responses
- Add UI input field in EventAdvancedTab for setting custom confirmation email subject

Fixes calcom#29658
@github-actions

Copy link
Copy Markdown
Contributor

Welcome to Cal.diy, @sciencebanda09! Thanks for opening this pull request.

A few things to keep in mind:

  • This is Cal.diy, not Cal.com. Cal.diy is a community-driven, fully open-source fork of Cal.com licensed under MIT. Your changes here will be part of Cal.diy — they will not be deployed to the Cal.com production app.
  • Please review our Contributing Guidelines if you haven't already.
  • Make sure your PR title follows the Conventional Commits format.

A maintainer will review your PR soon. Thanks for contributing!

@github-actions github-actions Bot added the 🐛 bug Something isn't working label Jun 27, 2026
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a947fadd-bdb6-4219-b1c4-d357ec0c4741

📥 Commits

Reviewing files that changed from the base of the PR and between c984538 and 0fe7e40.

📒 Files selected for processing (1)
  • packages/emails/templates/attendee-scheduled-email.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/emails/templates/attendee-scheduled-email.ts

📝 Walkthrough

Walkthrough

A new optional confirmationEmailSubject field is added to event type metadata and exposed on CalendarEvent as customEmailSubject. RegularBookingService passes event type metadata into CalendarEventBuilder, which sets customEmailSubject from confirmationEmailSubject. AttendeeScheduledEmail uses that value for the email subject and interpolates {fieldIdentifier} placeholders from booking responses. The event advanced settings UI adds a field for this value and new localized strings.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main change: supporting custom email subjects with booking field placeholders.
Description check ✅ Passed The description matches the code changes and summarizes the custom subject placeholder flow accurately.
Linked Issues check ✅ Passed The changes propagate and interpolate custom confirmation subjects so {company} resolves from booking responses in the first email.
Out of Scope Changes check ✅ Passed The changed files all relate to the custom confirmation email subject feature and its data flow.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with 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.

❤️ Share

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

@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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/features/bookings/lib/service/RegularBookingService.ts (1)

1382-1397: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Pass metadata through here instead of customEmailSubject. CalendarEventBuilder.withEventType() only reads confirmationEmailSubject from metadata, so this value is dropped and the booking-created email keeps the default subject.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/features/bookings/lib/service/RegularBookingService.ts` around lines
1382 - 1397, Pass the event type metadata through RegularBookingService’s
withEventType call instead of mapping only customEmailSubject, because
CalendarEventBuilder.withEventType reads confirmationEmailSubject from metadata
and the subject is currently being dropped. Update the eventType object passed
from RegularBookingService so it includes metadata (with
confirmationEmailSubject) and keep the existing fields like customReplyToEmail
unchanged.
🧹 Nitpick comments (1)
packages/emails/templates/attendee-scheduled-email.ts (1)

114-117: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Drop the what-comment above getInterpolatedSubject.

The method name already explains this. As per coding guidelines, “Only add code comments that explain why, not what” and “Never add comments that simply restate what the code does.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/emails/templates/attendee-scheduled-email.ts` around lines 114 -
117, Remove the redundant what-comment above getInterpolatedSubject in
attendee-scheduled-email.ts. The method name already conveys the behavior, so
delete the JSDoc block and keep the implementation self-explanatory; if any
comment remains, make sure it explains intent or rationale rather than restating
what getInterpolatedSubject does.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/modules/event-types/components/tabs/advanced/EventAdvancedTab.tsx`:
- Around line 1346-1352: The confirmation email subject field in
EventAdvancedTab adds a visible Label and helper text but does not
programmatically associate them with the TextField. Update the TextField/Label
wiring so the input has an accessible name and description, using the existing
confirmation_email_subject elements and the form field registration for
metadata.confirmationEmailSubject; the helper text paragraph should also be
linked as the field’s description.

In `@packages/emails/templates/attendee-scheduled-email.ts`:
- Around line 122-124: The placeholder replacement in
attendee-scheduled-email.ts should preserve missing tokens instead of dropping
them. Update the replace callback in the template handling logic so that when
responses[key] is absent in the relevant formatter function, it returns the
original matched placeholder from template.replace rather than an empty string.
This keeps unresolved placeholders visible for saved templates and avoids
silently stripping missing or renamed response keys.

In `@packages/i18n/locales/en/common.json`:
- Line 3314: Update the example string for
confirmation_email_subject_placeholder in the common locale so it demonstrates a
booking-field placeholder that matches the booking response field identifier
resolution used by the first attendee email. Replace the current {eventName} and
{organizer} example with a booking-field token such as {company}, keeping the
wording aligned with the placeholder behavior exposed by the interpolation path.

---

Outside diff comments:
In `@packages/features/bookings/lib/service/RegularBookingService.ts`:
- Around line 1382-1397: Pass the event type metadata through
RegularBookingService’s withEventType call instead of mapping only
customEmailSubject, because CalendarEventBuilder.withEventType reads
confirmationEmailSubject from metadata and the subject is currently being
dropped. Update the eventType object passed from RegularBookingService so it
includes metadata (with confirmationEmailSubject) and keep the existing fields
like customReplyToEmail unchanged.

---

Nitpick comments:
In `@packages/emails/templates/attendee-scheduled-email.ts`:
- Around line 114-117: Remove the redundant what-comment above
getInterpolatedSubject in attendee-scheduled-email.ts. The method name already
conveys the behavior, so delete the JSDoc block and keep the implementation
self-explanatory; if any comment remains, make sure it explains intent or
rationale rather than restating what getInterpolatedSubject does.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: edfd26dd-3ce7-442b-95bc-cd5118ec6d05

📥 Commits

Reviewing files that changed from the base of the PR and between b97cd62 and f0935cc.

📒 Files selected for processing (7)
  • apps/web/modules/event-types/components/tabs/advanced/EventAdvancedTab.tsx
  • packages/emails/templates/attendee-scheduled-email.ts
  • packages/features/CalendarEventBuilder.ts
  • packages/features/bookings/lib/service/RegularBookingService.ts
  • packages/i18n/locales/en/common.json
  • packages/prisma/zod-utils.ts
  • packages/types/Calendar.d.ts

Comment thread apps/web/modules/event-types/components/tabs/advanced/EventAdvancedTab.tsx Outdated
Comment thread packages/emails/templates/attendee-scheduled-email.ts Outdated
Comment thread packages/i18n/locales/en/common.json Outdated
- Remove duplicate customEmailSubject field in RegularBookingService
- Preserve unresolved placeholders as {key} instead of empty string
- Remove what-comment above getInterpolatedSubject
@sciencebanda09

sciencebanda09 commented Jun 27, 2026

Copy link
Copy Markdown
Author

@bandhan-majumder Ready for review. All CodeRabbit comments addressed. Happy to make any changes the maintainers suggest. also could a maintainer please add the run-ci label to trigger CI? Happy to address any feedback. Thanks!

@yschnegg

Copy link
Copy Markdown

This bug was encountered on the Cal.com free plan (cal.eu), so I assume it also exists in the calcom/cal.com repository. Will this fix be merged there as well?

@bandhan-majumder bandhan-majumder left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

changes looks good. Can u add a video demo?

@bandhan-majumder bandhan-majumder marked this pull request as draft June 27, 2026 20:25
@sciencebanda09 sciencebanda09 marked this pull request as ready for review June 27, 2026 21:24
@sciencebanda09

Copy link
Copy Markdown
Author

Hi @bandhan-majumder a live demo isn't possible right now as the feature requires a running local instance with a database. Here's the full data flow instead:

Data Flow

Step File Change
1 zod-utils.ts (line 152) confirmationEmailSubject added to event type metadata schema
2 Calendar.d.ts (line 226) customEmailSubject added to CalendarEvent interface
3 EventAdvancedTab.tsx (line 1345) TextField in Advanced tab for organizers to set custom subject
4 RegularBookingService.ts (line 1396) passes metadata through withEventType()
5 CalendarEventBuilder.ts (line 338) extracts confirmationEmailSubject → sets customEmailSubject
6 attendee-scheduled-email.ts (line 54-56) uses customEmailSubject if set, falls back to calEvent.title
7 getInterpolatedSubject() (line 114-137) replaces {fieldIdentifier} tokens with attendee booking responses

Example

Organizer sets: Meeting with {name} is confirmed
Attendee books with name John Doe
Email subject becomes: Meeting with John Doe is confirmed

Happy to set up a local instance for a full end-to-end demo if that's a hard requirement!

@bandhan-majumder

Copy link
Copy Markdown
Member

@sciencebanda09 please don't make change if u are not reviewing it locally yourself

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

Labels

🐛 bug Something isn't working size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom field placeholder silently stripped from first booking confirmation email

3 participants