diff -crN ./original/Makefile ./modified/Makefile
*** ./original/Makefile	Sun Oct  1 08:41:29 2023
--- ./modified/Makefile	Sun Oct  1 08:48:53 2023
***************
*** 125,130 ****
--- 125,134 ----
  compile auto_usera.c
  	./compile auto_usera.c
  
+ base64.o: \
+ compile base64.c base64.h
+ 	./compile base64.c
+ 
  binm1: \
  binm1.sh conf-qmail
  	cat binm1.sh \
***************
*** 1430,1441 ****
  load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \
  timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \
  ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \
! substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
  	./load qmail-remote control.o constmap.o timeoutread.o \
  	timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
  	ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
  	lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
! 	str.a fs.a auto_qmail.o  `cat dns.lib` `cat socket.lib`
  
  qmail-remote.0: \
  qmail-remote.8
--- 1434,1445 ----
  load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \
  timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \
  ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \
! substdio.a error.a str.a fs.a auto_qmail.o base64.o dns.lib socket.lib
  	./load qmail-remote control.o constmap.o timeoutread.o \
  	timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
  	ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
  	lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
! 	str.a fs.a auto_qmail.o base64.o  `cat dns.lib` `cat socket.lib`
  
  qmail-remote.0: \
  qmail-remote.8
diff -crN ./original/base64.c ./modified/base64.c
*** ./original/base64.c	Thu Jan  1 09:00:00 1970
--- ./modified/base64.c	Tue Jan  9 03:48:28 2001
***************
*** 0 ****
--- 1,90 ----
+ #include "base64.h"
+ #include "stralloc.h"
+ #include "substdio.h"
+ #include "str.h"
+ 
+ static char *b64alpha =
+   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ #define B64PAD '='
+ 
+ /* returns 0 ok, 1 illegal, -1 problem */
+ 
+ int b64decode(in,l,out)
+ const unsigned char *in;
+ int l;
+ stralloc *out; /* not null terminated */
+ {
+   int i, j;
+   unsigned char a[4];
+   unsigned char b[3];
+   char *s;
+ 
+   if (l == 0)
+   {
+     if (!stralloc_copys(out,"")) return -1;
+     return 0;
+   }
+ 
+   if (!stralloc_ready(out,l + 2)) return -1; /* XXX generous */
+   s = out->s;
+ 
+   for (i = 0;i < l;i += 4) {
+     for (j = 0;j < 4;j++)
+       if ((i + j) < l && in[i + j] != B64PAD)
+       {
+         a[j] = str_chr(b64alpha,in[i + j]);
+         if (a[j] > 63) return 1;
+       }
+       else a[j] = 0;
+ 
+     b[0] = (a[0] << 2) | (a[1] >> 4);
+     b[1] = (a[1] << 4) | (a[2] >> 2);
+     b[2] = (a[2] << 6) | (a[3]);
+ 
+     *s++ = b[0];
+ 
+     if (in[i + 1] == B64PAD) break;
+     *s++ = b[1];
+ 
+     if (in[i + 2] == B64PAD) break;
+     *s++ = b[2];
+   }
+   out->len = s - out->s;
+   while (out->len && !out->s[out->len - 1]) --out->len; /* XXX avoid? */
+   return 0;
+ }
+ 
+ int b64encode(in,out)
+ stralloc *in;
+ stralloc *out; /* not null terminated */
+ {
+   unsigned char a, b, c;
+   int i;
+   char *s;
+ 
+   if (in->len == 0)
+   {
+     if (!stralloc_copys(out,"")) return -1;
+     return 0;
+   }
+ 
+   if (!stralloc_ready(out,in->len / 3 * 4 + 4)) return -1;
+   s = out->s;
+ 
+   for (i = 0;i < in->len;i += 3) {
+     a = in->s[i];
+     b = i + 1 < in->len ? in->s[i + 1] : 0;
+     c = i + 2 < in->len ? in->s[i + 2] : 0;
+ 
+     *s++ = b64alpha[a >> 2];
+     *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)];
+ 
+     if (i + 1 >= in->len) *s++ = B64PAD;
+     else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)];
+ 
+     if (i + 2 >= in->len) *s++ = B64PAD;
+     else *s++ = b64alpha[c & 63];
+   }
+   out->len = s - out->s;
+   return 0;
+ }
diff -crN ./original/base64.h ./modified/base64.h
*** ./original/base64.h	Thu Jan  1 09:00:00 1970
--- ./modified/base64.h	Tue Jan  9 03:48:28 2001
***************
*** 0 ****
--- 1,7 ----
+ #ifndef BASE64_H
+ #define BASE64_H
+ 
+ extern int b64decode();
+ extern int b64encode();
+ 
+ #endif
diff -crN ./original/qmail-remote.c ./modified/qmail-remote.c
*** ./original/qmail-remote.c	Sun Oct  1 08:41:29 2023
--- ./modified/qmail-remote.c	Sun Oct  1 00:24:36 2023
***************
*** 43,48 ****
--- 43,50 ----
  struct constmap maproutes;
  stralloc host = {0};
  stralloc sender = {0};
+ stralloc auth_smtp_user = {0};
+ stralloc auth_smtp_pass = {0};
  
  saa reciplist = {0};
  
***************
*** 221,242 ****
    unsigned long code;
    int flagbother;
    int i;
!  
    code = smtpcode();
    if (code >= 500 && code < 600) quit("DConnected to "," but greeting failed");
    if (code >= 400 && code < 500) return; /* try next MX, see RFC-2821 */
    if (code != 220) quit("ZConnected to "," but greeting failed");
   
