*.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],
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
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.
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.
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:
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>
<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 ≥ 3.9. </p>
-
-
</DD>
<DT><b><a name="error_notice_recipient">error_notice_recipient</a>
</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 ≥ 3.9. </p>
+
+
</DD>
<DT><b><a name="fork_attempts">fork_attempts</a>
.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
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)
(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"
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;
<p> This feature is available in Postfix ≥ 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>
/* (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
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,
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,
};
*/
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. */
|| *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,
#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
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;
char *tls_ciphers;
#if defined(DICT_MYSQL_SSL_VERIFY_SERVER_CERT)
int tls_verify_cert;
-#endif
#endif
int require_result_set;
} DICT_MYSQL;
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);
}
int numrows;
int expansion;
const char *r;
- db_quote_callback_t quote_func = dict_mysql_quote;
int domain_rc;
dict->error = 0;
* 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 */
{
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.
*/
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.
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;
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,
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),
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);
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);
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");
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)
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)
#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
* 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