`CalendarEvent/set` fails to assign organizer and send scheduling messages

Issue Description

Creating a CalendarEvent through CalendarEvent/set with participants, but without an explicit organizerCalendarAddress, succeeds without Stalwart assigning an organizer address.

When sendSchedulingMessages: true is supplied, the create also succeeds, but no scheduling message is sent to the attendee.

This appears contrary to JMAP Calendars draft-26. When creating an event with participants, the server is required to set organizerCalendarAddress if the client did not supply one. After a successful create with sendSchedulingMessages: true, the server is also required to send the appropriate iTIP scheduling messages.

This reproduces even when the client supplies an explicit accepted owner participant corresponding to the creating account.

Source inspection suggests the failure occurs in crates/jmap/src/calendar_event/set.rs.

The create path converts the submitted JSCalendar event to iCalendar without first assigning an organizer. It then calls itip_create().

itip_create() calls itip_snapshot(), which returns ItipError::NoSchedulingInfo when the generated iCalendar object has no ORGANIZER.

CalendarEvent/set only converts errors for which ItipError::is_jmap_error() is true into a SetError. NoSchedulingInfo is not classified as such, so the scheduling failure appears to be ignored and the event is successfully stored without any scheduling messages being queued.

Expected Behavior

For a CalendarEvent/set create containing participants but no organizerCalendarAddress, Stalwart should assign an appropriate organizer address.

Draft-26 requires:

When creating an event with participants, or adding participants to an event that previously did not have participants, the server MUST set the “organizerCalendarAddress” property of the event if not present.

With sendSchedulingMessages: true, Stalwart should also send the appropriate iTIP scheduling message after successful creation.

For an origin event creation, this should be a REQUEST to the event participants other than any participant corresponding to the calendar owner.

Actual Behavior

CalendarEvent/set reports the event as successfully created.

The stored event contains:

  • an accepted owner participant corresponding to the creating account;
  • a separate attendee with participationStatus: "needs-action";
  • isOrigin: true.

However, organizerCalendarAddress remains absent/null.

No scheduling result appears on the attendee account:

  • no same-UID CalendarEvent is created;
  • no new CalendarEventNotification is created.

The same organizer-assignment failure also reproduces if the client does not supply an owner participant.

Source inspection indicates that the missing organizer causes the generated iCalendar object to have no ORGANIZER. itip_create() consequently returns ItipError::NoSchedulingInfo, which is not surfaced as a SetError and is instead silently ignored.

Reproduction Steps

  1. Have two local accounts, for example:

  2. Create a future event in [email protected] using CalendarEvent/set.

  3. Include an explicit owner participant and a separate attendee, for example:

"participants": {
  "owner": {
    "@type": "Participant",
    "calendarAddress": "mailto:[email protected]",
    "roles": {
      "owner": true,
      "attendee": true
    },
    "participationStatus": "accepted",
    "expectReply": false
  },
  "attendee1": {
    "@type": "Participant",
    "calendarAddress": "mailto:[email protected]",
    "roles": {
      "attendee": true
    },
    "participationStatus": "needs-action",
    "expectReply": true
  }
}
  1. Do not supply organizerCalendarAddress.

  2. Set:

"sendSchedulingMessages": true
  1. Observe that CalendarEvent/set reports the event as successfully created.

  2. Fetch the created event with CalendarEvent/get.

  3. Observe that:

    • the owner participant is present;
    • the attendee is present;
    • isOrigin is true;
    • organizerCalendarAddress is still absent/null.
  4. Query [email protected] for:

    • a CalendarEvent with the same UID;
    • new CalendarEventNotification objects.
  5. Observe that neither a scheduled event nor a scheduling notification was created.

Relevant Log Output

No relevant error is returned from the successful CalendarEvent/set request.

Source inspection indicates that the internal scheduling attempt returns ItipError::NoSchedulingInfo because the generated iCalendar object has no ORGANIZER. This error is not treated as a JMAP SetError and the create therefore succeeds without scheduling.

Stalwart Version

v0.16.x

Installation Method

Docker

Database Backend

RocksDB

Blob Storage

RocksDB

Search Engine

Internal

Directory Backend

Internal

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

This confirms the report’s technical analysis precisely matches the current source. I have enough to give a grounded, accurate confirmation reply.

Your source analysis is accurate. Looking at the current code:

  • CalendarEvent/set builds the iCalendar object from the submitted JSCalendar without inserting an ORGANIZER property when organizerCalendarAddress isn’t supplied by the client (crates/jmap/src/calendar_event/set.rs, create path).
  • itip_create() calls itip_snapshot(), which explicitly checks for a component with an ORGANIZER property and returns ItipError::NoSchedulingInfo if none is found (crates/groupware/src/scheduling/snapshot.rs).
  • ItipError::is_jmap_error() in crates/groupware/src/scheduling/mod.rs does not include NoSchedulingInfo in its match arms, so the create path’s Err(err) => { if err.is_jmap_error() { ... } } branch falls through silently, leaving the event stored with no organizer and no scheduling messages queued.

So this is a confirmed gap: the server never auto-assigns organizerCalendarAddress from the owner participant (or account identity) before generating the iCalendar object, and the resulting NoSchedulingInfo error is swallowed rather than surfaced or acted upon. This does look like it deviates from the JMAP Calendars draft requirement you cited.

I’ve laid out the exact code paths involved so a staff engineer can pick this up directly; a human will follow up on a fix.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Fixed in v0.16.18 (yet to be released).