If you set the environment variable QQEH before calling qmail-queue (or anything that subsequently calls it), the contents of it will be prepended to the email prior to the Received: header that qmail-queue inserts. diff -u orig/condredirect.c ./condredirect.c --- orig/condredirect.c 1998-06-15 06:53:16.000000000 -0400 +++ ./condredirect.c 2004-07-15 12:19:42.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-15 12:18:22.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-14 16:20:51.000000000 -0400 @@ -1421,9 +1421,11 @@ 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 \ +env.a \ 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 \ + env.a \ alloc.a substdio.a error.a str.a fs.a auto_qmail.o \ auto_split.o auto_uids.o @@ -1434,6 +1436,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-15 12:23:03.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-15 12:21:51.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-15 11:41:31.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-16 11:51:02.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-15 11:53:46.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) @@ -276,6 +279,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 +488,7 @@ if (!(host = *argv++)) usage(); if (!(sender = *argv++)) usage(); if (!(aliasempty = *argv++)) usage(); + if (!(qqeh = *argv++)) usage(); if (*argv) usage(); if (homedir[0] != '/') usage(); @@ -495,6 +500,7 @@ if (!env_put2("HOME",homedir)) temp_nomem(); if (!env_put2("USER",user)) temp_nomem(); if (!env_put2("LOCAL",local)) temp_nomem(); + if (!env_put2("QQEH",qqeh)) temp_nomem(); if (!stralloc_copys(&envrecip,local)) temp_nomem(); if (!stralloc_cats(&envrecip,"@")) temp_nomem(); 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-15 10:41:17.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-07-16 11:53:50.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 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-07-14 16:23:52.000000000 -0400 @@ -16,6 +16,7 @@ #include "auto_uids.h" #include "date822fmt.h" #include "fmtqfn.h" +#include "env.h" #define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */ #define ADDR 1003 @@ -155,7 +156,9 @@ { unsigned int len; char ch; + char *qqeh; + qqeh = env_get("QQEH"); sig_blocknone(); umask(033); if (chdir(auto_qmail) == -1) die(61); @@ -216,6 +219,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-15 11:04:39.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-15 12:16:28.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-15 10:43:19.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-15 10:31:58.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(); + while (!stralloc_0(sa)) nomem(); + } + if (line.s[0] == 'e') { + while (!stralloc_copys(eh,line.s + 1)) nomem(); + while (!stralloc_0(eh)) nomem(); + } + } close(fdinfo); - if (!match) return 0; - if (line.s[0] != 'F') return 0; *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-15 10:41:27.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(); .