aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>1996-09-11 19:01:53 +0000
committerEric S. Raymond <esr@thyrsus.com>1996-09-11 19:01:53 +0000
commite2035c018f293db615fb4c46984ea033b9e7f50b (patch)
tree81803a87e383b510be5682b634758c35e1ee7cde
parent7e3ec8c9d872b906a803c406f4851f30ff98ee5c (diff)
downloadfetchmail-e2035c018f293db615fb4c46984ea033b9e7f50b.tar.gz
fetchmail-e2035c018f293db615fb4c46984ea033b9e7f50b.tar.bz2
fetchmail-e2035c018f293db615fb4c46984ea033b9e7f50b.zip
Most of the way to SMTP forwarding.
svn path=/trunk/; revision=79
-rw-r--r--Makefile.in7
-rw-r--r--NEWS9
-rw-r--r--driver.c272
-rw-r--r--fetchmail.c4
-rw-r--r--fetchmail.h7
-rw-r--r--fetchmail.man15
-rw-r--r--options.c15
-rw-r--r--pop2.c2
-rw-r--r--rcfile_l.l1
-rw-r--r--rcfile_y.y3
-rw-r--r--smtp.c351
-rw-r--r--socket.c5
12 files changed, 214 insertions, 477 deletions
diff --git a/Makefile.in b/Makefile.in
index ed9efb98..4b40f40f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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 a10697a7..6d432204 100644
--- 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
diff --git a/driver.c b/driver.c
index b424151d..02994f00 100644
--- a/driver.c
+++ b/driver.c
@@ -25,16 +25,23 @@
#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);
}
diff --git a/fetchmail.c b/fetchmail.c
index a9ed8fc6..2a609973 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -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);
diff --git a/fetchmail.h b/fetchmail.h
index 571a39d8..6cd1b480 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -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 *);
diff --git a/fetchmail.man b/fetchmail.man
index db79f303..d88c68ec 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -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
diff --git a/options.c b/options.c
index 70c9ac71..804effa3 100644
--- a/options.c
+++ b/options.c
@@ -38,10 +38,11 @@
#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 a5ca1cd0..7c611629 100644
--- 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
;
diff --git a/rcfile_l.l b/rcfile_l.l
index dfc45cfb..b158d2ad 100644
--- a/rcfile_l.l
+++ b/rcfile_l.l
@@ -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; }
diff --git a/rcfile_y.y b/rcfile_y.y
index 7232dbaa..5cd20368 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -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 c46128e1..8d1a4637 100644
--- 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>
@@ -22,22 +17,16 @@
#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;
-}
-
-
diff --git a/socket.c b/socket.c
index 664415f2..058b3ea6 100644
--- 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;