Issue Description
We created calendar events from one internal account to another internal account using JMAP Calendars. The organizer account had a valid default ParticipantIdentity,
global scheduling was enabled, and we explicitly tested several event payload variants, including:
- a normal event with attendees
- an event with attendee sendTo.imip
- an event with sendSchedulingMessages: true
- an event with both sendSchedulingMessages: true and explicit replyTo.imip
In every case, the event was created successfully in the organizer’s calendar, but no invitation was generated or delivered:
- no CalendarEvent appeared in the invitee account
- no CalendarEventNotification appeared in the invitee account
- no email invitation appeared in the invitee mailboxes
- no background CalendarItipMessage task appeared in the task queue
- no outbound queued message appeared
This does not look like a simple autoAddInvitations issue, because even when automatic calendar insertion is disabled, we would still expect scheduling/invitation
processing to happen when explicitly requested.
Expected Behavior
Expected behavior:
-
When an event is created via CalendarEvent/set with attendees and sendSchedulingMessages: true, Stalwart should generate the appropriate scheduling workflow for
those attendees. -
For an internal attendee, this should result in either:
-
a scheduling notification/invitation being available to the recipient account, or
-
delivery through the supported scheduling path configured by Stalwart.
-
At minimum, we would expect server-side evidence that scheduling was triggered, such as a CalendarItipMessage task or an outbound queued message if iMIP is used.
Relevant docs/spec references:
- Stalwart Scheduling docs: Scheduling | Stalwart
- Stalwart CalendarScheduling object: CalendarScheduling | Stalwart
- JMAP Calendars spec: https://jmap.io/spec-calendars.html
The JMAP Calendars spec says CalendarEvent/set supports sendSchedulingMessages, and when this is true, the server must send the appropriate scheduling messages.
Actual Behavior
Actual behavior:
- CalendarEvent/set succeeds and stores the event in the organizer’s calendar.
- The attendee remains only as a participant on the organizer-side object.
- Nothing is created or delivered on the recipient side.
Specifically:
- recipient CalendarEvent/query returns no events
- recipient CalendarEventNotification/query returns no notifications
- recipient Email/query shows no invitation email
- admin x:Task/query shows no CalendarItipMessage
- admin x:QueuedMessage/query shows no outbound queued invitation message
So the deviation is that scheduling appears not to start at all, even when explicitly requested.
Reproduction Steps
-
Ensure Stalwart JMAP is reachable and calendars are enabled.
-
Verify admin configuration:
- x:CalendarScheduling/get returns:
- enable: true
- httpRsvpEnable: true
- autoAddInvitations: false
- x:CalendarScheduling/get returns:
-
Verify the organizer account has a default participant identity:
- ParticipantIdentity/get returns a default identity such as mailto:[email protected]
-
Create an event from organizer to invitee using CalendarEvent/set with:
- organizer participant
- internal attendee participant
- sendTo.imip on the attendee
- sendSchedulingMessages: true
-
Observe that the event is created successfully in the organizer account.
-
Query the invitee account:
- CalendarEvent/query
- CalendarEventNotification/query
- Email/query
-
Query admin endpoints:
- x:Task/query
- x:QueuedMessage/query
-
Observe that no scheduling artifact is produced anywhere.
Example JMAP request used for reproduction:
{
"using": [
"urn:ietf:params:jmap:core",
"urn:ietf:params:jmap:calendars"
],
"methodCalls": [
[
"CalendarEvent/set",
{
"accountId": "ORGANIZER_ACCOUNT_ID",
"sendSchedulingMessages": true,
"create": {
"test1": {
"@type": "Event",
"title": "Scheduling reproduction test",
"description": "<p>Test event</p>",
"start": "2026-06-07T12:00:00",
"duration": "PT30M",
"timeZone": "Africa/Djibouti",
"showWithoutTime": false,
"status": "confirmed",
"freeBusyStatus": "busy",
"privacy": "public",
"calendarIds": {
"DEFAULT_CALENDAR_ID": true
},
"participants": {
"p1": {
"@type": "Participant",
"calendarAddress": "mailto:[email protected]",
"name": "User One",
"roles": {
"owner": true,
"attendee": true
},
"participationStatus": "accepted",
"expectReply": false,
"kind": "individual"
},
"p2": {
"@type": "Participant",
"calendarAddress": "mailto:[email protected]",
"name": "User Two",
"roles": {
"attendee": true
},
"participationStatus": "needs-action",
"expectReply": true,
"kind": "individual",
"sendTo": {
"imip": "mailto:[email protected]"
}
}
}
}
}
},
"c1"
]
]
}
Observed response:
{
"methodResponses": [
[
"CalendarEvent/set",
{
"accountId": "ORGANIZER_ACCOUNT_ID",
"newState": "…",
"created": {
"test1": {
"id": "EVENT_ID"
}
}
},
"c1"
]
],
"sessionState": "…"
}
Then:
- invitee CalendarEvent/query returns ids:
- invitee CalendarEventNotification/query returns ids:
- invitee Email/query shows no invitation
- admin x:QueuedMessage/query returns ids:
- admin x:Task/query does not contain any CalendarItipMessage
Relevant Log Output
No relevant logs were collected yet.
What we did verify through JMAP:
x:CalendarScheduling/get:
- enable = true
- httpRsvpEnable = true
- autoAddInvitations = false
ParticipantIdentity/get on organizer:
- default participant identity exists
Recipient-side checks after event creation:
- CalendarEvent/query =>
- CalendarEventNotification/query =>
- Email/query => no invitation message found
Admin-side checks:
- x:Task/query => no CalendarItipMessage task
- x:QueuedMessage/query => no queued outbound message
Stalwart Version
v0.16.x
Installation Method
Binary (Linux)
Database Backend
PostgreSQL
Blob Storage
PostgreSQL
Search Engine
Meilisearch
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