diff -ruN netqmail-1.05-orig/Makefile netqmail-1.05/Makefile
--- netqmail-1.05-orig/Makefile	2005-03-05 10:40:51.000000000 +0100
+++ netqmail-1.05/Makefile	2005-03-05 10:57:12.000000000 +0100
@@ -808,7 +808,7 @@
 forward preline condredirect bouncesaying except maildirmake \
 maildir2mbox maildirwatch qail elq pinq idedit install-big install \
 instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
-binm3 binm3+df
+binm3 binm3+df qmail-newrbl
 
 load: \
 make-load warn-auto.sh systype
@@ -935,7 +935,7 @@
 maildir2mbox.0 maildirwatch.0 qmail.0 qmail-limits.0 qmail-log.0 \
 qmail-control.0 qmail-header.0 qmail-users.0 dot-qmail.0 \
 qmail-command.0 tcp-environ.0 maildir.0 mbox.0 addresses.0 \
-envelopes.0 forgeries.0
+envelopes.0 forgeries.0 rbladdress.0 qmail-newrbl.0
 
 mbox.0: \
 mbox.5
@@ -1241,6 +1241,29 @@
 uint32.h substdio.h
 	./compile qmail-newmrh.c
 
+qmail-newrbl: \
+load qmail-newrbl.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \
+stralloc.a alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o
+	./load qmail-newrbl cdbmss.o getln.a open.a cdbmake.a \
+	seek.a case.a stralloc.a alloc.a strerr.a substdio.a \
+	error.a str.a fs.a auto_qmail.o 
+
+qmail-newrbl.0: \
+qmail-newrbl.8
+	nroff -man qmail-newrbl.8 > qmail-newrbl.0
+
+qmail-newrbl.8: \
+qmail-newrbl.9 conf-break conf-spawn
+	cat qmail-newrbl.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	> qmail-newrbl.8
+
+qmail-newrbl.o: \
+compile qmail-newrbl.c strerr.h stralloc.h gen_alloc.h substdio.h \
+getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \
+uint32.h substdio.h fmt.h
+	./compile qmail-newrbl.c
+
 qmail-newu: \
 load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \
 stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o
@@ -1532,15 +1555,15 @@
 	./compile qmail-showctl.c
 
 qmail-smtpd: \
-load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
+load qmail-smtpd.o rblallow.o rcpthosts.o commands.o timeoutread.o \
 timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
 date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
 open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
 fs.a auto_qmail.o socket.lib
