JMAP Event Source reports interval in ms instead of seconds

Issue Description

On a ping interval, the server sends { “interval”: 30000 } , which is 30 seconds in milliseconds, but the spec states seconds.

https://www.rfc-editor.org/rfc/rfc8620.html#section-7.3

Expected Behavior

{ “interval”: 30 }

Actual Behavior

{ “interval”: 30000 }

Relevant Log Output

On client:
4 (times) JMAP push: event “ping” data {“interval”: 30000}

Stalwart Version

v0.16.x

Installation Method

Docker

Database Backend

RocksDB

Blob Storage

RocksDB

Search Engine

Internal

Directory Backend

Internal

Additional Context

#spec-violation

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

Good catch. Let me verify the relevant source code to confirm this bug.

Found it. The bug is clearly visible in the source code at line 81 and 83 of event_source.rs.

The bug is confirmed in the source code. On line 81, the server computes interval = std::cmp::max(ping, 30) * 1000 (converting seconds to milliseconds for use with Duration::from_millis), but then on line 88 it embeds that same interval value – the milliseconds value – directly into the SSE payload string:

payload: Bytes::from(format!(
    "event: ping\ndata: {{\"interval\": {}}}\\n\\n",
    interval   // <-- this is already in ms (e.g. 30000), not seconds
)),

Per RFC 8620 §7.3, the interval field in the ping event must be in seconds. The fix is straightforward: the payload should serialize ping (the original seconds value, e.g. 30) rather than interval (the derived milliseconds value, e.g. 30000). This is a clear spec violation in the server source at crates/jmap/src/api/event_source.rs.

This is a confirmed bug. A human maintainer will follow up with 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.