Skip to content

Exchange/Outlook strips ORGANIZER from iMIP replies, causing CalendarImpl.php to discard all incoming acceptances #58904

@khnjrdm

Description

@khnjrdm

Hi Everyone,

Running Nextcloud 32.0.6 (Hub 25 Autumn) with Mail app 5.7.1, and have fully confirmed a bug where meeting acceptances from Exchange/Outlook 365 attendees are silently discarded — leaving PARTSTAT permanently stuck at NEEDS-ACTION regardless of how many times IMipMessageJob runs.

The setup is straightforward: a Nextcloud user creates and sends a calendar invite via the Nextcloud web UI. The external Outlook 365 attendee receives it, accepts it through their native Outlook client, and the acceptance email arrives correctly in the inbox. Everything looks fine — until you realise the CalDAV event never updates.

The cause is a two-party problem. Nextcloud generates a fully RFC 5546-compliant invite, including both ORGANIZER and ATTENDEE fields. Exchange/Outlook 365 however strips the ORGANIZER property entirely when generating its METHOD:REPLY, returning only the ATTENDEE field. This is a direct violation of RFC 5546 §3.2.3, which requires ORGANIZER to be present in all reply payloads. Microsoft has behaved this way for years across both Exchange on-premise and Exchange Online, and there is no indication this will change on their end.

When IMipMessageJob processes the incoming reply, it hits the validation check in CalendarImpl.php:291 which looks for an attendee in the inbound payload matching the current user. Since the Nextcloud user is the organiser — not an attendee — and Exchange stripped the ORGANIZER field, the check fails, throws a CalendarException, and the message is discarded before any UID lookup or PARTSTAT update is ever attempted.

This is not a configuration issue. The Mail app IMAP integration works, the background job fires on schedule, and the CalDAV store is healthy. The pipeline fails at a single validation check that is simply too strict about data Microsoft refuses to provide.

I’m aware of issue #50665 and the fix landed in #54819 (backported to stable32 as #55763, present since 32.0.1). However that fix addresses a Nextcloud user accepting an Outlook-originated invite. This is the opposite direction — an Outlook user accepting a Nextcloud-originated invite — and it remains broken on 32.0.6.

The fix is relatively contained: when processing a METHOD:REPLY, ownership verification should fall back to the existing CalDAV event looked up by UID, rather than relying solely on the inbound payload — which Exchange will never populate correctly. A proposed change is included in the linked GitHub issue.

Given that Exchange/Outlook 365 is the dominant enterprise mail platform, this effectively means iMIP reply processing is broken for the majority of real-world mixed-environment deployments. Would appreciate confirmation from maintainers on whether this specific scenario is tracked and whether a fix is planned for the stable32 branch.

Suggested fix
When processing METHOD:REPLY, ownership should be verified against the existing CalDAV event by UID — not against the inbound payload alone, since Exchange will never carry ORGANIZER forward. Oh, and the typo isn’t mine 🙂

// CURRENT — breaks on all Exchange replies:
if (!$this->attendeeMatchesUser($vEvent, $userEmail)) {
throw new CalendarException(
“iMip message dose not contain an attendee that matches the user”
);
}

// PROPOSED — RFC-tolerant, falls back to CalDAV store lookup:
$existingEvent = $this->findEventByUID($vEvent->UID, $userEmail);
$isOrganizer   = $existingEvent && $this->organizerMatchesUser($existingEvent, $userEmail);
$isAttendee    = $this->attendeeMatchesUser($vEvent, $userEmail);

if (!$isOrganizer && !$isAttendee) {
throw new CalendarException(
“iMip message does not match any calendar owned by the user”
);
}

Kind Regards,

Kim @ njordium.com

Metadata

Metadata

Assignees

No one assigned

    Labels

    0. Needs triagePending check for reproducibility or if it fits our roadmapenhancementfeature: caldavRelated to CalDAV internals

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions