Skip to content

Commit

Permalink
lmtp: Implement client vfuncs for SMTP transaction commands.
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanbosch committed Dec 11, 2018
1 parent f8629e3 commit 3655f90
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 44 deletions.
4 changes: 4 additions & 0 deletions src/lmtp/client.c
Expand Up @@ -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,
};
9 changes: 9 additions & 0 deletions src/lmtp/client.h
Expand Up @@ -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 {
Expand Down
120 changes: 76 additions & 44 deletions src/lmtp/commands.c
Expand Up @@ -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();
Expand All @@ -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,
Expand Down Expand Up @@ -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));
Expand All @@ -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, "<lmtp DATA 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, "<lmtp DATA 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,
Expand Down Expand Up @@ -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, "<lmtp DATA 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, "<lmtp DATA 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;
}
27 changes: 27 additions & 0 deletions src/lmtp/commands.h
Expand Up @@ -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

0 comments on commit 3655f90

Please sign in to comment.