Skip to content

fix(api): return original email without OAuth suffix in bookings#25593

Merged
ThyMinimalDev merged 13 commits intomainfrom
fix/email-suffix-api-response
Jan 12, 2026
Merged

fix(api): return original email without OAuth suffix in bookings#25593
ThyMinimalDev merged 13 commits intomainfrom
fix/email-suffix-api-response

Conversation

@pedroccastro
Copy link
Contributor

@pedroccastro pedroccastro commented Dec 3, 2025

What does this PR do?

This PR fixes a bug in API v2 (2024-08-13) where emails in booking API responses contained the OAuth client ID as a suffix (+{cuid}). This suffix exists to prevent email collisions between managed users of different OAuth clients.

Fixes #25494 | Linear: CAL-6843

Problem:

  • Managed user emails were returned as: bob+cmidditrv0000mza4q93hbcau@example.com
  • Expected display: bob@example.com

Solution:
To avoid breaking changes for platform customers who may rely on the original email format, we preserve the original email field and add a new displayEmail field with the CUID suffix removed.

Key Changes:

  • Add getDisplayEmail() helper to strip CUID suffix from emails
  • Add displayEmail field to all relevant response objects
  • Keep original email field unchanged for backwards compatibility

Regex pattern used: /\+[a-zA-Z0-9]{25}/ (CUID format, consistent with google-calendar.service.ts)

Affected Fields

Field Value
hosts[].email bob+{cuid}@example.com (unchanged)
hosts[].displayEmail bob@example.com (new)
attendees[].email bob+{cuid}@example.com (unchanged)
attendees[].displayEmail bob@example.com (new)
bookingFieldsResponses.email bob+{cuid}@example.com (unchanged)
bookingFieldsResponses.displayEmail bob@example.com (new)
bookingFieldsResponses.guests[] guest+{cuid}@example.com (unchanged)
bookingFieldsResponses.displayGuests[] guest@example.com (new)
reassignedTo.email bob+{cuid}@example.com (unchanged)
reassignedTo.displayEmail bob@example.com (new)

How should this be tested?

Test Scenario 1 - Managed user as HOST:

  1. Create an event type using managed user's access token
  2. Create booking on that event type (external user booking managed user)
  3. GET /v2/bookings/{uid} with header Cal-Api-Version: 2024-08-13
  4. Verify hosts[].email returns original email with suffix
  5. Verify hosts[].displayEmail returns email without suffix

Test Scenario 2 - Managed user as ATTENDEE:

  1. Create booking where attendee is a managed user
  2. GET /v2/bookings/{uid} with header Cal-Api-Version: 2024-08-13
  3. Verify attendees[].email returns original email with suffix
  4. Verify attendees[].displayEmail returns email without suffix

Test Scenario 3 - Self-booking:

  1. Managed user books their own event type
  2. Verify both email and displayEmail fields are present and correct

Expected result: email fields preserve original value, displayEmail fields return clean email without +{cuid} suffix

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • 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, OpenAPI spec auto-updated
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

Human Review Checklist

  • Verify regex pattern /\+[a-zA-Z0-9]{25}/ correctly strips CUID suffixes without affecting normal emails
  • Confirm backwards compatibility: original email field values are unchanged
  • Verify displayEmail is added to all booking output types (hosts, attendees, reassignedTo)

@pedroccastro pedroccastro requested a review from a team as a code owner December 3, 2025 17:57
@graphite-app graphite-app bot requested a review from a team December 3, 2025 17:57
@github-actions github-actions bot added High priority Created by Linear-GitHub Sync reactive⚡︎ 🐛 bug Something isn't working labels Dec 3, 2025
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

ThyMinimalDev
ThyMinimalDev previously approved these changes Dec 4, 2025
@vercel
Copy link

vercel bot commented Dec 9, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
cal-companion Canceled Canceled Jan 13, 2026 7:46am
3 Skipped Deployments
Project Deployment Review Updated (UTC)
api-v2 Ignored Ignored Preview Jan 13, 2026 7:46am
cal Ignored Ignored Jan 13, 2026 7:46am
cal-eu Ignored Ignored Jan 13, 2026 7:46am

