]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
submission: Add submission_backend_capabilities setting.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Wed, 3 Oct 2018 23:37:24 +0000 (01:37 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Tue, 9 Oct 2018 06:41:17 +0000 (06:41 +0000)
This can be used to specify which capabilities the (relay) backend supports,
avoiding the need to query the backend explicitly before the EHLO reply is sent
to the client.

src/submission/submission-backend-relay.c
src/submission/submission-backend-relay.h
src/submission/submission-client.c
src/submission/submission-client.h
src/submission/submission-commands.c
src/submission/submission-settings.c
src/submission/submission-settings.h

index ace0519801d580c705e40f8a83f6940260d26eab..43244d1b9839a609e28c71abccc5ac3a384b6949 100644 (file)
@@ -166,6 +166,8 @@ int cmd_helo_relay(struct client *client, struct smtp_server_cmd_ctx *cmd,
        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;
@@ -319,6 +321,8 @@ int cmd_mail_relay(struct client *client, struct smtp_server_cmd_ctx *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;
@@ -793,7 +797,6 @@ static void client_proxy_ready_cb(const struct smtp_reply *reply,
 {
        struct client *client = context;
        struct submission_backend_relay *backend = &client->backend;
-       enum smtp_capability caps;
 
        /* check relay status */
        if ((reply->status / 100) != 2) {
@@ -804,25 +807,23 @@ static void client_proxy_ready_cb(const struct smtp_reply *reply,
                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 */
index 9aa6d0f8a6335af5fa7b4a68d97423168750c5e0..94fe6b9f107aaadc8cb0d33e62a092b9eabca7cd 100644 (file)
@@ -28,6 +28,7 @@ struct submission_backend_relay {
        struct smtp_client_connection *conn;
 
        bool xclient_sent:1;
+       bool started:1;
 };
 
 void client_proxy_create(struct client *client,
index f0d9c655dc19e75db2da4d197ed9e34e7dccc8a2..976c8180a483730d245f886c9d3e91fb97a56a6d 100644 (file)
@@ -69,6 +69,58 @@ static const char *client_remote_id(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 };
@@ -132,17 +184,25 @@ struct client *client_create(int fd_in, int fd_out,
                        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' &&
index 6c977fb6993cad3a40900f2ffd219f6361e11355..71d73b4d1754271062c83f970dfd4510babc908b 100644 (file)
@@ -36,12 +36,14 @@ struct client {
 
        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;
@@ -61,6 +63,10 @@ void client_disconnect(struct client *client, const char *prefix,
 
 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);
index 055a05c68eae7d9ae72272bb41194aebfa0e522f..fec5e02b79c8db437dc7adc7979f90603d3eacfa 100644 (file)
@@ -11,8 +11,6 @@
 #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"
@@ -26,9 +24,7 @@ void submission_helo_reply_submit(struct smtp_server_cmd_ctx *cmd,
                                  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;
 
@@ -51,16 +47,16 @@ void submission_helo_reply_submit(struct smtp_server_cmd_ctx *cmd,
                                    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");
index ed962851fcefa756f8a27a81551da080859da604..99fdfb008200c51ab2b64f90bd1e6c0f7c4a9d95 100644 (file)
@@ -70,6 +70,8 @@ static const struct setting_define submission_setting_defines[] = {
        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),
@@ -107,6 +109,8 @@ static const struct submission_settings submission_default_settings = {
        .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,
index c033c7dc8c1999bae6f0f34f9114d8e17bd688f7..691cd8970e1c35e1c2445963aaa543a352122fe1 100644 (file)
@@ -25,6 +25,9 @@ struct submission_settings {
        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;