fix(calendar): suppress provider invitations and deduplicate ICS builder #55

Merged
eleith merged 1 commits from fix/suppress-duplicate-calendar-invites into main 2026-08-31 12:33:12 +00:00
Owner

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)

### 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)
eleith force-pushed fix/suppress-duplicate-calendar-invites from e7832f2eba to d3a5bc6caa 2026-08-31 12:25:20 +00:00 Compare
eleith added 1 commit 2026-08-31 12:27:53 +00:00
fix(calendar): suppress provider invitations and deduplicate ICS builder
ci/woodpecker/pr/calendar Pipeline was successful
ci/woodpecker/pr/cli Pipeline was successful
ci/woodpecker/pr/web Pipeline was successful
ci/woodpecker/pr/worker Pipeline was successful
09c9947aef
- 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
eleith force-pushed fix/suppress-duplicate-calendar-invites from d3a5bc6caa to 09c9947aef 2026-08-31 12:27:53 +00:00 Compare
eleith merged commit db9db003d8 into main 2026-08-31 12:33:12 +00:00
eleith deleted branch fix/suppress-duplicate-calendar-invites 2026-08-31 12:33:12 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: eleith/when#55