diff --unidirectional-new-file -u /usr/local/src/qmail-1.03/case_startb.c ./case_startb.c
--- /usr/local/src/qmail-1.03/case_startb.c	1969-12-31 19:00:00.000000000 -0500
+++ ./case_startb.c	2003-03-06 17:53:59.000000000 -0500
@@ -0,0 +1,21 @@
+#include "case.h"
+
+int case_startb(s,len,t)
+register char *s;
+unsigned int len;
+register char *t;
+{
+  register unsigned char x;
+  register unsigned char y;
+
+  for (;;) {
+    y = *t++ - 'A';
+    if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
+    if (!y) return 1;
+    if (!len) return 0;
+    --len;
+    x = *s++ - 'A';
+    if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
+    if (x != y) return 0;
+  }
+}
diff --unidirectional-new-file -u /usr/local/src/qmail-1.03/Makefile ./Makefile
--- /usr/local/src/qmail-1.03/Makefile	1998-06-15 06:53:16.000000000 -0400
+++ ./Makefile	2003-03-10 10:49:44.000000000 -0500
@@ -217,9 +217,9 @@
 
 case.a: \
 makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \
-case_starts.o
+case_starts.o case_startb.o
 	./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \
-	case_lowers.o case_starts.o
+	case_lowers.o case_starts.o case_startb.o
 
 case_diffb.o: \
 compile case_diffb.c case.h
@@ -237,6 +237,10 @@
 compile case_lowers.c case.h
 	./compile case_lowers.c
 
+case_startb.o: \
+compile case_startb.c case.h
+	./compile case_startb.c
+
 case_starts.o: \
 compile case_starts.c case.h
 	./compile case_starts.c
diff --unidirectional-new-file -u /usr/local/src/qmail-1.03/qmail-smtpd.c ./qmail-smtpd.c
--- /usr/local/src/qmail-1.03/qmail-smtpd.c	1998-06-15 06:53:16.000000000 -0400
+++ ./qmail-smtpd.c	2003-08-31 09:07:32.000000000 -0400
@@ -281,9 +281,101 @@
 struct qmail qqt;
 unsigned int bytestooverflow = 0;
 
+int putinheader;
+int linespastheader;       /* =0 after boundary is found in body, */
+                                /* until blank line */
+char linetype;
+int flagexecutable;
+
+stralloc line = {0};
+stralloc content = {0};
+stralloc boundary = {0};
+
 void put(ch)
 char *ch;
 {
+  char *cp, *cpstart, *cpafter;
+  unsigned int len;
+
+  if (line.len < 1024)
+    if (!stralloc_catb(&line,ch,1)) die_nomem();
+
+  if (*ch == '\n') {
+    if (putinheader) {
+      /*substdio_put(&ssout,line.s,line.len);*/
+      if (line.len == 1) {
+	putinheader = 0;
+	if (content.len) {			/* MIME header */
+	  cp = content.s;
+	  len = content.len;
+	  while (len && (*cp == ' ' || *cp == '\t')) { ++cp; --len; }
+	  cpstart = cp;
+	  if (len && *cp == '"') {			/* might be commented */
+	    ++cp; --len; cpstart = cp;
+	    while (len && *cp != '"') { ++cp; --len; }
+	  } else {
+	    while (len && *cp != ' ' && *cp != '\t' && *cp != ';') {
+	      ++cp; --len;
+	    }
+	  }
+
+	  cpafter = content.s+content.len;
+	  while((cp += byte_chr(cp,cpafter-cp,';')) != cpafter) {
+	    ++cp;
+	    while (cp < cpafter && (*cp == ' ' || *cp == '\t')) ++cp;
+	    if (case_startb(cp,cpafter - cp,"boundary=")) {
+	      cp += 9;			/* after boundary= */
+	      if (cp < cpafter && *cp == '"') {
+		++cp;
+		cpstart = cp;
+		while (cp < cpafter && *cp != '"') ++cp;
+	      } else {
+		cpstart = cp;
+		while (cp < cpafter &&
+		   *cp != ';' && *cp != ' ' && *cp != '\t') ++cp;
+	      }
+	      if (!stralloc_copys(&boundary,"--")) die_nomem();
+	      if (!stralloc_catb(&boundary,cpstart,cp-cpstart))
+		      die_nomem();
+	      break;
+	    }
+	  }
+	}
+      } else {
+	if ((*line.s == ' ' || *line.s == '\t')) {
+	  switch(linetype) {
+	    case 'C': if (!stralloc_catb(&content,line.s,line.len-1)) die_nomem(); break;
+	    default: break;
+	  }
+	} else {
+	  if (case_startb(line.s,line.len,"content-type:")) {
+	    if (!stralloc_copyb(&content,line.s+13,line.len-14)) die_nomem();
+	    linetype = 'C';
+	  } else {
+	    linetype = ' ';
+	  }
+	}
+      }
+    } else {
+      if (boundary.len && *line.s == '-' && line.len > boundary.len &&
+	  !str_diffn(line.s,boundary.s,boundary.len)) {
+	  linespastheader = 0;
+      } else if (linespastheader == 0 && line.len == 1) {
+	linespastheader = 1;
+      } else if (linespastheader == 1) {
+	if (line.len >= 9)
+	  if (!str_diffn(line.s,"TVqQAAMAA",9) ||
+	      !str_diffn(line.s,"UEsDBBQAA",9) || /* .zip */
+	      !str_diffn(line.s,"TVpQAAIAA",9)) {
+	    flagexecutable = 1;
+	    qmail_fail(&qqt);
+	}
+	linespastheader = 2;
+      }
+    }
+    line.len = 0;
+  }
+
   if (bytestooverflow)
     if (!--bytestooverflow)
       qmail_fail(&qqt);
@@ -374,6 +466,12 @@
   if (!rcptto.len) { err_wantrcpt(); return; }
   seenmail = 0;
   if (databytes) bytestooverflow = databytes + 1;
+  boundary.len = 0;
+  content.len = 0;
+  putinheader = 1;
+  linespastheader = -1;
+  flagexecutable = 0;
+  linetype = ' ';
   if (qmail_open(&qqt) == -1) { err_qqt(); return; }
   qp = qmail_qp(&qqt);
   out("354 go ahead\r\n");
@@ -389,6 +487,7 @@
   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 (flagexecutable) { out("552 we don't accept email with executable content (#5.3.4)\r\n"); return; }
   if (*qqx == 'D') out("554 "); else out("451 ");
   out(qqx + 1);
   out("\r\n");

