<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">Apply this patch to qmail using "patch &lt;patchfile".  Recompile and
reinstall according to qmail's INSTALL documentation.

This patch to qmail-remote causes it to attempt qmtp first if the MX priority
indicates so.  Read http://cr.yp.to/proto/mxps.txt for more information.
If you want this qmail-remote to be able to send email to you using qmtp,
then you should be running a qmtpd on port 209, and you should have your
lowest MX priority be 12801.

This is version 2 of the patch.  Ian Lance Taylor fixed a problem
whereby qmtp did not properly fall back to smtp if the qmtp connect()
failed.  This would cause problems for hosts with an MXPS QMTP
priority, or hosts whose firewall was rejecting QMTP but not SMTP.

diff -u orig/qmail-remote.c ./qmail-remote.c
--- orig/qmail-remote.c	Fri Jan  5 01:31:36 2001
+++ ./qmail-remote.c	Wed Jan 17 10:11:29 2001
@@ -1,4 +1,5 @@
 #include &lt;sys/types.h&gt;
+#include &lt;sys/stat.h&gt;
 #include &lt;sys/socket.h&gt;
 #include &lt;netinet/in.h&gt;
 #include &lt;arpa/inet.h&gt;
@@ -14,6 +15,7 @@
 #include "dns.h"
 #include "alloc.h"
 #include "quote.h"
+#include "fmt.h"
 #include "ip.h"
 #include "ipalloc.h"
 #include "ipme.h"
@@ -31,8 +33,8 @@
 
 #define HUGESMTPTEXT 5000
 
-#define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */
-unsigned long port = PORT_SMTP;
+unsigned long smtp_port = 25; /* silly rabbit, /etc/services is for users */
+unsigned long qmtp_port = 209;
 
 GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
 GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
