]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.9-20230903
authorWietse Venema <wietse@porcupine.org>
Sun, 3 Sep 2023 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Mon, 4 Sep 2023 16:21:30 +0000 (12:21 -0400)
15 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/WISHLIST
postfix/html/cleanup.8.html
postfix/html/postconf.5.html
postfix/man/man5/postconf.5
postfix/man/man8/cleanup.8
postfix/mantools/postlink
postfix/proto/postconf.proto
postfix/src/cleanup/cleanup.c
postfix/src/cleanup/cleanup_init.c
postfix/src/cleanup/cleanup_message.c
postfix/src/global/dict_mysql.c
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h

index d80549b426c799231983a231050cd30c07400d8e..e37bf54a4f5fb84b277633faef45e9970af756a8 100644 (file)
@@ -27326,7 +27326,7 @@ Apologies for any names omitted.
             *.other.example IN A     10.0.0.1
             *.other.example IN TLSA  ..certificate info...
 
-       Such syntax is blesed in RFC 1034 section 4.3.3.
+       Such syntax is blessed in RFC 1034 section 4.3.3.
 
        This problem was reported first in the context of TLSA
        record lookups. Files: util/valid_hostname.[hc],
@@ -27341,7 +27341,7 @@ Apologies for any names omitted.
 
 20230901
 
-       Feature: enforce_mime_input_conversion (default: no) to
+       Feature: force_mime_input_conversion (default: no) to
        convert content that claims to be 8-bit into quoted-printable,
        before header_checks, body_checks, Milters, and before
        after-queue content filters. The typical use case is an MTA
@@ -27352,3 +27352,17 @@ Apologies for any names omitted.
        limit. Files: global/mail_params.c, cleanup/cleanup_message.c,
        cleanup/cleanup.c, cleanup/cleanup_init.c, proto/postconf.proto,
        mantools/postlink.
+
+20230902
+
+       Cleanup: renamed enforce_mime_input_conversion to
+       force_mime_input_conversion.
+
+20230903
+
+       Cleanup: removed support for MySQL < 4.0 (released 2003),
+       removed the deprecated mysql_escape_string() call, added
+       the preferred mysql_real_escape_string_quote() call, and
+       added error handling for the unlikely case that the legacy
+       mysql_real_escape_string() returns an error. File:
+       global/dict_mysql.c.
index ddd29daff9888ee70518e85766bde2f0dd57aa6d..7396b3ee036bff70322e14b175be33edcaf8ebfa 100644 (file)
@@ -26,11 +26,17 @@ now also distributed with the more recent Eclipse Public License
 license of their choice. Those who are more comfortable with the
 IPL can continue with that license.
 
+Incompatible changes with snapshot 20230903
+===========================================
+
+The MySQL client no longer supports MySQL versions < 4.0. MySQL
+version 4.0 was released in 2003.
+
 Major changes with snapshot 20230901
 ====================================
 
-New parameter enforce_mime_input_conversion (default: no) to convert
-content that claims to be 8-bit into quoted-printable, before
+New parameter force_mime_input_conversion (default: no) to convert
+body content that claims to be 8-bit into quoted-printable, before
 header_checks, body_checks, Milters, and before after-queue content
 filters. This feature does not affect messages that are sent into
 smtpd_proxy_filter.
index 5a860c18d8e242884918bd23b1eac697621d7e9e..ee2cca0f151db31b4953da64c0b9695568c1ed34 100644 (file)
@@ -9,7 +9,7 @@ Wish list:
        postfix-install should mention makedefs.out.
 
        Update DKIM examples for signing with the benefits of forced
-       MIME converison with "enforce_mime_input_conversion = yes"
+       MIME converison with "force_mime_input_conversion = yes"
  
        Deprecate permit_mx_backup. It is fundamentally incompatible
        with recipient address validation. There is no way to fix that:
index 442ce03dbf74d85477c569b9d66fa0737a6040e1..42b048a6e8a5a5eb83b367d811fc0d8856a311bf 100644 (file)
@@ -515,9 +515,9 @@ CLEANUP(8)                                                          CLEANUP(8)
 
        Available in Postfix 3.9 and later:
 
-       <b><a href="postconf.5.html#enforce_mime_input_conversion">enforce_mime_input_conversion</a> (no)</b>
-              Convert content that claims to be 8-bit  into  quoted-printable,
-              before   <a href="postconf.5.html#header_checks">header_checks</a>,   <a href="postconf.5.html#body_checks">body_checks</a>,   Milters,   and   before
+       <b><a href="postconf.5.html#force_mime_input_conversion">force_mime_input_conversion</a> (no)</b>
+              Convert body content that claims to be 8-bit into  quoted-print-
+              able,  before  <a href="postconf.5.html#header_checks">header_checks</a>,  <a href="postconf.5.html#body_checks">body_checks</a>,  Milters, and before
               after-queue content filters.
 
 <b>FILES</b>
index d9bc50bc6475c2bde13778bde7274290000ac746..5588d27985fa15232d5a9c52183995697d278d3c 100644 (file)
@@ -3423,25 +3423,6 @@ instead of deleting only the non-delivery notification. </dd>
 <p> This feature is available in Postfix 3.6 and later. </p>
 
 
-</DD>
-
-<DT><b><a name="enforce_mime_input_conversion">enforce_mime_input_conversion</a>
-(default: no)</b></DT><DD>
-
-<p> Convert content that claims to be 8-bit into quoted-printable,
-before <a href="postconf.5.html#header_checks">header_checks</a>, <a href="postconf.5.html#body_checks">body_checks</a>, Milters, and before after-queue
-content filters. This feature does not affect messages that are
-sent into <a href="postconf.5.html#smtpd_proxy_filter">smtpd_proxy_filter</a>. </p>
-
-<p> The typical use case is an MTA that applies this conversion
-before signing outbound messages, so that the signatures will remain
-valid when a message is later delivered to an MTA that does not
-announce 8BITMIME support, or when a message line exceeds the SMTP
-length limit. </p>
-
-<p> This feature is available in Postfix &ge; 3.9. </p>
-
-
 </DD>
 
 <DT><b><a name="error_notice_recipient">error_notice_recipient</a>
@@ -3715,6 +3696,25 @@ This feature is available in Postfix 2.0 and later.
 </p>
 
 
+</DD>
+
+<DT><b><a name="force_mime_input_conversion">force_mime_input_conversion</a>
+(default: no)</b></DT><DD>
+
+<p> Convert body content that claims to be 8-bit into quoted-printable,
+before <a href="postconf.5.html#header_checks">header_checks</a>, <a href="postconf.5.html#body_checks">body_checks</a>, Milters, and before after-queue
+content filters. This feature does not affect messages that are
+sent into <a href="postconf.5.html#smtpd_proxy_filter">smtpd_proxy_filter</a>. </p>
+
+<p> The typical use case is an MTA that applies this conversion
+before signing outbound messages, so that the signatures will remain
+valid when a message is later delivered to an MTA that does not
+announce 8BITMIME support, or when a message line exceeds the SMTP
+length limit. </p>
+
+<p> This feature is available in Postfix &ge; 3.9. </p>
+
+
 </DD>
 
 <DT><b><a name="fork_attempts">fork_attempts</a>
index 8ddb007c2b01843e6d5cc9ee8e3be7caeb59f6a0..d6e3d8c6285ed3c205d6d77aa211301410f293dc 100644 (file)
@@ -2206,19 +2206,6 @@ instead of deleting only the non\-delivery notification.
 .br
 .PP
 This feature is available in Postfix 3.6 and later.
