]> Pileus Git - ~andy/fetchmail/commitdiff
Most of the way to SMTP forwarding.
authorEric S. Raymond <esr@thyrsus.com>
Wed, 11 Sep 1996 19:01:53 +0000 (19:01 -0000)
committerEric S. Raymond <esr@thyrsus.com>
Wed, 11 Sep 1996 19:01:53 +0000 (19:01 -0000)
svn path=/trunk/; revision=79

12 files changed:
Makefile.in
NEWS
driver.c
fetchmail.c
fetchmail.h
fetchmail.man
options.c
pop2.c
rcfile_l.l
rcfile_y.y
smtp.c
socket.c

index ed9efb98073c89bd4e680661b5413c42ac4daf9f..4b40f40fba57d0ed0278a333a2902065f2434aa8 100644 (file)
@@ -63,14 +63,14 @@ ETAGS = etags -tw
 CTAGS = ctags -tw
 
 popobjs = socket.o getpass.o pop2.o pop3.o imap.o popclient.o options.o        \
-       poprc_l.o poprc_y.o poprc.o daemon.o driver.o xmalloc.o
+       poprc_l.o poprc_y.o poprc.o daemon.o driver.o smtp.o xmalloc.o
 
 objs = $(popobjs) $(EXTRAOBJ) $(extras)
 
 srcs = $(srcdir)/socket.c $(srcdir)/getpass.c $(srcdir)/pop2.c                 \
        $(srcdir)/pop3.c $(srcdir)/imap.c $(srcdir)/popclient.c         \
        $(srcdir)/options.c $(srcdir)/poprc.c $(srcdir)/daemon.c        \
-       $(srcdir)/driver.c $(srcdir)/xmalloc.c $(EXTRASRC)
+       $(srcdir)/driver.c $(srcdir)/smtp.c $(srcdir)/xmalloc.c $(EXTRASRC)
 
 .SUFFIXES:
 .SUFFIXES: .o .c .h .y .l .ps .dvi .info .texi
@@ -189,7 +189,8 @@ $(srcdir)/poprc_l.c: $(srcdir)/poprc_l.l
 $(srcdir)/poprc_y.c: $(srcdir)/poprc_y.y
 
 parser = $(srcdir)/poprc_l.l $(srcdir)/poprc_y.y
-headers = $(srcdir)/popclient.h $(srcdir)/socket.h $(srcdir)/poproto.h
+headers = $(srcdir)/popclient.h $(srcdir)/socket.h $(srcdir)/poproto.h \
+       $(srcdir)/smtp.h
 extra = $(srcdir)/alloca.c $(srcdir)/bzero.[ch] $(srcdir)/errorcodes \
        $(srcdir)/getopt.[ch] $(srcdir)/getopt1.c $(srcdir)/md5*.[ch] \
        $(srcdir)/strcasecmp.c $(srcdir)/strdup.c
diff --git a/NEWS b/NEWS
index a10697a779a04dab0971b5aece7e33c07ac8614f..6d432204d4ea1df49df33ad555d10c3026766c59 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,10 +9,8 @@ Option to enable EMACS-like user folder versioning on each run.
 S/key for secure challenge-response.
 
 Recode POP2 to use the same driver/method strategy as POP3/IMAP, so 
-all three protocols will be able to forward messages through the
-generic driver.  (This requires that we find a POP2 server to test with.)
-
-Support SMTP forwarding.
+all three protocols will be able to forward messages through the generic
+driver to SMTP.  (This requires that we find a POP2 server to test with.)
 
 3.1:
 
@@ -25,6 +23,9 @@ Support SMTP forwarding.
 * Code now autoprobes for a POP3, IMAP, or POP2 server if no protocol is
   specified.
 
+* SMTP forwarding support.  Thanks to Harry Hochheiser <harry@tigger.jvnc.net>
+  for this simple but very clever idea.  
 3.05:
 
 * Experimental support for RFC1725-compliant POP servers with the UIDL
index b424151d4d9b73d3a9b0e34fbeee07d127b4108c..02994f00e2158953ec83c8cc45cc950c265c2a53 100644 (file)
--- a/driver.c
+++ b/driver.c
 #include  <sys/time.h>
 #include  <ctype.h>
 #include  <errno.h>
+#include  <malloc.h>
 
 #include  "socket.h"
 #include  "popclient.h"
+#include  "smtp.h"
 
 static struct method *protocol;
 
+#define        SMTP_PORT       25      /* standard SMTP service port */
+
 char tag[TAGLEN];
 static int tagnum;
 #define GENSYM (sprintf(tag, "a%04d", ++tagnum), tag)
 
