struct submission_backend_relay *backend = &client->backend;
struct relay_cmd_helo_context *helo;
+ client_proxy_start(client);
+
helo = p_new(cmd->pool, struct relay_cmd_helo_context, 1);
helo->backend = backend;
helo->cmd = cmd;
relay_cmd_mail_update_xclient(backend);
+ client_proxy_start(client);
+
/* queue command (pipeline) */
mail_cmd = p_new(cmd->pool, struct relay_cmd_mail_context, 1);
mail_cmd->backend = backend;
{
struct client *client = context;
struct submission_backend_relay *backend = &client->backend;
- enum smtp_capability caps;
/* check relay status */
if ((reply->status / 100) != 2) {
return;
}
- /* propagate capabilities */
- caps = smtp_client_connection_get_capabilities(backend->conn);
- caps |= SMTP_CAPABILITY_AUTH | SMTP_CAPABILITY_PIPELINING |
- SMTP_CAPABILITY_SIZE | SMTP_CAPABILITY_ENHANCEDSTATUSCODES |
- SMTP_CAPABILITY_CHUNKING | SMTP_CAPABILITY_BURL |
- SMTP_CAPABILITY_VRFY;
- caps &= SUBMISSION_SUPPORTED_SMTP_CAPABILITIES;
- smtp_server_connection_set_capabilities(client->conn, caps);
-
- /* now that we know our capabilities, commence server protocol dialog */
- smtp_server_connection_resume(client->conn);
+ /* notify the client about the fact that we're ready and propagate our
+ capabilities */
+ client_default_backend_started(client,
+ smtp_client_connection_get_capabilities(backend->conn));
}
void client_proxy_start(struct client *client)
{
struct submission_backend_relay *backend = &client->backend;
+ if (backend->started)
+ return;
+
smtp_client_connection_connect(backend->conn,
client_proxy_ready_cb, client);
+
+ backend->started = TRUE;
}
/* try to proxy pipelined commands in a similarly pipelined fashion */
struct smtp_client_connection *conn;
bool xclient_sent:1;
+ bool started:1;
};
void client_proxy_create(struct client *client,
return addr;
}
+static void client_parse_backend_capabilities(struct client *client)
+{
+ const struct submission_settings *set = client->set;
+ const char *const *str;
+
+ client->backend_capabilities = SMTP_CAPABILITY_NONE;
+ if (set->submission_backend_capabilities == NULL)
+ return;
+
+ str = t_strsplit_spaces(set->submission_backend_capabilities, " ,");
+ for (; *str != NULL; str++) {
+ enum smtp_capability cap = smtp_capability_find_by_name(*str);
+
+ if (cap == SMTP_CAPABILITY_NONE) {
+ i_warning("Unknown SMTP capability in submission_backend_capabilities: "
+ "%s", *str);
+ continue;
+ }
+
+ client->backend_capabilities |= cap;
+ }
+
+ client->backend_capabilities_configured = TRUE;
+}
+
+void client_apply_backend_capabilities(struct client *client)
+{
+ enum smtp_capability caps = client->backend_capabilities;
+
+ /* propagate capabilities */
+ caps |= SMTP_CAPABILITY_AUTH | SMTP_CAPABILITY_PIPELINING |
+ SMTP_CAPABILITY_SIZE | SMTP_CAPABILITY_ENHANCEDSTATUSCODES |
+ SMTP_CAPABILITY_CHUNKING | SMTP_CAPABILITY_BURL |
+ SMTP_CAPABILITY_VRFY;
+ caps &= SUBMISSION_SUPPORTED_SMTP_CAPABILITIES;
+ smtp_server_connection_set_capabilities(client->conn, caps);
+}
+
+void client_default_backend_started(struct client *client,
+ enum smtp_capability caps)
+{
+ /* propagate capabilities from backend to frontend */
+ if (!client->backend_capabilities_configured) {
+ client->backend_capabilities = caps;
+ client_apply_backend_capabilities(client);
+
+ /* resume the server now that we have the backend
+ capabilities */
+ smtp_server_connection_resume(client->conn);
+ }
+}
+
static void client_init_urlauth(struct client *client)
{
static const char *access_apps[] = { "submit+", NULL };
SMTP_SERVER_WORKAROUND_MAILBOX_FOR_PATH;
}
+ client_parse_backend_capabilities(client);
+
client->conn = smtp_server_connection_create(smtp_server,
fd_in, fd_out, user->conn.remote_ip, user->conn.remote_port,
FALSE, &smtp_set, &smtp_callbacks, client);
client_proxy_create(client, set);
- client_proxy_start(client);
smtp_server_connection_login(client->conn,
client->user->username, helo,
pdata, pdata_len, user->conn.ssl_secured);
- smtp_server_connection_start_pending(client->conn);
+
+ if (client->backend_capabilities_configured) {
+ client_apply_backend_capabilities(client);
+ smtp_server_connection_start(client->conn);
+ } else {
+ client_proxy_start(client);
+ smtp_server_connection_start_pending(client->conn);
+ }
mail_set = mail_user_set_get_storage_set(user);
if (*set->imap_urlauth_host != '\0' &&
struct smtp_server_stats stats;
+ enum smtp_capability backend_capabilities;
struct submission_backend_relay backend;
bool standalone:1;
bool disconnected:1;
bool destroyed:1;
bool anvil_sent:1;
+ bool backend_capabilities_configured:1;
};
extern struct client *submission_clients;
typedef void (*client_input_callback_t)(struct client *context);
+void client_apply_backend_capabilities(struct client *client);
+void client_default_backend_started(struct client *client,
+ enum smtp_capability caps);
+
const char *client_state_get_name(struct client *client);
uoff_t client_get_max_mail_size(struct client *client);
#include "imap-msgpart-url.h"
#include "imap-urlauth.h"
#include "imap-urlauth-fetch.h"
-#include "smtp-client.h"
-#include "smtp-client-connection.h"
#include "submission-recipient.h"
#include "submission-commands.h"
struct smtp_server_cmd_helo *data)
{
struct client *client = smtp_server_connection_get_context(cmd->conn);
- struct submission_backend_relay *backend = &client->backend;
- enum smtp_capability proxy_caps =
- smtp_client_connection_get_capabilities(backend->conn);
+ enum smtp_capability backend_caps = client->backend_capabilities;
struct smtp_server_reply *reply;
uoff_t cap_size;
client->set->imap_urlauth_port);
}
- if ((proxy_caps & SMTP_CAPABILITY_8BITMIME) != 0)
+ if ((backend_caps & SMTP_CAPABILITY_8BITMIME) != 0)
smtp_server_reply_ehlo_add(reply, "8BITMIME");
smtp_server_reply_ehlo_add(reply, "AUTH");
- if ((proxy_caps & SMTP_CAPABILITY_BINARYMIME) != 0 &&
- (proxy_caps & SMTP_CAPABILITY_CHUNKING) != 0)
+ if ((backend_caps & SMTP_CAPABILITY_BINARYMIME) != 0 &&
+ (backend_caps & SMTP_CAPABILITY_CHUNKING) != 0)
smtp_server_reply_ehlo_add(reply, "BINARYMIME");
smtp_server_reply_ehlo_add_param(reply,
"BURL", "%s", str_c(burl_params));
smtp_server_reply_ehlo_add(reply, "CHUNKING");
- if ((proxy_caps & SMTP_CAPABILITY_DSN) != 0)
+ if ((backend_caps & SMTP_CAPABILITY_DSN) != 0)
smtp_server_reply_ehlo_add(reply, "DSN");
smtp_server_reply_ehlo_add(reply,
"ENHANCEDSTATUSCODES");
DEF(SET_STR, submission_client_workarounds),
DEF(SET_STR, submission_logout_format),
+ DEF(SET_STR, submission_backend_capabilities),
+
DEF(SET_STR, submission_relay_host),
DEF(SET_IN_PORT, submission_relay_port),
DEF(SET_BOOL, submission_relay_trusted),
.submission_client_workarounds = "",
.submission_logout_format = "in=%i out=%o",
+ .submission_backend_capabilities = NULL,
+
.submission_relay_host = "",
.submission_relay_port = 25,
.submission_relay_trusted = FALSE,
const char *submission_client_workarounds;
const char *submission_logout_format;
+ /* submission backend: */
+ const char *submission_backend_capabilities;
+
/* submission relay: */
const char *submission_relay_host;
in_port_t submission_relay_port;