diff --git a/src/lmtp/client.c b/src/lmtp/client.c index 777929754e..2cb49898a8 100644 --- a/src/lmtp/client.c +++ b/src/lmtp/client.c @@ -348,4 +348,8 @@ static const struct smtp_server_callbacks lmtp_callbacks = { static const struct lmtp_client_vfuncs lmtp_client_vfuncs = { .destroy = client_default_destroy, + + .cmd_mail = client_default_cmd_mail, + .cmd_rcpt = client_default_cmd_rcpt, + .cmd_data = client_default_cmd_data, }; diff --git a/src/lmtp/client.h b/src/lmtp/client.h index 406dfb1dd5..e359566c46 100644 --- a/src/lmtp/client.h +++ b/src/lmtp/client.h @@ -27,6 +27,15 @@ struct client_state { struct lmtp_client_vfuncs { void (*destroy)(struct client *client, const char *enh_code, const char *reason); + + int (*cmd_mail)(struct client *client, struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_mail *data); + int (*cmd_rcpt)(struct client *client, struct smtp_server_cmd_ctx *cmd, + struct lmtp_recipient *lrcpt); + int (*cmd_data)(struct client *client, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_transaction *trans, + struct istream *data_input, uoff_t data_size); }; struct client { diff --git a/src/lmtp/commands.c b/src/lmtp/commands.c index 7081df94f6..ab50ab2caa 100644 --- a/src/lmtp/commands.c +++ b/src/lmtp/commands.c @@ -23,11 +23,18 @@ */ int cmd_mail(void *conn_ctx, - struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, - struct smtp_server_cmd_mail *data ATTR_UNUSED) + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_mail *data) { struct client *client = (struct client *)conn_ctx; + return client->v.cmd_mail(client, cmd, data); +} + +int client_default_cmd_mail(struct client *client, + struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, + struct smtp_server_cmd_mail *data ATTR_UNUSED) +{ if (client->lmtp_set->lmtp_user_concurrency_limit > 0) { /* connect to anvil before dropping privileges */ lmtp_anvil_init(); @@ -44,11 +51,21 @@ int cmd_rcpt(void *conn_ctx, struct smtp_server_cmd_ctx *cmd, { struct client *client = (struct client *)conn_ctx; struct lmtp_recipient *lrcpt; + + lrcpt = lmtp_recipient_create(client, rcpt); + + return client->v.cmd_rcpt(client, cmd, lrcpt); +} + +int client_default_cmd_rcpt(struct client *client, + struct smtp_server_cmd_ctx *cmd, + struct lmtp_recipient *lrcpt) +{ + struct smtp_server_recipient *rcpt = lrcpt->rcpt; const char *username, *detail; char delim = '\0'; int ret; - lrcpt = lmtp_recipient_create(client, rcpt); smtp_address_detail_parse_temp( client->unexpanded_lda_set->recipient_delimiter, @@ -99,8 +116,8 @@ cmd_data_finish(struct client *client, struct smtp_server_transaction *trans) { struct client_state *state = &client->state; - struct istream *input_msg, *input_local, *input_proxy; - struct istream *inputs[3]; + struct istream *input_msg; + int ret; i_assert(HAS_ALL_BITS(trans->flags, SMTP_SERVER_TRANSACTION_FLAG_REPLY_PER_RCPT)); @@ -111,47 +128,11 @@ cmd_data_finish(struct client *client, input_msg = iostream_temp_finish(&state->mail_data_output, IO_BLOCK_SIZE); - /* formulate prepended headers for both local and proxy delivery */ - cmd_data_create_added_headers(client, cmd, trans); - - /* construct message streams for local and proxy delivery */ - input_local = input_proxy = NULL; - if (client->local != NULL) { - inputs[0] = i_stream_create_from_data( - state->added_headers_local, - strlen(state->added_headers_local)); - inputs[1] = input_msg; - inputs[2] = NULL; - - input_local = i_stream_create_concat(inputs); - i_stream_set_name(input_local, ""); - i_stream_unref(&inputs[0]); - } - if (client->proxy != NULL) { - inputs[0] = i_stream_create_from_data( - state->added_headers_proxy, - strlen(state->added_headers_proxy)); - inputs[1] = input_msg; - inputs[2] = NULL; - - input_proxy = i_stream_create_concat(inputs); - i_stream_set_name(input_proxy, ""); - i_stream_unref(&inputs[0]); - } - + ret = client->v.cmd_data(client, cmd, trans, + input_msg, client->state.data_size); i_stream_unref(&input_msg); - /* local delivery */ - if (client->local != NULL) { - lmtp_local_data(client, cmd, trans, input_local); - i_stream_unref(&input_local); - } - /* proxy delivery */ - if (client->proxy != NULL) { - lmtp_proxy_data(client, cmd, trans, input_proxy); - i_stream_unref(&input_proxy); - } - return 0; + return ret; } int cmd_data_continue(void *conn_ctx, struct smtp_server_cmd_ctx *cmd, @@ -216,3 +197,54 @@ int cmd_data_begin(void *conn_ctx, client->state.data_input = data_input; return 0; } + +int client_default_cmd_data(struct client *client, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_transaction *trans, + struct istream *data_input, + uoff_t data_size ATTR_UNUSED) +{ + struct client_state *state = &client->state; + struct istream *input_local, *input_proxy; + struct istream *inputs[3]; + + /* formulate prepended headers for both local and proxy delivery */ + cmd_data_create_added_headers(client, cmd, trans); + + /* construct message streams for local and proxy delivery */ + input_local = input_proxy = NULL; + if (client->local != NULL) { + inputs[0] = i_stream_create_from_data( + state->added_headers_local, + strlen(state->added_headers_local)); + inputs[1] = data_input; + inputs[2] = NULL; + + input_local = i_stream_create_concat(inputs); + i_stream_set_name(input_local, ""); + i_stream_unref(&inputs[0]); + } + if (client->proxy != NULL) { + inputs[0] = i_stream_create_from_data( + state->added_headers_proxy, + strlen(state->added_headers_proxy)); + inputs[1] = data_input; + inputs[2] = NULL; + + input_proxy = i_stream_create_concat(inputs); + i_stream_set_name(input_proxy, ""); + i_stream_unref(&inputs[0]); + } + + /* local delivery */ + if (client->local != NULL) { + lmtp_local_data(client, cmd, trans, input_local); + i_stream_unref(&input_local); + } + /* proxy delivery */ + if (client->proxy != NULL) { + lmtp_proxy_data(client, cmd, trans, input_proxy); + i_stream_unref(&input_proxy); + } + return 0; +} diff --git a/src/lmtp/commands.h b/src/lmtp/commands.h index 4aaa51c811..f580c8693e 100644 --- a/src/lmtp/commands.h +++ b/src/lmtp/commands.h @@ -5,14 +5,41 @@ struct client; struct smtp_server_cmd_ctx; struct smtp_server_cmd_helo; +/* + * MAIL command + */ + int cmd_mail(void *conn_ctx, struct smtp_server_cmd_ctx *cmd, struct smtp_server_cmd_mail *data); + +int client_default_cmd_mail(struct client *client, + struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, + struct smtp_server_cmd_mail *data ATTR_UNUSED); + +/* + * RCPT command + */ + int cmd_rcpt(void *conn_ctx, struct smtp_server_cmd_ctx *cmd, struct smtp_server_recipient *rcpt); + +int client_default_cmd_rcpt(struct client *client, + struct smtp_server_cmd_ctx *cmd, + struct lmtp_recipient *lrcpt); + +/* + * DATA command + */ + int cmd_data_continue(void *conn_ctx, struct smtp_server_cmd_ctx *cmd, struct smtp_server_transaction *trans); int cmd_data_begin(void *conn_ctx, struct smtp_server_cmd_ctx *cmd ATTR_UNUSED, struct smtp_server_transaction *trans, struct istream *data_input); +int client_default_cmd_data(struct client *client, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_transaction *trans, + struct istream *data_input, uoff_t data_size); + #endif