The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
diff -Nur qmail-1.03/Makefile qmail-1.03.tap/Makefile
--- qmail-1.03/Makefile	1998-06-15 05:53:16.000000000 -0500
+++ qmail-1.03.tap/Makefile	2005-02-15 12:50:37.000000000 -0600
@@ -1419,13 +1419,14 @@
 	nroff -man qmail-qstat.8 > qmail-qstat.0
 
 qmail-queue: \
-load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o \
-datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \
-str.a fs.a auto_qmail.o auto_split.o auto_uids.o
+load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o qregex.o \
+datetime.a seek.a case.a ndelay.a open.a sig.a getln.a stralloc.a alloc.a \
+substdio.a error.a control.o constmap.o str.a fs.a auto_qmail.o \
+auto_split.o auto_uids.o 
 	./load qmail-queue triggerpull.o fmtqfn.o now.o \
-	date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
-	alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
-	auto_split.o auto_uids.o 
+	date822fmt.o qregex.o control.o constmap.o datetime.a case.a seek.a \
+	ndelay.a open.a sig.a getln.a stralloc.a alloc.a substdio.a error.a \
+	str.a fs.a auto_qmail.o auto_split.o auto_uids.o
 
 qmail-queue.0: \
 qmail-queue.8
diff -Nur qmail-1.03/qmail-control.9 qmail-1.03.tap/qmail-control.9
--- qmail-1.03/qmail-control.9	1998-06-15 05:53:16.000000000 -0500
+++ qmail-1.03.tap/qmail-control.9	2005-02-15 12:59:52.000000000 -0600
@@ -63,6 +63,8 @@
 .I rcpthosts	\fR(none)	\fRqmail-smtpd
 .I smtpgreeting	\fIme	\fRqmail-smtpd
 .I smtproutes	\fR(none)	\fRqmail-remote
+.I taps	\fR(none)	\fRqmail-queue
+.I tapscopy	\fR(none)	\fRqmail-queue
 .I timeoutconnect	\fR60	\fRqmail-remote
 .I timeoutremote	\fR1200	\fRqmail-remote
 .I timeoutsmtpd	\fR1200	\fRqmail-smtpd
@@ -72,6 +74,7 @@
 .SH "SEE ALSO"
 qmail-inject(8),
 qmail-qmqpc(8),
+qmail-queue(8),
 qmail-remote(8),
 qmail-send(8),
 qmail-showctl(8),
diff -Nur qmail-1.03/qmail-queue.8 qmail-1.03.tap/qmail-queue.8
--- qmail-1.03/qmail-queue.8	1998-06-15 05:53:16.000000000 -0500
+++ qmail-1.03.tap/qmail-queue.8	2005-02-15 12:56:16.000000000 -0600
@@ -40,6 +40,13 @@
 However, the recipients probably expect to see a proper header,
 as described in
 .BR qmail-header(5) .
+.SH "CONTROL FILES"
+.TP 5
+.I taps
+Should contain regex syntax of email addresses to tap.
+.TP 5
+.I tapscopy
+Email address for all tapped mail copies. 
 .SH "FILESYSTEM RESTRICTIONS"
 .B qmail-queue
 imposes two constraints on the queue structure:
diff -Nur qmail-1.03/qmail-queue.c qmail-1.03.tap/qmail-queue.c
--- qmail-1.03/qmail-queue.c	1998-06-15 05:53:16.000000000 -0500
+++ qmail-1.03.tap/qmail-queue.c	2005-02-15 12:46:33.000000000 -0600
@@ -16,6 +16,8 @@
 #include "auto_uids.h"
 #include "date822fmt.h"
 #include "fmtqfn.h"
+#include "stralloc.h"
+#include "constmap.h"
 
 #define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
 #define ADDR 1003
@@ -25,6 +27,14 @@
 char outbuf[256];
 struct substdio ssout;
 
+int tapok = 0;
+stralloc tap = {0};
+struct constmap maptap;
+stralloc chkaddr = {0};
+int tapped;
+stralloc tapaddr = {0};
+stralloc controlfile = {0};
+
 datetime_sec starttime;
 struct datetime dt;
 unsigned long mypid;
@@ -175,6 +185,18 @@
 
  alarm(DEATH);
 
+ stralloc_copys( &controlfile, auto_qmail);
+ stralloc_cats( &controlfile, "/control/taps");
+ stralloc_0( &controlfile);
+ tapok = control_readfile(&tap,controlfile.s,0);
+ if (tapok == -1) die(65);
+ if (!constmap_init(&maptap,tap.s,tap.len,0)) die(65);
+
+ stralloc_copys( &controlfile, auto_qmail);
+ stralloc_cats( &controlfile, "/control/tapscopy");
+ stralloc_0( &controlfile);
+ if ( control_readline(&tapaddr,controlfile.s) == -1 ) die(65);
+
  pidopen();
  if (fstat(messfd,&pidst) == -1) die(63);
 
