diff -u orig/condredirect.c ./condredirect.c
--- orig/condredirect.c	1998-06-15 06:53:16.000000000 -0400
+++ ./condredirect.c	2004-07-19 12:06:45.000000000 -0400
@@ -34,6 +34,7 @@
 {
   char *sender;
   char *dtline;
+  char *qqeh;
   int pid;
   int wstat;
   char *qqx;
@@ -71,6 +72,11 @@
   if (qmail_open(&qqt) == -1)
     strerr_die2sys(111,FATAL,"unable to fork: ");
   qmail_puts(&qqt,dtline);
+
+  qqeh = env_get("QQEH");
+  if (qqeh)
+    qmail_puts(&qqt,qqeh);
+
   if (substdio_copy(&ssout,&ssin) != 0)
     strerr_die2sys(111,FATAL,"unable to read message: ");
   substdio_flush(&ssout);
diff -u orig/forward.c ./forward.c
--- orig/forward.c	1998-06-15 06:53:16.000000000 -0400
+++ ./forward.c	2004-07-19 12:06:45.000000000 -0400
@@ -32,6 +32,7 @@
 {
   char *sender;
   char *dtline;
+  char *qqeh;
   char *qqx;
  
   sig_pipeignore();
@@ -46,6 +47,11 @@
   if (qmail_open(&qqt) == -1)
     strerr_die2sys(111,FATAL,"unable to fork: ");
   qmail_puts(&qqt,dtline);
+
+  qqeh = env_get("QQEH");
+  if (qqeh)
+    qmail_puts(&qqt,qqeh);
+
   if (substdio_copy(&ssout,&ssin) != 0)
     strerr_die2sys(111,FATAL,"unable to read message: ");
   substdio_flush(&ssout);
diff -u orig/Makefile ./Makefile
--- orig/Makefile	1998-06-15 06:53:16.000000000 -0400
+++ ./Makefile	2004-07-19 12:06:45.000000000 -0400
@@ -1421,11 +1421,14 @@
 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
+str.a fs.a auto_qmail.o auto_split.o auto_uids.o \
+../libdomainkeys.a env.a control.o stralloc.a dns.lib
 	./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 
+	substdio.a error.a fs.a auto_qmail.o \
+	auto_split.o auto_uids.o \
+        ../libdomainkeys.a -lcrypto env.a control.o open.a getln.a \
+	stralloc.a alloc.a  scan_ulong.o str.a `cat dns.lib`
 
 qmail-queue.0: \
 qmail-queue.8
@@ -1434,6 +1437,7 @@
 qmail-queue.o: \
 compile qmail-queue.c readwrite.h sig.h exit.h open.h seek.h fmt.h \
 alloc.h substdio.h datetime.h now.h datetime.h triggerpull.h extra.h \
+env.h \
 auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h
 	./compile qmail-queue.c
 
diff -u orig/preline.1 ./preline.1
--- orig/preline.1	1998-06-15 06:53:16.000000000 -0400
+++ ./preline.1	2004-07-19 12:06:45.000000000 -0400
@@ -39,6 +39,11 @@
 .B control/virtualdomains
 for manual routing.
 .TP
+.B \-e
+Do not include the
+.B QQEH
+contents.
+.TP
 .B \-f
 Do not include the
 .B From_
diff -u orig/preline.c ./preline.c
--- orig/preline.c	1998-06-15 06:53:16.000000000 -0400
+++ ./preline.c	2004-07-19 12:06:45.000000000 -0400
@@ -20,6 +20,7 @@
 int flagufline = 1; char *ufline;
 int flagrpline = 1; char *rpline;
 int flagdtline = 1; char *dtline;
+int flagqqeh = 1; char *qqeh;
 
 char outbuf[SUBSTDIO_OUTSIZE];
 char inbuf[SUBSTDIO_INSIZE];
@@ -46,9 +47,11 @@
       case 'f': flagufline = 0; break;
       case 'r': flagrpline = 0; break;
       case 'd': flagdtline = 0; break;
+      case 'e': flagqqeh   = 0; break;
       case 'F': flagufline = 1; break;
       case 'R': flagrpline = 1; break;
       case 'D': flagdtline = 1; break;
+      case 'E': flagqqeh   = 1; break;
       default: die_usage();
     }
   argc -= optind;
@@ -77,6 +80,7 @@
   if (flagufline) substdio_bputs(&ssout,ufline);
   if (flagrpline) substdio_bputs(&ssout,rpline);
   if (flagdtline) substdio_bputs(&ssout,dtline);
+  if (flagqqeh)   substdio_bputs(&ssout,qqeh);
   if (substdio_copy(&ssout,&ssin) != 0)
     strerr_die2sys(111,FATAL,"unable to copy input: ");
   substdio_flush(&ssout);
diff -u orig/qmail-command.8 ./qmail-command.8
--- orig/qmail-command.8	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-command.8	2004-07-19 12:06:45.000000000 -0400
@@ -143,6 +143,10 @@
 adds to
 .IR mbox -format
 files.
+.B QQEH
+is the same QQEH that was set when
+.B qmail-queue
+was invoked for this email.
 .SH "SEE ALSO"
 dot-qmail(5),
 envelopes(5),
diff -u orig/qmail-local.8 ./qmail-local.8
--- orig/qmail-local.8	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-local.8	2004-07-19 12:06:45.000000000 -0400
@@ -14,6 +14,7 @@
 .I domain
 .I sender
 .I defaultdelivery
+.I qqeh
 .SH DESCRIPTION
 .B qmail-local
 reads a mail message
@@ -70,6 +71,9 @@
 .BR .qmail\fIext :
 namely, following the delivery instructions in
 .IR defaultdelivery .
+Prepend the contents of
+.IR qqeh
+to the message on standard input.
 
 The standard input for
 .B qmail-local
diff -u orig/qmail-local.c ./qmail-local.c
--- orig/qmail-local.c	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-local.c	2004-07-20 00:10:58.000000000 -0400
@@ -52,6 +52,7 @@
 char *host;
 char *sender;
 char *aliasempty;
+char *qqeh;
 
 stralloc safeext = {0};
 stralloc ufline = {0};
@@ -116,6 +117,7 @@
  substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf));
  if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail;
  if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail;