ThyMinimalDev
ThyMinimalDev previously approved these changes Dec 12, 2025
The seated booking tests were missing displayEmail in the attendee
assertions for the second booking test and cancel-as-host test,
causing CI test failures
volnei
volnei previously approved these changes Dec 22, 2025
ThyMinimalDev
ThyMinimalDev previously approved these changes Jan 6, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 9, 2026

Devin AI is resolving merge conflicts

This PR has merge conflicts with the main branch. A Devin session has been created to automatically resolve them.

View Devin Session

Devin will:

  1. Merge the latest main into this branch
  2. Resolve any conflicts intelligently
  3. Run lint/type checks to ensure validity
  4. Push the resolved changes

If you prefer to resolve conflicts manually, you can close the Devin session and handle it yourself.

Resolved merge conflicts in docs/api-reference/v2/openapi.json by:
- Preserving the displayEmail field additions from the PR
- Using the multi-line array formatting from main branch

Co-Authored-By: unknown <>
@devin-ai-integration devin-ai-integration bot dismissed stale reviews from volnei and ThyMinimalDev via b6cbb56 January 9, 2026 20:45
@keithwillcode keithwillcode added the core area: core, team members only label Jan 10, 2026
@ThyMinimalDev ThyMinimalDev merged commit 0994050 into main Jan 12, 2026
45 of 46 checks passed
@ThyMinimalDev ThyMinimalDev deleted the fix/email-suffix-api-response branch January 12, 2026 07:48
Anshumancanrock pushed a commit to Anshumancanrock/cal.com that referenced this pull request Jan 12, 2026
…com#25593)

* fix(api): remove OAuth client ID suffix from email in booking API responses

Fixes calcom#25494 | Linear: CAL-6843

When managed users create or receive bookings, their emails were being returned with an internal OAuth client ID suffix (e.g., bob+cuid123@example.com). This suffix is used internally for user identification but should not be exposed in API responses.

Changes:
- Add cleanOAuthEmailSuffix() helper using CUID regex pattern
- Clean email suffix in hosts[], attendees[], bookingFieldsResponses.email, bookingFieldsResponses.guests[], and reassignedTo.email
- Pattern consistent with google-calendar.service.ts implementation

Affected output methods:
- getOutputBooking
- getOutputRecurringBooking
- getOutputSeatedBooking
- getOutputRecurringSeatedBooking
- getOutputReassignedBooking
- getHost

* refactor(api): preserve original email, add displayEmail field

Per team discussion, keep original email unchanged to avoid breaking changes for platform customers.
Add displayEmail field with CUID suffix removed for display purposes

* feat(api): add displayEmail to booking output DTOs

Add displayEmail property to BookingAttendee, BookingHost and ReassignedToDto for API documentation and type safety

* test(api): add e2e tests for displayEmail fields in managed user bookings

Add tests to verify that displayEmail fields correctly strip CUID suffix from OAuth managed user emails in booking API responses:

- Test host displayEmail returns email without CUID suffix
- Test attendee displayEmail returns email without CUID suffix
- Test bookingFieldsResponses.displayEmail returns clean email
- Test displayGuests array returns emails without CUID suffix

* false positive breaking change

* false positive breaking change

* test(api): update existing e2e tests to expect displayEmail field

* fix(api): add missing displayEmail to seated booking test assertions

The seated booking tests were missing displayEmail in the attendee
assertions for the second booking test and cancel-as-host test,
causing CI test failures

---------

Co-authored-by: cal.com <morgan@cal.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
@vercel vercel bot temporarily deployed to Preview – cal-companion January 13, 2026 07:46 Inactive
@vercel vercel bot temporarily deployed to Preview – dev January 13, 2026 07:46 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 bug Something isn't working core area: core, team members only devin-conflict-resolution High priority Created by Linear-GitHub Sync reactive⚡︎ ready-for-e2e size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Emails are being modified with +{suffix} when attendee & host emails overlap

4 participants