Skip to content

Commit c485687

Browse files
committed
IMAP: Fix SPECIAL-USE mailbox calculation.
The original algorithm to compute the SPECIAL-USE mailboxes was incorrect when multiple SPECIAL-USE mailboxes are present (e.g. multiple mailboxes in different namespaces), resulting in operations like "Delete", "Junk", etc. moving messages to the wrong folder. The logic has been amended to be more careful to ensure the right mailboxes are calculated.
1 parent 6b7bb2e commit c485687

File tree

3 files changed

+23
-3
lines changed

3 files changed

+23
-3
lines changed

evergreen.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,7 +2140,7 @@ static int process_option(struct config *config, const char *optname, const char
21402140
char *tmp;
21412141

21422142
if (phony_options) {
2143-
client_debug(5, "Processed option '%s'", optname);
2143+
client_debug(10, "Processed option '%s'", optname);
21442144
return 0;
21452145
}
21462146

@@ -2353,7 +2353,7 @@ static int load_config(struct config *restrict config, int argc, char *argv[])
23532353
process_option(config, long_options[option_index].name, optarg);
23542354
break;
23552355
default:
2356-
client_debug(5, "Processed option '%c'", c);
2356+
client_debug(10, "Processed option '%c'", c);
23572357
break;
23582358
}
23592359
}

imap.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,9 @@ static int ends_with(const char *s, const char *sub)
951951
static struct mailbox *find_specialuse_mailbox(struct client *client, int flag, const char *suffix)
952952
{
953953
int i;
954+
char parent[512], parent2[512];
955+
int has_parent_a, has_parent_b;
956+
size_t parentlen;
954957
struct mailbox *best = NULL;
955958
int max_common = 0, common;
956959
int found_specialuse = 0;
@@ -960,6 +963,9 @@ static struct mailbox *find_specialuse_mailbox(struct client *client, int flag,
960963
* but if there are multiple namespaces available to use, we may have
961964
* several Trash mailboxes, and we need to select the right one. */
962965

966+
has_parent_a = mkparent(client, parent, sizeof(parent), client->sel_mbox->name);
967+
parentlen = strlen(parent);
968+
963969
for (i = 0; i < client->num_mailboxes; i++) {
964970
if (!(client->mailboxes[i].flags & flag)) {
965971
continue;
@@ -972,8 +978,22 @@ static struct mailbox *find_specialuse_mailbox(struct client *client, int flag,
972978
* Other Users.jsmith.Sub.Folder
973979
* Other Users.jsmith.Trash is likely the correct trash mailbox,
974980
* not Trash, or anything else. */
981+
has_parent_b = mkparent(client, parent2, sizeof(parent2), client->mailboxes[i].name);
982+
if (has_parent_a != has_parent_b) {
983+
client_debug(5, "One has a parent and one doesn't: %s / %s, %d / %d\n", parent, parent2, has_parent_a, has_parent_b);
984+
continue;
985+
} else if (has_parent_a) {
986+
/* One parent must at least start with the other,
987+
* for example, Gmail's special use folders are in
988+
* subfolders of [Gmail]. */
989+
if (strncmp(parent, parent2, parentlen) && strncmp(parent, parent2, strlen(parent2))) {
990+
client_debug(5, "Different parents: %s != %s\n", parent, parent2);
991+
continue;
992+
}
993+
}
975994
common = num_common_prefix_chars(client->sel_mbox->name, client->mailboxes[i].name);
976995
if (common >= max_common) { /* >=, so even if 0 common prefix chars, Trash should override */
996+
client_debug(5, "%s is a better match than %s: %d", client->mailboxes[i].name, best ? best->name : "(empty)", common);
977997
best = &client->mailboxes[i];
978998
max_common = common;
979999
}

messages.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ void delete_message(struct client *client, struct message *msg)
152152
free_message(client, msg);
153153
}
154154

155-
/* XXX For messages like move, when called from viewer (as opposed to message list),
155+
/* XXX For operations like move,
156156
* the number of messages is changed after we return, which clears the status pane,
157157
* so the status update is essentially lost. */
158158
int handle_message_op(struct client *client, struct pollfd *pfds, struct message *msg, struct message_data *mdata, int c)

0 commit comments

Comments
 (0)