struct client *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 imap_settings *set) { const struct mail_storage_settings *mail_set; struct client *client; const char *ident; pool_t pool; bool explicit_capability = FALSE; /* always use nonblocking I/O */ net_set_nonblock(fd_in, TRUE); net_set_nonblock(fd_out, TRUE); pool = pool_alloconly_create("imap client", 2048); client = p_new(pool, struct client, 1); client->pool = pool; client->v = imap_client_vfuncs; client->set = set; client->service_user = service_user; client->session_id = p_strdup(pool, session_id); client->fd_in = fd_in; client->fd_out = fd_out; client->input = i_stream_create_fd(fd_in, set->imap_max_line_length, FALSE); client->output = o_stream_create_fd(fd_out, (size_t)-1, FALSE); o_stream_set_no_error_handling(client->output, TRUE); i_stream_set_name(client->input, "<imap client>"); o_stream_set_name(client->output, "<imap client>"); o_stream_set_flush_callback(client->output, client_output, client); p_array_init(&client->module_contexts, client->pool, 5); client->io = io_add_istream(client->input, client_input, client); client->last_input = ioloop_time; client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS, client_idle_timeout, client); client->command_pool = pool_alloconly_create(MEMPOOL_GROWING"client command", 1024*2); client->user = user; client->notify_count_changes = TRUE; client->notify_flag_changes = TRUE; mail_namespaces_set_storage_callbacks(user->namespaces, &mail_storage_callbacks, client); client->capability_string = str_new(client->pool, sizeof(CAPABILITY_STRING)+64); if (*set->imap_capability == '\0') str_append(client->capability_string, CAPABILITY_STRING); else if (*set->imap_capability != '+') { explicit_capability = TRUE; str_append(client->capability_string, set->imap_capability); } else { str_append(client->capability_string, CAPABILITY_STRING); str_append_c(client->capability_string, ' '); str_append(client->capability_string, set->imap_capability + 1); } if (user->fuzzy_search && !explicit_capability) { /* Enable FUZZY capability only when it actually has a chance of working */ str_append(client->capability_string, " SEARCH=FUZZY"); } mail_set = mail_user_set_get_storage_set(user); if (mail_set->mailbox_list_index && !explicit_capability) { /* NOTIFY is enabled only when mailbox list indexes are enabled, although even that doesn't necessarily guarantee it always */ str_append(client->capability_string, " NOTIFY"); } if (*set->imap_urlauth_host != '\0' && *mail_set->mail_attribute_dict != '\0') { /* Enable URLAUTH capability only when dict is configured correctly */ client_init_urlauth(client); if (!explicit_capability) str_append(client->capability_string, " URLAUTH URLAUTH=BINARY"); } if (set->imap_metadata && *mail_set->mail_attribute_dict != '\0') { client->imap_metadata_enabled = TRUE; if (!explicit_capability) str_append(client->capability_string, " METADATA"); } if (!explicit_capability && user_has_special_use_mailboxes(user)) { /* Advertise SPECIAL-USE only if there are actually some SPECIAL-USE flags in mailbox configuration. */ str_append(client->capability_string, " SPECIAL-USE"); } ident = mail_user_get_anvil_userip_ident(client->user); if (ident != NULL) { master_service_anvil_send(master_service, t_strconcat( "CONNECT\t", my_pid, "\timap/", ident, "\n", NULL)); client->anvil_sent = TRUE; } imap_client_count++; DLLIST_PREPEND(&imap_clients, client); if (hook_client_created != NULL) hook_client_created(&client); imap_refresh_proctitle(); return client; }
struct client *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 submission_settings *set, const char *helo, const unsigned char *pdata, unsigned int pdata_len) { const struct mail_storage_settings *mail_set; struct smtp_server_settings smtp_set; const char *ident; struct client *client; /* always use nonblocking I/O */ net_set_nonblock(fd_in, TRUE); net_set_nonblock(fd_out, TRUE); client = i_new(struct client, 1); client->user = user; client->service_user = service_user; client->set = set; client->session_id = i_strdup(session_id); i_zero(&smtp_set); smtp_set.hostname = set->hostname; smtp_set.login_greeting = set->login_greeting; smtp_set.max_recipients = set->submission_max_recipients; smtp_set.max_client_idle_time_msecs = CLIENT_IDLE_TIMEOUT_MSECS; smtp_set.debug = user->mail_debug; client->conn = smtp_server_connection_create(smtp_server, fd_in, fd_out, user->conn.remote_ip, user->conn.remote_port, FALSE, &smtp_set, &smtp_callbacks, client); client_proxy_create(client, set); smtp_server_connection_login(client->conn, client->user->username, helo, pdata, pdata_len, user->conn.ssl_secured); smtp_server_connection_start_pending(client->conn); mail_set = mail_user_set_get_storage_set(user); if (*set->imap_urlauth_host != '\0' && *mail_set->mail_attribute_dict != '\0') { /* Enable BURL capability only when urlauth dict is configured correctly */ client_init_urlauth(client); } submission_client_count++; DLLIST_PREPEND(&submission_clients, client); ident = mail_user_get_anvil_userip_ident(client->user); if (ident != NULL) { master_service_anvil_send(master_service, t_strconcat( "CONNECT\t", my_pid, "\tsubmission/", ident, "\n", NULL)); client->anvil_sent = TRUE; } if (hook_client_created != NULL) hook_client_created(&client); submission_refresh_proctitle(); return client; }