+static int gen_readmsg (int socket, int mboxfd, long len, int delimited,
+       char *host, int topipe, int rewrite);
+
 /*********************************************************************
   function:      do_protocol
   description:   retrieve messages from the specified mail server
@@ -57,26 +64,37 @@ struct method *proto;
 {
     int ok, len;
     int mboxfd;
-    char buf [POPBUFSIZE];
+    char buf [POPBUFSIZE], host[HOSTLEN];
     int socket;
     int first,number,count;
 
     tagnum = 0;
     protocol = proto;
 
-    /* open stdout or the mailbox, locking it if it is a folder */
-    if (queryctl->output == TO_FOLDER || queryctl->output == TO_STDOUT) 
+    /* open the output sink, locking it if it is a folder */
+    if (queryctl->output == TO_FOLDER || queryctl->output == TO_STDOUT) {
        if ((mboxfd = openuserfolder(queryctl)) < 0) 
            return(PS_IOERR);
+    } else if (queryctl->output == TO_SMTP) {
+       if ((mboxfd = Socket(queryctl->smtphost,SMTP_PORT)) < 0) 
+           return(PS_SOCKET);
     
-    /* open the socket */
+       /* make it look like mail is coming from the server */
+       if (SMTP_helo(mboxfd,queryctl->servername) != SM_OK) {
+           close(mboxfd);
+           mboxfd = 0;
+           return(PS_SMTP);
+       }
+    }
+
+    /* open a socket to the mail server */
     if ((socket = Socket(queryctl->servername,protocol->port)) < 0) {
        perror("do_protocol: socket");
        ok = PS_SOCKET;
        goto closeUp;
     }
 
-    /* accept greeting message from server */
+    /* accept greeting message from mail server */
     ok = (protocol->parse_response)(buf, socket);
     if (ok != 0) {
        if (ok != PS_SOCKET)
@@ -128,13 +146,13 @@ struct method *proto;
                (*protocol->fetch)(socket, number, linelimit, &len);
                if (outlevel == O_VERBOSE)
                    if (protocol->delimited)
-                   fprintf(stderr,"fetching message %d (delimited)\n",number);
-               else
-                   fprintf(stderr,"fetching message %d (%d bytes)\n",number,len);
+                       fprintf(stderr,"fetching message %d (delimited)\n",number);
+                   else
+                       fprintf(stderr,"fetching message %d (%d bytes)\n",number,len);
                ok = gen_readmsg(socket,mboxfd,len,protocol->delimited,
-                                 queryctl->servername,
-                                 queryctl->output == TO_MDA
-                                 queryctl->rewrite);
+                                queryctl->servername,
+                                queryctl->output
+                                queryctl->rewrite);
                if (protocol->trail)
                    (*protocol->trail)(socket, queryctl, number);
                if (ok != 0)
@@ -189,9 +207,13 @@ cleanUp:
 
 closeUp:
     if (queryctl->output == TO_FOLDER)
+    {
        if (closeuserfolder(mboxfd) < 0 && ok == 0)
            ok = PS_IOERR;
-    
+    }
+    else if (queryctl->output == TO_SMTP && mboxfd  > 0)
+       close(mboxfd);
+
     if (ok == PS_IOERR || ok == PS_SOCKET) 
        perror("do_protocol: cleanUp");
 