-	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
-	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
-	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
-	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
+	./load qmail-smtpd rblallow.o rcpthosts.o commands.o \
+	timeoutread.o timeoutwrite.o ip.o ipme.o ipalloc.o control.o \
+	constmap.o received.o date822fmt.o now.o qmail.o cdb.a fd.a \
+	wait.a datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
 	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
 	socket.lib`
 
@@ -1553,7 +1576,8 @@
 substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
 error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
 substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
-exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h
+exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h \
+rblallow.h
 	./compile qmail-smtpd.c
 
 qmail-start: \
@@ -1676,6 +1700,15 @@
 compile quote.c stralloc.h gen_alloc.h str.h quote.h
 	./compile quote.c
 
+rbladdress.0:\
+rbladdress.5
+	nroff -man rbladdress.5 > rbladdress.0
+
+rblallow.o:\
+rblallow.c stralloc.h error.h cdb.h env.h open.h case.h gen_alloc.h \
+uint32.h
+	./compile rblallow.c
+
 rcpthosts.o: \
 compile rcpthosts.c cdb.h uint32.h byte.h open.h error.h control.h \
 constmap.h stralloc.h gen_alloc.h rcpthosts.h
diff -ruN netqmail-1.05-orig/TARGETS netqmail-1.05/TARGETS
--- netqmail-1.05-orig/TARGETS	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05/TARGETS	2005-03-05 10:58:27.000000000 +0100
@@ -250,6 +250,7 @@
 qmail-qmtpd.o
 rcpthosts.o
 qmail-qmtpd
+rblallow.o
 qmail-smtpd.o
 qmail-smtpd
 sendmail.o
@@ -259,6 +260,8 @@
 tcp-env
 qmail-newmrh.o
 qmail-newmrh
+qmail-newrbl.o
+qmail-newrbl
 config
 config-fast
 dnscname.o
@@ -352,6 +355,8 @@
 qmail-qmtpd.0
 qmail-smtpd.0
 tcp-env.0
+qmail-newrbl.8
+qmail-newrbl.0
 qmail-newmrh.8
 qmail-newmrh.0
 qreceipt.0
@@ -382,6 +387,7 @@
 addresses.0
 envelopes.0
 forgeries.0
+rbladdress.0
 man
 setup
 check
diff -ruN netqmail-1.05-orig/qmail-newrbl.9 netqmail-1.05/qmail-newrbl.9
--- netqmail-1.05-orig/qmail-newrbl.9	1970-01-01 01:00:00.000000000 +0100
+++ netqmail-1.05/qmail-newrbl.9	2005-03-05 10:58:46.000000000 +0100
@@ -0,0 +1,41 @@
+.TH qmail-newrbl 8
+.SH NAME
+qmail-newrbl \- prepare rbladdress for qmail-smtpd
+.SH SYNOPSIS
+.B qmail-newrbl
+.SH DESCRIPTION
+.B qmail-newrbl
+reads the instructions in
+.B QMAILHOME/control/rbladdress
+and writes them into
+.B QMAILHOME/control/rbladdress.cdb
+in a binary format suited
+for quick access by
+.BR qmail-smtpd .
+
+If there is a problem with
+.BR control/rbladdress ,
+.B qmail-newrbl
+complains and leaves
+.B control/rbladdress.cdb
+alone.
+
+.B qmail-newrbl
+ensures that
+.B control/rbladdress.cdb
+is updated atomically,
+so
+.B qmail-smtpd
+never has to wait for
+.B qmail-newrbl
+to finish.
+However,
+.B qmail-newrbl
+makes no attempt to protect against two simultaneous updates of
+.BR control/rbladdress.cdb .
+
+The binary
+.B control/rbladdress.cdb
+format is portable across machines.
+.SH "SEE ALSO"
+qmail-smtpd(8)
diff -ruN netqmail-1.05-orig/qmail-newrbl.c netqmail-1.05/qmail-newrbl.c
--- netqmail-1.05-orig/qmail-newrbl.c	1970-01-01 01:00:00.000000000 +0100
+++ netqmail-1.05/qmail-newrbl.c	2005-03-05 10:59:09.000000000 +0100
@@ -0,0 +1,114 @@
+#include "strerr.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "getln.h"
+#include "exit.h"
+#include "readwrite.h"
+#include "open.h"
+#include "fmt.h"
+#include "auto_qmail.h"
+#include "cdbmss.h"
+
+#define FATAL "qmail-newrbl: fatal: "
+
+void die_read()
+{
+  strerr_die2sys(111,FATAL,"unable to read control/rbladdress: ");
+}
+void die_write()
+{
+  strerr_die2sys(111,FATAL,"unable to write to control/rbladdress.tmp: ");
+}
+char ln[FMT_ULONG];
+void die_badchar(l, s) int l; char *s; {
+  ln[fmt_uint(ln,l)] = 0;
+  strerr_die6x(100,FATAL,"control/rbladdress: syntax error at line ", ln,": bad character '",s,"'");
+}
+
+char inbuf[1024];
+substdio ssin;
+
+int fd;
+int fdtemp;
+
+struct cdbmss cdbmss;
+stralloc line = {0};
+int match;
+
+void main()
+{
+  int i,j,l;
+  int first;
+
+  umask(033);
+  if (chdir(auto_qmail) == -1)
+    strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": ");
+
+  fd = open_read("control/rbladdress");
+  if (fd == -1) die_read();
+
+  substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf);
+
+  fdtemp = open_trunc("control/rbladdress.tmp");
+  if (fdtemp == -1) die_write();
+
+  if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write();
+
+  for (l=1;;l++) {
+    if (getln(&ssin,&line,&match,'\n') != 0) die_read();
+    while (line.len) {
+      if (line.s[line.len - 1] == ' ') { --line.len; continue; }
+      if (line.s[line.len - 1] == '\n') { --line.len; continue; }
+      if (line.s[line.len - 1] == '\t') { --line.len; continue; }
+      if (line.s[0] != '#') {
+        stralloc_0(&line);
+	i = str_rchr(line.s, ':');
+	j = str_chr(line.s, '@');
+	if (line.s[i] != ':') {
+	  ln[fmt_uint(ln,l)] = 0;
+	  strerr_die4x(100,FATAL,"control/rbladdress:", ln,": syntax error: missing ':'");
+	} else if (i > 0 && j > i) {
+	  ln[fmt_uint(ln,l)] = 0;
+	  strerr_die4x(100,FATAL,"control/rbladdress:", ln,": syntax error: missing '@' in address");
+	} else {
+	  line.s[i] = 'Z'; /*aggressive programming*/
+	  first = 1;
+	  for (j = i+1; j < line.len-1; j++) {
+	    switch (line.s[j]) {
+	      case '\0': case ',':
+	        line.s[j] = '\0';
+	        first = 1;
+		break;
+	      case '-':
+	        if (!first) die_badchar(l,line.s+j);
+		break;
+	      case '0': case '1': case '2': case '3': case '4':
+	      case '5': case '6': case '7': case '8': case '9':
+	        if (first) die_badchar(l,line.s+j);
+		break;
+	      default:
+		first = 0;
+		if (line.s[j] == '_') break;
+	        if (line.s[j] >= 'A' && line.s[j] <= 'Z') break;
+	        if (line.s[j] >= 'a' && line.s[j] <= 'z') break;
+		die_badchar(l,line.s+j);
+	    }
+	  }
+          case_lowerb(line.s,i);
+	  if (cdbmss_add(&cdbmss,line.s,i,line.s+i+1,line.len-i-1) == -1)
+	    die_write();
+	}
+      }
+      break;
+    }
+    if (!match) break;
+  }
+
+  if (cdbmss_finish(&cdbmss) == -1) die_write();
+  if (fsync(fdtemp) == -1) die_write();
+  if (close(fdtemp) == -1) die_write(); /* NFS stupidity */
+  if (rename("control/rbladdress.tmp","control/rbladdress.cdb") == -1)
+    strerr_die2sys(111,FATAL,"unable to move control/rbladdress.tmp to control/rbladdress.cdb");
+
+  _exit(0);
+}
diff -ruN netqmail-1.05-orig/qmail-showctl.c netqmail-1.05/qmail-showctl.c
--- netqmail-1.05-orig/qmail-showctl.c	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05/qmail-showctl.c	2005-03-05 10:59:29.000000000 +0100
@@ -255,6 +255,22 @@
       else
         substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n");
 
+  do_lst("rbladdress","DNS per-address blacklisting is disabled.","DNS per-address blacklisting: `","'");
+  if (stat("rbladdress",&stmrh) == -1)
+    if (stat("rbladdress.cdb",&stmrhcdb) == -1)
+      substdio_puts(subfdout,"(Default.) No effect.\n");
+    else
+      substdio_puts(subfdout,"Oops! rbladdress.cdb exists but rbladdress doesn't.\n");
+  else
+    if (stat("rbladdress.cdb",&stmrhcdb) == -1)
+      substdio_puts(subfdout,"Oops! rbladdress exists but rbladdress.cdb doesn't.\n");
+    else
+      if (stmrh.st_mtime > stmrhcdb.st_mtime)
+        substdio_puts(subfdout,"Oops! rbladdress.cdb is older than rbladdress.\n");
+      else
+        substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n");
+
+
   do_str("smtpgreeting",1,"smtpgreeting","SMTP greeting: 220 ");
   do_lst("smtproutes","No artificial SMTP routes.","SMTP route: ","");
   do_int("timeoutconnect","60","SMTP client connection timeout is "," seconds");
