
   *** qmail-rcptcheck-20070418.patch ***

Author: Fabio Busatto <fbusatto@users.sourceforge.net>

Applies to: qmail-1.03, netqmail-1.05

   *** qmail-rcptcheck-20070418.patch ***



diff -uNr qmail-1.03-orig/qmail-control.9 qmail-1.03/qmail-control.9
--- qmail-1.03-orig/qmail-control.9	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03/qmail-control.9	2007-04-18 15:15:15.000000000 +0200
@@ -61,6 +61,7 @@
 .I qmqpservers	\fR(none)	\fRqmail-qmqpc
 .I queuelifetime	\fR604800	\fRqmail-send
 .I rcpthosts	\fR(none)	\fRqmail-smtpd
+.I rcptcheck	\fR(none)	\fRqmail-smtpd
 .I smtpgreeting	\fIme	\fRqmail-smtpd
 .I smtproutes	\fR(none)	\fRqmail-remote
 .I timeoutconnect	\fR60	\fRqmail-remote
diff -uNr qmail-1.03-orig/qmail-showctl.c qmail-1.03/qmail-showctl.c
--- qmail-1.03-orig/qmail-showctl.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03/qmail-showctl.c	2007-04-18 15:15:15.000000000 +0200
@@ -234,6 +234,7 @@
   do_str("plusdomain",1,"plusdomain","Plus domain name is ");
   do_lst("qmqpservers","No QMQP servers.","QMQP server: ",".");
   do_int("queuelifetime","604800","Message lifetime in the queue is "," seconds");
+  do_str("rcptcheck",0,"disabled","Recipient check helper is ");
 
   if (do_lst("rcpthosts","SMTP clients may send messages to any recipient.","SMTP clients may send messages to recipients at ","."))
     do_lst("morercpthosts","No effect.","SMTP clients may send messages to recipients at ",".");
@@ -289,6 +290,7 @@
     if (str_equal(d->d_name,"plusdomain")) continue;
     if (str_equal(d->d_name,"qmqpservers")) continue;
     if (str_equal(d->d_name,"queuelifetime")) continue;
+    if (str_equal(d->d_name,"rcptcheck")) continue;
     if (str_equal(d->d_name,"rcpthosts")) continue;
     if (str_equal(d->d_name,"smtpgreeting")) continue;
     if (str_equal(d->d_name,"smtproutes")) continue;
diff -uNr qmail-1.03-orig/qmail-smtpd.8 qmail-1.03/qmail-smtpd.8
--- qmail-1.03-orig/qmail-smtpd.8	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03/qmail-smtpd.8	2007-04-18 15:15:15.000000000 +0200
@@ -120,6 +120,16 @@
 and the rest into
 .IR morercpthosts .
 .TP 5
+.I rcptcheck
+Recipient check program.
+If
+.I rcptcheck
+is supplied,
+.B qmail-smtpd
+will reject every recipient address for a message
+if the program exits non-zero
+and no other recipient check authorizes the delivery.
+.TP 5
 .I rcpthosts
 Allowed RCPT domains.
 If
diff -uNr qmail-1.03-orig/qmail-smtpd.c qmail-1.03/qmail-smtpd.c
--- qmail-1.03-orig/qmail-smtpd.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03/qmail-smtpd.c	2007-04-18 15:15:15.000000000 +0200
@@ -23,6 +23,7 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 #include "commands.h"
+#include "wait.h"
 
 #define MAXHOPS 100
 unsigned int databytes = 0;
@@ -50,6 +51,7 @@
 void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
 
 void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
+void err_nomailbox() { out("553 sorry, no mailbox here by that name (#5.1.1)\r\n"); }
 void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
 void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
 void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
@@ -96,6 +98,8 @@
 int bmfok = 0;
 stralloc bmf = {0};
 struct constmap mapbmf;
+int rcptcheckok = 0;
+stralloc rcptcheckbin = {0};
 
 void setup()
 {
@@ -116,6 +120,8 @@
   if (bmfok == -1) die_control();
   if (bmfok)
     if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
+  rcptcheckok = control_readline(&rcptcheckbin,"control/rcptcheck");
+  if (rcptcheckok == -1) die_control();
  
   if (control_readint(&databytes,"control/databytes") == -1) die_control();
   x = env_get("DATABYTES");
@@ -208,6 +214,42 @@
   return 0;
 }
 
+stralloc rcptcheckcmd = {0};
+
+int rcptcheck()
+{
+  int child;
+  char *(args[4]);
+  int wstat;
+
+  if (!rcptcheckok) return 0;
+  if (!addr.s[0]) return 1;
+
+  switch(child = fork())
+  {
+    case -1:
+      return 0;
+    case 0:
+      if (!stralloc_copys(&rcptcheckcmd,"")) die_nomem();
+      if (!stralloc_copy(&rcptcheckcmd,&rcptcheckbin)) die_nomem();
+      if (!stralloc_cats(&rcptcheckcmd," ")) die_nomem();
+      if (!stralloc_cat(&rcptcheckcmd,&addr)) die_nomem();
+      if (!stralloc_0(&rcptcheckcmd)) die_nomem();
+      close(0);
+      close(1);
+      close(2);
+      args[0] = "/bin/sh";
+      args[1] = "-c";
+      args[2] = rcptcheckcmd.s;
+      args[3] = 0;
+      execv(*args,args);
+      _exit(1);
+  }
+
+  wait_pid(&wstat,child);
+  return wait_exitcode(wstat);
+}
+
 int addrallowed()
 {
   int r;
@@ -256,8 +298,10 @@
     if (!stralloc_cats(&addr,relayclient)) die_nomem();
     if (!stralloc_0(&addr)) die_nomem();
   }
-  else
+  else {
     if (!addrallowed()) { err_nogateway(); return; }
+    if (rcptcheck()) { err_nomailbox(); return; }
+  }
   if (!stralloc_cats(&rcptto,"T")) die_nomem();
   if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
   if (!stralloc_0(&rcptto)) die_nomem();