@@ -219,14 +241,30 @@
  if (substdio_get(&ssin,&ch,1) < 1) die_read();
  if (ch != 'F') die(91);
  if (substdio_bput(&ssout,&ch,1) == -1) die_write();
+ stralloc_0(&chkaddr);
  for (len = 0;len < ADDR;++len)
   {
+   if ( len == 1 ) stralloc_copyb(&chkaddr, &ch,1);
+   else if ( len > 1 ) stralloc_catb(&chkaddr, &ch,1);
    if (substdio_get(&ssin,&ch,1) < 1) die_read();
    if (substdio_put(&ssout,&ch,1) == -1) die_write();
    if (!ch) break;
   }
  if (len >= ADDR) die(11);
 
+ /* check the from address */
+ stralloc_0(&chkaddr);
+ if (tapped == 0 && tapcheck()==1 ) 
+  {
+   tapped = 1;
+   if ( tapaddr.len > 0 ) 
+    {
+     if (substdio_bput(&ssout,"T",1) == -1) die_write();
+     if (substdio_bput(&ssout,tapaddr.s,tapaddr.len) == -1) die_write();
+     if (substdio_bput(&ssout,"",1) == -1) die_write();
+    }
+ }
+
  if (substdio_bput(&ssout,QUEUE_EXTRA,QUEUE_EXTRALEN) == -1) die_write();
 
  for (;;)
@@ -237,10 +275,26 @@
    if (substdio_bput(&ssout,&ch,1) == -1) die_write();
    for (len = 0;len < ADDR;++len)
     {
+     if ( len == 1 ) stralloc_copyb(&chkaddr, &ch,1);
+     else if ( len > 1 ) stralloc_catb(&chkaddr, &ch,1);
      if (substdio_get(&ssin,&ch,1) < 1) die_read();
      if (substdio_bput(&ssout,&ch,1) == -1) die_write();
      if (!ch) break;
     }
+
+    /* check the to address */
+    stralloc_0(&chkaddr);
+    if (tapped == 0 && tapcheck()==1 ) 
+	 {
+      tapped = 1;
+      if ( tapaddr.len > 0 ) 
+	   {
+        if (substdio_bput(&ssout,"T",1) == -1) die_write();
+        if (substdio_bput(&ssout,tapaddr.s,tapaddr.len) == -1) die_write();
+        if (substdio_bput(&ssout,"",1) == -1) die_write();
+       }
+     }
+
    if (len >= ADDR) die(11);
   }
 
@@ -252,3 +306,33 @@
  triggerpull();
  die(0);
 }
+
+int tapcheck()
+{
+ int i = 0;
+ int j = 0;
+ int x = 0;
+ int negate = 0;
+ stralloc curregex = {0};
+ char tmpbuf[200];
+
+ while (j < tap.len) 
+  {
+   i = j;
+   while ((tap.s[i] != '\0') && (i < tap.len)) i++;
+   if (tap.s[j] == '!') 
+    {
+     negate = 1;
+     j++;
+    }
+   stralloc_copyb(&curregex,tap.s + j,(i - j));
+   stralloc_0(&curregex);
+   x = matchregex(chkaddr.s, curregex.s, tmpbuf);
+  
+   if ((negate) && (x == 0)) return 1;
+   if (!(negate) && (x > 0)) return 1;
+   j = i + 1;
+   negate = 0;
+  }
+  return 0;
+}
diff -Nur qmail-1.03/README.tap qmail-1.03.tap/README.tap
--- qmail-1.03/README.tap	1969-12-31 18:00:00.000000000 -0600
+++ qmail-1.03.tap/README.tap	2005-02-15 13:00:37.000000000 -0600
@@ -0,0 +1,33 @@
+qmail provides the ability to make a copy of each email that flows through the system.
+This is done using the QUEUE_EXTRA code. See qmail FAQ #8.2
+
+The qmail tap patch adds additional functionality:
+1) Specify which email addresses tap using a regex style control file. With the
+   regex function, you can specify full domains or individual email addresses.
+2) Specify which email address to send the emails to using a control file.
+3) Qmail does not need to be recompiled to change the above. Just updated 
+   the control files.
+
+The regex match is applied to both the to and from email addresses. So email
+sent to or from the addresses will be copied.
+
+The queue tap patch adds two new control files:
+
+1) control/taps
+Contains a regex style list of addresses to tap.
+
+Examples:
+a) To tap a whole domain add a line like:
+.*@domain.com
+
+
+b) To tap an individual email address add a line like:
+user@domain.com
+
+2) control/tapscopy
+Contains the email address to send the copies to.
+
+example:
+backup@otherdomain.com
+
+The tapscopy address can be a local or remote email address.