Skip to content

Commit 24f28cb

Browse files
committed
mod_webmail: Improve handling of partial FETCH failures.
* Use a bitfield to keep track if the connection is to Office365 so we can restrict Microsoft-only workarounds to these connections only. * Prefer 'Sent' to 'Trash' of the alternate-SELECT folders, since Sent is a more common folder name than 'Deleted' * Add missing newline in warning message and also include folder name. * Sent a status message to clients when partial FETCH failures occur.
1 parent 7ff8e40 commit 24f28cb

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

modules/mod_webmail.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct imap_client {
6969
unsigned int has_status_size:1;
7070
unsigned int has_list_status:1;
7171
unsigned int has_notify:1;
72+
unsigned int office365:1; /* Is it a Microsoft Office 365 server? */
7273
/* Sorting */
7374
char *sort;
7475
char *filter;
@@ -736,6 +737,7 @@ static int client_imap_init(struct ws_session *ws, struct imap_client *client)
736737
}
737738

738739
client->imap = imap;
740+
client->office365 = strstr(hostname, "outlook") || strstr(hostname, "office365"); /* We don't store the hostname, but we do need to know later if it's Office 365 (for workarounds) */
739741

740742
mailimap_set_logger(imap, libetpan_log, client);
741743
mailimap_set_timeout(imap, 10); /* If the IMAP server hasn't responded by now, I doubt it ever will */
@@ -2049,10 +2051,10 @@ static int select_another_mailbox_on_remote_server(struct imap_client *client)
20492051
* and that might be faster, but the code to do a basic LIST would be more involved
20502052
* and not worth it for this off-nominal case? This code is written to be the simplest
20512053
* way possible of selecting another folder. */
2052-
strcpy(tmp, strstr(client->mailbox, "Deleted") ? "Sent" : "Deleted"); /* Safe */
2054+
strcpy(tmp, strstr(client->mailbox, "Sent") ? "Deleted" : "Sent"); /* Safe */
20532055
} else {
2054-
strcpy(otherfolder, strstr(client->mailbox, "Deleted") ? "Sent" : "Deleted"); /* Safe */
2055-
/* condition will be false next time we tset */
2056+
strcpy(otherfolder, strstr(client->mailbox, "Sent") ? "Deleted" : "Sent"); /* Safe */
2057+
/* condition will be false next time we test */
20562058
}
20572059
bbs_debug(3, "Attempting to select '%s'\n", otherfolder);
20582060
res = mailimap_select(client->imap, otherfolder);
@@ -2071,7 +2073,7 @@ static int select_another_mailbox_on_remote_server(struct imap_client *client)
20712073
/* It's possible the SELECT failed if we went all the way to the top of the hierarchy without finding a match.
20722074
* In that case, we're probably screwed anyways, but continue. */
20732075
if (res != MAILIMAP_NO_ERROR) {
2074-
bbs_warning("Failed to calculate closest existing (but different) SPECIAL-USE folder...");
2076+
bbs_warning("Failed to calculate closest existing (but different) SPECIAL-USE folder to %s\n", client->mailbox);
20752077
/* Don't break... continue, though since it won't be a brand new SELECT,
20762078
* it probably won't have the desired effect. */
20772079
return -1;
@@ -2369,6 +2371,12 @@ static int fetchlist(struct ws_session *ws, struct imap_client *client, const ch
23692371
}
23702372
}
23712373

2374+
/* If not Office 365, don't retry since we'll likely just get the same results again */
2375+
if (!client->office365) {
2376+
client_set_status(client->ws, "Partial FETCH failure");
2377+
break;
2378+
}
2379+
23722380
/* Reissue FETCH headers, by continuing loop and making another request. */
23732381

23742382
/* Microsoft won't show the new messages unless we select another IMAP folder and then go back to the target folder */
@@ -2389,6 +2397,7 @@ static int fetchlist(struct ws_session *ws, struct imap_client *client, const ch
23892397
res = mailimap_fetch(client->imap, set, fetch_type, &fetch_result);
23902398
if (MAILIMAP_ERROR(res)) {
23912399
log_mailimap_warning(client->imap, res, "FETCH failed");
2400+
client_set_status(client->ws, "Partial FETCH failure");
23922401
break; /* At least return what we already have, assuming we got something */
23932402
}
23942403
json_array_clear(arr); /* Remove all existing items from array since we have a new set to process */

0 commit comments

Comments
 (0)