@@ -70,6 +72,8 @@
 Unable to switch to home directory. (#4.3.0)\n"); zerodie(); }
 void temp_control() { out("Z\
 Unable to read control files. (#4.3.0)\n"); zerodie(); }
+void temp_proto() { out("Z\
+recipient did not talk proper QMTP (#4.3.0)\n"); zerodie(); }
 void perm_partialline() { out("D\
 SMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); zerodie(); }
 void perm_usage() { out("D\
@@ -122,9 +126,9 @@
   return r;
 }
 
-char inbuf[1024];
+char inbuf[1500];
 substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf);
-char smtptobuf[1024];
+char smtptobuf[1500];
 substdio smtpto = SUBSTDIO_FDBUF(safewrite,-1,smtptobuf,sizeof smtptobuf);
 char smtpfrombuf[128];
 substdio smtpfrom = SUBSTDIO_FDBUF(saferead,-1,smtpfrombuf,sizeof smtpfrombuf);
@@ -273,6 +277,113 @@
   quit("K"," accepted message");
 }
 
+int qmtp_priority(int pref)
+{
+  if (pref &lt; 12800) return 0;
+  if (pref &gt; 13055) return 0;
+  if (pref % 16 == 1) return 1;
+  return 0;
+}
+
+void qmtp()
+{
+  struct stat st;
+  unsigned long len;
+  int len2;
+  char *x;
+  int i;
+  int n;
+  unsigned char ch;
+  char num[FMT_ULONG];
+  int flagallok;
+
+  if (fstat(0,&amp;st) == -1) quit("Z", " unable to fstat stdin");
+  len = st.st_size;
+
+  /* the following code was substantially taken from serialmail'ss serialqmtp.c */
+  substdio_put(&amp;smtpto,num,fmt_ulong(num,len+1));
+  substdio_put(&amp;smtpto,":\n",2);
+  while (len &gt; 0) {
+    n = substdio_feed(&amp;ssin);
+    if (n &lt;= 0) _exit(32); /* wise guy again */
+    x = substdio_PEEK(&amp;ssin);
+    substdio_put(&amp;smtpto,x,n);
+    substdio_SEEK(&amp;ssin,n);
+    len -= n;
+  }
+  substdio_put(&amp;smtpto,",",1);
+
+  len = sender.len;
+  substdio_put(&amp;smtpto,num,fmt_ulong(num,len));
+  substdio_put(&amp;smtpto,":",1);
+  substdio_put(&amp;smtpto,sender.s,sender.len);
+  substdio_put(&amp;smtpto,",",1);
+
+  len = 0;
+  for (i = 0;i &lt; reciplist.len;++i)
+    len += fmt_ulong(num,reciplist.sa[i].len) + 1 + reciplist.sa[i].len + 1;
+  substdio_put(&amp;smtpto,num,fmt_ulong(num,len));
+  substdio_put(&amp;smtpto,":",1);
+  for (i = 0;i &lt; reciplist.len;++i) {
+    substdio_put(&amp;smtpto,num,fmt_ulong(num,reciplist.sa[i].len));
+    substdio_put(&amp;smtpto,":",1);
+    substdio_put(&amp;smtpto,reciplist.sa[i].s,reciplist.sa[i].len);
+    substdio_put(&amp;smtpto,",",1);
+  }
+  substdio_put(&amp;smtpto,",",1);
+  substdio_flush(&amp;smtpto);
+
+  flagallok = 1;
+
+  for (i = 0;i &lt; reciplist.len;++i) {
+    len = 0;
+    for (;;) {
+      get(&amp;ch);
+      if (ch == ':') break;
+      if (len &gt; 200000000) temp_proto();
+      if (ch - '0' &gt; 9) temp_proto();
+      len = 10 * len + (ch - '0');
+    }
+    if (!len) temp_proto();
+    get(&amp;ch); --len;
+    if ((ch != 'Z') &amp;&amp; (ch != 'D') &amp;&amp; (ch != 'K')) temp_proto();
+
+    if (!stralloc_copyb(&amp;smtptext,&amp;ch,1)) temp_proto();
+    if (!stralloc_cats(&amp;smtptext,"qmtp: ")) temp_nomem();
+
+    while (len &gt; 0) {
+      get(&amp;ch);
+      --len;
+    }
+
+    for (len = 0;len &lt; smtptext.len;++len) {
+      ch = smtptext.s[len];
+      if ((ch &lt; 32) || (ch &gt; 126)) smtptext.s[len] = '?';
+    }
+    get(&amp;ch);
+    if (ch != ',') temp_proto();
+    smtptext.s[smtptext.len-1] = '\n';
+
+    if (smtptext.s[0] == 'K') out("r");
+    else if (smtptext.s[0] == 'D') {
+      out("h");
+      flagallok = 0;
+    }
+    else { /* if (smtptext.s[0] == 'Z') */
+      out("s");
+      flagallok = 0;
+    }
+    if (substdio_put(subfdoutsmall,smtptext.s+1,smtptext.len-1) == -1) temp_noconn();
+    zero();
+  }
+  if (!flagallok) {
+    out("DGiving up on ");outhost();out("\n");
+  } else {
+    out("KAll received okay by ");outhost();out("\n");
+  }
+  zerodie();
+}
+
 stralloc canonhost = {0};
 stralloc canonbox = {0};
 
@@ -357,7 +468,7 @@
   if (relayhost) {
     i = str_chr(relayhost,':');
     if (relayhost[i]) {
-      scan_ulong(relayhost + i + 1,&amp;port);
+      scan_ulong(relayhost + i + 1,&amp;smtp_port);
       relayhost[i] = 0;
     }
     if (!stralloc_copys(&amp;host,relayhost)) temp_nomem();
@@ -414,7 +525,17 @@
     smtpfd = socket(AF_INET,SOCK_STREAM,0);
     if (smtpfd == -1) temp_oserr();
  
-    if (timeoutconn(smtpfd,&amp;ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
+    if (qmtp_priority(ip.ix[i].pref)) {
+      if (timeoutconn(smtpfd,&amp;ip.ix[i].ip,(unsigned int) qmtp_port,timeoutconnect) == 0) {
+	tcpto_err(&amp;ip.ix[i].ip,0);
+	partner = ip.ix[i].ip;
+	qmtp(); /* does not return */
+      }
+      close(smtpfd);
+      smtpfd = socket(AF_INET,SOCK_STREAM,0);
+      if (smtpfd == -1) temp_oserr();
+    }
+    if (timeoutconn(smtpfd,&amp;ip.ix[i].ip,(unsigned int) smtp_port,timeoutconnect) == 0) {
       tcpto_err(&amp;ip.ix[i].ip,0);
       partner = ip.ix[i].ip;
       smtp(); /* does not return */
</pre></body></html>