I'm writing a milter using pymilter-0.9.3, which interfaces to
libmilter1.0.1 (from sendmail 8.14.3) and running under postfix-2.6.5.
This is on Ubuntu jaunty (I have built the newer pymilter and postfix
versions in a PPA. The same postfix behaviour was observed with the
stock postfix 2.5.x package).

However, it seems that under some circumstances, postfix and libmilter
will fail to inter-operate in a couple of ways.

My milter doesn't care about "RCPT TO", and hence doesn't define an
envrcpt() function in the pymilter class. This leads pymilter/libmilter
to negotiate an SMFIP value of 0x4a790. I can confirm this value from
both libmilter and postfix logs. This decodes to:

Set:

SMFIP_NOBODY, SMFIP_NR_HDR, SMFIP_NOUNKNOWN, SMFIP_NODATA, SMFIP_SKIP,
SMFIP_NR_HELO, SMFIP_NR_RCPT, SMFIP_NR_EOH

Not set:

SMFIP_NOCONNECT, SMFIP_NOHELO, SMFIP_NOMAIL, SMFIP_NORCPT, SMFIP_NOHDRS,
SMFIP_NOEOH, SMFIP_RCPT_REJ, SMFIP_NR_CONN, SMFIP_NR_MAIL,
SMFIP_NR_DATA, SMFIP_NR_UNKN, SMFIP_NR_BODY, SMFIP_HDR_LEADSPC

In particular, note that SMFIP_NORCPT is NOT set, although SMFIP_NR_RCPT is.

I dumped the communication between postfix and the milter using
wireshark. Ignoring "D" commands to define macros, I see C
(SMFIC_CONNECT), H (SMFIC_HELO), M (SMFIC_MAIL), L (SMFIC_HEADER), N
(SMFIC_EOH), E (SMFIC_BODYEOB). I see the same thing from libmilter's
debug output.

The problem here is that there's no R (SMFIC_RCPT) command at all,
despite the message have non-rejected recipients on the postfix side,
and despite SMFIP_NORCPT NOT being set in the negotiated flags.

This appears to be a bug in postfix. I can't see why this is happening
from the postfix source; src/milter/milter*.c doesn't seem to have
anything that would skip sending this command. The only thing I can
think of is that the output vstream/vbuf isn't being flushed out
correctly due to SMFIP_NR_RCPT being set. Note that I do see a few lines
in the postfix log that confirm postfix is attempting to send this command:

Sep  9 23:16:11 severn postfix/smtpd[18705]: event: SMFIC_RCPT; macros:
{rcpt_addr}=swar...@wwwdotorg.org {rcpt_host}=severn
.wwwdotorg.org {rcpt_mailer}=local
Sep  9 23:16:11 severn postfix/smtpd[18705]: skipping reply for event
SMFIC_RCPT from milter inet:2092

The second of these only happens after the command (request) in question
is queued into the vstream/vbuf by postfix. It should only skip waiting
for the reply, not sending the command/request.

I wouldn't care about this, except that libmilter has some "state"
validation code, which only allows a "transition" from a given command
type to specific other command types. The transition from SMFIC_MAIL to
SMFIC_HEADER without SMFIC_RCPT in-between is deemed illegal.
Consequently, libmilter calls the abort callback. However, this doesn't
seem to do anything useful, such as send an error back to postfix, drop
the socket, etc. Instead, libmilter simply never sends anything back,
leaving postfix to time out communicating with the milter. Specifically,
the postfix logs say:

Sep  9 23:16:21 severn postfix/cleanup[18710]: warning: milter
inet:2092: can't read SMFIC_BODYEOB reply packet header: Conn
ection timed out

Sep  9 23:16:21 severn postfix/cleanup[18710]: CBC29E45B7:
milter-reject: END-OF-MESSAGE from unknown[99.99.99.1]: 4.7.1 Ser
vice unavailable - try again later; from=<swar...@wwwdotorg.org>
to=<swar...@wwwdotorg.org> proto=ESMTP helo=<esk.wwwdotorg.
org>

This seems like a bug in libmilter; the milter protocol allows
SMFIP_NORCPT to be set, which should request skipping the SMFIC_RCPT
message). However, if that is done, libmilter will reject the transition.

Does anyone have any clues what's up? It seems a little unlikely that
nobody ever written a milter that doesn't care about RCPTs. I feel I've
got to be missing something!

To work around this, I simply defined a stub envrcpt() function in my
pymilter class. This causes an SMFIP value of 0x42790 to be negotiated,
which is the same as before except SMFIP_NR_RCPT is not set. In turn,
this causes postfix to send the SMFIC_RCPT command to the milter, and
everything works OK.

Any help greatly appreciated!

Reply via email to