diff -ruN qmail-1.03-7.07/qmail-smtpd.c qmail-1.03-7.08/qmail-smtpd.c --- qmail-1.03-7.07/qmail-smtpd.c 2008-06-02 21:38:14.000000000 -0400 +++ qmail-1.03-7.08/qmail-smtpd.c 2008-09-19 21:11:23.000000000 -0400 @@ -87,6 +87,7 @@ int log_mail = 0; int log_rcpt = 0; unsigned long pw_expire = 0; +char rcptcheck_err[1024]; #ifdef TLS unsigned int force_tls = 0; @@ -741,25 +742,64 @@ { int pid; int wstat; + int pierr[2] ; + substdio ss; + char ssbuf[sizeof(rcptcheck_err)]; + int len = 0 ; + char ch; if (!rcptcheck[0]) return 1; + if (pipe(pierr) == -1) die_rcpt2(); switch(pid = fork()) { - case -1: die_fork(); + case -1: + close(pierr[0]); + close(pierr[1]); + die_fork(); case 0: if (!env_put2("SENDER",mailfrom.s)) die_nomem(); if (!env_put2("RECIPIENT",addr.s)) die_nomem(); if (!env_put2("HELO",helohost.s)) die_nomem(); + if (!env_put2("USE_FD4","1")) die_nomem(); close(1); dup2(2,1); + close(pierr[0]); + if (fd_move(4,pierr[1]) == -1) die_rcpt2(); execv(*rcptcheck,rcptcheck); _exit(120); } + + close(pierr[1]); if (wait_pid(&wstat,pid) == -1) die_rcpt2(); if (wait_crashed(wstat)) die_rcpt2(); + + substdio_fdbuf(&ss,read,pierr[0],ssbuf,sizeof(ssbuf)); + while ( substdio_bget(&ss,&ch,1) && len < (sizeof(ssbuf)-3) ) + rcptcheck_err[len++] = ch; + close(pierr[0]); + + while (len&&((rcptcheck_err[len-1]=='\n')||(rcptcheck_err[len-1]=='\r'))) + len -- ; + if (len) { + rcptcheck_err[len] = '\0'; + strerr_warn3(title.s,"RCPTCHECK error: ",rcptcheck_err,0); + rcptcheck_err[len++] = '\r'; + rcptcheck_err[len++] = '\n'; + } + rcptcheck_err[len] = '\0'; + switch(wait_exitcode(wstat)) { - case 100: return 0; - case 111: die_rcpt(); + case 100: + if (!len) { + len = str_copy(rcptcheck_err,"553 no mailbox here by that name"); + rcptcheck_err[len] = '\0' ; + } + case 111: + if (!len) { + len = str_copy(rcptcheck_err,"450 unable to verify recipient"); + rcptcheck_err[len] = '\0' ; + } + return 0; case 120: die_rcpt2(); } return 1; @@ -1021,7 +1061,13 @@ return; } - if (!addrvalid()) { err_badrcpt(); return; } + if (!addrvalid()) { + if (rcptcheck_err[0]) + out (rcptcheck_err); + else + err_badrcpt(); + return; + } if (!stralloc_cats(&rcptto,"T")) die_nomem(); if (!stralloc_cats(&rcptto,addr.s)) die_nomem();