fix(dav): send reply email to organizer when attendee responds via invitation link#61213
fix(dav): send reply email to organizer when attendee responds via invitation link#61213ndo84bw wants to merge 1 commit into
Conversation
|
Thank you for your contribution! If you are using AI, please follow our AI Policy. E.g.:
Seeing only a wall of text generated by an LLM often means that the author did not really look at the generated code and shifts all work to the reviewers. This is not a good and fair approach, and cannot scale properly on open source projects. |
…vitation link Signed-off-by: Nico Donath <ndo84bw@gmx.de> Assisted-by: ClaudeCode:claude-opus-4-8 Assisted-by: ClaudeCode:claude-fable-5
5df8127 to
2cd1b8e
Compare
|
Hi @susnux Thanks for pointing out the new policies and the updated contribution guidelines. I've expanded the AI section in the PR body and updated the trailer. The patch intervenes in the workflow triggered by the link in the invitation email. The result is now an email sent to the organizer, just as it would be if the participant used the CalDAV client to respond. However, during my tests, I noticed that the patch does not resolve the issue where no email is sent to the organizer if the participant does not have an account on this NC instance. I’ve put this decision on the to-do list in the PR. A partial fix with the code as-is + a follow-up PR, or doing everything at once with a bigger PR and likely a longer review period. |
Summary
When an attendee responds to a calendar invitation via the Accept/Decline links in the invitation email (
/apps/dav/invitation/{accept,decline}/{token}), the attendee's participation status is updated on the organizer's event, but the organizer is never notified by email. Responding to the same invitation through the Calendar web UI or through a CalDAV client does notify the organizer. nextcloud/calendar#7636 reports this inconsistency.Root cause
The invitation links are handled by
InvitationResponseController, which delivers the reply through a dedicated minimal DAV server,InvitationResponseServer. Delivering the reply to the attendee's calendar already triggers sabre's scheduling cascade (Sabre\CalDAV\Schedule\Plugin::scheduleLocalDelivery()→processICalendarChange()→deliver()): a second iTip REPLY addressed to the organizer is generated and emitted as ascheduleevent. This is how the organizer's copy of the event gets updated today.Sending the email is the responsibility of
IMipPlugin, which listens on that samescheduleevent. On the regular DAV server it is registered (apps/dav/lib/Server.php), onInvitationResponseServerit is not. The event that would produce the organizer email fires with nobody listening.Fix
Register
IMipPluginon theInvitationResponseServer, but only inhandleITipMessage(), which is exclusively used by the invitation-link controller. It must not be registered unconditionally in the constructor: the same server class is also used byCalendarImpl(e.g. iMIP processing for the Mail app) and byICreateFromString::createFromStringMinimal(), whose API documentation explicitly guarantees "no iMIP plugin, no invitation emails". Registering the plugin globally would cause duplicate emails in those flows.With this change, responding via the email links produces the same organizer notification as responding via the Calendar web UI, generated by the same broker/IMip machinery.
Known limitation (intentionally out of scope)
Attendees that are not users on the instance (external attendees) still do not trigger an organizer email when they use the links. Their reply takes a different path: it is delivered directly into the organizer's calendar via
scheduleLocalDelivery()without ever passing through thescheduleevent, and the token-built REPLY object lacks the event data (DTSTART,SUMMARY) needed to render the email. Supporting that case requires enriching the reply from the stored event first, which is a considerably larger change. I would prefer to address it in a follow-up PR so this fix is not blocked by that discussion. Whether nextcloud/calendar#7636 can be closed with this PR alone or only together with the follow-up is up to the maintainers.TODO
Manual tests
Performed on a Nextcloud 33.0.3 instance with this change applied (
handleITipMessage()is identical on master and stable33). User A (organizer) and user B (attendee) are users on the instance, user C is an external attendee invited by email address only.Checklist
InvitationResponseServerTestasserts that the constructor does not register the iMIP plugin (thecreateFromStringMinimal()guarantee) and thathandleITipMessage()does.3. to review, feature component)stable32)AI (if applicable)