Wietse Venema via Postfix-users:
> Wietse Venema via Postfix-users:
> > (This message was rejected because it was all HTNML and too lage)
> >
> > Hello,
> >
> > I have observed the following behavior in Postfix 3.5.3 and 3.6.4:
> >
> > 1. A client opens a long-lived SMTP connection and sends multiple messages
> > over the same session.
> > 2. Postfix creates a smtpd process and a single corresponding milter
> > connection for that session.
> > 3. If the milter process is restarted during this active SMTP session, the
> > Postfix?milter socket disappears.
> > 4. Postfix does *not* recreate a new milter connection for the ongoing
> > smtpd session.
> > 5. Any subsequent MAIL FROM results in errors such as:
> >
> > * `can't read SMFIC_MAIL reply packet header: Application error` (3.6.4)
> > * `can't read SMFIC_MAIL reply packet header: Success` (3.5.3)
> >
> > This leaves the smtpd session in a state where CONNECT was processed
> > earlier(first time) but no further mails come to milter as postfix
> > probably still tries to send messages to the old socket only(which
> > doesn't exist now)
>
> After a Milter connection breaks, the Postfi SNTP server replies
> with:
>
> 451 4.7.1 Service unavailable - try again later
>
> For Postfix, reconnecting to the Milter would not be sufficient.
> Postfix would have to replay past events. That would include not
> only sending a CONNECT event, but may also need to include MAIL,
> RCPT, DATA, and message content, depending on the SMTP protocol
> stage where the Milter was terminated.
Postfix behaves as promised (accept, reject or tempfail all
commands received during the remaining lifetime of the SMTP session),
but I agree that the behavior is not useful when a connection is
used for multiple mail transactions.
I have a very small patch that adds support for:
milter_default_action = shutdown
Postfix will close the SMTP connection after replying with:
421 4.7.1 Service unavailable- try again later
This will be the default response in Postfix 3.11. I expect to
include this patch with the next update for Postfix 3.7 - 3.10.
If source code patching is not an option, an alternative is to
patch the smtpd executable file.
Save backup copies of postfix-daemon_directory/smtpd:
# cd postfix-daemon_directory
# cp smtpd smtpd-backup
# cp smtpd smtpd-new
# strings -td smtpd-new | grep '4.7.1 Service unavailable -'
XXXXX 451 4.7.1 Service unavailable - try again later
Here, XXXXX is the location where the string "451 4.7.1 Service
unavailable -" was found (with the 'strings' command, byte locations
start at 0).
Replace one byte in the default "tempfail" responses:
# perl -pi -e 's/451 4.7.1 Service unavailable/421 4.7.1 Service
unavailable/' smtpd-new
Verify the change:
# strings -td smtpd-new | grep '4.7.1 Service unavailable -'
XXXXX 421 4.7.1 Service unavailable - try again later
# cmp -l smtpd smtpd-new
YYYYY 65 62
Where 65 is the ASCII value for '5', and 62 the ASCII value for '2',
and where the offset YYYYY must be two higher than XXXXX (with the
'cmp' command, byte locations start at 1).
Commit to using the patched smtpd:
# mv smtpd-new smtpd
If there are any problems, you still have smtpd-backup.
Wietse
diff '--exclude=man' '--exclude=html' '--exclude=README_FILES'
'--exclude=INSTALL' --no-dereference -r -ur --new-file
/var/tmp/postfix-3.11-20251201/src/milter/milter8.c ./src/milter/milter8.c
--- /var/tmp/postfix-3.11-20251201/src/milter/milter8.c 2025-01-07
17:25:43.000000000 -0500
+++ ./src/milter/milter8.c 2025-12-08 15:32:45.237589032 -0500
@@ -523,6 +523,8 @@
}
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 = "Hdefault_action";
} else {
@@ -557,6 +559,8 @@
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 = "Hdefault_action";
} else {
_______________________________________________
Postfix-users mailing list -- [email protected]
To unsubscribe send an email to [email protected]