[Greylist-users] qmail implementation

Tony Arcieri tarcieri at atmos.colostate.edu
Wed Jun 25 15:29:59 PDT 2003


Attached is a patch to qmail-1.03 containing my own modifications to Kelly
French's original patch for a generic envelope scanner.

This will invoke a program (which should be located in
/var/qmail/bin/qmail-env-scanner) with the From address as the first
argument and the To address as the second.  The remote MTA's IP is an
environment variable set by tcpserver called TCPREMOTEIP.

As is the patch interprets return codes as follows:
0 - message is okay, allow delivery
100 - permanent failure
Anything else - temporary failure

I think it might be better to pass messages for any return code from
qmail-env-scanner except specific ones designed to indicate temporary and
permanent failures, as if the envelope scanner crashes we might as well
pass the message along anyway (i.e. to prevent some failure of the
envelope scanner program to prevent mail delivery)  Thoughts?

Some others have mention that they have already implemented a MySQL-backed
program for exim which takes similar arguments (although probably has some
other way of communicating the MTA's remote IP)  Would you mind posting
those programs to this list?  I will make the necessary tweaks to make
such a program work with qmail.

Tony Arcieri
-------------- next part --------------
--- qmail-1.03/qmail-smtpd.c	Mon Jun 15 04:53:16 1998
+++ qmail-1.03-scanenv/qmail-smtpd.c	Wed Jun 25 14:19:00 2003
@@ -19,6 +19,8 @@
 #include "env.h"
 #include "now.h"
 #include "exit.h"
+#include "fork.h"
+#include "wait.h"
 #include "rcpthosts.h"
 #include "timeoutread.h"
 #include "timeoutwrite.h"
@@ -45,10 +47,15 @@
 void die_read() { _exit(1); }
 void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); }
 void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); }
+void die_tempfail() { out("421 temporary envelope failure (#4.3.0)\r\n"); flush(); _exit(1); } 
+void die_fork() { out("421 Unable to fork (#4.3.0)\r\n"); flush(); _exit(1); }
+void die_exec() { out("421 Unable to exec (#4.3.0)\r\n"); flush(); _exit(1); }
+void die_childcrashed() { out("421 Aack, child crached. (#4.3.0)\r\n"); flush(); _exit(1); }
 void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); }
 void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }
 void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
 
+void err_permfail() { out("553 permanent envelope failure (#5.7.1)\r\n"); }
 void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.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"); }
@@ -222,6 +229,31 @@
 stralloc mailfrom = {0};
 stralloc rcptto = {0};
 
+int env_scanner()
+{
+  int child;
+  int wstat;
+  char *env_scannerarg[] = { "bin/qmail-env-scanner", mailfrom.s, addr.s, 0 };
+  
+  switch(child = vfork()) {
+    case -1:
+      die_fork();
+    case 0:
+      execv(*env_scannerarg,env_scannerarg);
+      die_exec();
+  }
+
+  wait_pid(&wstat,child);
+  if (wait_crashed(wstat))
+    default:
+      die_tempfail();
+    case 0:
+      return 1;
+    case 100:
+      return 0;
+  }
+}
+
 void smtp_helo(arg) char *arg;
 {
   smtp_greet("250 "); out("\r\n");
@@ -245,6 +277,7 @@
   if (!stralloc_copys(&rcptto,"")) die_nomem();
   if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
   if (!stralloc_0(&mailfrom)) die_nomem();
+  if(!env_scanner()) { err_permfail(); return; }
   out("250 ok\r\n");
 }
 void smtp_rcpt(arg) char *arg; {


More information about the Greylist-users mailing list