rcpt->data_callback = data_callback;
rcpt->context = context;
- if (client->global_fail_string != NULL)
+ if (client->global_fail_string != NULL) {
+ client->rcpt_next_receive_idx++;
+ i_assert(client->rcpt_next_receive_idx ==
+ array_count(&client->recipients));
+
+ rcpt->failed = TRUE;
rcpt_to_callback(FALSE, client->global_fail_string, context);
- else if (client->input_state == LMTP_INPUT_STATE_RCPT_TO)
+ } else if (client->input_state == LMTP_INPUT_STATE_RCPT_TO)
lmtp_client_send_rcpts(client);
}
lmtp_client_send_data_cmd(client);
}
+bool lmtp_client_is_data_input_finished(struct lmtp_client *client)
+{
+ return client->data_input != NULL;
+}
+
void lmtp_client_send_more(struct lmtp_client *client)
{
if (client->input_state == LMTP_INPUT_STATE_DATA)
lmtp_callback_t *data_callback, void *context);
/* Start sending input stream as DATA. */
void lmtp_client_send(struct lmtp_client *client, struct istream *data_input);
+/* Returns TRUE if data_input is no longer needed. */
+bool lmtp_client_is_data_input_finished(struct lmtp_client *client);
/* Call this function whenever input stream can potentially be read forward.
This is useful with non-blocking istreams and tee-istreams. */
void lmtp_client_send_more(struct lmtp_client *client);
unsigned int finished:1;
};
-static void lmtp_proxy_conn_deinit(struct lmtp_proxy_connection *conn,
- const char *reason);
static void lmtp_proxy_data_input(struct lmtp_proxy *proxy);
struct lmtp_proxy *
conns = array_get(&proxy->connections, &count);
for (i = 0; i < count; i++)
- lmtp_proxy_conn_deinit(conns[i], "451 4.3.0 Aborting");
+ lmtp_client_fail(conns[i]->client, "451 4.3.0 Aborting");
}
void lmtp_proxy_deinit(struct lmtp_proxy **_proxy)
return conn;
}
-static void lmtp_proxy_conn_deinit(struct lmtp_proxy_connection *conn,
- const char *reason)
+static void lmtp_proxy_conn_close(struct lmtp_proxy_connection *conn)
{
- struct lmtp_proxy_recipient *rcpt;
-
- /* set failure replies to all recipients in this connection */
- array_foreach_modifiable(&conn->proxy->rcpt_to, rcpt) {
- if (rcpt->conn == conn && !rcpt->rcpt_to_failed)
- rcpt->reply = reason;
- }
-
if (conn->client != NULL)
lmtp_client_deinit(&conn->client);
if (conn->data_input != NULL)
i_stream_unref(&conn->data_input);
- conn->failed = TRUE;
}
static bool lmtp_proxy_send_replies(struct lmtp_proxy *proxy)
}
i_assert(i != count);
+ if (!success && conn->rcpt_next_reply_low_idx == count &&
+ lmtp_client_is_data_input_finished(conn->client))
+ lmtp_proxy_conn_close(conn);
+
/* send replies only if we've already sent DATA. */
if (conn->proxy->data_input != NULL)
lmtp_proxy_try_finish(conn->proxy);
}
}
i_assert(i != count);
+
+ if (conn->data_next_reply_low_idx == count &&
+ lmtp_client_is_data_input_finished(conn->client))
+ lmtp_proxy_conn_close(conn);
+
lmtp_proxy_try_finish(conn->proxy);
}
for (i = 0; i < count; i++) {
(void)i_stream_get_data(conns[i]->data_input, &size);
if (size == max_size) {
- lmtp_proxy_conn_deinit(conns[i],
- ERRSTR_TEMP_REMOTE_FAILURE
- " (DATA output timeout)");
+ lmtp_client_fail(conns[i]->client,
+ ERRSTR_TEMP_REMOTE_FAILURE
+ " (DATA output timeout)");
}
}
return TRUE;