From: Timo Sirainen Date: Wed, 18 Nov 2015 11:08:57 +0000 (+0200) Subject: pop3: Send "OK Logged in" before reading mailbox. X-Git-Tag: 2.2.20.rc1~63 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=def59847005dd515d35fe67df57abe016095d5a1;p=thirdparty%2Fdovecot%2Fcore.git pop3: Send "OK Logged in" before reading mailbox. 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. --- diff --git a/src/pop3/main.c b/src/pop3/main.c index e6ffd02861..6561f86677 100644 --- a/src/pop3/main.c +++ b/src/pop3/main.c @@ -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; } diff --git a/src/pop3/pop3-client.c b/src/pop3/pop3-client.c index 45170cd41c..0cb91ad07b 100644 --- a/src/pop3/pop3-client.c +++ b/src/pop3/pop3-client.c @@ -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; } diff --git a/src/pop3/pop3-client.h b/src/pop3/pop3-client.h index d51fdfa58c..6b6fc282d9 100644 --- a/src/pop3/pop3-client.h +++ b/src/pop3/pop3-client.h @@ -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 */