Repeating an identical cross-account Email/copy creates a duplicate Email in Stalwart. This is unsafe when retrying after a lost response: the first copy may have succeeded, but retrying creates another.
Expected Behavior
Return alreadyExists with the first copy’s existingId, as permitted by RFC 8621 §4.7.
Cyrus explicitly implements and tests this behavior:
Actual Behavior
Repeating the same Email/copy creates another destination Email with a new ID.
Reproduction Steps
Create source and destination accounts and a destination mailbox.
Copy one Email between the accounts using Email/copy.
Repeat the same Email/copy in a new request.
Query the destination account and observe two copied Emails.
Relevant Log Output
No server error is emitted. Both requests return a successful created response with different Email IDs.
Stalwart Version
v0.16.x
Installation Method
Docker
Database Backend
PostgreSQL
Blob Storage
S3-compatible
Search Engine
PostgreSQL
Directory Backend
OIDC
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.
Confirmed by inspecting the current Email/copy implementation: it does not perform any dedup or idempotency check before copying. The copy_message function in crates/email/src/message/copy.rs only returns CopyMessageError::NotFound or CopyMessageError::OverQuota as failure conditions, there is no lookup for an existing copy with the same source message and no alreadyExistsSetError returned anywhere in the copy path (crates/jmap/src/email/copy.rs). Each successful Email/copy call unconditionally ingests a new message and returns a new id, so a retried request will indeed create a duplicate rather than returning the id of the previously created copy.
This matches your reproduction: the behavior you’re describing is accurate for the current codebase, and there’s no existing mechanism implementing the RFC 8621 §4.7 alreadyExists semantics for Email/copy. This is a genuine gap versus the spec’s recommended idempotency handling, not something covered/handled in current docs.
This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.