Index: sendmail/milter.c diff -pur sendmail-8.13.7-orig/sendmail/milter.c sendmail-8.13.7/sendmail/milter.c --- sendmail-8.13.7-orig/sendmail/milter.c 2005-08-06 00:49:04.000000000 +0300 +++ sendmail-8.13.7/sendmail/milter.c 2007-04-19 20:33:12.000000000 +0300 @@ -3417,29 +3437,30 @@ milter_connect(hostname, addr, e, state) milter_per_connection_check(e); /* + * There used to be the following comment here: + * ** SMFIR_REPLYCODE can't work with connect due to ** the requirements of SMTP. Therefore, ignore the ** reply code text but keep the state it would reflect. + * + * However, this is wrong. RFC2821, section 3.9 states, that: + * + * "An SMTP server MUST NOT intentionally close the connection except: + * [...] + * - After detecting the need to shut down the SMTP service and + * returning a 421 response code. This response code can be issued + * after the server receives any command or, if necessary, + * asynchronously from command receipt (on the assumption that the + * client will receive it after the next command is issued)." + * + * I see no reason why a milter cannot supply its own textual + * explanation in xxfi_connect. So, instead of blindly filtering + * out the user-supllied response, I return it to smtp(). The latter + * is crafted so that it will graciously abort the connection, if + * the response begins with 421, giving the user-supplied textual + * message, and will proceed with nullserver otherwise. + * --gray */ - - if (*state == SMFIR_REPLYCODE) - { - if (response != NULL && - *response == '4') - { - if (strncmp(response, "421 ", 4) == 0) - *state = SMFIR_SHUTDOWN; - else - *state = SMFIR_TEMPFAIL; - } - else - *state = SMFIR_REJECT; - if (response != NULL) - { - sm_free(response); /* XXX */ - response = NULL; - } - } return response; } /* Index: sendmail/srvrsmtp.c diff -pur sendmail-8.13.7-orig/sendmail/srvrsmtp.c sendmail-8.13.7/sendmail/srvrsmtp.c --- sendmail-8.13.7-orig/sendmail/srvrsmtp.c 2006-05-31 23:56:37.000000000 +0300 +++ sendmail-8.13.7/sendmail/srvrsmtp.c 2007-04-19 20:34:01.000000000 +0300 @@ -850,12 +850,38 @@ smtp(nullserver, d_flags, e) { char state; char *response; - + static char greetcodebuf[4]; + size_t len; + response = milter_connect(peerhostname, RealHostAddr, e, &state); switch (state) { case SMFIR_REPLYCODE: /* REPLYCODE shouldn't happen */ + if (MilterLogLevel > 3) + sm_syslog(LOG_INFO, e->e_id, + "Milter: connect: host=%s, addr=%s, reject=%s", + peerhostname, + anynet_ntoa(&RealHostAddr), + response); + len = strlen(response); + if (len >= 3) { + /* RFC 2821, Section 3.9 */ + if (memcmp(response, "421", 3) == 0) { + message(response); + /* arrange to ignore send list */ + e->e_sendqueue = NULL; + goto doquit; + } else { + nullserver = newstr(response); + memcpy(greetcodebuf, response, 3); + greetcodebuf[3] = 0; + greetcode = greetcodebuf; + break; + } + } + /* FALL THROUGH */ + case SMFIR_REJECT: if (MilterLogLevel > 3) sm_syslog(LOG_INFO, e->e_id,