server
server copied to clipboard
[Bug]: Deleting/Canceling an Instance of a Recurring Event Generates an Unhelpful iMIP Message
Bug description
Deleting/Canceling an Instance of a Recurring Event Generates an Unhelpful iMIP Message
Steps to reproduce
- Create an event and configure it to repeat weekly.
- Add Alice as an attendee.
- Select one instance of the recurring event and delete/cancel it.
- 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.
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 |
|---|---|