-.SH enforce_mime_input_conversion (default: no)
-Convert content that claims to be 8\-bit into quoted\-printable,
-before header_checks, body_checks, Milters, and before after\-queue
-content filters. This feature does not affect messages that are
-sent into smtpd_proxy_filter.
-.PP
-The typical use case is an MTA that applies this conversion
-before signing outbound messages, so that the signatures will remain
-valid when a message is later delivered to an MTA that does not
-announce 8BITMIME support, or when a message line exceeds the SMTP
-length limit.
-.PP
-This feature is available in Postfix >= 3.9.
 .SH error_notice_recipient (default: postmaster)
 The recipient of postmaster notifications about mail delivery
 problems that are caused by policy, resource, software or protocol
@@ -2368,6 +2355,19 @@ logfiles with the queue file names of mail that is queued for those
 destinations.
 .PP
 This feature is available in Postfix 2.0 and later.
+.SH force_mime_input_conversion (default: no)
+Convert body content that claims to be 8\-bit into quoted\-printable,
+before header_checks, body_checks, Milters, and before after\-queue
+content filters. This feature does not affect messages that are
+sent into smtpd_proxy_filter.
+.PP
+The typical use case is an MTA that applies this conversion
+before signing outbound messages, so that the signatures will remain
+valid when a message is later delivered to an MTA that does not
+announce 8BITMIME support, or when a message line exceeds the SMTP
+length limit.
+.PP
+This feature is available in Postfix >= 3.9.
 .SH fork_attempts (default: 5)
 The maximal number of attempts to fork() a child process.
 .SH fork_delay (default: 1s)
index d9170647ebfdcd82dbee14d259426ee67a456a8a..3180bc9f8a526bcbf8af0d8df8fb337938d7ccd6 100644 (file)
@@ -461,8 +461,8 @@ The email address form that will be used in non\-debug logging
 (info, warning, etc.).
 .PP
 Available in Postfix 3.9 and later:
-.IP "\fBenforce_mime_input_conversion (no)\fR"
-Convert content that claims to be 8\-bit into quoted\-printable,
+.IP "\fBforce_mime_input_conversion (no)\fR"
+Convert body content that claims to be 8\-bit into quoted\-printable,
 before header_checks, body_checks, Milters, and before after\-queue
 content filters.
 .SH "FILES"
