Fixes an issue where guests receive duplicate, inconsistent email notifications for a single appointment (one branded email from When and an unbranded/casing-mismatched email from
external calendar providers like Google Calendar or CalDAV).
When sends a branded confirmation email with an attached invite.ics (METHOD:REQUEST) using the owner's configured name from when.yaml.
External calendar providers (Google Calendar, RFC 6638 CalDAV servers) by default attempt to deliver their own native calendar invitation emails when an event containing attendees is
created.
This leads to duplicate emails for guests, often with inconsistent formatting and casing (e.g. when.yaml's lowercase display name vs. the host's capitalized Google Account profile
name).
Solution
Aligned calendar provider integrations with industry standards (Cal.com, Calendly, RFC 6638, Google Calendar API) to ensure When remains the single source of truth for appointment
notifications:
Google Calendar (sendUpdates=none):
• Appended sendUpdates=none to POST (create), PUT (update), and DELETE (cancel) API endpoints in google.ts.
• This creates/updates events on the host's calendar with attendee details without triggering Google's native email notifications.
CalDAV (SCHEDULE-AGENT=CLIENT):
• Added SCHEDULE-AGENT=CLIENT parameter to ATTENDEE entries generated in ics.ts per RFC 6638 § 3.2.4.
• Explicitly instructs CalDAV servers (e.g. Nextcloud, SabreDAV, Fastmail, Apple Calendar) that the client application handles invitation delivery, suppressing server-side iMIP/iTIP
mailers.
Deduplicate Worker buildIcs:
• Refactored ics.ts to delegate to the canonical buildIcs in @when/calendar, eliminating ~60 lines of duplicate code and ensuring all .ics outputs share the same formatting and
security checks.
──────
Verification
• Unit Tests:
• pnpm --filter @when/calendar test (114 tests passed)
• pnpm --filter @when/worker test (176 tests passed)
• Monorepo Suite:
• pnpm test (all 67 test files and 628 tests passed)
• pnpm check (TypeScript check passed with 0 errors)
• pnpm lint (Prettier & ESLint passed with 0 errors)
### Summary
Fixes an issue where guests receive duplicate, inconsistent email notifications for a single appointment (one branded email from When and an unbranded/casing-mismatched email from
external calendar providers like Google Calendar or CalDAV).
fixes #49
### Problem & Context
When an appointment is confirmed or updated:
1. When sends a branded confirmation email with an attached invite.ics (METHOD:REQUEST) using the owner's configured name from when.yaml.
2. External calendar providers (Google Calendar, RFC 6638 CalDAV servers) by default attempt to deliver their own native calendar invitation emails when an event containing attendees is
created.
3. This leads to duplicate emails for guests, often with inconsistent formatting and casing (e.g. when.yaml's lowercase display name vs. the host's capitalized Google Account profile
name).
### Solution
Aligned calendar provider integrations with industry standards (Cal.com, Calendly, RFC 6638, Google Calendar API) to ensure When remains the single source of truth for appointment
notifications:
1. Google Calendar (sendUpdates=none):
• Appended sendUpdates=none to POST (create), PUT (update), and DELETE (cancel) API endpoints in google.ts.
• This creates/updates events on the host's calendar with attendee details without triggering Google's native email notifications.
2. CalDAV (SCHEDULE-AGENT=CLIENT):
• Added SCHEDULE-AGENT=CLIENT parameter to ATTENDEE entries generated in ics.ts per RFC 6638 § 3.2.4.
• Explicitly instructs CalDAV servers (e.g. Nextcloud, SabreDAV, Fastmail, Apple Calendar) that the client application handles invitation delivery, suppressing server-side iMIP/iTIP
mailers.
3. Deduplicate Worker buildIcs:
• Refactored ics.ts to delegate to the canonical buildIcs in @when/calendar, eliminating ~60 lines of duplicate code and ensuring all .ics outputs share the same formatting and
security checks.
──────
### Verification
• Unit Tests:
• pnpm --filter @when/calendar test (114 tests passed)
• pnpm --filter @when/worker test (176 tests passed)
• Monorepo Suite:
• pnpm test (all 67 test files and 628 tests passed)
• pnpm check (TypeScript check passed with 0 errors)
• pnpm lint (Prettier & ESLint passed with 0 errors)
- Append sendUpdates=none to Google Calendar API event create, update, and delete calls
- Inject SCHEDULE-AGENT=CLIENT into ATTENDEE lines per RFC 6638 for CalDAV servers
- Refactor apps/worker to consume canonical buildIcs from @when/calendar
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Fixes an issue where guests receive duplicate, inconsistent email notifications for a single appointment (one branded email from When and an unbranded/casing-mismatched email from
external calendar providers like Google Calendar or CalDAV).
fixes #49
Problem & Context
When an appointment is confirmed or updated:
created.
name).
Solution
Aligned calendar provider integrations with industry standards (Cal.com, Calendly, RFC 6638, Google Calendar API) to ensure When remains the single source of truth for appointment
notifications:
• Appended sendUpdates=none to POST (create), PUT (update), and DELETE (cancel) API endpoints in google.ts.
• This creates/updates events on the host's calendar with attendee details without triggering Google's native email notifications.
• Added SCHEDULE-AGENT=CLIENT parameter to ATTENDEE entries generated in ics.ts per RFC 6638 § 3.2.4.
• Explicitly instructs CalDAV servers (e.g. Nextcloud, SabreDAV, Fastmail, Apple Calendar) that the client application handles invitation delivery, suppressing server-side iMIP/iTIP
mailers.
• Refactored ics.ts to delegate to the canonical buildIcs in @when/calendar, eliminating ~60 lines of duplicate code and ensuring all .ics outputs share the same formatting and
security checks.
──────
Verification
• Unit Tests:
• pnpm --filter @when/calendar test (114 tests passed)
• pnpm --filter @when/worker test (176 tests passed)
• Monorepo Suite:
• pnpm test (all 67 test files and 628 tests passed)
• pnpm check (TypeScript check passed with 0 errors)
• pnpm lint (Prettier & ESLint passed with 0 errors)
e7832f2ebatod3a5bc6caad3a5bc6caato09c9947aef