# 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)
}
}
+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;
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;
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),
.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"
};