@@ -289,6 +305,8 @@
     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,"rbladdress")) continue;
+    if (str_equal(d->d_name,"rbladdress.cdb")) 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 -ruN netqmail-1.05-orig/qmail-smtpd.8 netqmail-1.05/qmail-smtpd.8
--- netqmail-1.05-orig/qmail-smtpd.8	1998-06-15 12:53:16.000000000 +0200
+++ netqmail-1.05/qmail-smtpd.8	2005-03-05 10:59:44.000000000 +0100
@@ -24,6 +24,12 @@
 
 .B qmail-smtpd
 supports ESMTP, including the 8BITMIME and PIPELINING options.
+
+.B qmail-smtpd
+implements DNS per-address blacklisting via
+.BR envrbldir .
+See envrbldir(1) and rbladdress(5) for details.
+
 .SH TRANSPARENCY
 .B qmail-smtpd
 converts the SMTP newline convention into the UNIX newline convention
@@ -151,6 +157,20 @@
 
 Envelope recipient addresses without @ signs are
 always allowed through.
+
+.TP 5
+.I rbladdress
+Per-address blacklisting configuration.
+Each entry has the form:
+.IR address-wilcard\fB:\fI[-]envvar[,...] ,
+without any extra spaces.
+
+You must run
+.B qmail-newrbl
+whenever
+.I rbladdress
+changes.
+
 .TP 5
 .I smtpgreeting
 SMTP greeting message.
