nextcloud / nextcloud/server

PARTSTAT change on a single occurrence of a recurring event triggers METHOD:REQUEST re-invite to all other attendees

Open
#60,452 0 comments 0 reactions 1 assignee View on GitHub

@DerDreschner is already working on this.

Since Aug 17, 2026.

2. developing 33-feedback bug feature: caldav
Dominant language
PHP
Stars
36.9k
Forks
5.2k
Avg merge
2d 3h
Merged PRs (30d)
713

Description

Bug description

When an attendee accepts or declines a single occurrence of a recurring event, a recurrence exception (VEVENT with RECURRENCE-ID) is created. This modification to the calendar object causes Nextcloud to send a METHOD:REQUEST email to all other attendees, even though nothing changed for them.

This does not happen for single (non-recurring) events, where a PARTSTAT change correctly results in only a METHOD:REPLY to the organizer.

Related: nextcloud/calendar#6535 (notification spam), nextcloud/calendar#7771 (accept creates recurrence exception instead of updating master PARTSTAT), nextcloud/calendar#7850 (recurring event exception handling), #60451 (iMIP mail body issues for recurring events).

Setup:

  • Calendar app: 6.4.0
  • dav: 1.36.0
  • All users on the same instance, invited via the internal user picker (principal-based scheduling).
  • Attendees use Thunderbird 128.x via CalDAV.

Scenario 1: Attendee declines a single occurrence

User A creates a weekly recurring event "Weekly 3x" (3 occurrences), adds User B and User C as attendees. Both accept the series via Thunderbird. User B then declines only the 2026-05-12 occurrence via Thunderbird.

User A (organizer) receives a correct METHOD:REPLY with RECURRENCE-ID for 2026-05-12 and PARTSTAT=DECLINED. The mail says "User B has declined your invitation" with the correct date. This is correct.

User C (other attendee) receives a METHOD:REQUEST re-invite for the entire series:

METHOD:REQUEST
 
BEGIN:VEVENT
UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
DTSTART;TZID=Europe/Berlin:20260505T113000
RRULE:FREQ=WEEKLY;COUNT=3;BYDAY=TU
SUMMARY:Weekly 3x
ATTENDEE;PARTSTAT=ACCEPTED:mailto:user-b@example.com
ATTENDEE;PARTSTAT=ACCEPTED:mailto:user-c@example.com
ORGANIZER;CN=admin:mailto:user-a@example.com
END:VEVENT
BEGIN:VEVENT
UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
DTSTART;TZID=Europe/Berlin:20260512T113000
RECURRENCE-ID;TZID=Europe/Berlin:20260512T113000
ATTENDEE;PARTSTAT=DECLINED:mailto:user-b@example.com
ATTENDEE;PARTSTAT=ACCEPTED:mailto:user-c@example.com
ORGANIZER;CN=admin:mailto:user-a@example.com
END:VEVENT

Thunderbird at User C: "admin has invited you to Weekly 3x"
Nextcloud mail body: "admin möchte dich zu 'Weekly 3x' einladen."

User C already accepted. Nothing changed for User C. This email provides no useful information.

Scenario 2: Attendee accepts a single occurrence

