server icon indicating copy to clipboard operation
server copied to clipboard

[Bug]: Deleting/Canceling an Instance of a Recurring Event Generates an Unhelpful iMIP Message

Open kesselb opened this issue 7 months ago • 1 comments

Bug description

Deleting/Canceling an Instance of a Recurring Event Generates an Unhelpful iMIP Message

Steps to reproduce

  1. Create an event and configure it to repeat weekly.
  2. Add Alice as an attendee.
  3. Select one instance of the recurring event and delete/cancel it.
  4. Observe that Alice receives a generic email stating that the event was updated, but the information specifying that only that particular instance was canceled is missing.

Expected behavior

Alice should receive a clear and specific notification indicating that a particular instance of the recurring event has been canceled, rather than a generic update message.

Additional info

By comparing the exdate, it is possible to determine the reason for the update and generate a more informative iMIP message. This will help attendees understand exactly which instance of the event has been canceled.

kesselb avatar Jun 16 '25 12:06 kesselb

PoC:

Index: apps/dav/lib/CalDAV/Schedule/IMipService.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/dav/lib/CalDAV/Schedule/IMipService.php b/apps/dav/lib/CalDAV/Schedule/IMipService.php
--- a/apps/dav/lib/CalDAV/Schedule/IMipService.php	(revision b3ffe4bf660a19d0af05640c007278c7131f4dae)
+++ b/apps/dav/lib/CalDAV/Schedule/IMipService.php	(date 1750077642010)
@@ -134,6 +134,12 @@
 		$data = [];
 		$data['meeting_when'] = $this->generateWhenString($eventReaderCurrent);
 
+		$a = $eventReaderPrevious->getExdates();
+		$b = $eventReaderCurrent->getExdates();
+		$c = array_diff($b, $a);
+
+		$cancelRecurrenceInstance = count($c) > 0;
+
 		foreach (self::STRING_DIFF as $key => $property) {
 			$data[$key] = self::readPropertyWithDefault($vEvent, $property, $defaultVal);
 		}
@@ -159,6 +165,10 @@
 		if ($eventReaderCurrent->recurs()) {
 			$data['meeting_occurring'] = $this->generateOccurringString($eventReaderCurrent);
 		}
+		if ($cancelRecurrenceInstance) {
+			$data['meeting_description'] .=  'This update cancelles the recurrence of this event at: ' . implode(', ', $c);;
+			$data['meeting_description_html'] .=  'This update cancelles the recurrence of this event at: ' . implode(', ', $c);;
+		}
 		return $data;
 	}
 
Index: apps/dav/lib/CalDAV/EventReader.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/dav/lib/CalDAV/EventReader.php b/apps/dav/lib/CalDAV/EventReader.php
--- a/apps/dav/lib/CalDAV/EventReader.php	(revision b3ffe4bf660a19d0af05640c007278c7131f4dae)
+++ b/apps/dav/lib/CalDAV/EventReader.php	(date 1750068371035)
@@ -38,6 +38,8 @@
 	protected array $recurrenceModified;
 	protected ?DateTimeInterface $recurrenceCurrentDate;
 
+	protected array $exdates = [];
+
 	protected array $dayNamesMap = [
 		'MO' => 'Monday', 'TU' => 'Tuesday', 'WE' => 'Wednesday', 'TH' => 'Thursday', 'FR' => 'Friday', 'SA' => 'Saturday', 'SU' => 'Sunday'
 	];
@@ -223,6 +225,7 @@
 			$dates = [];
 			foreach ($this->baseEvent->EXDATE as $entry) {
 				$dates[] = $entry->getValue();
+				$this->exdates[] = $entry->getValue();
 			}
 			$this->edateIterator = new EventReaderRDate(
 				implode(',', $dates),
@@ -768,4 +771,8 @@
 		}
 	}
 
+	public function getExdates(): array {
+		return $this->exdates;
+	}
+
 }

B A
Image Image

kesselb avatar Jun 16 '25 12:06 kesselb