summaryrefslogtreecommitdiffstats
path: root/src/lib-smtp/smtp-client-transaction.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
commitf7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch)
treea3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /src/lib-smtp/smtp-client-transaction.h
parentInitial commit. (diff)
downloaddovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.tar.xz
dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.zip
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib-smtp/smtp-client-transaction.h')
-rw-r--r--src/lib-smtp/smtp-client-transaction.h259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/lib-smtp/smtp-client-transaction.h b/src/lib-smtp/smtp-client-transaction.h
new file mode 100644
index 0000000..d0cc58b
--- /dev/null
+++ b/src/lib-smtp/smtp-client-transaction.h
@@ -0,0 +1,259 @@
+#ifndef SMTP_CLIENT_TRANSACTION_H
+#define SMTP_CLIENT_TRANSACTION_H
+
+#include "net.h"
+#include "istream.h"
+
+struct smtp_address;
+struct smtp_client_transaction;
+struct smtp_client_transaction_mail;
+struct smtp_client_transaction_rcpt;
+
+enum smtp_client_transaction_flags {
+ SMTP_CLIENT_TRANSACTION_FLAG_REPLY_PER_RCPT = BIT(0),
+};
+
+enum smtp_client_transaction_state {
+ SMTP_CLIENT_TRANSACTION_STATE_NEW = 0,
+ SMTP_CLIENT_TRANSACTION_STATE_PENDING,
+ SMTP_CLIENT_TRANSACTION_STATE_MAIL_FROM,
+ SMTP_CLIENT_TRANSACTION_STATE_RCPT_TO,
+ SMTP_CLIENT_TRANSACTION_STATE_DATA,
+ SMTP_CLIENT_TRANSACTION_STATE_RESET,
+ SMTP_CLIENT_TRANSACTION_STATE_FINISHED,
+ SMTP_CLIENT_TRANSACTION_STATE_ABORTED
+ /* NOTE: keep synced with smtp_client_transaction_state_names[] */
+};
+extern const char *const smtp_client_transaction_state_names[];
+
+struct smtp_client_transaction_times {
+ struct timeval started;
+ struct timeval finished;
+};
+
+/* Called when the transaction is finished, either because the MAIL FROM
+ failed, all RCPT TOs failed or because all DATA replies have been
+ received. */
+typedef void
+smtp_client_transaction_callback_t(void *context);
+
+/* Create an empty transaction (i.e. even without the parameters for the
+ MAIL FROM command) */
+struct smtp_client_transaction *
+smtp_client_transaction_create_empty(
+ struct smtp_client_connection *conn,
+ enum smtp_client_transaction_flags flags,
+ smtp_client_transaction_callback_t *callback, void *context)
+ ATTR_NULL(4);
+#define smtp_client_transaction_create_empty(conn, flags, callback, context) \
+ smtp_client_transaction_create_empty(conn, flags - \
+ CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
+ (smtp_client_transaction_callback_t *)callback, context)
+/* Create a new transaction, including the parameters for the MAIL FROM
+ command */
+struct smtp_client_transaction *
+smtp_client_transaction_create(struct smtp_client_connection *conn,
+ const struct smtp_address *mail_from,
+ const struct smtp_params_mail *mail_params,
+ enum smtp_client_transaction_flags flags,
+ smtp_client_transaction_callback_t *callback, void *context)
+ ATTR_NULL(2, 3, 6);
+#define smtp_client_transaction_create(conn, \
+ mail_from, mail_params, flags, callback, context) \
+ smtp_client_transaction_create(conn, mail_from, mail_params, flags - \
+ CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
+ (smtp_client_transaction_callback_t *)callback, context)
+
+void smtp_client_transaction_ref(struct smtp_client_transaction *trans);
+void smtp_client_transaction_unref(struct smtp_client_transaction **_trans);
+void smtp_client_transaction_destroy(struct smtp_client_transaction **trans);
+
+void smtp_client_transaction_abort(struct smtp_client_transaction *trans);
+void smtp_client_transaction_fail_reply(struct smtp_client_transaction *trans,
+ const struct smtp_reply *reply);
+void smtp_client_transaction_fail(struct smtp_client_transaction *trans,
+ unsigned int status, const char *error);
+
+void smtp_client_transaction_set_event(struct smtp_client_transaction *trans,
+ struct event *event);
+void smtp_client_transaction_set_timeout(struct smtp_client_transaction *trans,
+ unsigned int timeout_msecs);
+
+/* Start the transaction with a MAIL command. The mail_from_callback is
+ called once the server replies to the MAIL FROM command. Calling this
+ function is not mandatory; it is called implicitly by
+ smtp_client_transaction_send() if the transaction wasn't already started.
+ */
+void smtp_client_transaction_start(struct smtp_client_transaction *trans,
+ smtp_client_command_callback_t *mail_callback, void *context);
+#define smtp_client_transaction_start(trans, mail_callback, context) \
+ smtp_client_transaction_start(trans, \
+ (smtp_client_command_callback_t *)mail_callback, TRUE ? context : \
+ CALLBACK_TYPECHECK(mail_callback, void (*)( \
+ const struct smtp_reply *reply, typeof(context))))
+/* Start the transaction with a MAIL command. This function allows providing the
+ parameters for the MAIL FROM command for when the transaction was created
+ empty. The mail_from_callback is called once the server replies to the MAIL
+ FROM command. Calling this function is not mandatory; it is called implicitly
+ by smtp_client_transaction_send() if the transaction wasn't already started.
+ In that case, the NULL sender ("<>") will be used when the transaction was
+ created empty.
+ */
+void smtp_client_transaction_start_empty(
+ struct smtp_client_transaction *trans,
+ const struct smtp_address *mail_from,
+ const struct smtp_params_mail *mail_params,
+ smtp_client_command_callback_t *mail_callback, void *context);
+#define smtp_client_transaction_start_empty(trans, mail_from, mail_params, \
+ mail_callback, context) \
+ smtp_client_transaction_start_empty(trans, mail_from, mail_params, \
+ (smtp_client_command_callback_t *)mail_callback, TRUE ? context : \
+ CALLBACK_TYPECHECK(mail_callback, void (*)( \
+ const struct smtp_reply *reply, typeof(context))))
+
+/* Add an extra pipelined MAIL command to the transaction. The mail_callback is
+ called once the server replies to the MAIL command. This is usually only
+ useful for forwarding pipelined SMTP transactions, which can involve more
+ than a single MAIL command (e.g. to have an implicit fallback sender address
+ in the pipeline when the first one fails). Of course, only one MAIL command
+ will succeed and therefore error replies for the others will not abort the
+ transaction. This function returns a struct that can be used to abort the
+ MAIL command prematurely (see below). */
+struct smtp_client_transaction_mail *
+smtp_client_transaction_add_mail(struct smtp_client_transaction *trans,
+ const struct smtp_address *mail_from,
+ const struct smtp_params_mail *mail_params,
+ smtp_client_command_callback_t *mail_callback,
+ void *context)
+ ATTR_NOWARN_UNUSED_RESULT ATTR_NULL(3,5);
+#define smtp_client_transaction_add_mail(trans, \
+ mail_from, mail_params, mail_callback, context) \
+ smtp_client_transaction_add_mail(trans, mail_from - \
+ CALLBACK_TYPECHECK(mail_callback, void (*)( \
+ const struct smtp_reply *reply, typeof(context))), \
+ mail_params, \
+ (smtp_client_command_callback_t *)mail_callback, context)
+/* Abort the MAIL command prematurely. This function must not be called after
+ the mail_callback from smtp_client_transaction_add_mail() is called. */
+void smtp_client_transaction_mail_abort(
+ struct smtp_client_transaction_mail **_mail);
+
+/* Add recipient to the transaction with a RCPT TO command. The
+ rcpt_to_callback is called once the server replies to the RCPT TO command.
+ If RCPT TO succeeded, the data_callback is called once the server replies
+ to the DATA command. The data_callback will not be called until
+ smtp_client_transaction_send() is called for the transaction (see below).
+ Until that time, any failure is remembered. This function returns a struct
+ that can be used to abort the RCPT command prematurely (see below). This
+ struct must not be used after the rcpt_callback is called. */
+struct smtp_client_transaction_rcpt *
+smtp_client_transaction_add_rcpt(struct smtp_client_transaction *trans,
+ const struct smtp_address *rcpt_to,
+ const struct smtp_params_rcpt *rcpt_params,
+ smtp_client_command_callback_t *rcpt_callback,
+ smtp_client_command_callback_t *data_callback,
+ void *context)
+ ATTR_NOWARN_UNUSED_RESULT ATTR_NULL(3,5,6);
+#define smtp_client_transaction_add_rcpt(trans, \
+ rcpt_to, rcpt_params, rcpt_callback, data_callback, context) \
+ smtp_client_transaction_add_rcpt(trans, rcpt_to - \
+ CALLBACK_TYPECHECK(rcpt_callback, void (*)( \
+ const struct smtp_reply *reply, typeof(context))) - \
+ CALLBACK_TYPECHECK(data_callback, void (*)( \
+ const struct smtp_reply *reply, typeof(context))), \
+ rcpt_params, \
+ (smtp_client_command_callback_t *)rcpt_callback, \
+ (smtp_client_command_callback_t *)data_callback, context)
+/* Add recipient to the transaction with a RCPT TO command. The
+ rcpt_to_callback is called once the server replies to the RCPT TO command.
+ This function returns a struct that can be used to abort the RCPT command
+ prematurely (see below). This struct is allocated on the provided pool (the
+ pool is referenced) and remains valid until the destruction of the
+ transaction.
+ */
+struct smtp_client_transaction_rcpt *
+smtp_client_transaction_add_pool_rcpt(
+ struct smtp_client_transaction *trans, pool_t pool,
+ const struct smtp_address *rcpt_to,
+ const struct smtp_params_rcpt *rcpt_params,
+ smtp_client_command_callback_t *rcpt_callback, void *context)
+ ATTR_NOWARN_UNUSED_RESULT ATTR_NULL(4,6,7);
+#define smtp_client_transaction_add_pool_rcpt(trans, pool, \
+ rcpt_to, rcpt_params, rcpt_callback, context) \
+ smtp_client_transaction_add_pool_rcpt(trans, pool, rcpt_to - \
+ CALLBACK_TYPECHECK(rcpt_callback, void (*)( \
+ const struct smtp_reply *reply, typeof(context))), \
+ rcpt_params, \
+ (smtp_client_command_callback_t *)rcpt_callback, context)
+/* Abort the RCPT command prematurely. This function must not be called after
+ the rcpt_callback from smtp_client_transaction_add_rcpt() is called. */
+void smtp_client_transaction_rcpt_abort(
+ struct smtp_client_transaction_rcpt **_rcpt);
+/* Set the DATA callback for this recipient. If RCPT TO succeeded, the callback
+ is called once the server replies to the DATA command. Until that time, any
+ failure is remembered. The callback will not be called until
+ smtp_client_transaction_send() is called for the transaction (see below). */
+void smtp_client_transaction_rcpt_set_data_callback(
+ struct smtp_client_transaction_rcpt *rcpt,
+ smtp_client_command_callback_t *callback, void *context)
+ ATTR_NULL(3);
+#define smtp_client_transaction_rcpt_set_data_callback(trans, \
+ callback, context) \
+ smtp_client_transaction_rcpt_set_data_callback(trans, \
+ (smtp_client_command_callback_t *)callback, \
+ (TRUE ? context : \
+ CALLBACK_TYPECHECK(callback, void (*)( \
+ const struct smtp_reply *reply, typeof(context)))))
+
+/* Start sending input stream as DATA. This completes the transaction, which
+ means that any pending failures that got recorded before this function was
+ called will be triggered now. If any RCPT TO succeeded, the provided
+ data_callback is called once the server replies to the DATA command. This
+ callback is mainly useful for SMTP, for LMTP it will only yield the reply for
+ the last recipient. This function starts the transaction implicitly. */
+void smtp_client_transaction_send(
+ struct smtp_client_transaction *trans, struct istream *data_input,
+ smtp_client_command_callback_t *data_callback, void *data_context);
+#define smtp_client_transaction_send(trans, \
+ data_input, data_callback, data_context) \
+ smtp_client_transaction_send(trans, data_input - \
+ CALLBACK_TYPECHECK(data_callback, void (*)( \
+ const struct smtp_reply *reply, typeof(data_context))), \
+ (smtp_client_command_callback_t *)data_callback, data_context)
+
+/* Gracefully reset the transaction by sending the RSET command and waiting for
+ the response. This does not try to abort pending MAIL and RCPT commands,
+ allowing the transaction to be evaluated without proceeding with the DATA
+ command. */
+void smtp_client_transaction_reset(
+ struct smtp_client_transaction *trans,
+ smtp_client_command_callback_t *reset_callback, void *reset_context);
+#define smtp_client_transaction_reset(trans, reset_callback, reset_context) \
+ smtp_client_transaction_reset(trans, \
+ (smtp_client_command_callback_t *)reset_callback, \
+ TRUE ? reset_context : \
+ CALLBACK_TYPECHECK(reset_callback, void (*)( \
+ const struct smtp_reply *reply, typeof(reset_context))))
+
+/* Enables mode in which all commands are submitted immediately and (non-
+ transaction) commands can be interleaved. This is mainly important for
+ relaying SMTP in realtime. */
+void smtp_client_transaction_set_immediate(
+ struct smtp_client_transaction *trans, bool immediate);
+
+/* Return transaction statistics. */
+const struct smtp_client_transaction_times *
+smtp_client_transaction_get_times(struct smtp_client_transaction *trans);
+
+/* Return transaction state */
+enum smtp_client_transaction_state
+smtp_client_transaction_get_state(struct smtp_client_transaction *trans)
+ ATTR_PURE;
+const char *
+smtp_client_transaction_get_state_name(struct smtp_client_transaction *trans)
+ ATTR_PURE;
+const char *
+smtp_client_transaction_get_state_destription(
+ struct smtp_client_transaction *trans);
+
+#endif