@@ -172,8 +192,12 @@
 .SH "SEE ALSO"
 tcp-env(1),
 tcp-environ(5),
+envrbldir(1),
+rbladdress(5),
 qmail-control(5),
 qmail-inject(8),
 qmail-newmrh(8),
+qmail-newrbl(8),
 qmail-queue(8),
 qmail-remote(8)
+
diff -ruN netqmail-1.05-orig/qmail-smtpd.c netqmail-1.05/qmail-smtpd.c
--- netqmail-1.05-orig/qmail-smtpd.c	2005-03-05 10:40:51.000000000 +0100
+++ netqmail-1.05/qmail-smtpd.c	2005-03-05 10:39:49.000000000 +0100
@@ -23,6 +23,7 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 #include "commands.h"
+#include "rblallow.h"
 
 #define MAXHOPS 100
 unsigned int databytes = 0;
@@ -58,7 +59,7 @@
 void err_noop(arg) char *arg; { out("250 ok\r\n"); }
 void err_vrfy(arg) char *arg; { out("252 send some mail, i'll try my best\r\n"); }
 void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
-
+void err_rbl() { out(rblallow_msg()); }
 
 stralloc greeting = {0};
 
@@ -111,6 +112,7 @@
   if (timeout <= 0) timeout = 1;
 
   if (rcpthosts_init() == -1) die_control();
+  if (rblallow_init() == -1) die_control();
 
   bmfok = control_readfile(&bmf,"control/badmailfrom",0);
   if (bmfok == -1) die_control();
@@ -258,6 +260,10 @@
   }
   else
     if (!addrallowed()) { err_nogateway(); return; }
+  switch (rblallow_rcpt(&addr)) {
+    case 0: err_rbl(); return;
+    case -1: die_nomem();
+  }
   if (!stralloc_cats(&rcptto,"T")) die_nomem();
   if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
   if (!stralloc_0(&rcptto)) die_nomem();
