Skip to content

fix(dav): keep a cancelled occurrence cancelled for attendees#60658

Open
ndo84bw wants to merge 1 commit into
nextcloud:masterfrom
ndo84bw:fix/dav-itip-keep-cancelled-occurrence-in-request
Open

fix(dav): keep a cancelled occurrence cancelled for attendees#60658
ndo84bw wants to merge 1 commit into
nextcloud:masterfrom
ndo84bw:fix/dav-itip-keep-cancelled-occurrence-in-request

Conversation

@ndo84bw

@ndo84bw ndo84bw commented May 22, 2026

Copy link
Copy Markdown

Summary

When the organizer cancels a single occurrence of a recurring event, the attendee receives a "Cancelled" email, but the occurrence still shows up as not cancelled in the attendee's calendar. Both users are on the same Nextcloud instance. (tested on master)

The TipBroker first sends the CANCEL and then follows up with a REQUEST that does not include the cancelled instance. This overwrites the cancellation for that instance: Sabre's processMessageRequest replaces the attendee's entire stored object with the components of the REQUEST.

The patch:

  1. TipBroker: keeps the cancelled instances in the REQUEST
  2. IMipPlugin: still sends the Cancelled email as before, but filters the invitation email for newly cancelled occurrences (only those come with a CANCEL email).
  3. TipBroker: overrides parseEventForAttendee to take the STATUS from the master instead of the last VEVENT. Otherwise, the whole event counts as cancelled and the attendee's REPLYs no longer reach the organizer.

Note:

  • A STATUS:CANCELLED override inside a REQUEST is not foreseen by RFC 5546 3.2.2 (STATUS there: TENTATIVE/CONFIRMED); external clients still receive the unchanged, RFC-conformant per-instance CANCEL as the authoritative signal.
  • Backport only paired with the broker rework fix(CalDAV): iTipBroker message generation and testing #50843, which exists as of stable34 only.

Tested:

  • Unit: 47 tests green (16 IMipPluginTest, 31 TipBrokerTest), 5 of them new: REQUEST email suppression for a pure cancellation; the email is kept when cancelling a pre-existing override; a real change with a cancelled override riding along mails the real change; attendee REPLY despite a cancelled override in the copy; the REQUEST keeps the cancelled instance.
  • Scripted (CalDAV/curl, AI-assisted): after the cancellation, the attendee's stored copy keeps the cancelled override (without the patch: only the master remains); email counts: keeping the override without the IMipPlugin filter produced an additional bogus "Invitation:" email per cancellation, with the filter only the Cancelled email goes out.
  • Manual (web UI + Thunderbird, without accepting beforehand): the occurrence stays struck through in the attendee's calendar instead of reappearing as a normal event; only the Cancelled email arrives; accepting/declining via Thunderbird after the cancellation reaches the organizer (email + participation status); moving an occurrence and then cancelling it still produces an update email.

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI
  • analyze the code and find the root cause
  • Suggest Code
  • Wrote and ran Unit Tests
  • Translation of PR Body

@ChristophWurst

Copy link
Copy Markdown
Member

Thanks for the contribution

Mind restoring the pull request template and filling it out? Thanks

@ndo84bw

ndo84bw commented May 22, 2026

Copy link
Copy Markdown
Author

Mind restoring the pull request template and filling it out? Thanks

🤦‍♂️ Restored and filled out the template, thanks!

@ChristophWurst ChristophWurst added bug 3. to review Waiting for reviews feature: dav feature: caldav Related to CalDAV internals labels May 22, 2026
@ChristophWurst ChristophWurst added this to the Nextcloud 35 milestone May 22, 2026
@SebastianKrupinski

Copy link
Copy Markdown
Contributor

Hi @ndo84bw

Thanks for the PR, I will test this when I have a min

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

(If you believe you should not receive this message, you can add yourself to the blocklist.)

@susnux susnux added the community pull requests from community label Jun 9, 2026
@ndo84bw ndo84bw force-pushed the fix/dav-itip-keep-cancelled-occurrence-in-request branch from 05a46d2 to c3067b2 Compare June 11, 2026 13:32
@ndo84bw ndo84bw force-pushed the fix/dav-itip-keep-cancelled-occurrence-in-request branch from c3067b2 to be907d7 Compare June 19, 2026 09:49
… it cancelled

When an organizer cancels a single occurrence of a recurring event, the broker
emits a per-instance CANCEL plus a REQUEST for the attendee's remaining
instances. The REQUEST omitted the cancelled instance, but processMessageRequest
replaces all components of the attendee's stored object, so it dropped the
CANCELLED override the CANCEL had just added and the occurrence reappeared as a
normal event on the attendee's calendar.

Keep the cancelled instance in the REQUEST so the override survives the
component replace. Two adjustments keep the pipeline coherent with the kept
override:

- IMipPlugin no longer builds an email from a newly cancelled override, which
  sent a second "Invitation:" email (with response buttons) for the occurrence
  the CANCEL email had just cancelled. Cancelling a previously modified
  occurrence produces no CANCEL message, so that override keeps its REQUEST
  email.
- TipBroker derives the attendee-side event status from the master instance;
  the aggregate status (last component wins) would treat the attendee copy as a
  cancelled event once it carries the override, muting all attendee replies.

Assisted-by: ClaudeCode:claude-opus-4-7
Assisted-by: ClaudeCode:claude-fable-5
Signed-off-by: Nico Donath <ndo84bw@gmx.de>
@ndo84bw ndo84bw force-pushed the fix/dav-itip-keep-cancelled-occurrence-in-request branch from be907d7 to 3d8bfef Compare July 2, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews bug community pull requests from community feature: caldav Related to CalDAV internals feature: dav feedback-requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Recurrent Events: When the organizer changes the status of an occurrence to 'cancelled', the whole event becomes cancelled on the attendee's calendar

4 participants