56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#ifndef SMTP_SERVER_H
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#define SMTP_SERVER_H
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "smtp-common.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "smtp-command.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "smtp-params.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_address;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_reply;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_command;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_helo_data;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_esmtp_param;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_cmd_ehlo;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_cmd_mail;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_cmd_ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_command;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_reply;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/*
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch * Types
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschenum smtp_server_state {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_STATE_GREETING = 0,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_STATE_XCLIENT,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_STATE_HELO,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_STATE_STARTTLS,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_STATE_AUTH,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_STATE_READY,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_STATE_MAIL_FROM,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_STATE_RCPT_TO,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_STATE_DATA,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschextern const char *const smtp_server_state_names[];
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_helo_data {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *domain;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool domain_valid:1; /* valid domain/literal specified */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool old_smtp:1; /* client sent HELO rather than EHLO */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/*
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch * Transaction
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_recipient {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_address *path;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_params_rcpt params;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void *context;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan BoschARRAY_DEFINE_TYPE(smtp_server_recipient, struct smtp_server_recipient *);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_transaction {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch pool_t pool;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_connection *conn;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *id;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct timeval timestamp;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_address *mail_from;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_params_mail params;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ARRAY_TYPE(smtp_server_recipient) rcpt_to;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void *context;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
499ca6dc5d746fd7a7efc6d497deede89553669fStephan Boschstruct smtp_server_recipient *
499ca6dc5d746fd7a7efc6d497deede89553669fStephan Boschsmtp_server_transaction_find_rcpt_duplicate(
499ca6dc5d746fd7a7efc6d497deede89553669fStephan Bosch struct smtp_server_transaction *trans,
499ca6dc5d746fd7a7efc6d497deede89553669fStephan Bosch struct smtp_server_recipient *rcpt);
499ca6dc5d746fd7a7efc6d497deede89553669fStephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_transaction_fail_data(
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_transaction *trans,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *data_cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int status, const char *enh_code,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fmt, va_list args) ATTR_FORMAT(5, 0);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_transaction_write_trace_record(string_t *str,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_transaction *trans);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/*
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch * Callbacks
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_cmd_helo {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_helo_data helo;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool first:1; /* this is the first */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool changed:1; /* this EHLO/HELO/LHLO is the first or
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch different from a previous one */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_cmd_mail {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_address *path;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_params_mail params;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct timeval timestamp;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_cmd_rcpt {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_address *path;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_params_rcpt params;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* called once the recipient is definitively added to the transaction */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void (*hook_finished)(struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_transaction *trans,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_recipient *rcpt,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int index);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void *trans_context;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_cmd_auth {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *sasl_mech;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *initial_response;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_callbacks {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* Command callbacks:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch These are used to override/implement the behavior of the various core
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP commands. Commands are handled asynchronously, which means that
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch the command is not necessarily finished when the callback ends. A
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch command is finished either when 1 is returned or a reply is submitted
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch for it. When a callback returns 0, the command implementation is
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch waiting for an external event and when it returns -1 an error
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch occurred. When 1 is returned, a default success reply is set if no
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch reply was submitted. Not submitting an error reply when -1 is
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch returned causes an assert fail. Except for RCPT and DATA, all these
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch callbacks are optional to implement; appropriate default behavior is
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch provided.
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch The SMTP server API takes care of transaction state checking.
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch However, until all previous commands are handled, a transaction
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch command cannot rely on the transaction state being final. Use
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd->hook_next to get notified when all previous commands are
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch finished and the current command is next in line to reply.
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch If the implementation does not need asynchronous behavior, set
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch max_pipelined_commands=1 and don't return 0 from any command handler.
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* HELO/EHLO/LHLO */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_helo)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_helo *data);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* STARTTLS */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_starttls)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* AUTH */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_auth)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_auth *data);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_auth_continue)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd, const char *response);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* MAIL */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_mail)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_mail *data);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* RCPT */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_rcpt)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_rcpt *data);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* RSET */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_rset)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* DATA */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_data_begin)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_transaction *trans,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct istream *data_input);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_data_continue)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_transaction *trans);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* VRFY */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_vrfy)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *param);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* NOOP */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_noop)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* QUIT */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int (*conn_cmd_quit)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* XCLIENT */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void (*conn_cmd_xclient)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_proxy_data *data);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* Command input callbacks:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch These can be used to do stuff before and after a pipelined group of
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch commands is read.
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void (*conn_cmd_input_pre)(void *context);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void (*conn_cmd_input_post)(void *context);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* Transaction events */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void (*conn_trans_free)(void *context,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_transaction *trans);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* Protocol state events */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void (*conn_state_changed)(void *context,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch enum smtp_server_state newstate);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* Proxy data */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void (*conn_proxy_data_updated)(void *conn_ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct smtp_proxy_data *data);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* Connection */
9249c80276766fdc4d31fc3eebc22fba7d53d77cStephan Bosch int (*conn_start_tls)(void *conn_ctx,
9249c80276766fdc4d31fc3eebc22fba7d53d77cStephan Bosch struct istream **input, struct ostream **output);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void (*conn_disconnect)(void *context, const char *reason);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void (*conn_destroy)(void *context);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* Security */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool (*conn_is_trusted)(void *context);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/*
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch * Server
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_settings {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch enum smtp_protocol protocol;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch enum smtp_capability capabilities;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *hostname;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *login_greeting;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *rawlog_dir;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* The maximum time in milliseconds a client is allowed to be idle
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch before it is disconnected. */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int max_client_idle_time_msecs;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* maximum number of commands in pipeline per connection (default = 1)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int max_pipelined_commands;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* maximum number of sequential bad commands */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int max_bad_commands;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch /* maximum number of recipients in a transaction
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch (0 means unlimited, which is the default) */
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch unsigned int max_recipients;
4dd460cf19f1df3b51090427fea87e9c4b73c6d4Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* command limits */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_command_limits command_limits;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* accept these additional custom XCLIENT fields */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *const *xclient_extensions;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* The kernel send/receive buffer sizes used for the connection sockets.
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch Configuring this is mainly useful for the test suite. The kernel
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch defaults are used when these settings are 0. */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch size_t socket_send_buffer_size;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch size_t socket_recv_buffer_size;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool debug:1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool auth_optional:1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool tls_required:1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool rcpt_domain_optional:1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool param_extensions:1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_stats {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int command_count, reply_count;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch uoff_t input, output;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server *smtp_server_init(const struct smtp_server_settings *set);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_deinit(struct smtp_server **_server);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/*
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch * Connection
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Create connection. It is still inactive and needs to be started with
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch one of the functions below. */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_connection *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_connection_create(struct smtp_server *server,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int fd_in, int fd_out,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct ip_addr *remote_ip, in_port_t remote_port,
40a926a1aeae93b3d4944b56eacb013d3059b549Stephan Bosch bool ssl_start, const struct smtp_server_settings *set,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct smtp_server_callbacks *callbacks, void *context)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ATTR_NULL(4, 6, 8);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_connection *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_connection_create_from_streams(struct smtp_server *server,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct istream *input, struct ostream *output,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct ip_addr *remote_ip, in_port_t remote_port,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct smtp_server_settings *set,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct smtp_server_callbacks *callbacks, void *context)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ATTR_NULL(4, 6, 8);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_connection_ref(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschbool smtp_server_connection_unref(struct smtp_server_connection **_conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
6b312949dcd641f1196dd299240dec03b46b5042Stephan Bosch/* Initialize the connection with state and data from login service */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_connection_login(struct smtp_server_connection *conn,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *username, const char *helo,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const unsigned char *pdata,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int pdata_len, bool ssl_secured);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
b85a1bcaa9f82dd5b326967da5f1a26595173ee9Stephan Bosch/* Start the connection. Establishes SSL layer immediately if instructed,
b85a1bcaa9f82dd5b326967da5f1a26595173ee9Stephan Bosch and sends the greeting once the connection is ready for commands. */
b85a1bcaa9f82dd5b326967da5f1a26595173ee9Stephan Boschvoid smtp_server_connection_start(struct smtp_server_connection *conn);
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch/* Start the connection, but only establish SSL layer and send greeting;
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch handling command input is held off until smtp_server_connection_resume() is
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch called. */
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Boschvoid smtp_server_connection_start_pending(struct smtp_server_connection *conn);
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch/* Halt connection command input and idle timeout entirely. */
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Boschvoid smtp_server_connection_halt(struct smtp_server_connection *conn);
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Bosch/* Resume connection command input and idle timeout. */
912e87d5be9dd8895e8cb7c6cb51d8a752edbe8cStephan Boschvoid smtp_server_connection_resume(struct smtp_server_connection *conn);
b85a1bcaa9f82dd5b326967da5f1a26595173ee9Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_connection_input_lock(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_connection_input_unlock(struct smtp_server_connection *conn);
55f1e5a6f22a7ea13a12b17be715e661e7f02471Stephan Bosch
55f1e5a6f22a7ea13a12b17be715e661e7f02471Stephan Boschvoid smtp_server_connection_set_streams(struct smtp_server_connection *conn,
55f1e5a6f22a7ea13a12b17be715e661e7f02471Stephan Bosch struct istream *input, struct ostream *output);
55f1e5a6f22a7ea13a12b17be715e661e7f02471Stephan Boschvoid smtp_server_connection_set_ssl_streams(struct smtp_server_connection *conn,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct istream *input, struct ostream *output);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_connection_close(struct smtp_server_connection **_conn,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *reason) ATTR_NULL(2);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_connection_terminate(struct smtp_server_connection **_conn,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *enh_code, const char *reason)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ATTR_NULL(3);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschbool smtp_server_connection_data_check_state(struct smtp_server_cmd_ctx *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_connection_data_chunk_init(struct smtp_server_cmd_ctx *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschint smtp_server_connection_data_chunk_add(struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct istream *chunk, uoff_t chunk_size, bool chunk_last,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch bool client_input);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschenum smtp_server_state
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_connection_get_state(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschconst char *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_connection_get_security_string(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_transaction *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_connection_get_transaction(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschconst char *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_connection_get_transaction_id(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschconst struct smtp_server_stats *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_connection_get_stats(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid *smtp_server_connection_get_context(struct smtp_server_connection *conn)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ATTR_PURE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschenum smtp_protocol
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_connection_get_protocol(struct smtp_server_connection *conn)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ATTR_PURE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschconst char *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_connection_get_protocol_name(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_helo_data *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_connection_get_helo_data(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_connection_get_proxy_data(struct smtp_server_connection *conn,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_proxy_data *proxy_data);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_connection_set_capabilities(
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_connection *conn, enum smtp_capability capabilities);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschbool smtp_server_connection_is_ssl_secured(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschbool smtp_server_connection_is_trusted(struct smtp_server_connection *conn);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/*
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch * Command
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschenum smtp_server_command_flags {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_CMD_FLAG_PRETLS = BIT(0),
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch SMTP_SERVER_CMD_FLAG_PREAUTH = BIT(1)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Commands are handled asynchronously, which means that the command is not
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch necessary finished when the start function ends. A command is finished
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch when a reply is submitted for it. Several command hooks are available to
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch get notified about events in the command's life cycle.
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschtypedef void smtp_server_cmd_input_callback_t(struct smtp_server_cmd_ctx *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschtypedef void smtp_server_cmd_start_func_t(struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *params);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschtypedef void smtp_server_cmd_func_t(struct smtp_server_cmd_ctx *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_cmd_ctx {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch pool_t pool;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *name;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server *server;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_connection *conn;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct smtp_server_command *cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* public hooks */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* next: command is next to reply but has not submittted all replies
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch yet */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_cmd_func_t *hook_next;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* replied: command has submitted all replies */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_cmd_func_t *hook_replied;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* completed: server is about to send last replies for this command */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_cmd_func_t *hook_completed;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* destroy: command is about to be destroyed */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_cmd_func_t *hook_destroy;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch void *context;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* The core SMTP commands are pre-registered. Special connection callbacks are
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch provided for the core SMTP commands. Only use this command registration API
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch when custom/extension SMTP commands are required.
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_command_register(struct smtp_server *server, const char *name,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_cmd_start_func_t *func,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch enum smtp_server_command_flags);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_command_unregister(struct smtp_server *server,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *name);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_command_set_reply_count(struct smtp_server_command *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int count);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_command_fail(struct smtp_server_command *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int status, const char *enh_code,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fmt, ...) ATTR_FORMAT(4, 5);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_reply *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_command_get_reply(struct smtp_server_command *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int idx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschbool smtp_server_command_reply_status_equals(struct smtp_server_command *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int status);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschbool smtp_server_command_is_replied(struct smtp_server_command *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschbool smtp_server_command_replied_success(struct smtp_server_command *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_command_input_lock(struct smtp_server_cmd_ctx *cmd);
e69ac57b1a97e56011e988564985728be31bfb2aStephan Boschvoid smtp_server_command_input_unlock(struct smtp_server_cmd_ctx *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_command_input_capture(struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch smtp_server_cmd_input_callback_t *callback);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* AUTH */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_cmd_auth_send_challenge(struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *challenge);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_cmd_auth_success(struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *username, const char *success_msg)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ATTR_NULL(3);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/*
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch * Reply
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_reply *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_reply_create_index(struct smtp_server_command *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int index, unsigned int status, const char *enh_code)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ATTR_NULL(3);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_reply *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_reply_create(struct smtp_server_command *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int status, const char *enh_code) ATTR_NULL(3);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_reply *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_reply_create_forward(struct smtp_server_command *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int index, const struct smtp_reply *from);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_add_text(struct smtp_server_reply *reply,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *line);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_submit(struct smtp_server_reply *reply);
3aabd70db569ee56c48ad3a8d216091e7cb07215Stephan Boschvoid smtp_server_reply_submit_duplicate(struct smtp_server_cmd_ctx *_cmd,
3aabd70db569ee56c48ad3a8d216091e7cb07215Stephan Bosch unsigned int index,
3aabd70db569ee56c48ad3a8d216091e7cb07215Stephan Bosch unsigned int from_index);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Submit a reply for the command at the specified index (> 0 only if more than
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch a single reply is expected). */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_indexv(struct smtp_server_cmd_ctx *_cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int index, unsigned int status, const char *enh_code,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fmt, va_list args) ATTR_FORMAT(5, 0);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_index(struct smtp_server_cmd_ctx *_cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int index, unsigned int status, const char *enh_code,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fmt, ...) ATTR_FORMAT(5, 6);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Submit the reply for the specified command. */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply(struct smtp_server_cmd_ctx *_cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int status, const char *enh_code, const char *fmt, ...)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ATTR_FORMAT(4, 5);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Forward a reply for the command at the specified index (> 0 only if more
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch than a single reply is expected). */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_index_forward(struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int index, const struct smtp_reply *from);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Forward the reply for the specified command. */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_forward(struct smtp_server_cmd_ctx *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct smtp_reply *from);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Submit the same message for all expected replies for this command. */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_all(struct smtp_server_cmd_ctx *_cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int status, const char *enh_code,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fmt, ...) ATTR_FORMAT(4, 5);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Submit and send the same message for all expected replies for this command
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch early; i.e., no matter whether all command data is received completely. */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_early(struct smtp_server_cmd_ctx *_cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int status, const char *enh_code,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fmt, ...) ATTR_FORMAT(4, 5);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Reply the command with a 221 bye message */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_quit(struct smtp_server_cmd_ctx *_cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_switch_ioloop(struct smtp_server *server);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* EHLO */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct smtp_server_reply *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschsmtp_server_reply_create_ehlo(struct smtp_server_command *cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_ehlo_add(struct smtp_server_reply *reply,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *keyword);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_ehlo_add_param(struct smtp_server_reply *reply,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *keyword, const char *param_fmt, ...) ATTR_FORMAT(3, 4);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid smtp_server_reply_ehlo_add_xclient(struct smtp_server_reply *reply);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#endif