diff -N -u netqmail-1.06/errbits.c netqmail-1.06.errmsg-v1.1/errbits.c
--- netqmail-1.06/errbits.c	1970-01-01 01:00:00.000000000 +0100
+++ netqmail-1.06.errmsg-v1.1/errbits.c	2008-11-02 19:17:54.000000000 +0000
@@ -0,0 +1,54 @@
+#include "stralloc.h"
+#include "readwrite.h"
+#include "errbits.h"
+#include "substdio.h"
+#include "fmt.h"
+#include "exit.h"
+
+char sserrbuf[512];
+static substdio sserr = SUBSTDIO_FDBUF(write,2,sserrbuf,sizeof sserrbuf);
+static stralloc foo = {0};
+
+static char pid_str[FMT_ULONG]="?PID?";
+
+void esetfd(fd) int fd; { sserr.fd=fd; }
+
+void eout(s1)  char *s1; {substdio_puts(&sserr,s1);}
+void eout2(s1,s2) char *s1,*s2; {substdio_puts(&sserr,s1);substdio_puts(&sserr,s2);}
+void eout3(s1,s2,s3) char *s1,*s2,*s3; {substdio_puts(&sserr,s1);substdio_puts(&sserr,s2);substdio_puts(&sserr,s3);}
+
+void epid()
+{
+  if (*pid_str == '?') /* not yet set from getpid() */
+    pid_str[fmt_ulong(pid_str,getpid())] = 0;
+  eout(pid_str);
+}
+void eflush() { substdio_flush(&sserr); }
+
+/* The functions below here come from qsutil.c with minor changes */
+void eoutsa(sa) stralloc *sa; { substdio_putflush(&sserr,sa->s,sa->len); }
+
+void nomem() { substdio_putsflush(&sserr,"Out Of Memory: quitting.\n"); _exit(1); }
+
+static int issafe(ch) char ch;
+{ /* Differs from qsutil.c version: space and % permitted */
+ if (ch == ':') return 0; /* Replace since used as delimiter in logs */
+ if (ch == '<') return 0; /* Replace since used around addresses in logs */
+ if (ch == '>') return 0; /* Replace since used around addresses in logs */
+ if (ch < 32)   return 0; /* Note that space (32) is permitted */
+ if (ch > 126)  return 0;
+ return 1;
+}
+
+void eoutclean(s) char *s;
+{
+ int i;
+ while (!stralloc_copys(&foo,s)) nomem();
+ for (i = 0;i < foo.len;++i)
+   if (foo.s[i] == '\n')
+     foo.s[i] = '/';
+   else
+     if (!issafe(foo.s[i]))
+       foo.s[i] = '_';
+ eoutsa(&foo);
+}
diff -N -u netqmail-1.06/errbits.h netqmail-1.06.errmsg-v1.1/errbits.h
--- netqmail-1.06/errbits.h	1970-01-01 01:00:00.000000000 +0100
+++ netqmail-1.06.errmsg-v1.1/errbits.h	2008-10-21 12:05:44.000000000 +0100
@@ -0,0 +1,13 @@
+extern void esetfd(); /* functions in this module default to FD 2 (stderr) for output, change with esetfd */
+extern void eout();
+extern void eout2();
+extern void eout3();
+#define eout4(s1,s2,s3,s4)		        	{ eout3(s1,s2,s3); eout(s4); }
+#define eout5(s1,s2,s3,s4,s5)		        { eout3(s1,s2,s3); eout2(s4,s5); }
+#define eout6(s1,s2,s3,s4,s5,s6)	    	{ eout3(s1,s2,s3); eout3(s4,s5,s6); }
+#define eout7(s1,s2,s3,s4,s5,s6,s7) 		{ eout3(s1,s2,s3); eout4(s4,s5,s6,s7); }
+#define eout8(s1,s2,s3,s4,s5,s6,s7,s8)		{ eout3(s1,s2,s3); eout5(s4,s5,s6,s7,s8); }
+#define eout9(s1,s2,s3,s4,s5,s6,s7,s8,s9)	{ eout3(s1,s2,s3); eout6(s4,s5,s6,s7,s8,s9); }
+extern void eoutsa();
+extern void epid();
+extern void eflush();
diff -N -u netqmail-1.06/Makefile netqmail-1.06.errmsg-v1.1/Makefile
--- netqmail-1.06/Makefile	2007-11-30 20:22:54.000000000 +0000
+++ netqmail-1.06.errmsg-v1.1/Makefile	2008-10-21 12:04:48.000000000 +0100
@@ -508,6 +508,10 @@
 compile envread.c env.h str.h
 	./compile envread.c
 
+errbits.o: \
+compile errbits.c errbits.h stralloc.h gen_alloc.h fmt.h exit.h
+	./compile errbits.c
+
 error.a: \
 makelib error.o error_str.o error_temp.o
 	./makelib error.a error.o error_str.o error_temp.o
@@ -1535,12 +1539,14 @@
 load qmail-smtpd.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 \