index 54d29adb3e4ac731aafce358eba2b686387afce4..35337f5da5dd471d2a25840821d95b90bab1b58a 100755 (executable)
@@ -169,7 +169,7 @@ while (<>) {
     s;\bdisable_dns_lookups\b;<a href="postconf.5.html#disable_dns_lookups">$&</a>;g;
     s;\bdisable_mime_input_processing\b;<a href="postconf.5.html#disable_mime_input_processing">$&</a>;g;
     s;\bdisable_mime_output_conversion\b;<a href="postconf.5.html#disable_mime_output_conversion">$&</a>;g;
-    s;\benforce_mime_input_conversion\b;<a href="postconf.5.html#enforce_mime_input_conversion">$&</a>;g;
+    s;\bforce_mime_input_conversion\b;<a href="postconf.5.html#force_mime_input_conversion">$&</a>;g;
     s;\bdisable_verp_bounces\b;<a href="postconf.5.html#disable_verp_bounces">$&</a>;g;
     s;\bdisable_vrfy_command\b;<a href="postconf.5.html#disable_vrfy_command">$&</a>;g;
     s;\bdont_remove\b;<a href="postconf.5.html#dont_remove">$&</a>;g;
index 6de5a6c3ba219000e98d2025f79afa0ccd477ba9..c8523a90ab2d28171605b9efd2c5b2272e328ee9 100644 (file)
@@ -19027,9 +19027,9 @@ SMTP client input. This feature is enabled by default with Postfix
 <p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
 3.6.10, and 3.5.20. </p>
 
-%PARAM enforce_mime_input_conversion no
+%PARAM force_mime_input_conversion no
 
-<p> Convert content that claims to be 8-bit into quoted-printable,
+<p> Convert body content that claims to be 8-bit into quoted-printable,
 before header_checks, body_checks, Milters, and before after-queue
 content filters. This feature does not affect messages that are
 sent into smtpd_proxy_filter. </p>
index ab9ae249e55c0f9fd9b00a477a7a18af7f4b2efb..99e5a592ef2dc2cbf1a833cd6cdf1cad29fc33bc 100644 (file)
 /*     (info, warning, etc.).
 /* .PP
 /*     Available in Postfix 3.9 and later:
-/* .IP "\fBenforce_mime_input_conversion (no)\fR"
-/*     Convert content that claims to be 8-bit into quoted-printable,
+/* .IP "\fBforce_mime_input_conversion (no)\fR"
+/*     Convert body content that claims to be 8-bit into quoted-printable,
 /*     before header_checks, body_checks, Milters, and before after-queue
 /*     content filters.
 /* FILES
index a25068dd94120f82512166a7e2a50d8e4d59992e..ddf64b2884550869efe56f6c0fdc9b0176099eda 100644 (file)
@@ -174,7 +174,7 @@ int     var_auto_8bit_enc_hdr;              /* auto-detect 8bit encoding header */
 int     var_always_add_hdrs;           /* always add missing headers */
 int     var_virt_addrlen_limit;                /* stop exponential growth */
 char   *var_hfrom_format;              /* header_from_format */
-int     var_enforce_mime_iconv;                /* enforce mime downgrade on input */
+int     var_force_mime_iconv;          /* force mime downgrade on input */
 
 const CONFIG_INT_TABLE cleanup_int_table[] = {
     VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
@@ -191,7 +191,7 @@ const CONFIG_BOOL_TABLE cleanup_bool_table[] = {
     VAR_VERP_BOUNCE_OFF, DEF_VERP_BOUNCE_OFF, &var_verp_bounce_off,
     VAR_AUTO_8BIT_ENC_HDR, DEF_AUTO_8BIT_ENC_HDR, &var_auto_8bit_enc_hdr,
     VAR_ALWAYS_ADD_HDRS, DEF_ALWAYS_ADD_HDRS, &var_always_add_hdrs,
-    VAR_ENFORCE_MIME_ICONV, DEF_ENFORCE_MIME_ICONV, &var_enforce_mime_iconv,
+    VAR_FORCE_MIME_ICONV, DEF_FORCE_MIME_ICONV, &var_force_mime_iconv,
     0,
 };
 
index 3eb89386334053930ac6f03da70dfa4b14a29c73..bd951f34447730ed256c5557f645db690f397722 100644 (file)
@@ -1052,9 +1052,9 @@ void    cleanup_message(CLEANUP_STATE *state, int type, const char *buf, ssize_t
      */
     mime_options = 0;
     if (var_disable_mime_input) {
-       if (var_enforce_mime_iconv)
+       if (var_force_mime_iconv)
            msg_fatal("do not specify both %s=yes and %s=yes",
-                     VAR_DISABLE_MIME_INPUT, VAR_ENFORCE_MIME_ICONV);
+                     VAR_DISABLE_MIME_INPUT, VAR_FORCE_MIME_ICONV);
        mime_options |= MIME_OPT_DISABLE_MIME;
     } else {
        /* Turn off content checks if bouncing or forwarding mail. */
@@ -1071,7 +1071,7 @@ void    cleanup_message(CLEANUP_STATE *state, int type, const char *buf, ssize_t
                || *var_nesthdr_checks)
                mime_options |= MIME_OPT_REPORT_NESTING;
        }
-       if (var_enforce_mime_iconv)
+       if (var_force_mime_iconv)
            mime_options |= MIME_OPT_DOWNGRADE;
     }
     state->mime_state = mime_state_alloc(mime_options,
index 2a9d424260cc3055a4d5ed9054b536c0a7ee63ef..bf4c2a848e30db144e139e41280faf8a6739bbb7 100644 (file)
 #include <limits.h>
 #include <errno.h>
 
+#if !defined(MYSQL_VERSION_ID) || MYSQL_VERSION_ID < 40000
+#error "MySQL versions <4 are no longer supported"
+#endif
+
 #ifdef STRCASECMP_IN_STRINGS_H
 #include <strings.h>
 #endif
@@ -150,7 +154,6 @@ typedef struct {
     char   *charset;
     ARGV   *hosts;
     PLMYSQL *pldb;
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
     HOST   *active_host;
     char   *tls_cert_file;
     char   *tls_key_file;
@@ -159,7 +162,6 @@ typedef struct {
     char   *tls_ciphers;
 #if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT)
     int     tls_verify_cert;
-#endif
 #endif
     int     require_result_set;
 } DICT_MYSQL;
@@ -206,13 +208,21 @@ static void dict_mysql_quote(DICT *dict, const char *name, VSTRING *result)
     buflen = 2 * len + 1;
     VSTRING_SPACE(result, buflen);
 
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
-    if (dict_mysql->active_host)
-       mysql_real_escape_string(dict_mysql->active_host->db,
-                                vstring_end(result), name, len);
-    else
+    if (dict_mysql->active_host == 0)
+       msg_panic("dict_mysql_quote: no active host");
+#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 50700
+    mysql_real_escape_string_quote(dict_mysql->active_host->db,
+                                  vstring_end(result), name, len, '\'');
+#else
+    if (mysql_real_escape_string(dict_mysql->active_host->db,
+                                vstring_end(result), name, len) ==
+       (unsigned long) -1) {
+       msg_warn("dict_mysql: host (%s) cannot escape input string: >%s<",
+                dict_mysql->active_host->hostname,
+                mysql_error(dict_mysql->active_host->db));
+       dict_mysql->active_host->stat = STATFAIL;
+    }
 #endif
-       mysql_escape_string(vstring_end(result), name, len);
 
     VSTRING_SKIP(result);
 }
@@ -232,7 +242,6 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name)
     int     numrows;
     int     expansion;
     const char *r;
-    db_quote_callback_t quote_func = dict_mysql_quote;
     int     domain_rc;
 
     dict->error = 0;
@@ -292,11 +301,8 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name)
      * quoting happens separately for each connection, we don't bother with
      * quoting...
      */
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
-    quote_func = 0;
-#endif
     if (!db_common_expand(dict_mysql->ctx, dict_mysql->query,
-                         name, 0, query, quote_func))
+                         name, 0, query, (db_quote_callback_t) 0))
        return (0);
 
     /* do the query - set dict->error & cleanup if there's an error */
