Skip to content

Commit f4c471a

Browse files
fix: iMip reply from outlook.com does not contain organizer property
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com> [skip ci]
1 parent c7f8afb commit f4c471a

File tree

2 files changed

+89
-5
lines changed

2 files changed

+89
-5
lines changed

lib/private/Calendar/Manager.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,13 @@ protected function handleIMip(
258258
}
259259

260260
if (!isset($vEvent->ORGANIZER)) {
261-
$this->logger->warning('iMip message event dose not contains an organizer');
262-
return false;
261+
// quirks mode: for Microsoft Exchange Servers use recipient as organizer if no organizer is set
262+
if (isset($options['recipient']) && $options['recipient'] !== '') {
263+
$vEvent->add('ORGANIZER', 'mailto:' . $options['recipient']);
264+
} else {
265+
$this->logger->warning('iMip message event does not contain an organizer and no recipient was provided');
266+
return false;
267+
}
263268
}
264269

265270
if (!isset($vEvent->ATTENDEE)) {
@@ -308,7 +313,8 @@ public function handleIMipRequest(
308313
return false;
309314
}
310315
$userId = substr($principalUri, 17);
311-
return $this->handleIMip($userId, $calendarData);
316+
$options = ['recipient' => $recipient];
317+
return $this->handleIMip($userId, $calendarData, $options);
312318
}
313319

314320
/**
@@ -327,7 +333,8 @@ public function handleIMipReply(
327333
return false;
328334
}
329335
$userId = substr($principalUri, 17);
330-
return $this->handleIMip($userId, $calendarData);
336+
$options = ['recipient' => $recipient];
337+
return $this->handleIMip($userId, $calendarData, $options);
331338
}
332339

333340
/**
@@ -347,7 +354,8 @@ public function handleIMipCancel(
347354
return false;
348355
}
349356
$userId = substr($principalUri, 17);
350-
return $this->handleIMip($userId, $calendarData);
357+
$options = ['recipient' => $recipient];
358+
return $this->handleIMip($userId, $calendarData, $options);
351359
}
352360

353361
public function createEventBuilder(): ICalendarEventBuilder {

tests/lib/Calendar/ManagerTest.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,82 @@ public function testHandleImipWithNoEvent(): void {
382382
$this->assertFalse($result);
383383
}
384384

385+
public function testHandleImipMissingOrganizerWithRecipient(): void {
386+
// construct mock user calendar
387+
$userCalendar = $this->createMock(ITestCalendar::class);
388+
$userCalendar->expects(self::once())
389+
->method('isDeleted')
390+
->willReturn(false);
391+
$userCalendar->expects(self::once())
392+
->method('isWritable')
393+
->willReturn(true);
394+
$userCalendar->expects(self::once())
395+
->method('search')
396+
->willReturn([['uri' => 'principals/user/attendee1/personal']]);
397+
// construct mock calendar manager and returns
398+
/** @var Manager&MockObject $manager */
399+
$manager = $this->getMockBuilder(Manager::class)
400+
->setConstructorArgs([
401+
$this->coordinator,
402+
$this->container,
403+
$this->logger,
404+
$this->time,
405+
$this->secureRandom,
406+
$this->userManager,
407+
$this->serverFactory,
408+
$this->propertyMapper,
409+
])
410+
->onlyMethods(['getCalendarsForPrincipal'])
411+
->getMock();
412+
$manager->expects(self::once())
413+
->method('getCalendarsForPrincipal')
414+
->willReturn([$userCalendar]);
415+
// construct parameters
416+
$userId = 'attendee1';
417+
$calendar = $this->vCalendar1a;
418+
$calendar->add('METHOD', 'REQUEST');
419+
$calendar->VEVENT->remove('ORGANIZER');
420+
// construct user calendar returns
421+
$userCalendar->expects(self::once())
422+
->method('handleIMipMessage');
423+
// test method
424+
$result = $manager->handleIMip($userId, $calendar->serialize(), ['recipient' => 'organizer@testing.com']);
425+
}
426+
427+
public function testHandleImipMissingOrganizerNoRecipient(): void {
428+
// construct mock user calendar
429+
$userCalendar = $this->createMock(ITestCalendar::class);
430+
// construct mock calendar manager and returns
431+
/** @var Manager&MockObject $manager */
432+
$manager = $this->getMockBuilder(Manager::class)
433+
->setConstructorArgs([
434+
$this->coordinator,
435+
$this->container,
436+
$this->logger,
437+
$this->time,
438+
$this->secureRandom,
439+
$this->userManager,
440+
$this->serverFactory,
441+
$this->propertyMapper,
442+
])
443+
->onlyMethods(['getCalendarsForPrincipal'])
444+
->getMock();
445+
$manager->expects(self::once())
446+
->method('getCalendarsForPrincipal')
447+
->willReturn([$userCalendar]);
448+
// construct parameters
449+
$userId = 'attendee1';
450+
$calendar = $this->vCalendar1a;
451+
$calendar->add('METHOD', 'REQUEST');
452+
$calendar->VEVENT->remove('ORGANIZER');
453+
// Logger expects warning
454+
$this->logger->expects($this->once())
455+
->method('warning')
456+
->with('iMip message event does not contain an organizer and no recipient was provided');
457+
458+
$result = $manager->handleIMip($userId, $calendar->serialize(), []);
459+
}
460+
385461
public function testHandleImipWithNoUid(): void {
386462
// construct mock user calendar
387463
$userCalendar = $this->createMock(ITestCalendar::class);

0 commit comments

Comments
 (0)