Skip to content

Commit

Permalink
net_imap: Fix incorrect sequence numbers in untagged EXPUNGE.
Browse files Browse the repository at this point in the history
Fix the wrong sequence numbers being used in untagged
EXPUNGE replies created by the MOVE command. Originally,
it was using the same sequence numbers provided to the
command, but this is wrong since sequence numbers decrement
implicitly when a message is expunged, and would cause
some MUAs to behave erratically since they were misled
about what messages were expunged from the mailbox.

Correct this by adjusting bookkeeping during the MOVE traversal
to ensure the correct sequence numbers go out in the EXPUNGE reply.
  • Loading branch information
InterLinked1 committed Feb 19, 2024
1 parent 317a17c commit 8d3f6cf
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions nets/net_imap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2093,6 +2093,7 @@ static int handle_move(struct imap_session *imap, const char *sequences, const c
char newboxdir[256];
char srcfile[516];
int files, fno = 0;
unsigned int expunge_seqno = 0;
int seqno = 0;
unsigned int *olduids = NULL, *newuids = NULL, *expunged = NULL, *expungedseqs = NULL;
int lengths = 0, allocsizes = 0;
Expand Down Expand Up @@ -2129,7 +2130,9 @@ static int handle_move(struct imap_session *imap, const char *sequences, const c
if (entry->d_type != DT_REG || !strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
goto cleanup;
}
msguid = imap_msg_in_range(imap, ++seqno, entry->d_name, sequences, usinguid, &error);
++seqno;
++expunge_seqno;
msguid = imap_msg_in_range(imap, seqno, entry->d_name, sequences, usinguid, &error);
if (!msguid) {
goto cleanup;
}
Expand All @@ -2147,8 +2150,22 @@ static int handle_move(struct imap_session *imap, const char *sequences, const c
* RFC 6851 3.3
* We still store UIDs so we can call maildir_indicate_expunged with a batch of all UIDs, for efficiency.
*/
uintlist_append2(&expunged, &expungedseqs, &exp_lengths, &exp_allocsizes, msguid, (unsigned int) seqno); /* store UID and seqno */

uintlist_append2(&expunged, &expungedseqs, &exp_lengths, &exp_allocsizes, msguid, expunge_seqno); /* store UID and seqno */

/* When a mail user agent (MUA) deletes messages from a folder by issuing a MOVE,
* untagged EXPUNGEs will go out to inform clients of this.
* However, since EXPUNGE decrements the sequence number of all messages in a mailbox,
* we need to decrement the sequence number used for the EXPUNGE reply every time we move a message.
* We do the same thing in handle_expunge.
*
* Failing to do so will manifest itself as UI weirdness where clients will hide certain messages
* that were not expunged after such an operation, only to show them again later when the folder
* is navigated to again.
*
* We use a separate seqno variable for this, since we want to use the original seqno for checking
* if it's in range or not, but include the updated one for the EXPUNGE response. */
expunge_seqno--;

cleanup:
free(entry);
}
Expand Down

0 comments on commit 8d3f6cf

Please sign in to comment.