This avoids the need to do that in application code.
struct cmd_data_context *data_cmd)
{
struct smtp_server_connection *conn = cmd->conn;
+ struct smtp_server_transaction *trans = conn->state.trans;
const struct smtp_server_callbacks *callbacks = conn->callbacks;
struct smtp_server_command *command = cmd->cmd;
int ret;
i_assert(data_cmd != NULL);
i_assert(conn->state.pending_mail_cmds == 0 &&
conn->state.pending_rcpt_cmds == 0);
+ i_assert(trans != NULL);
smtp_server_command_debug(cmd,
"Command is next to be replied");
if (!smtp_server_connection_data_check_state(cmd))
return;
- /* LMTP 'DATA' and 'BDAT LAST' commands need to send one reply
- per recipient
- */
- if (data_cmd->chunk_last && conn->set.protocol == SMTP_PROTOCOL_LMTP) {
- smtp_server_command_set_reply_count(command,
- array_count(&conn->state.trans->rcpt_to));
+ if (data_cmd->chunk_last) {
+ /* This is the last chunk */
+ smtp_server_transaction_last_data(trans, cmd);
+
+ /* LMTP 'DATA' and 'BDAT LAST' commands need to send more than
+ one reply per recipient */
+ if (conn->set.protocol == SMTP_PROTOCOL_LMTP) {
+ smtp_server_command_set_reply_count(command,
+ array_count(&trans->rcpt_to));
+ }
}
smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_DATA);
return;
}
- rcpt = smtp_server_recipient_create(conn, path);
+ rcpt = smtp_server_recipient_create(cmd, path);
rcpt_data = p_new(cmd->pool, struct smtp_server_cmd_rcpt, 1);
rcpt_data->rcpt = rcpt;
*/
struct smtp_server_recipient *
-smtp_server_recipient_create(struct smtp_server_connection *conn,
+smtp_server_recipient_create(struct smtp_server_cmd_ctx *cmd,
const struct smtp_address *rcpt_to);
void smtp_server_recipient_destroy(struct smtp_server_recipient **_rcpt);
void smtp_server_recipient_approved(struct smtp_server_recipient *rcpt);
+void smtp_server_recipient_last_data(struct smtp_server_recipient *rcpt,
+ struct smtp_server_cmd_ctx *cmd);
/*
* Transaction
unsigned int
smtp_server_transaction_rcpt_count(struct smtp_server_transaction *trans);
+
+void smtp_server_transaction_last_data(struct smtp_server_transaction *trans,
+ struct smtp_server_cmd_ctx *cmd);
+
/*
* Server
*/
enum smtp_server_recipient_hook_type type);
struct smtp_server_recipient *
-smtp_server_recipient_create(struct smtp_server_connection *conn,
+smtp_server_recipient_create(struct smtp_server_cmd_ctx *cmd,
const struct smtp_address *rcpt_to)
{
struct smtp_server_recipient_private *prcpt;
pool = pool_alloconly_create("smtp server recipient", 512);
prcpt = p_new(pool, struct smtp_server_recipient_private, 1);
prcpt->rcpt.pool = pool;
- prcpt->rcpt.conn = conn;
+ prcpt->rcpt.conn = cmd->conn;
+ prcpt->rcpt.cmd = cmd;
prcpt->rcpt.path = smtp_address_clone(pool, rcpt_to);
return &prcpt->rcpt;
i_assert(trans != NULL);
+ rcpt->cmd = NULL;
smtp_server_transaction_add_rcpt(trans, rcpt);
smtp_server_recipient_call_hooks(
rcpt, SMTP_SERVER_RECIPIENT_HOOK_APPROVED);
}
+void smtp_server_recipient_last_data(struct smtp_server_recipient *rcpt,
+ struct smtp_server_cmd_ctx *cmd)
+{
+ i_assert(rcpt->cmd == NULL);
+ rcpt->cmd = cmd;
+}
+
#undef smtp_server_recipient_add_hook
void smtp_server_recipient_add_hook(struct smtp_server_recipient *rcpt,
enum smtp_server_recipient_hook_type type,
return array_count(&trans->rcpt_to);
}
+void smtp_server_transaction_last_data(struct smtp_server_transaction *trans,
+ struct smtp_server_cmd_ctx *cmd)
+{
+ struct smtp_server_recipient *const *rcptp;
+
+ trans->cmd = cmd;
+
+ i_assert(array_is_created(&trans->rcpt_to));
+ array_foreach(&trans->rcpt_to, rcptp)
+ smtp_server_recipient_last_data(*rcptp, cmd);
+}
+
void smtp_server_transaction_fail_data(struct smtp_server_transaction *trans,
struct smtp_server_cmd_ctx *data_cmd,
unsigned int status, const char *enh_code,
struct smtp_address *path;
struct smtp_params_rcpt params;
+ /* The associated RCPT or DATA command (whichever applies). This is NULL
+ when no command is active. */
+ struct smtp_server_cmd_ctx *cmd;
+
/* The index in the list of approved recipients */
unsigned int index;
struct smtp_params_mail params;
ARRAY_TYPE(smtp_server_recipient) rcpt_to;
+ /* The associated DATA command. This is NULL until the last DATA/BDAT
+ command is issued.
+ */
+ struct smtp_server_cmd_ctx *cmd;
+
void *context;
};
void lmtp_recipient_init(struct lmtp_recipient *lrcpt,
struct client *client,
enum lmtp_recipient_type type,
- struct smtp_server_cmd_ctx *cmd,
struct smtp_server_recipient *rcpt)
{
lrcpt->client = client;
lrcpt->type = type;
- lrcpt->rcpt_cmd = cmd;
lrcpt->rcpt = rcpt;
}
-void lmtp_recipient_finish(struct lmtp_recipient *lrcpt)
-{
- lrcpt->rcpt_cmd = NULL;
-}
-
struct lmtp_recipient *
lmtp_recipient_find_duplicate(struct lmtp_recipient *lrcpt,
struct smtp_server_transaction *trans)
struct client *client;
struct smtp_server_recipient *rcpt;
enum lmtp_recipient_type type;
-
- struct smtp_server_cmd_ctx *rcpt_cmd;
};
void lmtp_recipient_init(struct lmtp_recipient *lrcpt,
struct client *client,
enum lmtp_recipient_type type,
- struct smtp_server_cmd_ctx *cmd,
struct smtp_server_recipient *rcpt);
-void lmtp_recipient_finish(struct lmtp_recipient *lrcpt);
-
struct lmtp_recipient *
lmtp_recipient_find_duplicate(struct lmtp_recipient *lrcpt,
struct smtp_server_transaction *trans);
{
struct client *client = llrcpt->rcpt.client;
struct smtp_server_recipient *rcpt = llrcpt->rcpt.rcpt;
- struct smtp_server_cmd_ctx *cmd = llrcpt->rcpt.rcpt_cmd;
+ struct smtp_server_cmd_ctx *cmd = rcpt->cmd;
struct smtp_address *address = rcpt->path;
struct mail_user *user;
struct mail_namespace *ns;
{
struct client *client = llrcpt->rcpt.client;
- lmtp_recipient_finish(&llrcpt->rcpt);
-
/* resolve duplicate recipient */
llrcpt->duplicate = (struct lmtp_local_recipient *)
lmtp_recipient_find_duplicate(&llrcpt->rcpt, rcpt->trans);
static bool
lmtp_local_rcpt_anvil_finish(struct lmtp_local_recipient *llrcpt)
{
- struct smtp_server_cmd_ctx *cmd = llrcpt->rcpt.rcpt_cmd;
+ struct smtp_server_recipient *rcpt = llrcpt->rcpt.rcpt;
+ struct smtp_server_cmd_ctx *cmd = rcpt->cmd;
int ret;
if ((ret = lmtp_local_rcpt_check_quota(llrcpt)) < 0)
{
struct lmtp_local_recipient *llrcpt =
(struct lmtp_local_recipient *)context;
- struct smtp_server_cmd_ctx *cmd = llrcpt->rcpt.rcpt_cmd;
struct client *client = llrcpt->rcpt.client;
struct smtp_server_recipient *rcpt = llrcpt->rcpt.rcpt;
+ struct smtp_server_cmd_ctx *cmd = rcpt->cmd;
struct smtp_address *address = rcpt->path;
const struct mail_storage_service_input *input;
unsigned int parallel_count = 0;
llrcpt = p_new(rcpt->pool, struct lmtp_local_recipient, 1);
lmtp_recipient_init(&llrcpt->rcpt, client,
- LMTP_RECIPIENT_TYPE_LOCAL, cmd, rcpt);
+ LMTP_RECIPIENT_TYPE_LOCAL, rcpt);
llrcpt->detail = p_strdup(rcpt->pool, detail);
llrcpt->service_user = service_user;
{
struct client *client = lprcpt->rcpt.client;
- lmtp_recipient_finish(&lprcpt->rcpt);
-
/* add to proxy recipients */
array_append(&client->proxy->rcpt_to, &lprcpt, 1);
}
lmtp_proxy_rcpt_cb(const struct smtp_reply *proxy_reply,
struct lmtp_proxy_recipient *lprcpt)
{
- struct smtp_server_cmd_ctx *cmd = lprcpt->rcpt.rcpt_cmd;
+ struct smtp_server_recipient *rcpt = lprcpt->rcpt.rcpt;
+ struct smtp_server_cmd_ctx *cmd = rcpt->cmd;
struct smtp_reply reply;
if (!lmtp_proxy_handle_reply(cmd, proxy_reply, &reply))
lprcpt = p_new(rcpt->pool, struct lmtp_proxy_recipient, 1);
lmtp_recipient_init(&lprcpt->rcpt, client,
- LMTP_RECIPIENT_TYPE_PROXY, cmd, rcpt);
+ LMTP_RECIPIENT_TYPE_PROXY, rcpt);
lprcpt->address = smtp_address_clone(rcpt->pool, address);
lprcpt->conn = conn;