!   substdio_puts(&smtpto,"HELO ");
    substdio_put(&smtpto,helohost.s,helohost.len);
    substdio_puts(&smtpto,"\r\n");
    substdio_flush(&smtpto);
!   if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
!  
!   substdio_puts(&smtpto,"MAIL FROM:<");
!   substdio_put(&smtpto,sender.s,sender.len);
!   substdio_puts(&smtpto,">\r\n");
!   substdio_flush(&smtpto);
    code = smtpcode();
    if (code >= 500) quit("DConnected to "," but sender was rejected");
    if (code >= 400) quit("ZConnected to "," but sender was rejected");
--- 223,282 ----
    unsigned long code;
    int flagbother;
    int i;
!   stralloc slop = {0};
! 
    code = smtpcode();
    if (code >= 500 && code < 600) quit("DConnected to "," but greeting failed");
    if (code >= 400 && code < 500) return; /* try next MX, see RFC-2821 */
    if (code != 220) quit("ZConnected to "," but greeting failed");
   
!   substdio_puts(&smtpto,"EHLO ");
    substdio_put(&smtpto,helohost.s,helohost.len);
    substdio_puts(&smtpto,"\r\n");
    substdio_flush(&smtpto);
! 
!   if (smtpcode() != 250) {
!     substdio_puts(&smtpto,"HELO ");
!     substdio_put(&smtpto,helohost.s,helohost.len);
!     substdio_puts(&smtpto,"\r\n");
!     substdio_flush(&smtpto);
!     if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
!   }
!   i = 0; 
!   while((i += str_chr(smtptext.s+i,'\n') + 1) && (i+14 < smtptext.len) &&
!         str_diffn(smtptext.s+i+4,"AUTH LOGIN\n",11) &&
!         str_diffn(smtptext.s+i+4,"AUTH LOGIN ",11) &&
!         str_diffn(smtptext.s+i+4,"AUTH PLAIN LOGIN\n",17) &&
!         str_diffn(smtptext.s+i+4,"AUTH PLAIN LOGIN ",17) &&
!         str_diffn(smtptext.s+i+4,"AUTH=LOGIN\n",11) &&
!         str_diffn(smtptext.s+i+4,"AUTH=LOGIN ",11));
!   if ((i+14 < smtptext.len) && auth_smtp_user.len && auth_smtp_pass.len)  {
!     substdio_puts(&smtpto,"AUTH LOGIN\r\n");
!     substdio_flush(&smtpto);
!     if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (AUTH LOGIN)");
!     if (b64encode(&auth_smtp_user,&slop) < 0) temp_nomem();
!     substdio_put(&smtpto,slop.s,slop.len);
!     substdio_puts(&smtpto,"\r\n");
!     substdio_flush(&smtpto);
!     if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (username)");
!     if (b64encode(&auth_smtp_pass,&slop) < 0) temp_nomem();
!     substdio_put(&smtpto,slop.s,slop.len);
!     substdio_puts(&smtpto,"\r\n");
!     substdio_flush(&smtpto);
!     if (smtpcode() != 235) quit("ZConnected to "," but authentication was rejected (password)");
!     substdio_puts(&smtpto,"MAIL FROM:<");
!     substdio_put(&smtpto,sender.s,sender.len);
!     substdio_puts(&smtpto,"> AUTH=<");
!     substdio_put(&smtpto,sender.s,sender.len);
!     substdio_puts(&smtpto,">\r\n");
!     substdio_flush(&smtpto);
!   } else {
!     substdio_puts(&smtpto,"MAIL FROM:<");
!     substdio_put(&smtpto,sender.s,sender.len);
!     substdio_puts(&smtpto,">\r\n");
!     substdio_flush(&smtpto);
!   }
! 
    code = smtpcode();
    if (code >= 500) quit("DConnected to "," but sender was rejected");
    if (code >= 400) quit("ZConnected to "," but sender was rejected");
***************
*** 334,340 ****
  char **argv;
  {
    static ipalloc ip = {0};
!   int i;
    unsigned long random;
    char **recips;
    unsigned long prefme;
--- 374,380 ----
  char **argv;
  {
    static ipalloc ip = {0};
!   int i,j;
    unsigned long random;
    char **recips;
    unsigned long prefme;
***************
*** 350,355 ****
--- 390,398 ----
   
    if (!stralloc_copys(&host,argv[1])) temp_nomem();
   
+   if (!stralloc_copys(&auth_smtp_user,"")) temp_nomem();
+   if (!stralloc_copys(&auth_smtp_pass,"")) temp_nomem();
+ 
    relayhost = 0;
    for (i = 0;i <= host.len;++i)
      if ((i == 0) || (i == host.len) || (host.s[i] == '.'))
***************
*** 358,363 ****
--- 401,416 ----
    if (relayhost && !*relayhost) relayhost = 0;
   
    if (relayhost) {
+     i = str_chr(relayhost,' ');
+     if (relayhost[i]) {
+       j = str_chr(relayhost + i + 1,' ');
+       if (relayhost[j]) {
+ 	relayhost[i] = 0;
+ 	relayhost[i + j + 1] = 0;
+ 	if (!stralloc_copys(&auth_smtp_user,relayhost + i + 1)) temp_nomem();
+ 	if (!stralloc_copys(&auth_smtp_pass,relayhost + i + j + 2)) temp_nomem();
+       }
+     }
      i = str_chr(relayhost,':');
      if (relayhost[i]) {
        scan_ulong(relayhost + i + 1,&port);
