add-ons/mail_daemon: IMAP: limit UIDs in UID FETCH

Some IMAP servers (such as dovecot) have hard line length limits for
commands.

The way UID FETCH was being scheduled was creating FETCHes longer than
the maximum length.

Limit these to a reasonable number of UIDs per fetch, such that we have
a hope of success when facing monsterous mailboxes.

Change-Id: I8a2184eec1b8fcab6f7914a9b14ad008700b96d1
Signed-off-by: Augustin Cavalier <waddlesplash@gmail.com>
Reviewed-on: https://review.haiku-os.org/c/haiku/+/626

Style fixes by me, and also replaced emplace_back with push_back
for GCC2 compatibility.
This commit is contained in:
Kuroneko 2018-10-12 08:30:24 +11:00 committed by Augustin Cavalier
parent 065c9986f8
commit ed08b22dec

View File

@ -21,6 +21,7 @@ using IMAP::MessageUIDList;
static const uint32 kMaxFetchEntries = 500;
static const uint32 kMaxDirectDownloadSize = 4096;
static const uint32 kMaxUIDsPerFetch = 32;
class WorkerPrivate {
@ -236,7 +237,7 @@ private:
class FetchHeadersCommand : public SyncCommand, public IMAP::FetchListener {
public:
FetchHeadersCommand(IMAPFolder& folder, IMAPMailbox& mailbox,
MessageUIDList& uids, int32 bodyFetchLimit)
const MessageUIDList& uids, int32 bodyFetchLimit)
:
fFolder(folder),
fMailbox(mailbox),
@ -402,16 +403,28 @@ public:
if (from == 1) {
fFolder->MessageEntriesFetched();
if (fUIDsToFetch.size() > 0) {
// Add pending command to fetch the message headers
WorkerCommand* command = new FetchHeadersCommand(*fFolder,
*fMailbox, fUIDsToFetch,
WorkerPrivate(worker).BodyFetchLimit());
if (!fFetchCommands.AddItem(command))
delete command;
IMAP::MessageUIDList uidsForSubFetch;
fUIDsToFetch.clear();
IMAP::MessageUIDList::iterator messageIterator
= fUIDsToFetch.begin();
while (messageIterator != fUIDsToFetch.end()) {
uidsForSubFetch.push_back(*messageIterator);
messageIterator++;
size_t uidsQueued = uidsForSubFetch.size();
if (uidsQueued >= kMaxUIDsPerFetch
|| (messageIterator == fUIDsToFetch.end()
&& uidsQueued > 0)) {
status_t fetchResult = QueueFetch(worker,
uidsForSubFetch);
if (fetchResult != B_OK) {
printf("IMAP: Error occured queueing UID FETCH\n");
return fetchResult;
}
uidsForSubFetch.clear();
}
}
fUIDsToFetch.clear();
fState = SELECT;
}
}
@ -424,6 +437,21 @@ public:
return fState == DONE;
}
private:
status_t QueueFetch(IMAPConnectionWorker& worker,
const IMAP::MessageUIDList& uids)
{
// Add pending command to fetch the message headers
WorkerCommand* command = new FetchHeadersCommand(*fFolder,
*fMailbox, uids,
WorkerPrivate(worker).BodyFetchLimit());
if (!fFetchCommands.AddItem(command)) {
delete command;
return B_ERROR;
}
return B_OK;
}
private:
enum State {
INIT,