diff -ruN netqmail-1.05-orig/rbladdress.5 netqmail-1.05/rbladdress.5
--- netqmail-1.05-orig/rbladdress.5	1970-01-01 01:00:00.000000000 +0100
+++ netqmail-1.05/rbladdress.5	2005-03-05 10:58:06.000000000 +0100
@@ -0,0 +1,98 @@
+.TH rbladdress 5
+.SH NAME
+control/rbladdress \- per-address DNS blacklisting
+.SH DESCRIPTION
+.I rbladdress
+contains per-address blacklisting configuration
+used by
+.BR qmail-smtpd .
+
+Each entry has the form:
+.IR address-wilcard\fB:\fI[-]envvar[,...] ,
+without any extra spaces.
+
+.SH "ADDRESS MATCHING"
+If
+.B RBLENV
+is set,
+.B qmail-smtpd
+search
+.I rbladdress.cdb
+for recipient address.
+Address wilcard are in the following form:
+.TP 20
+.I global-address@
+Recipient address match if local part is equal to the
+global address or is a sub-address of that address.
+.TP 20
+.I @
+Match any address, overriding any domain match.
+.TP 20
+.I local-address@domain.com
+Recipient address match if remote part is equal to 
+the specified domain, and local part is equal to the
+global address or is a sub-address of that address.
+.TP 20
+empty
+Default match (overrides default rejection).
+
+.SH "BLACKLIST MATCHING"
+
+.SH "EXAMPLES"
+
+Environmeny variables:
+.TP
+RBLENV=RBL_SBL,RBL_XBL,RBL_RELAYS
+.br
+RBL_SBL=Address is a spam source
+.br
+RBL_XBL=Address is a virus source
+.br
+RBL_RELAYS=Address is an open relay
+
+
+Content of
+.IR control/rbladdress :
+
+.TP
+abuse@:
+.br
+info@example.com:RBL_SBL,RBL_XBL
+.br
+@example.com:RBL_XBL
+.br
+ml@example.com:-RBL_RELAYS,-RBL_ABUSERS,RBL_XBL
+.br
+:RBL_ABUSERS,RBL_RELAYS
+
+Address
+.I ml-1@example.com
+matches
+.BR ml@example.com ;
+since blacklist RBL_RELAYS is flagged, recipient will be
+temporarly denied ("451 Address is an open relay (5.7.1)").
+
+Address
+.I abuse@example.com
+matches
+.BR abuse@ ;
+since no blacklists are flagged, recipient will be accepted.
+
+Address
+.I postmaster@otherdomain.net
+matches the default entry; since blacklist RBL_ABUSERS is not flagged
+and RBL_RELAYS is, recipient will be permanently rejected
+("500 Address is an open relay").
+
+.SH NOTES
+You must run
+.B qmail-newrbl
+whenever
+.I rbladdress
+changes.
+
+.SH "SEE ALSO"
+qmail-control(5),
+qmail-smtpd(8),
+qmail-newrbl(8),
+envrbldir(1)
diff -ruN netqmail-1.05-orig/rblallow.c netqmail-1.05/rblallow.c
--- netqmail-1.05-orig/rblallow.c	1970-01-01 01:00:00.000000000 +0100
+++ netqmail-1.05/rblallow.c	2005-03-05 11:02:09.000000000 +0100
@@ -0,0 +1,196 @@
+#include "stralloc.h"
+#include "error.h"
+#include "cdb.h"
+#include "env.h"
+#include "open.h"
+#include "case.h"
+
+stralloc rblenv = {0};
+
+static int rblcdb;
+static stralloc rblloc = {0}; /* address local part */
+static stralloc rbldom = {0}; /* address domain */
+static stralloc rblkey = {0}; /* cdb key */
+static stralloc rblmsg = {0}; /* last rbl message */
+
+static int setrblmsg(msg, temporary) char *msg; char temporary; {
+  int i;
+  char *eol;
+  eol = temporary ? " (#4.7.1)\r\n":" (#5.7.1)\r\n";
+  if (!stralloc_copys(&rblmsg, temporary?"451 ":"553 ")) return -1;
+  if (!msg || !*msg) {
+    if (!stralloc_copys(&rblmsg, "blacklisted - contact abuse@")) return -1;
+    if (!stralloc_cats(&rblmsg, rbldom.s)) return -1;
+  } else {
+    if (!stralloc_cats(&rblmsg, msg)) return -1;
+    for (i = 0; i < rblmsg.len; i++)
+      if (rblmsg.s[i] < 32 || rblmsg.s[i] > 126)
+        rblmsg.s[i] = '?';
+  }
+  if (!stralloc_catb(&rblmsg, eol, str_len(eol)+1)) return -1;
+  return 0;
+}
+static int rblmatch1(char *p, int offset, int maxlen, char *s, int len) {
+  char temporary;
+  int i;
+
+  p += offset;
+  maxlen -= offset;
+  if (*s == '-') {
+    s++;
+    len--;
+    temporary = 1;
+  } else {
+    temporary = 0;
+  }
+
+  if (maxlen < len || p[len] != '\0')
+    return 0;
+  for (i = 0; i < len; i++)
+    if (p[i] != s[i])
+      return 0;
+  if (setrblmsg(env_get(p), temporary) == -1)
+    return -1;
+  return 1;
+}
+
+static int rblmatch(char *s, int len) {
+  int offset;
+  offset = 0;
+  for (;;) {
+    switch (rblmatch1(rblenv.s, offset, rblenv.len, s, len)) {
+      case 1: return 1;
+      case -1: return -1;
+    }
+    while (rblenv.s[offset])
+      offset++;
+    offset++;
+    if (offset >= rblenv.len)
+      return 0;
+  }
+}
+
+static int rbladdresscmp(int dlen) {
+  int i,j;
+  if (dlen == 0)
+    return 1;
+  if (!stralloc_ready(&rblkey,dlen+1))
+    return -1;
+  if (cdb_bread(rblcdb,rblkey.s,dlen)==-1)
+    return 0;
+  rblkey.len = dlen;
+  if (!stralloc_0(&rblkey))
+    return -1;
+  i = 0;
+  for (;;) {
+    j = i;
+    while (rblkey.s[j]) {
+      if (rblkey.s[j] == ',')
+        break;
+      j++;
+    }
+    switch (rblmatch(rblkey.s+i, j-i)) {
+      case 1: return 0;
+      case -1: return -1;
+    }
+
+    if (rblkey.s[j] == '\0')
+      return 1;
+    i = j+1;
+  }
+
+  return 0;
+}
+
+char *rblallow_msg() {
+  return rblmsg.s;
+}
+
+int rblallow_init() {
+  char *env;
+  int first;
+
+  stralloc_copys(&rblmsg,"451 rbl check failure (#4.7.1)\r\n");
+  env = env_get("RBLENV");
+  if (env && *env) {
+    rblcdb = open_read("control/rbladdress.cdb");
+    if (rblcdb == -1) if (errno != error_noent) return -1;
+    if (!stralloc_copys(&rblenv, env)) return -1;
+    if (!stralloc_0(&rblenv)) return -1;
+    for (env = rblenv.s; *env; env++) {
+      if (*env == ',') {
+        *env = '\0';
+      } else if (!((*env >= '0' && *env <= '9')
+                || (*env >= 'A' && *env <= 'Z')
+                || (*env >= 'a' && *env <= 'z'))) {
+        *env = '_';
+      }
+    }
+    return 1;
+  } else {
+    rblcdb = -1;
+    return 0;
+  }
+}
+
+/**
+ * Example: if address is "local-User@DOMAIN", then
+ * cdb is searched for the following entries:
+ *	"local-user@"
+ *	"local@"
+ *	"@"
+ *	"local-user@domain"
+ *	"local@domain"
+ *	"@domain"
+ *     ""
+ * cdb value is a list of blacklist labels, NUL separated.
+ * Return values:
+ *  -1 on error (out of memory, open failed, read error)
+ *   0 if blacklist label match (side effect: rblmsg is set)
+ *   1 if blacklist label don't match
+ */
+int rblallow_rcpt(addr) stralloc *addr; {
+  int i, j;
+  uint32 dlen;
+
+  if (rblcdb == -1)
+    return 1;
+
+  i = str_rchr(addr->s,'@');
+  if (addr->s[i] == '@') {
+    if (!stralloc_copyb(&rblloc, addr->s, i)) return -1;
+    if (!stralloc_copyb(&rbldom, addr->s+i, addr->len-i)) return -1;
+  } else {
+    if (!stralloc_copyb(&rblloc, addr->s, addr->len-1)) return -1;
+    if (!stralloc_copyb(&rbldom,"@",2)) return -1;
+  }
+  case_lowerb(rblloc.s, rblloc.len);
+  case_lowerb(rbldom.s, rbldom.len);
+
+  i = rblloc.len;
+  while (i > 0) {
+    if (!stralloc_copyb(&rblkey,rblloc.s,i)) return -1;
+    if (!stralloc_catb(&rblkey,"@",2)) return -1;
+    j = cdb_seek(rblcdb, rblkey.s, rblkey.len-1, &dlen);
+    if (j) return rbladdresscmp(dlen);
+    do { i--; } while (i > 0 && rblloc.s[i] != '-');
+  }
+
+  if (rbldom.len <= 1)
+    return 0;
+  i = rblloc.len;
+  while (i > 0) {
+    if (!stralloc_copyb(&rblkey,rblloc.s,i)) return -1;
+    if (!stralloc_cat(&rblkey,&rbldom)) return -1;
+    j = cdb_seek(rblcdb, rblkey.s, rblkey.len-1, &dlen);
+    if (j) return rbladdresscmp(dlen);
+    do { i--; } while (i > 0 && rblloc.s[i] != '-');
+  }
+
+  j = cdb_seek(rblcdb, "", 0, &dlen);
+  if (j) return rbladdresscmp(dlen);
+
+  if (setrblmsg(env_get(rblenv.s, 1)) == -1)
+    return -1;
+  return 0;
+}
diff -ruN netqmail-1.05-orig/rblallow.h netqmail-1.05/rblallow.h
--- netqmail-1.05-orig/rblallow.h	1970-01-01 01:00:00.000000000 +0100
+++ netqmail-1.05/rblallow.h	2005-03-05 10:39:49.000000000 +0100
@@ -0,0 +1,8 @@
+#ifndef RBLALLOW_H
+#define RBLALLOW_H
+
+extern int rblallow_init();
+extern int rblallow_rcpt();
+extern char *rblallow_msg();
+
+#endif