@@ -289,134 +311,144 @@ va_dcl {
                  be written.
     len          length of text 
     pophost      name of the POP host 
-    topipe       true if we're writing to the system mailbox pipe.
+    output       output mode
 
   return value:  zero if success else PS_* return code.
   calls:         SockGets.
   globals:       reads outlevel. 
  *********************************************************************/
 
-int gen_readmsg (socket,mboxfd,len,delimited,pophost,topipe,rewrite)
+int gen_readmsg (socket,mboxfd,len,delimited,pophost,output,rewrite)
 int socket;
 int mboxfd;
 long len;
 int delimited;
 char *pophost;
-int topipe;
+int output;
 int rewrite;
 { 
-  char buf [MSGBUFSIZE]; 
-  char *bufp;
-  char savec;
-  char fromBuf[MSGBUFSIZE];
-  int n;
-  int needFrom;
-  int inheaders;
-  int lines,sizeticker;
-  time_t now;
-  /* This keeps the retrieved message count for display purposes */
-  static int msgnum = 0;  
-
-  /* set up for status message if outlevel allows it */
-  if (outlevel > O_SILENT && outlevel < O_VERBOSE) {
-    fprintf(stderr,"reading message %d",++msgnum);
-    /* won't do the '...' if retrieved messages are being sent to stdout */
-    if (mboxfd == 1)
-      fputs(".\n",stderr);
-    else
-      ;
-  }
-  else
-    ;
-
-  /* read the message content from the server */
-  inheaders = 1;
-  lines = 0;
-  sizeticker = MSGBUFSIZE;
-  while (delimited || len > 0) {
-    if ((n = SockGets(socket,buf,sizeof(buf))) < 0)
-      return(PS_SOCKET);
-    len -= n;
-    bufp = buf;
-    if (buf[0] == '\r' || buf[0] == '\n')
-      inheaders = 0;
-    if (*bufp == '.') {
-      bufp++;
-      if (delimited && *bufp == 0)
-        break;  /* end of message */
+    char buf [MSGBUFSIZE]; 
+    char *bufp;
+    char savec;
+    char fromBuf[MSGBUFSIZE];
+    int n;
+    int needFrom;
+    int inheaders;
+    int lines,sizeticker;
+    time_t now;
+    /* This keeps the retrieved message count for display purposes */
+    static int msgnum = 0;  
+
+    /* set up for status message if outlevel allows it */
+    if (outlevel > O_SILENT && outlevel < O_VERBOSE) {
+       fprintf(stderr,"reading message %d",++msgnum);
+       /* won't do the '...' if retrieved messages are being sent to stdout */
+       if (mboxfd == 1)
+           fputs(".\n",stderr);
     }
-    strcat(bufp,"\n");
+
+    /* read the message content from the server */
+    inheaders = 1;
+    lines = 0;
+    sizeticker = MSGBUFSIZE;
+    while (delimited || len > 0) {
+       if ((n = SockGets(socket,buf,sizeof(buf))) < 0)
+           return(PS_SOCKET);
+       len -= n;
+       bufp = buf;
+       if (buf[0] == '\r' || buf[0] == '\n')
+           inheaders = 0;
+       if (*bufp == '.') {
+           bufp++;
+           if (delimited && *bufp == 0)
+               break;  /* end of message */
+       }
+       strcat(bufp,"\n");
      
-    /* Check for Unix 'From' header, and add a bogus one if it's not
-       present -- only if not using an MDA.
-       XXX -- should probably parse real From: header and use its 
-              address field instead of bogus 'POPmail' string. 
-    */
-    if (!topipe && lines == 0) {
-      if (strlen(bufp) >= strlen("From ")) {
-        savec = *(bufp + 5);
-        *(bufp + 5) = 0;
-        needFrom = strcmp(bufp,"From ") != 0;
-        *(bufp + 5) = savec;
-      }
-      else
-        needFrom = 1;
-      if (needFrom) {
-        now = time(NULL);
-        sprintf(fromBuf,"From POPmail %s",ctime(&now));
-        if (write(mboxfd,fromBuf,strlen(fromBuf)) < 0) {
-          perror("gen_readmsg: write");
-          return(PS_IOERR);
-        }
-      }
-    }
+       /* Check for Unix 'From' header, and add a bogus one if it's not
+          present -- only if not using an MDA.
+          XXX -- should probably parse real From: header and use its 
+          address field instead of bogus 'POPmail' string. 
+          */
+       if (output != TO_MDA && lines == 0) {
+           if (strlen(bufp) >= strlen("From ")) {
+               savec = *(bufp + 5);
+               *(bufp + 5) = 0;
+               needFrom = strcmp(bufp,"From ") != 0;
+               *(bufp + 5) = savec;
+           }
+           else
+               needFrom = 1;
+           if (needFrom) {
+               now = time(NULL);
+               sprintf(fromBuf,"From POPmail %s",ctime(&now));
+               if (write(mboxfd,fromBuf,strlen(fromBuf)) < 0) {
+                   perror("gen_readmsg: write");
+                   return(PS_IOERR);
+               }
+           }
+       }
 
-    /*
-     * Edit some headers so that replies will work properly.
-     */
-    if (inheaders && rewrite)
-      reply_hack(bufp, pophost);
+       /*
+        * Edit some headers so that replies will work properly.
+        */
+       if (inheaders && rewrite)
+           reply_hack(bufp, pophost);
 
-    /* write this line to the file */
-    if (write(mboxfd,bufp,strlen(bufp)) < 0) {
-      perror("gen_readmsg: write");
-      return(PS_IOERR);
-    }
+       /* write this line to the file */
+       if (write(mboxfd,bufp,strlen(bufp)) < 0) {
+           perror("gen_readmsg: write");
+           return(PS_IOERR);
+       }
 
-    sizeticker -= strlen(bufp);
-    if (sizeticker <= 0) {
-      if (outlevel > O_SILENT && outlevel < O_VERBOSE && mboxfd != 1)
-        fputc('.',stderr);
-      sizeticker = MSGBUFSIZE;
-    }
-    lines++;
-  }
-
-  if (!topipe) {
-    /* The server may not write the extra newline required by the Unix
-       mail folder format, so we write one here just in case */
-    if (write(mboxfd,"\n",1) < 0) {
-      perror("gen_readmsg: write");
-      return(PS_IOERR);
+       sizeticker -= strlen(bufp);
+       if (sizeticker <= 0) {
+           if (outlevel > O_SILENT && outlevel < O_VERBOSE && mboxfd != 1)
+               fputc('.',stderr);
+           sizeticker = MSGBUFSIZE;
+       }
+       lines++;
     }
-  }
-  else {
-    /* The mail delivery agent may require a terminator.  Write it if
-       it has been defined */
+
+    /* write message terminator, if any */
+    switch (output)
+    {
+    case TO_SMTP:
+       if (write(mboxfd,".\r\n",3) < 0) {
+           perror("gen_readmsg: write");
+           return(PS_IOERR);
+       }
+       if (SMTP_ok(mboxfd, NULL) != SM_OK)
+           return(PS_SMTP);
+       break;
+
+    case TO_FOLDER:
+    case TO_STDOUT:
+       /* The server may not write the extra newline required by the Unix
+          mail folder format, so we write one here just in case */
+       if (write(mboxfd,"\n",1) < 0) {
+           perror("gen_readmsg: write");
+           return(PS_IOERR);
+       }
+       break;
+
+    case TO_MDA:
+       /* The mail delivery agent may require a terminator.  Write it if
+          it has been defined */
 #ifdef BINMAIL_TERM
-    if (write(mboxfd,BINMAIL_TERM,strlen(BINMAIL_TERM)) < 0) {
-      perror("gen_readmsg: write");
-      return(PS_IOERR);
-    }
-#endif
+       if (write(mboxfd,BINMAIL_TERM,strlen(BINMAIL_TERM)) < 0) {
+           perror("gen_readmsg: write");
+           return(PS_IOERR);
+       }
+#endif /* BINMAIL_TERM */
     }
 
-  /* finish up display output */
-  if (outlevel == O_VERBOSE)
-    fprintf(stderr,"(%d lines of message content)\n",lines);
-  else if (outlevel > O_SILENT && mboxfd != 1) 
-    fputs(".\n",stderr);
-  else
-    ;
-  return(0);
+    /* finish up display output */
+    if (outlevel == O_VERBOSE)
+       fprintf(stderr,"(%d lines of message content)\n",lines);
+    else if (outlevel > O_SILENT && mboxfd != 1) 
+       fputs(".\n",stderr);
+    else
+       ;
+    return(0);
 }
index a9ed8fc6898e3cbfb929b4bb58cdf2795b6f1c53..2a6099732129761b7f4bcf563a59abeb0d7f26fb 100644 (file)
@@ -234,10 +234,10 @@ char **argv;
 
        sleep(poll_interval);
     } while
-                                                    (poll_interval);
+       (poll_interval);
 
     if (outlevel == O_VERBOSE)
-       fprintf(stderr, "normal termination\n");
+       fprintf(stderr, "normal termination, status %d\n", popstatus);
 
     termhook(0);
     exit(popstatus);
index 571a39d88d0f7ed416698d9ec053d01d3b426ee9..6cd1b4803a2de353f1df345ee77c5ce9325187f2 100644 (file)
@@ -34,7 +34,8 @@
 #define                PS_IOERR        6       /* local folder I/O woes */
 #define                PS_ERROR        7       /* some kind of POP3 error condition */
 #define                PS_EXCLUDE      8       /* exclusion error */
-#define                PS_UNDEFINED    9       /* something I hadn't thought of */
+#define         PS_SMTP         9       /* SMTP error */
+#define                PS_UNDEFINED    10      /* something I hadn't thought of */
 
 /* output noise level */
 #define         O_SILENT       0       /* mute, max squelch, etc. */
@@ -42,6 +43,7 @@
 #define                O_VERBOSE       2       /* excessive */
 
 /* output sink type */
+#define                TO_SMTP         0       /* use SMTP forwarding */
 #define                TO_FOLDER       1       /* use a mailbox */
 #define                TO_STDOUT       2       /* use stdout */
 #define                TO_MDA          3       /* use agent */
@@ -54,6 +56,7 @@ struct hostrec
   char password [PASSWORDLEN];
   char userfolder [FOLDERLEN];
   char remotefolder [FOLDERLEN];
+  char smtphost[HOSTLEN];
   char mda [MDALEN];
   int keep;
   int protocol;
@@ -113,8 +116,6 @@ extern int versioninfo;             /* emit only version info */
 int gen_ok (char *buf, int socket);
 void gen_send ();
 int gen_transact ();
-int gen_readmsg (int socket, int mboxfd, long len, int delimited,
-       char *host, int topipe, int rewrite);
 
 /* prototypes for globally callable functions */
 int doPOP2 (struct hostrec *); 
index db79f303cdd9fdb9c570920614f1fc28b20157d9..d88c68ecb8a88fe7e91be48b841f248eca27f21d 100644 (file)
@@ -110,6 +110,12 @@ fetched mail to programs like procmail.  If the MDA string contains
 machine.  Some possible MDAs are "/usr/formail", "/usr/bin/deliver %s",
 "/usr/lib/sendmail -oem %s".
 .TP
+.B \-S host, --smtphost host
+Specify an SMTP forwarding host.  If you specify this option, fetched
+mail is delivered by SMTP over a socket connection to the specified
+host.  This simulates the way mail would be delivered to that host 
+by a normal Internet mail connection.  
+.TP
 .B \--protocol proto
 Specify the protocol to used when communicating with the remote 
 mailserver.  If no protocol is specified,
@@ -395,6 +401,7 @@ Legal keywords are:
     remotefolder (or remote)
     localfolder (or local)
     mda
+    smtphost (or smtp)
     keep
     flush
     fetchall
@@ -529,6 +536,10 @@ Exclusion error.  This means
 either found another copy of itself already running, or failed in such
 a way that it isn't sure whether another copy is running.
 .IP 9
+The 
+.I popclient.
+run failed while trying to do an SMTP port open or transaction.
+.IP 10
 Something totally undefined occured.  This is usually caused by a bug within
 .I popclient.
 Do let me know if this happens.
@@ -552,6 +563,10 @@ default location of file associating hosts with last message IDs seen
 (used only with newer RFC1725-compliant servers supporting the UIDL command).
 .SH BUGS
 .PP
+The --smtphost option doesn't work with POP2.  This isn't a protocol problem,
+it's because the developers couldn't find a POP2 server to test the
+necessary code reorganization with.
+.PP
 The --remotefolder option doesn't work with POP3.
 .PP
 The UIDL support for RFC1725-compliant servers without LAST is not yet
index 70c9ac7162e9dc3caa4d2ba4452ca01d689d8965..804effa3b46c824abb01653e94f5ff3335766036 100644 (file)
--- a/options.c
+++ b/options.c
 #define LA_REMOTEFILE  15
 #define        LA_LOCALFILE    16
 #define LA_MDA         17
-#define LA_LOGFILE     18
-#define LA_QUIT                19
-#define LA_NOREWRITE   20
-#define LA_YYDEBUG     21
+#define LA_SMTPHOST    18
+#define LA_LOGFILE     19
+#define LA_QUIT                20
+#define LA_NOREWRITE   21
+#define LA_YYDEBUG     22
  
 static char *shortoptions = "23VaKkvscl:Fd:f:u:r:o:m:L:qN";
 static struct option longoptions[] = {
@@ -63,6 +64,7 @@ static struct option longoptions[] = {
   {"remote",    required_argument, (int *) 0, LA_REMOTEFILE },
   {"local",     required_argument, (int *) 0, LA_LOCALFILE  },
   {"mda",      required_argument, (int *) 0, LA_MDA        },
+  {"smtphost", required_argument, (int *) 0, LA_SMTPHOST   },
   {"logfile",  required_argument, (int *) 0, LA_LOGFILE    },
   {"idfile",   required_argument, (int *) 0, LA_IDFILE     },
   {"quit",     no_argument,       (int *) 0, LA_QUIT       },
@@ -219,6 +221,10 @@ struct hostrec *queryctl;
       case LA_MDA:
         strncpy(queryctl->mda,optarg,sizeof(queryctl->mda)-1);
         break;
+      case 'S':
+      case LA_SMTPHOST:
+       strncpy(queryctl->smtphost,optarg,sizeof(queryctl->smtphost)-1);
+       break;
       case 'L':
       case LA_LOGFILE:
         logfile = optarg;
@@ -254,6 +260,7 @@ struct hostrec *queryctl;
     fputs("  -k, --keep       save new messages after retrieval\n", stderr);
     fputs("  -l, --limit      retrieve at most n message lines\n", stderr);
     fputs("  -m, --mda        set mail user agent to pass to\n", stderr);
+    fputs("  -S, --smtphost   set SMTP forwarding host\n", stderr);
     fputs("  -q, --quit       kill daemon process\n", stderr);
     fputs("  -s, --silent     work silently\n", stderr);
     fputs("  -v, --verbose    work noisily (diagnostic output)\n", stderr);
diff --git a/pop2.c b/pop2.c
index a5ca1cd0ded0ccb13bd759a4db97f3bbb13b0934..7c61162977bdb3784b3e4b26cbee86b4ded2df78 100644 (file)
--- a/pop2.c
+++ b/pop2.c
@@ -84,10 +84,12 @@ struct hostrec *queryctl;
     fprintf(stderr,"Option --all is not supported with POP2\n");
     return(PS_SYNTAX);
   }
+#ifdef FOO
   else if (queryctl->smtphost[0]) {
     fprintf(stderr,"Option --smtphost is not supported with POP2\n");
     return(PS_SYNTAX);
   }
+#endif /* FOO */
   else
     ;
 
index dfc45cfb217f81db317e36022709bed255a8c93c..b158d2ade688f46cb3bdd624d56e8baaf80b2a82 100644 (file)
@@ -31,6 +31,7 @@ user(name)?   { return KW_USERNAME; }
 pass(word)?    { return KW_PASSWORD; }
 remote(folder)? { return KW_REMOTEFOLDER; }
 local(folder)? { return KW_LOCALFOLDER; }
+smtp(host)?    { return KW_SMTPHOST; }
 mda            { return KW_MDA; }
 keep           { yylval.flag = TRUE; return KW_KEEP; }
 flush          { yylval.flag = TRUE; return KW_FLUSH; }
index 7232dbaa6ddfe14cf49930c469770a9943261d59..5cd20368035e84dc4ea6c12f020bc3fc548cc117 100644 (file)
@@ -30,7 +30,7 @@ int yydebug;  /* in case we didn't generate with -- debug */
 }
 
 %token KW_SERVER KW_PROTOCOL KW_USERNAME KW_PASSWORD
-%token KW_REMOTEFOLDER KW_LOCALFOLDER KW_MDA KW_EOL KW_DEFAULTS
+%token KW_REMOTEFOLDER KW_LOCALFOLDER KW_SMTPHOST KW_MDA KW_EOL KW_DEFAULTS
 %token <proto> PROTO_AUTO PROTO_POP2 PROTO_POP3 PROTO_IMAP PROTO_APOP PROTO_RPOP
 %token <sval> PARAM_STRING
 %token <flag> KW_KEEP KW_FLUSH KW_FETCHALL KW_REWRITE
@@ -68,6 +68,7 @@ serv_option_clause:
        |       KW_PASSWORD PARAM_STRING        {prc_setpassword($2);}
        |       KW_REMOTEFOLDER PARAM_STRING    {prc_setremote($2);}
        |       KW_LOCALFOLDER PARAM_STRING     {prc_setlocal($2);}
+       |       KW_SMTPHOST PARAM_STRING        {prc_setsmtphost($2);}
        |       KW_MDA PARAM_STRING             {prc_setmda($2);}
        |       KW_KEEP                         {prc_setkeep($1);}
        |       KW_FLUSH                        {prc_setflush($1);}
diff --git a/smtp.c b/smtp.c
index c46128e1402b69c2559366aa1eae1ef91db3dc39..8d1a4637106fa23c8d52eb92f372426f63a143de 100644 (file)
--- a/smtp.c
+++ b/smtp.c
@@ -1,20 +1,15 @@
-/* Copyright 1996 Harry Hochheiser
+/* Copyright 1996 Eric S. Raymond
  * All rights reserved.
  * For license terms, see the file COPYING in this directory.
  */
 
 /***********************************************************************
   module:       smtp.c
-  project:      popforward
+  project:      popclient
   programmer:   Harry Hochheiser
   description:  Handling of SMTP connections, and processing of mail 
                  to be forwarded via SMTP connections.
 
-  7/30/96.  Note: since this file is new from scratch, I'll assume
-  that  I'm working on a modern (ANSI) compiler, and I'll use
-  prototypes.
-
-
  ***********************************************************************/
 
 #include <config.h>
 #include <unistd.h>
 #include <string.h>
 #include "socket.h"
-#include "popforward.h"
+#include "popclient.h"
 #include "smtp.h"
 
-static int POP3_parseHeaders(int number, int socket,char **from,int *replFlag);
-static int SMTP_sendMessageHeaders(int mboxfd,struct optrec *option,
-                                  char *from);
-static int SendData(int f,char *buf,int check);
-
-
 /*********************************************************************
   function:      SMTP_helo
   description:   Send a "HELO" message to the SMTP server.
 
   arguments:     
     socket       TCP/IP socket for connection to SMTP
-  return value:  Result of SMTP_OK: based on codes in popforward.h.
+  return value:  Result of SMTP_OK: based on codes in popclient.h.
                  
  *********************************************************************/
 
@@ -45,6 +34,7 @@ int SMTP_helo(int socket,char *host)
 {
   int ok;
   char buf[SMTPBUFSIZE];
+
   sprintf(buf,"HELO %s\r\n",host);
   SockPrintf(socket,"%s",buf);
   ok = SMTP_ok(socket,buf);
@@ -64,7 +54,7 @@ int SMTP_helo(int socket,char *host)
     Note: these args are likely to change, as we get fancier about
     handling the names.
 
-  return value:  Result of SMTP_ok: based on codes in popforward.h.
+  return value:  Result of SMTP_ok: based on codes in popclient.h.
                  
  *********************************************************************/
 int SMTP_from(int socket,char *fromuser,char *fromhost)
@@ -72,7 +62,7 @@ int SMTP_from(int socket,char *fromuser,char *fromhost)
   char buf[SMTPBUFSIZE];  /* it's as good as size as any... */
   int ok;
   SockPrintf(socket,"MAIL FROM %s@%s\n",fromuser,fromhost);
-  ok= SMTP_ok(socket,buf);
+  ok = SMTP_ok(socket,buf);
 
   return ok;
 }
@@ -84,13 +74,13 @@ int SMTP_from(int socket,char *fromuser,char *fromhost)
 
   arguments:     
     socket       TCP/IP socket for connection to SMTP
-    toser:    user name of recipient
-    tohost:    host name of recipient
+    touser:      user name of recipient
+    tohost:      host name of recipient
 
-  return value:  Result of SMTP_OK: based on codes in popforward.h.
+  return value:  Result of SMTP_OK: based on codes in popclient.h.
                  
  *********************************************************************/
-int SMTP_rcpt(int socket,char *touser,char *tohost)
+int SMTP_rcpt(int socket,char *touser, char *tohost)
 {
   char buf[SMTPBUFSIZE];  /* it's as good as size as any... */
   int ok;
@@ -109,8 +99,6 @@ int SMTP_rcpt(int socket,char *touser,char *tohost)
   arguments:     
     socket       TCP/IP socket for connection to SMTP
 
-  return value:  Result of SMTP_OK: based on codes in popforward.h.
-                 
  *********************************************************************/
 int SMTP_data(int socket)
 {
@@ -120,29 +108,23 @@ int SMTP_data(int socket)
 
 /*********************************************************************
   function:      SMTP_rset
-  description:   Send a "DATA" message to the SMTP server.
+  description:   Send an "RSET" message to the SMTP server.
 
   arguments:     
     socket       TCP/IP socket for connection to SMTP
 
-  return value:  Result of SMTP_OK: based on codes in popforward.h.
-                 
  *********************************************************************/
 void SMTP_rset(int socket)
 {
   SockPrintf(socket,"RSET\n");
 }
 
-
-
 /*********************************************************************
   function:      SMTP_check
   description:   Returns the status of the smtp connection
-                 8/13/96, HSH
   arguments:     
     socket       TCP/IP socket for connection to SMTP
-
-  return value:  based on codes in popforward.h.
+  return value:  based on codes in popclient.h.
                  Do the dirty work of seeing what the status is..
  *********************************************************************/
 static int SMTP_check(int socket,char *argbuf)
@@ -159,21 +141,16 @@ static int SMTP_check(int socket,char *argbuf)
       ok = SM_ERROR;
   }
   else
-    ok= SM_UNRECOVERABLE;
+    ok = SM_UNRECOVERABLE;
   return (ok);
 }
 
 /*********************************************************************
   function:      SMTP_ok
   description:   Returns the statsus of the smtp connection
-                 7/31/96, HSH
   arguments:     
     socket       TCP/IP socket for connection to SMTP
-
-  return value:  based on codes in popforward.h.
-                 
-  NOTE:  As of 7/31/96 Initial implementation, we're just returning 
-  a dummy value of SM_OK. Eventually, we should really implement this.
+  return value:  based on codes in popclient.h.
  *********************************************************************/
 int SMTP_ok(int socket,char *argbuf)
 {
@@ -198,7 +175,7 @@ int SMTP_ok(int socket,char *argbuf)
        ok = SM_ERROR;                /* It's just a simple error, for*/
                                      /*         the current message  */
       else
-       ok = SM_UNRECOVERABLE;       /* if It still says error, we're */
+       ok = SM_UNRECOVERABLE;       /* if it still says error, we're */
                                      /* in bad shape                  */ 
     }
   return ok;
@@ -207,308 +184,12 @@ int SMTP_ok(int socket,char *argbuf)
 /*********************************************************************
   function:      SMTP_Gets
   description:   Gets  a line from the SMTP connection
-                 7/31/96, HSH
   arguments:     
     socket       TCP/IP socket for connection to SMTP
-
   return value:  number of bytes read.
-                 
  *********************************************************************/
 int SMTP_Gets(int socket,char *buf,int sz)
 {
   return read(socket,buf,sz);
 }
 
-
-/*********************************************************************
-  function:      POP3_readSMTP
-  description:   Read the message content as described in RFC 1225.
-  arguments:     
-    number       message number.
-    socket       ... to which the server is connected.
-    mboxfd       open file descriptor to which the retrieved message will
-                 be written. 
-    options      added 7/30/96, HSH send in the whole options package...
-    server:      originating pop server.  7/30/96, HSH
-
-  This procedure is the SMTP version of the original POP3_readmsg that 
-  is found in the original popforward.  8/2/96, HSH
-  return value:  zero if success else PS_* return code.
-  calls:         SockGets.
-  globals:       reads outlevel. 
- *********************************************************************/
-
-int POP3_readSMTP(int number,int socket,int mboxfd,struct optrec *options,
-                 char *server)
-{ 
-  char buf [MSGBUFSIZE]; 
-  char smtpbuf[SMTPBUFSIZE];
-  char *bufp;
-  char fromBuf[MSGBUFSIZE];
-  char *summaryHeaders[3];
-  int  sumLines =0;
-  int needFrom;
-  int inheaders;
-  int lines,sizeticker;
-  int n;
-  time_t now;
-
-  char *from = NULL;
-  int  replFlag = 0;
-  
-
-  /* HSH 8/19/96, Archive file  */
-
-  int archive = 0;
-
-  int msgnum = 0;
-
-
-  /* This keeps the retrieved message count for display purposes */
-  int ok=0;
-
-  /* set up for status message if outlevel allows it */
-  /* Get this into log file as well. */
-
-
-  ok = POP3_parseHeaders(number,socket,&from,&replFlag);
-  if (ok != 0)
-    {
-      if (from) free(from);
-      return(PS_IOERR);
-    }
-      
-  ok = POP3_sendGet(number,options,socket);
-  if (ok != 0)
-    {
-      if (from) free(from);
-      return(PS_IOERR);
-    }
-
-  /* 8/19/96 HSH open the archive file.. */
-
-  if ((archive =archGetFile(options,&msgnum)) <= 0)
-    {
-     if (from) free(from);
-      return(PS_IOERR);
-    }
-  
-  /* reads the message content from the server */
-  inheaders = 1;
-  lines = 0;
-  sizeticker = MSGBUFSIZE;
-  while (1) {
-    if (SockGets(socket,buf,sizeof(buf)) < 0)
-      {
-       if (from) free(from);
-       return(PS_SOCKET);
-      }
-    bufp = buf;
-    if (buf[0] == '\r' || buf[0] == '\n')
-      inheaders = 0;
-    if (*bufp == '.') {
-      bufp++;
-      if (*bufp == 0)
-        break;  /* end of message */
-    }
-    strcat(bufp,"\n");
-     
-    /* Check for Unix 'From' header, and add a bogus one if it's not
-       present -- only if not using an MDA.
-       XXX -- should probably parse real From: header and use its 
-              address field instead of bogus 'POPmail' string. 
-    */
-    
-
-   if (lines == 0) {
-      if (strlen(bufp) >= strlen("From ")) 
-       needFrom = strncasecmp(bufp,"From ",strlen("From "));
-      else
-        needFrom = 1;
-
-      if ((ok = SMTP_sendMessageHeaders(mboxfd,options,from)) != SM_OK)
-         goto smtperr;
-   
-      if (needFrom) {
-        now = time(NULL);
-        sprintf(fromBuf,"From POPmail %s",ctime(&now));
-        if ((ok =SendData(mboxfd,fromBuf,0)) != SM_OK) 
-         goto smtperr;
-      }
-   }
-
-   n = write(archive,bufp,strlen(bufp));
-
-    /* write this line to the file */
-    if ((ok =SendData(mboxfd,bufp,0)) != SM_OK)
-      {
-       /* Abort the message, so we'll be clear.. */
-       SendData(mboxfd,BINMAIL_TERM,0); 
-       goto smtperr;
-      }
-
-
-    sizeticker -= strlen(bufp);
-    lines++;
-  }
-
-  if ((ok =SendData(mboxfd,BINMAIL_TERM,0)) !=SM_OK) 
-    goto smtperr;
-
-
-  /* finish up display output */
-  
-  if (from) free(from);
-  if (archive != 0) close(archive);
-  return(0);
-
-smtperr:
-    if (archive != 0) close(archive);
-    SMTP_rset(mboxfd);
-    if (from) free(from);
-    return(ok);
-}
-
-/******************************************************************
-  function:    POP3_parseHeaders
-  description: Read the headers of the mail message, in order to grab the 
-                "From" and "reply to" fields, to be used for proper
-               mail processing.
-  arguments:
-      number    message number
-      socket    TCP socket for POP connection
-      from      character pointer to hold value of message "FROM" field
-      replFlag  indicates whether or not we've seen a reply flag.
-
-  ret. value:  non-zero on success, else zero.
-  globals:     SockGets POP3_OK.
-  calls:       reads outlevel.
- *****************************************************************/
-int POP3_parseHeaders(number,socket,from,replFlag)
-int number;
-int socket;
-char **from;
-int  *replFlag;
-{
-
-  int ok;
-  char buf[MSGBUFSIZE];
-  char *bufp;
-  int  len;
-
-  ok = POP3_sendTOP(number,0,socket);
-  if (ok != 0)
-      return(ok);
-  
-  ok = -1; /* we're not ok until we find "FROM: " */
-  /* read lines in until we're done.. */
-  while (1)
-    {
-
-      if (SockGets(socket,buf,sizeof(buf)) < 0)
-       {
-         return(PS_SOCKET);
-       }
-      bufp = buf;
-
-      if (*bufp == '.') {
-       bufp++;
-       if (*bufp == 0)
-         break;  /* end of message */
-      }
-
-      len = strlen(buf);
-      if (len < strlen(HEADER_FROM)) /* since From header is shorter than reply-to, it */
-       continue;                    /* can't be either type. */
-
-      /* if it starts with "FROM: ", grab from */
-      if (strncasecmp(buf,HEADER_FROM,strlen(HEADER_FROM)) == 0)
-       {
-         bufp = buf + strlen(HEADER_FROM);
-         *from = strdup(bufp); 
-         ok =0;
-       }
-      if (strncasecmp(buf,HEADER_REPLY,strlen(HEADER_REPLY)) == 0)
-         *replFlag = 1;
-    }
-
-  return(ok);
-}
-
-
-/******************************************************************
-  function:    SMTP_sendMessageHeaders
-  description: Send the headers for the smtp message along to the mailbox..
-  arguments:
-      number    message number
-      socket    TCP socket for POP connection
-      from      character pointer to hold value of message "FROM" field
-      replFlag  indicates whether or not we've seen a reply flag.
-
-  ret. value:  non-zero on success, else zero.
-  globals:     SockGets POP3_OK.
-  calls:       reads outlevel.
- *****************************************************************/
-int SMTP_sendMessageHeaders(int mboxfd,struct optrec *options,char *from)
-{
-  char smtpbuf[SMTPBUFSIZE];
-  char fromBuf[MSGBUFSIZE];
-
-  int ok;
-
-  /* 7/30/96, HSH add stuff to print out the SMTP commands. */
-  ok  = SMTP_ok(mboxfd,smtpbuf);
-  if (ok != SM_OK)
-    {
-      return ok;
-    }
-  /* mail is from whoever the headers said it was from */
-  sprintf(fromBuf,"MAIL FROM: %s\r\n",from);
-  if ((ok = SendData(mboxfd,fromBuf,1)) != SM_OK) 
-    return ok;
-  
-/* Now here, add something for the receipt field.  7/30/96,
-   HSH */
-  sprintf(fromBuf,"RCPT TO: %s@%s\r\n",options->forwarduser,
-         options->forwardhost);
-  if ((ok=SendData(mboxfd,fromBuf,1)) != SM_OK) 
-    return ok;
-
-  sprintf(fromBuf,"DATA\r\n");
-  ok =SendData(mboxfd,fromBuf,1);
-  return ok;
-   
-}
-
-/******************************************************************
-  function:    SendData
-  description: Write to socket or file, as appropriate for destination
-  arguments:
-    f          socket or file descriptor
-    buf         buffer to write
-    dest        options destination.
-    check       1 if we should check for SMTP_ok, 0 if not...
-                ignored if DEST is not TO_SMTP
-  7/30/96 HSH added
-
-  ret. value:  0 if ok, otherwise, non-zero..
-  globals:     none.
-  calls:       SockWrite
- *****************************************************************/
-
-static int SendData(int f,char *buf,int check)
-{ 
-  int res;
-  char smtpbuf[SMTPBUFSIZE];
-  int len = strlen(buf);
-
-  res = SockWrite(f,buf,len);
-  if (check != 0)
-    {
-          res  = SMTP_ok(f,smtpbuf);
-    }
-   return res;
-}
-
-
index 664415f2185ea020ae730cb45c4abf9eed648694..058b3ea6bf4ec7017b4a56ed8ed9a9b1c5a4c0f1 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -20,9 +20,7 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <sys/time.h>
-#ifdef SMTP_FORWARD
 #include <sys/ioctl.h>
-#endif /* SMTP_FORWARD */
 #if defined(STDC_HEADERS)
 #include <string.h>
 #endif
@@ -188,7 +186,6 @@ int len;
    return(len);
 }
 
-#ifdef SMTP_FORWARD
 /* SockClearHeader: call this procedure in order to kill off any
    forthcoming Header info from the socket that we no longer want.
    */
@@ -246,8 +243,6 @@ int  SockDataWaiting(int socket)
   fcntl(socket,F_SETFL,flags);
   return res;
 }
-#endif /* SMTP_FORWARD */
-
 
 int SockPrintf(socket,format,va_alist)
 int socket;