struct smtp_client_command *cmd_proxied;
};
+static void cmd_quit_finish(struct cmd_quit_context *quit_cmd)
+{
+ struct client *client = quit_cmd->client;
+ struct smtp_server_cmd_ctx *cmd = quit_cmd->cmd;
+
+ timeout_remove(&client->to_quit);
+ if (quit_cmd->cmd_proxied != NULL)
+ smtp_client_command_abort(&quit_cmd->cmd_proxied);
+ smtp_server_reply_quit(cmd);
+}
+
static void cmd_quit_proxy_cb(
const struct smtp_reply *proxy_reply ATTR_UNUSED,
struct cmd_quit_context *quit_cmd)
{
+ quit_cmd->cmd_proxied = NULL;
+ cmd_quit_finish(quit_cmd);
+}
+
+static void cmd_quit_proxy(struct cmd_quit_context *quit_cmd)
+{
+ struct client *client = quit_cmd->client;
struct smtp_server_cmd_ctx *cmd = quit_cmd->cmd;
- smtp_server_reply_quit(cmd);
+ if (quit_cmd->cmd_proxied != NULL)
+ return;
+
+ if (smtp_client_connection_get_state(client->proxy_conn)
+ < SMTP_CLIENT_CONNECTION_STATE_READY) {
+ /* Don't bother proxying QUIT command when proxy is not
+ fully initialized. */
+ smtp_server_reply_quit(cmd);
+ return;
+ }
+
+ /* RFC 5321, Section 4.1.1.10:
+
+ The sender MUST NOT intentionally close the transmission channel
+ until it sends a QUIT command, and it SHOULD wait until it receives
+ the reply (even if there was an error response to a previous
+ command). */
+ quit_cmd->cmd_proxied =
+ smtp_client_command_new(client->proxy_conn, 0,
+ cmd_quit_proxy_cb, quit_cmd);
+ smtp_client_command_write(quit_cmd->cmd_proxied, "QUIT");
+ smtp_client_command_submit(quit_cmd->cmd_proxied);
+}
+
+static void cmd_quit_next(struct smtp_server_cmd_ctx *cmd)
+{
+ struct cmd_quit_context *quit_cmd = cmd->context;
+ struct client *client = quit_cmd->client;
+
+ /* QUIT command is next to reply */
+
+ cmd_quit_proxy(quit_cmd);
+
+ if (quit_cmd->cmd_proxied != NULL) {
+ /* give relay server brief interval to reply */
+ client->to_quit = timeout_add(
+ SUBMISSION_MAX_WAIT_QUIT_REPLY_MSECS,
+ cmd_quit_finish, quit_cmd);
+ }
}
int cmd_quit(void *conn_ctx, struct smtp_server_cmd_ctx *cmd)
quit_cmd = p_new(cmd->pool, struct cmd_quit_context, 1);
quit_cmd->client = client;
quit_cmd->cmd = cmd;
+
+ cmd->hook_next = cmd_quit_next;
cmd->context = quit_cmd;
- quit_cmd->cmd_proxied = smtp_client_command_new
- (client->proxy_conn, 0, cmd_quit_proxy_cb, quit_cmd);
- smtp_client_command_write(quit_cmd->cmd_proxied, "QUIT");
- smtp_client_command_submit(quit_cmd->cmd_proxied); // FIXME: timeout
+ if (smtp_client_connection_get_state(client->proxy_conn)
+ >= SMTP_CLIENT_CONNECTION_STATE_READY)
+ cmd_quit_proxy(quit_cmd);
return 0;
}