diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-19 11:10:51 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-19 11:10:51 +0200 |
| commit | 41d0b94dcd2b4208e5d3e7483c88ce9b664ce565 (patch) | |
| tree | 61aceb2bd653d4c0df463955cc610942f928f46e /src/messagedetailsdialog.cpp | |
| parent | a36fff5617f16ac1d17c0c52f2112a20c4fa9336 (diff) | |
| download | qtmaildir-41d0b94dcd2b4208e5d3e7483c88ce9b664ce565.tar.gz qtmaildir-41d0b94dcd2b4208e5d3e7483c88ce9b664ce565.zip | |
fix(worker): give a moved message a fresh maildir name
mbsync's manual, under "the more efficient default UID mapping scheme": "it is
important that the MUA renames files when moving them between Maildir folders",
and "the general expectation is that a completely new filename is generated as
if the message was new".
qtmaildir is that MUA and did not rename. moveMessages() kept
QFileInfo(from).fileName() verbatim, `,U=<n>` included. That infix is mbsync's
per-folder IMAP UID, so carrying it across a folder boundary makes it a claim
about a folder the file is no longer in; moving a message out and back then
reinserts a UID the server has since reassigned. Reported by the user as
`Maildir error: duplicate UID 1`, and measured on the real Maildir: four
collisions in one folder, eight distinct messages, none lost.
freshMaildirName() regenerates the unique part and keeps ONLY the `:2,<flags>`
suffix. Keeping the flags is not a contradiction of "as if the message was new":
they record seen, flagged and replied, and maildir.synchronize_flags is true, so
dropping them would mark every deleted message unread and lose Important on the
way to the trash.
Two things fell out of the change and both were defects waiting to happen. The
already-in-the-destination guard compared full PATHS, which worked only because
the name was carried across; with a fresh name it can never be true, so a
message already in the destination would be renamed on every move. It compares
directories now. And test_mainwindow's folderHasMessageFile() matched on the
filename stem, so all fifty-odd assertions using it began reporting "the file is
not there" about files that were there. It reads the Message-ID out of each file
instead, which is what those assertions always meant.
Three mutations fail: the old name carried across, the flags dropped, and the
uniqueness counter frozen so two messages moved in one batch collide.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/messagedetailsdialog.cpp')
0 files changed, 0 insertions, 0 deletions