+ if (substdio_puts(&ssout,qqeh) == -1) goto fail;
 
  switch(substdio_copy(&ssout,&ss))
   {
@@ -196,6 +198,7 @@
  if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs;
  if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs;
  if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs;
+ if (substdio_puts(&ssout,qqeh) == -1) goto writeerrs;
  for (;;)
   {
    if (getln(&ss,&messline,&match,'\n') != 0) 
@@ -241,6 +244,7 @@
    case -1:
      temp_fork();
    case 0:
+     if (!env_put2("QQEH",qqeh)) temp_nomem();
      args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0;
      sig_pipedefault();
      execv(*args,args);
@@ -276,6 +280,7 @@
  if (qmail_open(&qqt) == -1) temp_fork();
  mailforward_qp = qmail_qp(&qqt);
  qmail_put(&qqt,dtline.s,dtline.len);
+ qmail_puts(&qqt,qqeh);
  do
   {
    if (getln(&ss,&messline,&match,'\n') != 0) { qmail_fail(&qqt); break; }
@@ -484,6 +489,7 @@
  if (!(host = *argv++)) usage();
  if (!(sender = *argv++)) usage();
  if (!(aliasempty = *argv++)) usage();
+ if (!(qqeh = *argv++)) usage();
  if (*argv) usage();
 
  if (homedir[0] != '/') usage();
diff -u orig/qmail-lspawn.c ./qmail-lspawn.c
--- orig/qmail-lspawn.c	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-lspawn.c	2004-07-19 12:06:45.000000000 -0400
@@ -165,15 +165,15 @@
   }
 }
 
-int spawn(fdmess,fdout,s,r,at)
+int spawn(fdmess,fdout,s,qqeh,r,at)
 int fdmess; int fdout;
-char *s; char *r; int at;
+char *s; char *qqeh; char *r; int at;
 {
  int f;
 
  if (!(f = fork()))
   {
-   char *(args[11]);
+   char *(args[12]);
    unsigned long u;
    int n;
    int uid;
@@ -217,7 +217,8 @@
    args[7] = r + at + 1;
    args[8] = s;
    args[9] = aliasempty;
-   args[10] = 0;
+   args[10] = qqeh;
+   args[11] = 0;
 
    if (fd_move(0,fdmess) == -1) _exit(QLX_SYS);
    if (fd_move(1,fdout) == -1) _exit(QLX_SYS);
diff -u orig/qmail-queue.8 ./qmail-queue.8
--- orig/qmail-queue.8	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-queue.8	2004-08-08 16:18:40.000000000 -0400
@@ -33,6 +33,14 @@
 always adds a
 .B Received
 line to the top of the message.
+.B qmail-queue
+keeps a copy of the
+.B QQEH
+environment variable (if set), and passes it into the queue.
+.B qmail-local
+and
+.B qmail-remote
+will prepend it to the headers of the email when it is delivered.
 Other than this,
 .B qmail-queue
 does not inspect the message
@@ -40,6 +48,64 @@
 However, the recipients probably expect to see a proper header,
 as described in
 .BR qmail-header(5) .
+
+.SH "DOMAINKEY"
+.B qmail-queue
+supports DomainKey signing and verification.  It uses the libdomainkey
+and OpenSSL libraries.  To sign a message, set the
+.B DKSIGN
+environment variable to the pathname to the private key that will be
+used to sign the message.  If there is a % character in the environment
+variable, it is removed and replaced by the domain name in the From: header.
+The selector will be taken from the
+basename of the file.  The private key should be created by 
+.BR dknewkey ,
+which comes with libdomainkey.
+
+To verify a message, set the
+.B DKVERIFY
+environment variable to a desired set of letters.  Precisely, if you
+want a libdomainkey return status to generate an error, include that
+letter, where A is the first return status (DK_STAT_OK), B is the
+second (DK_STAT_BADSIG), etc.  The letter should be uppercase if you
+want a permanent error to be returned (exit code 13), and lowercase if
+you want a temporary error to be returned (exit code 82).
+
+For example, if you want to permanently reject messages that have a
+signature that has been revoked, include the letter 'K' in the
+.B DKVERIFY
+environment variable.  A conservative set of letters is
+.BR DEGIJKfh .
+Reject permanently BADSIG, NOKEY, BADKEY, SYNTAX, ARGS, REVOKED, and
+INTERNAL errors, and temporarily CANTVRFY and NORESOURCE.  Add in
+.B B
+if you want to reject messages that have a signature that doesn't
+verify (presumably because the message is a forgery or has been
+damaged in transit.  Note that
+.B qmail-queue
+always inserts the 
+.B DomainKey-Status
+header, so that messages can be
+rejected at delivery time, or in the mail reader.
+
+Typically, you would sign messages generated on-host by setting
+.B DKSIGN
+in the environment before running an email program.  DKSIGN will be carried
+through qmail's sendmail emulation through 
+.B qmail-inject
+to
+.BR qmail-queue .
+You would also set it for
+.B qmail-smtpd
+at the same time
+.B RELAYCLIENT
+is set, most often in the tcpserver cdb file.  If a host is authorized
+to relay, you probably want to sign messages sent by that host.  There
+is currently no way to sign using a different key for different hosts.
+Suggestions entertained for the best way to do that.
+.B DKVERIFY
+should be set for all other hosts.
+
 .SH "FILESYSTEM RESTRICTIONS"
 .B qmail-queue
 imposes two constraints on the queue structure:
diff -u orig/qmail-queue.c ./qmail-queue.c
--- orig/qmail-queue.c	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-queue.c	2004-08-08 16:14:37.000000000 -0400
@@ -7,6 +7,7 @@
 #include "seek.h"
 #include "fmt.h"
 #include "alloc.h"
+#include "stralloc.h"
 #include "substdio.h"
 #include "datetime.h"
 #include "now.h"
@@ -16,6 +17,9 @@
 #include "auto_uids.h"
 #include "date822fmt.h"
 #include "fmtqfn.h"
+#include "env.h"
+#include "control.h"
+#include "../domainkeys.h"
 
 #define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
 #define ADDR 1003
@@ -59,6 +63,15 @@
 void die_read() { cleanup(); die(54); }
 void sigalrm() { /* thou shalt not clean up here */ die(52); }
 void sigbug() { die(81); }
+void maybe_die_dk(e) DK_STAT e; {
+  switch(e) {
+  case DK_STAT_BADKEY: _exit(55);
+  case DK_STAT_CANTVRFY: _exit(74);
+  case DK_STAT_NORESOURCE: _exit(51);
+  case DK_STAT_ARGS: _exit(12);
+  case DK_STAT_INTERNAL: _exit(81);
+  }
+}
 
 unsigned int receivedlen;
 char *received;
@@ -151,16 +164,90 @@
 
 char tmp[FMT_ULONG];
 
+char *dksign = 0;
+stralloc dksignature = {0};
+stralloc dkoutput = {0};
+char *dkverify = 0;
+DK_LIB *dklib;
+DK *dk;
+DK_STAT st;
+
+static void write_signature(DK *dk, char *keyfn)
+{
+ char advice[2048];
+ char *selector;
+ char *from;
+ static stralloc keyfnfrom = {0};
+ int i;
+
+ from = dk_from(dk);
+ i = str_chr(keyfn, '%');
+ if (keyfn[i]) {
+   if (!stralloc_copyb(&keyfnfrom,keyfn,i)) die(51);
+   if (!stralloc_cats(&keyfnfrom,from)) die(51);
+   if (!stralloc_cats(&keyfnfrom,keyfn + i + 1)) die(51);
+ } else {
+   if (!stralloc_copys(&keyfnfrom,keyfn)) die(51);
+ }
+ if (!stralloc_0(&keyfnfrom)) die(51);
+
+ if (control_readfile(&dksignature,keyfn,0) != 1) die(31);
+ for(i=0; i < dksignature.len; i++)
+   if (dksignature.s[i] == '\0') dksignature.s[i] = '\n';
+ if (!stralloc_0(&dksignature)) die(51);
+
+ st = dk_getsig(dk, dksignature.s, advice, sizeof(advice));
+ maybe_die_dk(st);
+
+ if (!stralloc_cats(&dkoutput,
+   "Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys\n"
+	   "DomainKey-Signature: a=rsa-sha1; q=dns; c=simple;\n"
+	   "  s=")) die(51);
+ selector = keyfn;
+ while (*keyfn) {
+   if (*keyfn == '/') selector = keyfn+1;
+    keyfn++;
+ }
+ if (!stralloc_cats(&dkoutput,selector)) die(51);
+ if (!stralloc_cats(&dkoutput,"; d=")) die(51);
+ if (from) {
+   if (!stralloc_cats(&dkoutput,from)) die(51);
+ } else if (!stralloc_cats(&dkoutput,"unknown")) die(51);
+ if (!stralloc_cats(&dkoutput,";\n  b=")) die(51);
+ if (!stralloc_cats(&dkoutput,advice)) die(51);
+ if (!stralloc_cats(&dkoutput,"  ;\n")) die(51);
+}
+
 void main()
 {
  unsigned int len;
  char ch;
+ char *qqeh;
 
+ qqeh = env_get("QQEH");
  sig_blocknone();
  umask(033);
  if (chdir(auto_qmail) == -1) die(61);
  if (chdir("queue") == -1) die(62);
 
+ dksign = env_get("DKSIGN");
+ dkverify = env_get("DKVERIFY");
+
+ if (dksign || dkverify) {
+   if (qqeh && *qqeh) {
+     if (!stralloc_cats(&dkoutput,qqeh)) die(51);
+   }
+   dklib = dk_init(0);
+   if (!dklib) die(51);
+ }
+ if (dksign) {
+    dk = dk_sign(dklib, &st);
+    if (!dk) die(31);
+ } else if (dkverify) {
+    dk = dk_verify(dklib, &st);
+    if (!dk) die(31);
+ }
+
  mypid = getpid();
  uid = getuid();
  starttime = now();
@@ -191,15 +278,61 @@
  substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
 
  if (substdio_bput(&ssout,received,receivedlen) == -1) die_write();
-
- switch(substdio_copy(&ssout,&ssin))
-  {
-   case -2: die_read();
-   case -3: die_write();
-  }
+ if (dksign) {
+   maybe_die_dk(dk_message(dk, received,receivedlen-1));
+   maybe_die_dk(dk_message(dk, "\r\n", 2));
+ }
+
+ for (;;) {
+   register int n;
+   register char *x;
+   int i;
+
+   n = substdio_feed(&ssin);
+   if (n < 0) die_read();
+   if (!n) break;
+   x = substdio_PEEK(&ssin);
+   if (dksign || dkverify)
+     for(i=0; i < n; i++) {
+       if (x[i] == '\n') st = dk_message(dk, "\r\n", 2);
+       else st = dk_message(dk, x+i, 1);
+       maybe_die_dk(st);
+      }
+   if (substdio_put(&ssout,x,n) == -1) die_write();
+   substdio_SEEK(&ssin,n);
+ }
 
  if (substdio_flush(&ssout) == -1) die_write();
  if (fsync(messfd) == -1) die_write();
+ if (dksign || dkverify) {
+   st = dk_eom(dk, (void *)0);
+   maybe_die_dk(st);
+   if (dksign) {
+     write_signature(dk, dksign);
+   } else if (dkverify) {
+     char *status;
+     if (!stralloc_copys(&dkoutput,"DomainKey-Status: ")) die(51);
+     switch(st) {
+     case DK_STAT_OK:         status = "good        "; break;
+     case DK_STAT_BADSIG:     status = "bad         "; break;
+     case DK_STAT_NOSIG:      status = "no signature"; break;
+     case DK_STAT_NOKEY:
+     case DK_STAT_CANTVRFY:   status = "no key      "; break;
+     case DK_STAT_BADKEY:     status = "bad key     "; break;
+     case DK_STAT_INTERNAL:
+     case DK_STAT_ARGS:
+     case DK_STAT_SYNTAX:     status = "bad format  "; break;
+     case DK_STAT_NORESOURCE: status = "no resources"; break;
+     case DK_STAT_REVOKED:    status = "revoked     "; break;
+     }
+     if (!stralloc_cats(&dkoutput,status)) die(51);
+     if (!stralloc_cats(&dkoutput,"\n")) die(51);
+     if (dkverify[str_chr(dkverify, 'A'+st)]) die(13);
+     if (dkverify[str_chr(dkverify, 'a'+st)]) die(82);
+   }
+   if (!stralloc_0(&dkoutput)) die(51);
+   qqeh = dkoutput.s;
+ }
 
  intdfd = open_excl(intdfn);
  if (intdfd == -1) die(65);
@@ -216,6 +349,12 @@
  if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,mypid)) == -1) die_write();
  if (substdio_bput(&ssout,"",1) == -1) die_write();
 
+ if (qqeh && *qqeh) {
+   if (substdio_bput(&ssout,"e",1) == -1) die_write();
+   if (substdio_bputs(&ssout,qqeh) == -1) die_write();
+   if (substdio_bput(&ssout,"",1) == -1) die_write();
+ }
+
  if (substdio_get(&ssin,&ch,1) < 1) die_read();
  if (ch != 'F') die(91);
  if (substdio_bput(&ssout,&ch,1) == -1) die_write();
diff -u orig/qmail-remote.8 ./qmail-remote.8
--- orig/qmail-remote.8	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-remote.8	2004-07-19 12:06:45.000000000 -0400
@@ -5,6 +5,7 @@
 .B qmail-remote
 .I host
 .I sender
+.I qqeh
 .I recip
 [
 .I recip ...
@@ -46,6 +47,8 @@
 .BR qmail-remote .
 The envelope sender address is listed as
 .I sender\fP.
+Any QQEH information passed to qmail-queue is passed in
+.I qqeh\fP.
 
 Note that
 .B qmail-remote
diff -u orig/qmail-remote.c ./qmail-remote.c
--- orig/qmail-remote.c	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-remote.c	2004-07-19 12:06:45.000000000 -0400
@@ -43,6 +43,7 @@
 struct constmap maproutes;
 stralloc host = {0};
 stralloc sender = {0};
+stralloc qqeh = {0};
 
 saa reciplist = {0};
 
@@ -193,7 +194,13 @@
 {
   int r;
   char ch;
+  int i;
 
+  for (i = 0; i < qqeh.len; i++) {
+    if (qqeh.s[i] == '\n')
+      substdio_put(&smtpto,"\r",1);
+    substdio_put(&smtpto,qqeh.s + i,1);
+  }
   for (;;) {
     r = substdio_get(&ssin,&ch,1);
     if (r == 0) break;
@@ -366,11 +373,13 @@
 
   addrmangle(&sender,argv[2],&flagalias,0);
  
+  if (!stralloc_copys(&qqeh,argv[3])) temp_nomem();
+
   if (!saa_readyplus(&reciplist,0)) temp_nomem();
   if (ipme_init() != 1) temp_oserr();
  
   flagallaliases = 1;
-  recips = argv + 3;
+  recips = argv + 4;
   while (*recips) {
     if (!saa_readyplus(&reciplist,1)) temp_nomem();
     reciplist.sa[reciplist.len] = sauninit;
diff -u orig/qmail-rspawn.c ./qmail-rspawn.c
--- orig/qmail-rspawn.c	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-rspawn.c	2004-07-19 12:06:45.000000000 -0400
@@ -77,18 +77,19 @@
     }
 }
 
-int spawn(fdmess,fdout,s,r,at)
+int spawn(fdmess,fdout,s,qqeh,r,at)
 int fdmess; int fdout;
-char *s; char *r; int at;
+char *s; char *qqeh; char *r; int at;
 {
  int f;
- char *(args[5]);
+ char *(args[6]);
 
  args[0] = "qmail-remote";
  args[1] = r + at + 1;
  args[2] = s;
- args[3] = r;
- args[4] = 0;
+ args[3] = qqeh;
+ args[4] = r;
+ args[5] = 0;
 
  if (!(f = vfork()))
   {
diff -u orig/qmail-send.c ./qmail-send.c
--- orig/qmail-send.c	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-send.c	2004-07-19 21:11:37.000000000 -0400
@@ -195,8 +195,9 @@
 
 /* this file is too long ---------------------------------------------- INFO */
 
-int getinfo(sa,dt,id)
+int getinfo(sa,eh,dt,id)
 stralloc *sa;
+stralloc *eh;
 datetime_sec *dt;
 unsigned long id;
 {
@@ -212,14 +213,22 @@
  if (fdinfo == -1) return 0;
  if (fstat(fdinfo,&st) == -1) { close(fdinfo); return 0; }
  substdio_fdbuf(&ss,read,fdinfo,buf,sizeof(buf));
- if (getln(&ss,&line,&match,'\0') == -1) { close(fdinfo); return 0; }
+ sa->len = eh->len = 0;
+ for (;;) {
+   if (getln(&ss,&line,&match,'\0') == -1) { close(fdinfo); return 0; }
+   if (!match) break;
+   if (line.s[0] == 'F') {
+     while (!stralloc_copys(sa,line.s + 1)) nomem();
+   }
+   if (line.s[0] == 'e') {
+     while (!stralloc_copys(eh,line.s + 1)) nomem();
+   }
+ }
  close(fdinfo);
- if (!match) return 0;
- if (line.s[0] != 'F') return 0;
+ while (!stralloc_0(sa)) nomem();
+ while (!stralloc_0(eh)) nomem();
 
  *dt = st.st_mtime;
- while (!stralloc_copys(sa,line.s + 1)) nomem();
- while (!stralloc_0(sa)) nomem();
  return 1;
 }
 
@@ -250,11 +259,12 @@
  return 1;
 }
 
-void comm_write(c,delnum,id,sender,recip)
+void comm_write(c,delnum,id,sender,qqeh,recip)
 int c;
 int delnum;
 unsigned long id;
 char *sender;
+char *qqeh;
 char *recip;
 {
  char ch;
@@ -267,6 +277,8 @@
  while (!stralloc_0(&comm_buf[c])) nomem();
  senderadd(&comm_buf[c],sender,recip);
  while (!stralloc_0(&comm_buf[c])) nomem();
+ while (!stralloc_cats(&comm_buf[c],qqeh)) nomem();
+ while (!stralloc_0(&comm_buf[c])) nomem();
  while (!stralloc_cats(&comm_buf[c],recip)) nomem();
  while (!stralloc_0(&comm_buf[c])) nomem();
  comm_pos[c] = 0;
@@ -486,6 +498,7 @@
   int channel;
   datetime_sec retry;
   stralloc sender;
+  stralloc qqeh;
   int numtodo;
   int flaghiteof;
   int flagdying;
@@ -503,6 +516,7 @@
   {
    jo[j].refs = 0;
    jo[j].sender.s = 0;
+   jo[j].qqeh.s = 0;
   }
 }
 
@@ -658,11 +672,12 @@
  char buf[128];
  char inbuf[128];
  static stralloc sender = {0};
+ static stralloc qqeh = {0};
  static stralloc quoted = {0};
  datetime_sec birth;
  unsigned long qp;
 
- if (!getinfo(&sender,&birth,id)) return 0; /* XXX: print warning */
+ if (!getinfo(&sender,&qqeh,&birth,id)) return 0; /* XXX: print warning */
 
  /* owner-@host-@[] -> owner-@host */
  if (sender.len >= 5)
@@ -855,7 +870,7 @@
  d[c][i].mpos = mpos;
  d[c][i].used = 1; ++concurrencyused[c];
 
- comm_write(c,i,jo[j].id,jo[j].sender.s,recip);
+ comm_write(c,i,jo[j].id,jo[j].sender.s,jo[j].qqeh.s,recip);
 
  strnum2[fmt_ulong(strnum2,d[c][i].delid)] = 0;
  strnum3[fmt_ulong(strnum3,jo[j].id)] = 0;
@@ -1059,6 +1074,7 @@
  datetime_sec birth;
  struct prioq_elt pe;
  static stralloc line = {0};
+ static stralloc qqeh = {0};
  int match;
 
  if (flagexitasap) return;
@@ -1074,13 +1090,14 @@
    pass[c].mpos = 0;
    pass[c].fd = open_read(fn.s);
    if (pass[c].fd == -1) goto trouble;
-   if (!getinfo(&line,&birth,pe.id)) { close(pass[c].fd); goto trouble; }
+   if (!getinfo(&line,&qqeh,&birth,pe.id)) { close(pass[c].fd); goto trouble; }
    pass[c].id = pe.id;
    substdio_fdbuf(&pass[c].ss,read,pass[c].fd,pass[c].buf,sizeof(pass[c].buf));
    pass[c].j = job_open(pe.id,c);
    jo[pass[c].j].retry = nextretry(birth,c);
    jo[pass[c].j].flagdying = (recent > birth + lifetime);
    while (!stralloc_copy(&jo[pass[c].j].sender,&line)) nomem();
+   while (!stralloc_copy(&jo[pass[c].j].qqeh,&qqeh)) nomem();
   }
 
  if (!del_avail(c)) return;
@@ -1346,8 +1363,15 @@
      case 'p':
        scan_ulong(todoline.s + 1,&pid);
        break;
+    case 'e':
+       if (substdio_put(&ssinfo,todoline.s,todoline.len) == -1)
+	{
+	 fnmake_info(id);
+         log3("warning: trouble writing to ",fn.s,"\n"); goto fail;
+	}
+       break;
      case 'F':
-       if (substdio_putflush(&ssinfo,todoline.s,todoline.len) == -1)
+       if (substdio_put(&ssinfo,todoline.s,todoline.len) == -1)
 	{
 	 fnmake_info(id);
          log3("warning: trouble writing to ",fn.s,"\n"); goto fail;
diff -u orig/spawn.c ./spawn.c
--- orig/spawn.c	1998-06-15 06:53:16.000000000 -0400
+++ ./spawn.c	2004-07-19 12:06:46.000000000 -0400
@@ -68,6 +68,7 @@
 int delnum;
 stralloc messid = {0};
 stralloc sender = {0};
+stralloc qqeh = {0};
 stralloc recip = {0};
 
 void err(s) char *s;
@@ -119,7 +120,7 @@
 
  coe(pi[0]);
 
- f = spawn(fdmess,pi[1],sender.s,recip.s,j);
+ f = spawn(fdmess,pi[1],sender.s,qqeh.s,recip.s,j);
  close(fdmess);
  if (f == -1)
   { close(pi[0]); close(pi[1]); err("Zqmail-spawn unable to fork. (#4.3.0)\n"); return; }
@@ -163,8 +164,12 @@
      case 2:
        if (!stralloc_append(&sender,&ch)) flagabort = 1;
        if (ch) break;
-       recip.len = 0; stage = 3; break;
+       qqeh.len = 0; stage = 3; break;
      case 3:
+       if (!stralloc_append(&qqeh,&ch)) flagabort = 1;
+       if (ch) break;
+       recip.len = 0; stage = 4; break;
+     case 4:
        if (!stralloc_append(&recip,&ch)) flagabort = 1;
        if (ch) break;
        docmd();