@@ -440,8 +446,12 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
 {
     HOST   *host;
     MYSQL_RES *first_result = 0;
+
+    /* In case all hosts are down. */
     int     query_error = 1;
 
+    errno = ENOTSUP;
+
     /*
      * Helper to avoid spamming the log with warnings.
      */
@@ -455,8 +465,6 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
 
     while ((host = dict_mysql_get_active(dict_mysql)) != NULL) {
 
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
-
        /*
         * The active host is used to escape strings in the context of the
         * active connection's character encoding.
@@ -466,8 +474,14 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
        VSTRING_TERMINATE(query);
        db_common_expand(dict_mysql->ctx, dict_mysql->query,
                         name, 0, query, dict_mysql_quote);
+       /* Check for potential dict_mysql_quote() failure. */
+       if (host->stat == STATFAIL) {
+           plmysql_down_host(host);
+           continue;
+       }
+       if (msg_verbose)
+           msg_info("expanded and quoted query: >%s<", vstring_str(query));
        dict_mysql->active_host = 0;
-#endif
 
        query_error = 0;
        errno = 0;
@@ -582,7 +596,6 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host)
        mysql_options(host->db, MYSQL_READ_DEFAULT_FILE, dict_mysql->option_file);
     if (dict_mysql->option_group && dict_mysql->option_group[0])
        mysql_options(host->db, MYSQL_READ_DEFAULT_GROUP, dict_mysql->option_group);
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
     if (dict_mysql->tls_key_file || dict_mysql->tls_cert_file ||
        dict_mysql->tls_CAfile || dict_mysql->tls_CApath || dict_mysql->tls_ciphers)
        mysql_ssl_set(host->db,
@@ -593,7 +606,6 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host)
     if (dict_mysql->tls_verify_cert != -1)
        mysql_options(host->db, DICT_MYSQL_SSL_VERIFY_SERVER_CERT,
                      &dict_mysql->tls_verify_cert);
-#endif
 #endif
     if (mysql_real_connect(host->db,
                           (host->type == TYPEINET ? host->name : 0),
@@ -657,7 +669,6 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf)
     dict_mysql->result_format = cfg_get_str(p, "result_format", "%s", 1, 0);
     dict_mysql->option_file = cfg_get_str(p, "option_file", NULL, 0, 0);
     dict_mysql->option_group = cfg_get_str(p, "option_group", "client", 0, 0);
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
     dict_mysql->tls_key_file = cfg_get_str(p, "tls_key_file", NULL, 0, 0);
     dict_mysql->tls_cert_file = cfg_get_str(p, "tls_cert_file", NULL, 0, 0);
     dict_mysql->tls_CAfile = cfg_get_str(p, "tls_CAfile", NULL, 0, 0);
@@ -665,7 +676,6 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf)
     dict_mysql->tls_ciphers = cfg_get_str(p, "tls_ciphers", NULL, 0, 0);
 #if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT)
     dict_mysql->tls_verify_cert = cfg_get_bool(p, "tls_verify_cert", -1);
-#endif
 #endif
     dict_mysql->require_result_set = cfg_get_bool(p, "require_result_set", 1);
 
@@ -749,9 +759,7 @@ DICT   *dict_mysql_open(const char *name, int open_flags, int dict_flags)
     dict_mysql->dict.flags = dict_flags;
     dict_mysql->parser = parser;
     mysql_parse_config(dict_mysql, name);
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
     dict_mysql->active_host = 0;
-#endif
     dict_mysql->pldb = plmysql_init(dict_mysql->hosts);
     if (dict_mysql->pldb == NULL)
        msg_fatal("couldn't initialize pldb!\n");
@@ -841,7 +849,6 @@ static void dict_mysql_close(DICT *dict)
        myfree(dict_mysql->option_file);
     if (dict_mysql->option_group)
        myfree(dict_mysql->option_group);
-#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
     if (dict_mysql->tls_key_file)
        myfree(dict_mysql->tls_key_file);
     if (dict_mysql->tls_cert_file)
@@ -852,7 +859,6 @@ static void dict_mysql_close(DICT *dict)
        myfree(dict_mysql->tls_CApath);
     if (dict_mysql->tls_ciphers)
        myfree(dict_mysql->tls_ciphers);
-#endif
     if (dict_mysql->hosts)
        argv_free(dict_mysql->hosts);
     if (dict_mysql->ctx)
index 649b8290a1d3ee3d68357233f76236498ab5b117..11d58a6e7e6039537cbba876661b59dfa18670fc 100644 (file)
@@ -3088,9 +3088,9 @@ extern bool var_disable_mime_input;
 #define DEF_DISABLE_MIME_OCONV         0
 extern bool var_disable_mime_oconv;
 
-#define VAR_ENFORCE_MIME_ICONV         "enforce_mime_input_conversion"
-#define DEF_ENFORCE_MIME_ICONV         0
-extern bool var_enforce_mime_iconv;
+#define VAR_FORCE_MIME_ICONV           "force_mime_input_conversion"
+#define DEF_FORCE_MIME_ICONV           0
+extern bool var_force_mime_iconv;
 
 #define VAR_STRICT_8BITMIME            "strict_8bitmime"
 #define DEF_STRICT_8BITMIME            0
index e85db1d769b99f67c0dc2f073aed82d5c5c6ddb1..5a7640d85cd9973babb745a784b37c940146d12f 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20230901"
+#define MAIL_RELEASE_DATE      "20230903"
 #define MAIL_VERSION_NUMBER    "3.9"
 
 #ifdef SNAPSHOT