From d5b5529d765513b49b9bb2a75bc3a02cfd944a60 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 1 Oct 2010 16:39:11 +0100 Subject: [PATCH] pop3: Added pop3_fast_size_lookups setting. --- doc/example-config/conf.d/20-pop3.conf | 7 +++++ src/pop3/pop3-client.c | 41 +++++++++++++++++++++++++- src/pop3/pop3-settings.c | 2 ++ src/pop3/pop3-settings.h | 1 + 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/doc/example-config/conf.d/20-pop3.conf b/doc/example-config/conf.d/20-pop3.conf index 1b32fda753..3559b9a7b0 100644 --- a/doc/example-config/conf.d/20-pop3.conf +++ b/doc/example-config/conf.d/20-pop3.conf @@ -19,6 +19,13 @@ protocol pop3 { # Keep the mailbox locked for the entire POP3 session. #pop3_lock_session = no + # POP3 requires message sizes to be listed as if they had CR+LF linefeeds. + # Many POP3 servers violate this by returning the sizes with LF linefeeds, + # because it's faster to get. When this setting is enabled, Dovecot still + # tries to do the right thing first, but if that requires opening the + # message, it fallbacks to the easier (but incorrect) size. + #pop3_fast_size_lookups = no + # POP3 UIDL (unique mail identifier) format to use. You can use following # variables, along with the variable modifiers described in # doc/wiki/Variables.txt (e.g. %Uf for the filename in uppercase) diff --git a/src/pop3/pop3-client.c b/src/pop3/pop3-client.c index 7baf191670..cfb125134b 100644 --- a/src/pop3/pop3-client.c +++ b/src/pop3/pop3-client.c @@ -64,6 +64,45 @@ static void client_idle_timeout(struct client *client) } } +static int +pop3_mail_get_size(struct client *client, struct mail *mail, uoff_t *size_r) +{ + struct mail_storage *storage; + enum mail_error error; + int ret; + + if (!client->set->pop3_fast_size_lookups) + return mail_get_virtual_size(mail, size_r); + + /* first try to get the virtual size */ + mail->lookup_abort = MAIL_LOOKUP_ABORT_READ_MAIL; + ret = mail_get_virtual_size(mail, size_r); + mail->lookup_abort = MAIL_LOOKUP_ABORT_NEVER; + if (ret == 0) + return 0; + + storage = mailbox_get_storage(mail->box); + (void)mail_storage_get_last_error(storage, &error); + if (error != MAIL_ERROR_NOTPOSSIBLE) + return -1; + + /* virtual size not available with a fast lookup. + fallback to trying the physical size */ + mail->lookup_abort = MAIL_LOOKUP_ABORT_READ_MAIL; + ret = mail_get_physical_size(mail, size_r); + mail->lookup_abort = MAIL_LOOKUP_ABORT_NEVER; + if (ret == 0) + return 0; + + (void)mail_storage_get_last_error(storage, &error); + if (error != MAIL_ERROR_NOTPOSSIBLE) + return -1; + + /* no way to quickly get the size. fallback to doing a slow virtual + size lookup */ + return mail_get_virtual_size(mail, size_r); +} + static int read_mailbox(struct client *client, uint32_t *failed_uid_r) { struct mailbox_status status; @@ -94,7 +133,7 @@ static int read_mailbox(struct client *client, uint32_t *failed_uid_r) mail = mail_alloc(t, MAIL_FETCH_VIRTUAL_SIZE, NULL); while (mailbox_search_next(ctx, mail)) { - if (mail_get_virtual_size(mail, &size) < 0) { + if (pop3_mail_get_size(client, mail, &size) < 0) { ret = mail->expunged ? 0 : -1; *failed_uid_r = mail->uid; break; diff --git a/src/pop3/pop3-settings.c b/src/pop3/pop3-settings.c index 0fa239f6ca..b6e3843aa8 100644 --- a/src/pop3/pop3-settings.c +++ b/src/pop3/pop3-settings.c @@ -68,6 +68,7 @@ static const struct setting_define pop3_setting_defines[] = { DEF(SET_BOOL, pop3_reuse_xuidl), DEF(SET_BOOL, pop3_save_uidl), DEF(SET_BOOL, pop3_lock_session), + DEF(SET_BOOL, pop3_fast_size_lookups), DEF(SET_STR, pop3_client_workarounds), DEF(SET_STR, pop3_logout_format), @@ -83,6 +84,7 @@ static const struct pop3_settings pop3_default_settings = { .pop3_reuse_xuidl = FALSE, .pop3_save_uidl = FALSE, .pop3_lock_session = FALSE, + .pop3_fast_size_lookups = FALSE, .pop3_client_workarounds = "", .pop3_logout_format = "top=%t/%p, retr=%r/%b, del=%d/%m, size=%s" }; diff --git a/src/pop3/pop3-settings.h b/src/pop3/pop3-settings.h index 43c148b586..174e2ba4ba 100644 --- a/src/pop3/pop3-settings.h +++ b/src/pop3/pop3-settings.h @@ -20,6 +20,7 @@ struct pop3_settings { bool pop3_reuse_xuidl; bool pop3_save_uidl; bool pop3_lock_session; + bool pop3_fast_size_lookups; const char *pop3_client_workarounds; const char *pop3_logout_format; -- 2.47.3