+open.a sig.a case.a env.a stralloc.a errbits.o \
+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 \
+	errbits.o \
 	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
 	socket.lib`
 
diff -N -u netqmail-1.06/qmail-smtpd.c netqmail-1.06.errmsg-v1.1/qmail-smtpd.c
--- netqmail-1.06/qmail-smtpd.c	2007-11-30 20:22:54.000000000 +0000
+++ netqmail-1.06.errmsg-v1.1/qmail-smtpd.c	2008-11-02 19:13:06.000000000 +0000
@@ -23,16 +23,35 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 #include "commands.h"
+#include "errbits.h"
 
+#define enew()	{ eout("qmail-smtpd: pid "); epid(); eout3(" from ",remoteip,": "); }
+/* Or if you prefer shorter log messages (deduce IP from tcpserver PID entry), */
+/*              { eout("qmail-smtpd: pid "); epid(); eout(": "); } */
 #define MAXHOPS 100
 unsigned int databytes = 0;
 int timeout = 1200;
 
+char *remoteip="(not yet set)";
+char *remotehost;
+char *remoteinfo;
+char *local;
+char *relayclient;
+
+stralloc mailfrom = {0};
+stralloc rcptto = {0};
+int rcptcount;
+stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */
+
 int safewrite(fd,buf,len) int fd; char *buf; int len;
 {
   int r;
   r = timeoutwrite(timeout,fd,buf,len);
-  if (r <= 0) _exit(1);
+  if (r <= 0)
+  {
+    enew(); eout("Write error (disconnect?): quitting\n"); eflush();
+    _exit(1);
+  }
   return r;
 }
 
@@ -42,22 +61,91 @@
 void flush() { substdio_flush(&ssout); }
 void out(s) char *s; { substdio_puts(&ssout,s); }
 
-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_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_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(arg) char *arg; { out("502 unimplemented (#5.5.1)\r\n"); }
-void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
-void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }
-void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); }
-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 die_read()
+{
+  enew(); eout("Read error (disconnect?): quitting\n"); eflush(); _exit(1);
+}
+void die_alarm()
+{
+  enew(); eout("Connection timed out: quitting\n"); eflush();
+  out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1);
+}
+void die_nomem()
+{
+  enew(); eout("Out of memory: quitting\n"); eflush();
+  out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1);
+}
+void die_control()
+{
+  enew(); eout("Unable to read controls: quitting\n"); eflush();
+  out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1);
+}
+void die_ipme()
+{
+  enew(); eout("Unable to figure out my IP addresses: quitting\n"); eflush();
+  out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1);
+}
+void straynewline()
+{
+  enew(); eout("Stray newline: quitting\n"); eflush();
+  out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1);
+}
+
+void err_bmf()
+{
+  enew(); eout("Sender address in badmailfrom\n"); eflush();
+  out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n");
+}
+void err_nogateway()
+{
+  enew(); eout("Recipient domain not in rcpthosts <"); eoutclean(addr.s); eout(">\n"); eflush();
+  out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n");
+}
+void err_unimpl(arg) char *arg;
+{
+  enew(); eout("Unimplemented command\n"); eflush();
+  out("502 unimplemented (#5.5.1)\r\n");
+}
+void err_syntax(arg) char *arg;
+{
+  enew(); eout("MAIL or RCPT address syntax error <"); eoutclean(arg); eout(">\n"); eflush();
+  out("555 syntax error (#5.5.4)\r\n");
+}
+void err_wantmail()
+{
+  enew(); eout("Attempted RCPT or DATA before MAIL\n"); eflush();
+  out("503 MAIL first (#5.5.1)\r\n");
+}
+void err_wantrcpt()
+{
+  enew(); eout("Attempted DATA before RCPT\n"); eflush();
+  out("503 RCPT first (#5.5.1)\r\n");
+}
+void err_noop(arg) char *arg;
+{
+  enew(); eout("NOOP\n"); eflush();
+  out("250 ok\r\n");
+}
+void err_vrfy(arg) char *arg;
+{
+  enew(); eout("VRFY requested\n"); eflush();
+  out("252 send some mail, i'll try my best\r\n");
+}
+void err_qqt()
+{
+  enew(); eout("qqt failure\n"); eflush();
+  out("451 qqt failure (#4.3.0)\r\n");
+}
+void err_hops()
+{
+  enew(); eout("Exceeded hop count\n"); eflush();
+  out("554 too many hops, this message is looping (#5.4.6)\r\n");
+}
+void err_databytes()
+{
+  enew(); eout("Exceeded DATABYTES limit\n"); eflush();
+  out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n");
+}
 
 
 stralloc greeting = {0};
@@ -73,15 +161,10 @@
 }
 void smtp_quit(arg) char *arg;
 {
+  enew(); eout("Remote end QUIT: quitting\n"); eflush();
   smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
 }
 
-char *remoteip;
-char *remotehost;
-char *remoteinfo;
-char *local;
-char *relayclient;
-
 stralloc helohost = {0};
 char *fakehelo; /* pointer into helohost, or 0 */
 
@@ -132,11 +215,10 @@
   remoteinfo = env_get("TCPREMOTEINFO");
   relayclient = env_get("RELAYCLIENT");
   dohelo(remotehost);
+  enew(); eout("New session\n"); eflush();
 }
 
 
-stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */
-
 int addrparse(arg)
 char *arg;
 {
@@ -219,37 +301,40 @@
 
 int seenmail = 0;
 int flagbarf; /* defined if seenmail */
-stralloc mailfrom = {0};
-stralloc rcptto = {0};
 
 void smtp_helo(arg) char *arg;
 {
+  enew(); eout("Received HELO "); eoutclean(arg); eout("\n"); eflush();
   smtp_greet("250 "); out("\r\n");
   seenmail = 0; dohelo(arg);
 }
 void smtp_ehlo(arg) char *arg;
 {
+  enew(); eout("Received EHLO "); eoutclean(arg); eout("\n"); eflush();
   smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
   seenmail = 0; dohelo(arg);
 }
 void smtp_rset(arg) char *arg;
 {
   seenmail = 0;
+  enew(); eout("Session RSET\n"); eflush();
   out("250 flushed\r\n");
 }
 void smtp_mail(arg) char *arg;
 {
-  if (!addrparse(arg)) { err_syntax(); return; }
+  if (!addrparse(arg)) { err_syntax(arg); return; }
   flagbarf = bmfcheck();
   seenmail = 1;
   if (!stralloc_copys(&rcptto,"")) die_nomem();
   if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
   if (!stralloc_0(&mailfrom)) die_nomem();
+  rcptcount = 0;
+  enew(); eout("Sender <"); eoutclean(mailfrom.s); eout(">\n"); eflush();
   out("250 ok\r\n");
 }
 void smtp_rcpt(arg) char *arg; {
   if (!seenmail) { err_wantmail(); return; }
-  if (!addrparse(arg)) { err_syntax(); return; }
+  if (!addrparse(arg)) { err_syntax(arg); return; }
   if (flagbarf) { err_bmf(); return; }
   if (relayclient) {
     --addr.len;
@@ -261,6 +346,8 @@
   if (!stralloc_cats(&rcptto,"T")) die_nomem();
   if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
   if (!stralloc_0(&rcptto)) die_nomem();
+  ++rcptcount;
+  enew(); eout("Recipient <"); eoutclean(addr.s); eout(">\n"); eflush();
   out("250 ok\r\n");
 }
 
@@ -280,6 +367,7 @@
 
 struct qmail qqt;
 unsigned int bytestooverflow = 0;
+unsigned int messagebytes = 0;
 
 void put(ch)
 char *ch;
@@ -287,6 +375,7 @@
   if (bytestooverflow)
     if (!--bytestooverflow)
       qmail_fail(&qqt);
+  messagebytes++;
   qmail_put(&qqt,ch,1);
 }
 
@@ -363,6 +452,11 @@
   accept_buf[fmt_ulong(accept_buf,qp)] = 0;
   out(accept_buf);
   out("\r\n");
+  enew(); eout2("Message accepted, qp ",accept_buf);
+  accept_buf[fmt_ulong(accept_buf,rcptcount)] = 0;
+  eout3(" (",accept_buf," recipients, ");
+  accept_buf[fmt_ulong(accept_buf,messagebytes)] = 0;
+  eout2(accept_buf," bytes)\n"); eflush();
 }
 
 void smtp_data(arg) char *arg; {
@@ -374,6 +468,7 @@
   if (!rcptto.len) { err_wantrcpt(); return; }
   seenmail = 0;
   if (databytes) bytestooverflow = databytes + 1;
+  messagebytes = 0;
   if (qmail_open(&qqt) == -1) { err_qqt(); return; }
   qp = qmail_qp(&qqt);
   out("354 go ahead\r\n");
@@ -387,11 +482,15 @@
  
   qqx = qmail_close(&qqt);
   if (!*qqx) { acceptmessage(qp); return; }
-  if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
-  if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
+  if (hops) { err_hops(); return; }
+  if (databytes) if (!bytestooverflow) { err_databytes(); return; }
   if (*qqx == 'D') out("554 "); else out("451 ");
   out(qqx + 1);
   out("\r\n");
+  enew(); eout("Message rejected (");
+  if (*qqx == 'D') eout("554 "); else eout("451 ");
+  eoutclean(qqx + 1); eout(")\n");
+  eflush();
 }
 
 struct commands smtpcommands[] = {
@@ -411,6 +510,7 @@
 void main()
 {
   sig_pipeignore();
+  /* esetfd(2); Errors default to FD2 (stderr), change here if needed */
   if (chdir(auto_qmail) == -1) die_control();
   setup();
   if (ipme_init() != 1) die_ipme();
diff -N -u netqmail-1.06/TARGETS netqmail-1.06.errmsg-v1.1/TARGETS
--- netqmail-1.06/TARGETS	1998-06-15 11:53:16.000000000 +0100
+++ netqmail-1.06.errmsg-v1.1/TARGETS	2008-10-21 15:07:28.000000000 +0100
@@ -96,6 +96,7 @@
 error_str.o
 error_temp.o
 error.a
+errbits.o
 str_len.o
 str_diff.o
 str_diffn.o
