large for the stable releases. Instead, the command "make
makefiles" will figure out how to make the compiler
backwards-compatible. File: makedefs.
+
+20251208
+
+ Improved Milter error handling for messages that arrive
+ over a long-lived SMTP connection, by changing the default
+ milter_default_action from "tempfail" to the new "shutdown"
+ action (i.e. disconnect the remote SMTP client).
+
+ The problem was that after a single Milter error, Postfix
+ could tempfail all messages that the client sends over a
+ long-lived connection, even if the Milter error was only
+ temporary. This problem was reported by Ankit Kulkarni.
+
+ Files: proto/postconf.proto global/mail_params.h milter/milter8.c.
+
+20260217
+
+ Bugfix: (defect introduced: Postfix 2.11): panic() after
+ recursive logging loop with "posttls-finger -v -v -v".
+ Reported by Geert Hendrickx, diagnosed by Viktor Dukhovni,
+ and fixed by Wietse. Files: util/vstream.[hc], util/msg_vstream.c.
</DD>
<DT><b><a name="milter_default_action">milter_default_action</a>
-(default: tempfail)</b></DT><DD>
+(default: see 'postconf -d <a href="postconf.5.html#milter_default_action">milter_default_action</a>' output)</b></DT><DD>
<p> The default action when a Milter (mail filter) response is
unavailable (for example, bad Postfix configuration or Milter
<dt>tempfail</dt> <dd>Reject all further commands in this session
with a temporary status code. </dd>
+<dt>shutdown</dt> <dd>Close the SMTP connection after sending a 421
+SMTP reply. Available in Postfix 3.11, 3.10.8, 3.9.9, 3.8.15, 3.7.20,
+and later. </dd>
+
<dt>quarantine</dt> <dd>Like "accept", but freeze the message in
the "<a href="QSHAPE_README.html#hold_queue">hold" queue</a>. Available with Postfix 2.6 and later. </dd>
</dl>
+<p> The current default action is "shutdown", i.e. disconnect the
+SMTP client. With the old "tempfail" default, Postfix could tempfail
+all messages that the client sends over a long-lived connection,
+even if a Milter failure is only temporary. </p>
+
<p> This feature is available in Postfix 2.3 and later. </p>
for a list of available macro names and their meanings.
.PP
This feature is available in Postfix 2.3 and later.
-.SH milter_default_action (default: tempfail)
+.SH milter_default_action (default: see 'postconf \-d milter_default_action' output)
The default action when a Milter (mail filter) response is
unavailable (for example, bad Postfix configuration or Milter
failure). Specify one of the following:
Reject all further commands in this session
with a temporary status code.
.br
+.IP "shutdown"
+Close the SMTP connection after sending a 421
+SMTP reply. Available in Postfix 3.11, 3.10.8, 3.9.9, 3.8.15, 3.7.20,
+and later.
+.br
.IP "quarantine"
Like "accept", but freeze the message in
the "hold" queue. Available with Postfix 2.6 and later.
.br
.br
.PP
+The current default action is "shutdown", i.e. disconnect the
+SMTP client. With the old "tempfail" default, Postfix could tempfail
+all messages that the client sends over a long\-lived connection,
+even if a Milter failure is only temporary.
+.PP
This feature is available in Postfix 2.3 and later.
.SH milter_end_of_data_macros (default: see "postconf \-d" output)
The macros that are sent to Milter (mail filter) applications
<p> This feature is available in Postfix 2.3 and later. </p>
-%PARAM milter_default_action tempfail
+%PARAM milter_default_action see 'postconf -d milter_default_action' output
<p> The default action when a Milter (mail filter) response is
unavailable (for example, bad Postfix configuration or Milter
<dt>tempfail</dt> <dd>Reject all further commands in this session
with a temporary status code. </dd>
+<dt>shutdown</dt> <dd>Close the SMTP connection after sending a 421
+SMTP reply. Available in Postfix 3.11, 3.10.8, 3.9.9, 3.8.15, 3.7.20,
+and later. </dd>
+
<dt>quarantine</dt> <dd>Like "accept", but freeze the message in
the "hold" queue. Available with Postfix 2.6 and later. </dd>
</dl>
+<p> The current default action is "shutdown", i.e. disconnect the
+SMTP client. With the old "tempfail" default, Postfix could tempfail
+all messages that the client sends over a long-lived connection,
+even if a Milter failure is only temporary. </p>
+
<p> This feature is available in Postfix 2.3 and later. </p>
%PARAM milter_connect_timeout 30s
extern char *var_cleanup_milters;
#define VAR_MILT_DEF_ACTION "milter_default_action"
-#define DEF_MILT_DEF_ACTION "tempfail"
+#define DEF_MILT_DEF_ACTION "shutdown"
extern char *var_milt_def_action;
#define VAR_MILT_CONN_MACROS "milter_connect_macros"
#define DEF_MILT_PROTOCOL "6"
extern char *var_milt_protocol;
-#define VAR_MILT_DEF_ACTION "milter_default_action"
-#define DEF_MILT_DEF_ACTION "tempfail"
-extern char *var_milt_def_action;
-
#define VAR_MILT_DAEMON_NAME "milter_macro_daemon_name"
#define DEF_MILT_DAEMON_NAME "$" VAR_MYHOSTNAME
extern char *var_milt_daemon_name;
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20251205"
-#define MAIL_VERSION_NUMBER "3.9.8"
+#define MAIL_RELEASE_DATE "20260218"
+#define MAIL_VERSION_NUMBER "3.9.9"
#ifdef SNAPSHOT
#define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE
}
if (strcasecmp(milter->def_action, "accept") == 0) {
reply = 0;
+ } else if (strcasecmp(milter->def_action, "shutdown") == 0) {
+ reply = "421 4.3.5 Server configuration problem - try again later";
} else if (strcasecmp(milter->def_action, "quarantine") == 0) {
reply = "H";
} else {
reply = "550 5.5.0 Service unavailable";
} else if (strcasecmp(milter->def_action, "tempfail") == 0) {
reply = "451 4.7.1 Service unavailable - try again later";
+ } else if (strcasecmp(milter->def_action, "shutdown") == 0) {
+ reply = "421 4.7.1 Service unavailable - try again later";
} else if (strcasecmp(milter->def_action, "quarantine") == 0) {
reply = "H";
} else {
msg_tag = name;
msg_stream = vp;
+ vstream_no_debug(vp);
if (first_call) {
first_call = 0;
msg_output(msg_vstream_print);
/* int vstream_fstat(stream, flags)
/* VSTREAM *stream;
/* int flags;
+/*
+/* void vstream_no_debug(stream)
+/* VSTREAM *stream;
/* DESCRIPTION
/* The \fIvstream\fR module implements light-weight buffered I/O
/* similar to the standard I/O routines.
/* .IP VSTREAM_FLAG_OWN_VSTRING
/* The stream 'owns' the VSTRING buffer, and is responsible
/* for cleaning up when the stream is closed.
+/*
+/* vstream_no_debug() disables 'spontaneous' logging of output
+/* activity on the last specified VSTREAM, to prevent recursive
+/* logging.
/* DIAGNOSTICS
/* Panics: interface violations. Fatal errors: out of memory.
/* SEE ALSO
} \
} while (0)
+static VSTREAM *vstream_log_veto;
+
/* vstream_buf_init - initialize buffer */
static void vstream_buf_init(VBUF *bp, int flags)
used = bp->len - bp->cnt;
left_over = used - to_flush;
- if (msg_verbose > 2 && stream != VSTREAM_ERR)
+ if (msg_verbose > 2 && stream != vstream_log_veto)
msg_info("%s: fd %d flush %ld", myname, stream->fd, (long) to_flush);
if (to_flush < 0 || left_over < 0)
msg_panic("%s: bad to_flush %ld", myname, (long) to_flush);
}
}
}
- if (msg_verbose > 2 && stream != VSTREAM_ERR && n != to_flush)
+ if (msg_verbose > 2 && stream != vstream_log_veto && n != to_flush)
msg_info("%s: %d flushed %ld/%ld", myname, stream->fd,
(long) n, (long) to_flush);
}
return (stream);
}
+/* vstream_no_debug - debug logging lockout */
+
+void vstream_no_debug(VSTREAM *stream)
+{
+ vstream_log_veto = stream;
+}
+
#ifdef TEST
static void copy_line(ssize_t bufsize)
vstream_memreopen((VSTREAM *) 0, (string), (flags))
VSTREAM *vstream_memreopen(VSTREAM *, struct VSTRING *, int);
+ /*
+ * Debug logging lockout.
+ */
+extern void vstream_no_debug(VSTREAM *);
+
/* LICENSE
/* .ad
/* .fi