]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
pop3: Send "OK Logged in" before reading mailbox.
authorTimo Sirainen <tss@iki.fi>
Wed, 18 Nov 2015 11:08:57 +0000 (13:08 +0200)
committerTimo Sirainen <tss@iki.fi>
Wed, 18 Nov 2015 11:08:57 +0000 (13:08 +0200)
This way if the reading takes a long time, the client still sees that the
login itself was successful. This is especially useful to avoid unnecessary
errors logged by proxies.

src/pop3/main.c
src/pop3/pop3-client.c
src/pop3/pop3-client.h

index e6ffd028618595a1eb116c9698a842fab7eb10d2..6561f86677b0ad46f6e70306c1a3ab3ce5c29263 100644 (file)
@@ -85,8 +85,6 @@ static void client_add_input(struct client *client, const buffer_t *buf)
        output = client->output;
        o_stream_ref(output);
        o_stream_cork(output);
-       if (!IS_STANDALONE())
-               client_send_line(client, "+OK Logged in.");
        (void)client_handle_input(client);
        o_stream_uncork(output);
        o_stream_unref(&output);
@@ -103,6 +101,7 @@ client_create_from_input(const struct mail_storage_service_input *input,
        struct mail_user *mail_user;
        struct client *client;
        const struct pop3_settings *set;
+       const char *error;
 
        if (mail_storage_service_lookup_next(storage_service, input,
                                             &user, &mail_user, error_r) <= 0) {
@@ -118,8 +117,16 @@ client_create_from_input(const struct mail_storage_service_input *input,
                verbose_proctitle = TRUE;
 
        if (client_create(fd_in, fd_out, input->session_id,
-                         mail_user, user, set, &client) == 0)
+                         mail_user, user, set, &client) < 0)
+               return 0;
+       if (!IS_STANDALONE())
+               client_send_line(client, "+OK Logged in.");
+       if (client_init_mailbox(client, &error) == 0)
                client_add_input(client, input_buf);
+       else {
+               i_error("%s", error);
+               client_destroy(client, error);
+       }
        return 0;
 }
 
index 45170cd41c461e3d0c250046ce73b1ee51ff09ee..0cb91ad07bc4deb9186308892143a2343c4202d6 100644 (file)
@@ -369,11 +369,7 @@ int client_create(int fd_in, int fd_out, const char *session_id,
                  struct mail_storage_service_user *service_user,
                  const struct pop3_settings *set, struct client **client_r)
 {
-       struct mail_storage *storage;
-       const char *ident;
        struct client *client;
-        enum mailbox_flags flags;
-       const char *errmsg;
        pool_t pool;
        int ret;
 
@@ -405,12 +401,30 @@ int client_create(int fd_in, int fd_out, const char *session_id,
 
        client->user = user;
 
+       client->mail_set = mail_user_set_get_storage_set(user);
+       client->uidl_keymask =
+               parse_uidl_keymask(client->mail_set->pop3_uidl_format);
+       if (client->uidl_keymask == 0)
+               i_fatal("Invalid pop3_uidl_format");
+
+       if (var_has_key(set->pop3_logout_format, 'u', "uidl_change")) {
+               /* logging uidl_change. we need hashes of the UIDLs */
+               client->message_uidls_save = TRUE;
+       } else if (strcmp(set->pop3_uidl_duplicates, "allow") != 0) {
+               /* UIDL duplicates aren't allowed, so we'll need to
+                  keep track of them */
+               client->message_uidls_save = TRUE;
+       }
+
        pop3_client_count++;
        DLLIST_PREPEND(&pop3_clients, client);
 
        client->inbox_ns = mail_namespace_find_inbox(user->namespaces);
        i_assert(client->inbox_ns != NULL);
 
+       if (hook_client_created != NULL)
+               hook_client_created(&client);
+
        if (set->pop3_lock_session && (ret = pop3_lock_session(client)) <= 0) {
                client_send_line(client, ret < 0 ?
                        "-ERR [SYS/TEMP] Failed to create POP3 session lock." :
@@ -419,42 +433,34 @@ int client_create(int fd_in, int fd_out, const char *session_id,
                return -1;
        }
 
+       *client_r = client;
+       return 0;
+
+}
+
+int client_init_mailbox(struct client *client, const char **error_r)
+{
+        enum mailbox_flags flags;
+       const char *ident, *errmsg;
+
        flags = MAILBOX_FLAG_POP3_SESSION;
-       if (!set->pop3_no_flag_updates)
+       if (!client->set->pop3_no_flag_updates)
                flags |= MAILBOX_FLAG_DROP_RECENT;
        client->mailbox = mailbox_alloc(client->inbox_ns->list, "INBOX", flags);
-       storage = mailbox_get_storage(client->mailbox);
        if (mailbox_open(client->mailbox) < 0) {
-               i_error("Couldn't open INBOX: %s",
+               *error_r = t_strdup_printf("Couldn't open INBOX: %s",
                        mailbox_get_last_error(client->mailbox, NULL));
                client_send_storage_error(client);
-               client_destroy(client, "Couldn't open INBOX");
                return -1;
        }
-       client->mail_set = mail_storage_get_settings(storage);
 
        if (init_pop3_deleted_flag(client, &errmsg) < 0 ||
            init_mailbox(client, &errmsg) < 0) {
-               i_error("Couldn't init INBOX: %s", errmsg);
-               client_destroy(client, "Mailbox init failed");
+               *error_r = t_strdup_printf("Couldn't init INBOX: %s", errmsg);
                return -1;
        }
 
-       client->uidl_keymask =
-               parse_uidl_keymask(client->mail_set->pop3_uidl_format);
-       if (client->uidl_keymask == 0)
-               i_fatal("Invalid pop3_uidl_format");
-
-       if (var_has_key(set->pop3_logout_format, 'u', "uidl_change")) {
-               /* logging uidl_change. we need hashes of the UIDLs */
-               client->message_uidls_save = TRUE;
-       } else if (strcmp(set->pop3_uidl_duplicates, "allow") != 0) {
-               /* UIDL duplicates aren't allowed, so we'll need to
-                  keep track of them */
-               client->message_uidls_save = TRUE;
-       }
-
-       if (!set->pop3_no_flag_updates && client->messages_count > 0)
+       if (!client->set->pop3_no_flag_updates && client->messages_count > 0)
                client->seen_bitmask = i_malloc(MSGS_BITMASK_SIZE(client));
 
        ident = mail_user_get_anvil_userip_ident(client->user);
@@ -464,11 +470,7 @@ int client_create(int fd_in, int fd_out, const char *session_id,
                client->anvil_sent = TRUE;
        }
 
-       if (hook_client_created != NULL)
-               hook_client_created(&client);
-
        pop3_refresh_proctitle();
-       *client_r = client;
        return 0;
 }
 
index d51fdfa58c0c40dca7c577515ed565db47e8de77..6b6fc282d9150276e5395918ecf30d0a1b69a487 100644 (file)
@@ -123,6 +123,7 @@ int client_create(int fd_in, int fd_out, const char *session_id,
                  struct mail_user *user,
                  struct mail_storage_service_user *service_user,
                  const struct pop3_settings *set, struct client **client_r);
+int client_init_mailbox(struct client *client, const char **error_r);
 void client_destroy(struct client *client, const char *reason) ATTR_NULL(2);
 
 /* Disconnect client connection */