User A creates a daily recurring event, adds User B and User C. User C accepts a single occurrence via the Nextcloud Calendar web UI (which creates a recurrence exception due to nextcloud/calendar#7771).

Result: User B receives a METHOD:REQUEST re-invite. The mail says "admin would like to invite you to 'Daily Test'" with the date of the first occurrence (in the past).

Scenario 3: Attendee removes event from calendar

Same setup. User C deletes the event in Thunderbird.

Result: User B again receives a METHOD:REQUEST re-invite.

Control test: Accepting the entire series

User A creates a weekly recurring event, adds User B and User C. User B accepts the entire series via Thunderbird iMIP ("Accept all").

Result: User C does not receive any email. Only User A receives the METHOD:REPLY. This is the correct behavior.

Control test: Single (non-recurring) event

User A creates a single event, adds User B and User C. User B accepts via Thunderbird.

Result: User C does not receive any email. Only User A receives the METHOD:REPLY. This is the correct behavior.

Pattern:

Scenario Other attendees receive re-invite? Correct?
Single event: attendee accepts No Yes
Series: attendee accepts entire series No Yes
Series: attendee accepts single instance Yes No
Series: attendee declines single instance Yes No
Series: attendee deletes event Yes No

The re-invite is only triggered when the PARTSTAT change creates a recurrence exception (VEVENT with RECURRENCE-ID). Operations that do not create exceptions behave correctly.

Steps to reproduce
  1. User A creates a weekly recurring event in the Nextcloud Calendar web UI (e.g. 3 occurrences), adds User B and User C as attendees via the user picker.
  2. User B accepts the entire series via Thunderbird iMIP.
  3. User C accepts the entire series via Thunderbird iMIP.
  4. User B declines a single occurrence via Thunderbird.
  5. User C receives a METHOD:REQUEST re-invite email for the entire series.
Expected behavior

A PARTSTAT change by one attendee should only generate a METHOD:REPLY to the organizer. Other attendees should not receive any email, regardless of whether the change creates a recurrence exception internally.

With N attendees, every accept/decline on a single instance currently generates up to N-1 unnecessary emails. On an instance with ~600 users, this creates significant email noise.

Nextcloud Server version

33

Operating system

Debian/Ubuntu

PHP engine version

PHP 8.3

Web server

Apache (supported)

Database engine version

MySQL

Is this bug present after an update or on a fresh install?

Upgraded to a MAJOR version (ex. 31 to 32)

Are you using the Nextcloud Server Encryption module?

Encryption is Disabled

What user-backends are you using?
  • Default user-backend (database)
  • LDAP/ Active Directory
  • SSO - SAML
  • Other
Configuration report
{
    "system": {
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "***REMOVED SENSITIVE VALUE***",
            "***REMOVED SENSITIVE VALUE***",
            "***REMOVED SENSITIVE VALUE***"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "dbtype": "mysql",
        "version": "33.0.3.2",
        "overwrite.cli.url": "***REMOVED SENSITIVE VALUE***",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbport": "",
        "dbtableprefix": "oc_",
        "mysql.utf8mb4": true,
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "installed": true,
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "htaccess.RewriteBase": "\/",
        "maintenance_window_start": 1,
        "maintenance": false,
        "default_phone_region": "de",
        "mail_smtpmode": "smtp",
        "mail_smtpsecure": "ssl",
        "mail_sendmailmode": "smtp",
        "mail_from_address": "***REMOVED SENSITIVE VALUE***",
        "mail_domain": "***REMOVED SENSITIVE VALUE***",
        "mail_smtphost": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpauth": 1,
        "mail_smtpname": "***REMOVED SENSITIVE VALUE***",
        "mail_smtppassword": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpport": "465",
        "theme": "",
        "loglevel": 2,
        "config_preset": 9,
        "app_install_overwrite": [
            "fairmeeting",
            "jitsi",
            "bbb"
        ],
        "memcache.local": "\\OC\\Memcache\\APCu"
    }
}
List of activated Apps
Enabled:
  - activity: 6.0.0
  - app_api: 33.0.0
  - bruteforcesettings: 6.0.0
  - calendar: 6.4.0
  - circles: 33.0.0
  - cloud_federation_api: 1.17.0
  - comments: 1.23.0
  - contacts: 8.4.5
  - contactsinteraction: 1.14.1
  - dashboard: 7.13.0
  - dav: 1.36.0
  - federatedfilesharing: 1.23.0
  - federation: 1.23.0
  - files: 2.5.0
  - files_downloadlimit: 5.1.0
  - files_pdfviewer: 6.0.0
  - files_reminders: 1.6.0
  - files_sharing: 1.25.2
  - files_trashbin: 1.23.0
  - files_versions: 1.26.0
  - firstrunwizard: 6.0.0
  - guests: 4.7.2
  - logreader: 6.0.0
  - lookup_server_connector: 1.21.0
  - mail: 5.7.15
  - nextcloud_announcements: 5.0.0
  - notifications: 6.0.0
  - oauth2: 1.21.0
  - password_policy: 5.0.0
  - photos: 6.0.0
  - privacy: 5.0.0
  - profile: 1.2.0
  - provisioning_api: 1.23.0
  - recommendations: 6.0.0
  - related_resources: 4.0.0
  - richdocuments: 10.1.3
  - serverinfo: 5.0.0
  - settings: 1.16.0
  - sharebymail: 1.23.0
  - support: 5.0.0
  - survey_client: 5.0.0
  - text: 7.0.1
  - theming: 2.8.0
  - twofactor_backupcodes: 1.22.0
  - twofactor_totp: 15.0.0
  - updatenotification: 1.23.0
  - user_status: 1.13.0
  - viewer: 6.0.0
  - weather_status: 1.13.0
  - webhook_listeners: 1.5.0
  - whiteboard: 1.5.8
  - workflowengine: 2.15.0
Disabled:
  - admin_audit: 1.23.0
  - bbb: 2.9.1 (installed 2.9.1)
  - calendar_resource_management: 0.12.1 (installed 0.12.1)
  - collectives: 4.4.0 (installed 4.4.0)
  - deck: 1.17.1 (installed 1.17.1)
  - encryption: 2.21.0
  - fairmeeting: 0.22.5 (installed 0.22.5)
  - files_external: 1.25.1
  - integration_mattermost: 3.1.0 (installed 3.1.0)
  - jitsi: 0.19.0 (installed 0.19.0)
  - richdocumentscode: 25.4.904 (installed 25.4.904)
  - riotchat: 0.20.0 (installed 0.20.0)
  - spreed: 23.0.4 (installed 23.0.4)
  - suspicious_login: 11.0.0
  - systemtags: 1.23.0 (installed 1.22.0)
  - tables: 2.1.1 (installed 2.1.1)
  - testing: 1.23.0
  - twofactor_nextcloud_notification: 7.0.0
  - user_ldap: 1.24.0
Nextcloud Signing status
No errors have been found.
Nextcloud Logs
 
Additional info

This is a test instance used for app development. The bug was reproduced using only the Calendar web UI and Thunderbird iMIP. No third-party apps are involved in the iMIP/iTIP code path.

Related issues:

  • #60451 (iMIP mail body does not show which occurrence was affected)
  • nextcloud/calendar#6535 (need a setting to disable notifications)
  • nextcloud/calendar#7771 (accept creates recurrence exception instead of updating master PARTSTAT)
  • nextcloud/calendar#7850 (recurring event exception handling)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.