diff options
-rw-r--r-- | Makefile.in | 10 | ||||
-rw-r--r-- | NEWS | 10 | ||||
-rw-r--r-- | configure.in | 86 | ||||
-rw-r--r-- | driver.c | 211 | ||||
-rw-r--r-- | fetchmail.c | 258 | ||||
-rw-r--r-- | fetchmail.h | 20 | ||||
-rw-r--r-- | fetchmail.man | 182 | ||||
-rw-r--r-- | imap.c | 12 | ||||
-rw-r--r-- | options.c | 89 | ||||
-rw-r--r-- | pop2.c | 9 | ||||
-rw-r--r-- | pop3.c | 12 | ||||
-rw-r--r-- | rcfile_l.l | 2 | ||||
-rw-r--r-- | rcfile_y.y | 4 |
13 files changed, 139 insertions, 766 deletions
diff --git a/Makefile.in b/Makefile.in index 7bbd795d..b7f7a016 100644 --- a/Makefile.in +++ b/Makefile.in @@ -72,15 +72,16 @@ ETAGS = etags -tw CTAGS = ctags -tw popobjs = socket.o getpass.o pop2.o pop3.o imap.o fetchmail.o options.o \ - rcfile_l.o rcfile_y.o rcfile.o daemon.o driver.o smtp.o xmalloc.o + rcfile_l.o rcfile_y.o rcfile.o daemon.o driver.o smtp.o xmalloc.o \ + md5c.o md5ify.o -objs = $(popobjs) $(EXTRAOBJ) $(extras) +objs = $(popobjs) $(extras) srcs = $(srcdir)/socket.c $(srcdir)/getpass.c $(srcdir)/pop2.c \ $(srcdir)/pop3.c $(srcdir)/imap.c $(srcdir)/fetchmail.c \ $(srcdir)/options.c $(srcdir)/rcfile.c $(srcdir)/daemon.c \ $(srcdir)/driver.c $(srcdir)/smtp.c $(srcdir)/xmalloc.c \ - $(EXTRASRC) + $(srcdir)/md5c.c $(srcdir)/md5ify.c .SUFFIXES: .SUFFIXES: .o .c .h .y .l .ps .dvi .info .texi @@ -134,8 +135,7 @@ tags: $(tagsrcs) .PHONY: install installdirs install: installdirs \ - # $(bindir)/$(instname) $(infodir)/fetchmail.info \ - $(mandir)/$(instname).$(manext) + $(bindir)/$(instname) $(mandir)/$(instname).$(manext) installdirs: $(SHELL) ${srcdir}/mkinstalldirs $(bindir) $(infodir) $(mandir) @@ -10,6 +10,16 @@ Inflict pain on the person(s) responsible for removing LAST from POP3. Release Notes: +fetchmail-1.2 (Sat Sep 28 15:40:50 EDT 1996): + +* The great option massacre. Remove --stdout, --limit, --local, --mda. + We get a significant code and complexity shrinkage this way (a lot of the + configuration machinery goes away too). These things are your MDA's job. + +* Link APOP support by default. + +* Fix embarrassing Makefile bug. + fetchmail-1.1 (Sat Sep 28 09:21:10 EDT 1996): * In POP3, don't send LAST if STAT shows count of waiting messages to be zero. diff --git a/configure.in b/configure.in index 33d13b7a..bde50e8f 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Autoconfigure input file for fetchmail -dnl Carl Harris, ceharris@mal.com +dnl Eric S. Raymond <esr@thyrsus.com> dnl dnl Process this file with autoconf to produce a configure script. dnl @@ -12,80 +12,6 @@ test -z "$CFLAGS" && CFLAGS=-g AC_SUBST(CFLAGS) test -z "$LDFLAGS" && LDFLAGS=-g AC_SUBST(LDFLAGS) AC_CANONICAL_HOST - -AC_MSG_CHECKING(system mailbox directory) -if test -d /var/mail -then - AC_DEFINE(USERFOLDER, "/var/mail/%s") - userfolder='/var/mail/$u' -elif test -d /usr/mail -then - AC_DEFINE(USERFOLDER, "/usr/mail/%s") - userfolder='/usr/mail/$u' -elif test -d /usr/spool/mail -then - AC_DEFINE(USERFOLDER, "/usr/spool/mail/%s") - userfolder='/usr/spool/mail/$u' -elif test -d /var/spool/mail -then - AC_DEFINE(USERFOLDER, "/var/spool/mail/%s") - userfolder='/var/mail/$u' -else - userfolder="can't find one, will fall back on system MDA." -fi -AC_MSG_RESULT($userfolder) - -AC_MSG_CHECKING(delivery agent for $host) -case $host in - *-*-*bsd*) - AC_DEFINE(DEF_MDA,"/usr/libexec/mail.local %s") - mdacmd="/usr/libexec/mail.local \$u" - ;; - - *-*-aix*) - AC_DEFINE(DEF_MDA,"/usr/bin/bellmail %s") - mdacmd="/usr/bin/bellmail \$u" - ;; - - *-*-sco*) - AC_DEFINE(DEF_MDA,"/usr/mmdf/bin/deliver %s") - mdacmd="/usr/mmdf/bin/deliver \$u" - AC_DEFINE(BINMAIL_TERM, "\001\001\001\001\n") - ;; - - *-*-hpux*) - AC_DEFINE(DEF_MDA,"/bin/rmail -d %s") - mdacmd="/bin/rmail -d \$u" - ;; - - *) - if test -x "/usr/bin/deliver %s" - then - AC_DEFINE(DEF_MDA,"/usr/bin/deliver %s") - mdacmd="/usr/bin/deliver \$u" - else - # Do *not* use the -t option! We explicitly want only - # local delivery to the recipients named on the command line. - # Also don't use -fpopmail -- this looks tempting, but will - # cause lossage unless you always run fetchmail from the - # account of a privileged user. - AC_DEFINE(DEF_MDA,"/usr/lib/sendmail -oem %s") - mdacmd="/usr/lib/sendmail -fpopmail \$u" - fi - ;; -esac -AC_MSG_RESULT($mdacmd) - - -AC_MSG_CHECKING(whether we want APOP support) -AC_ARG_WITH(APOP, - [ --with-APOP should we include APOP support?], - [EXTRASRC="$EXTRASRC \$(srcdir)/md5c.c \$(srcdir)/md5ify.c" - EXTRAOBJ="$EXTRAOBJ md5c.o md5ify.o" - AC_DEFINE(HAVE_APOP_SUPPORT) - AC_MSG_RESULT(yes)], - AC_MSG_RESULT(no)) - AC_PROG_CC AC_PROG_INSTALL AC_PROG_CPP dnl Later checks need this. @@ -108,14 +34,6 @@ AC_SUBST(LIBOBJS) AC_CHECK_LIB(socket,socket) AC_CHECK_LIB(nsl,inet_addr) - - -AC_CHECK_FUNC(bzero, AC_DEFINE(HAVE_BZERO), - AC_CHECK_FUNC(memset, [AC_DEFINE(HAVE_MEMSET) - AC_DEFINE(HAVE_MEMCPY)], - [EXTRASRC="$EXTRASRC \$(srcdir)/bzero.c" - EXTRAOBJ="$EXTRALIB bzero.o"])) - AC_CHECK_FUNC(strdup, AC_DEFINE(HAVE_STRDUP), [EXTRASRC="$EXTRASRC \$(srcdir)/strdup.c" EXTRAOBJ="$EXTRAOBJ strdup.o"]) @@ -140,7 +58,7 @@ dnl All AC_CHECK_FUNCs must precede the following AC_SUBSTs AC_SUBST(EXTRASRC) AC_SUBST(EXTRAOBJ) -AC_CHECK_FUNCS(dup2 strerror tcsetattr stty setsid flock rresvport) +AC_CHECK_FUNCS(dup2 strerror tcsetattr stty setsid rresvport) dnl AC_FUNC_SETVBUF_REVERSED @@ -273,14 +273,13 @@ char *hdr; globals: reads outlevel. *********************************************************************/ -static int gen_readmsg (socket,mboxfd,len,delimited,popuser,pophost,output,rewrite) +static int gen_readmsg (socket,mboxfd,len,delimited,popuser,pophost,rewrite) int socket; int mboxfd; long len; int delimited; char *popuser; char *pophost; -int output; int rewrite; { char buf [MSGBUFSIZE+1]; @@ -318,7 +317,7 @@ int rewrite; if (delimited && *bufp == 0) break; /* end of message */ } - strcat(bufp, output == TO_SMTP && !inheaders ? "\r\n" : "\n"); + strcat(bufp, !inheaders ? "\r\n" : "\n"); if (inheaders) { @@ -373,72 +372,43 @@ int rewrite; { char *cp; - switch (output) - { - case TO_SMTP: - if (SMTP_from(mboxfd, nxtaddr(fromhdr)) != SM_OK) - return(PS_SMTP); + if (SMTP_from(mboxfd, nxtaddr(fromhdr)) != SM_OK) + return(PS_SMTP); #ifdef SMTP_RESEND - /* - * This is what we'd do if fetchmail were a real MDA - * a la sendmail -- crack all the destination headers - * and send to every address we can reach via SMTP. - */ - if ((cp = nxtaddr(tohdr)) != (char *)NULL) - do { - if (SMTP_rcpt(mboxfd, cp) == SM_UNRECOVERABLE) - return(PS_SMTP); - } while - (cp = nxtaddr(NULL)); - if ((cp = nxtaddr(cchdr)) != (char *)NULL) - do { - if (SMTP_rcpt(mboxfd, cp) == SM_UNRECOVERABLE) - return(PS_SMTP); - } while - (cp = nxtaddr(NULL)); - if ((cp = nxtaddr(bcchdr)) != (char *)NULL) - do { - if (SMTP_rcpt(mboxfd, cp) == SM_UNRECOVERABLE) - return(PS_SMTP); - } while - (cp = nxtaddr(NULL)); + /* + * This is what we'd do if fetchmail were a real MDA + * a la sendmail -- crack all the destination headers + * and send to every address we can reach via SMTP. + */ + if ((cp = nxtaddr(tohdr)) != (char *)NULL) + do { + if (SMTP_rcpt(mboxfd, cp) == SM_UNRECOVERABLE) + return(PS_SMTP); + } while + (cp = nxtaddr(NULL)); + if ((cp = nxtaddr(cchdr)) != (char *)NULL) + do { + if (SMTP_rcpt(mboxfd, cp) == SM_UNRECOVERABLE) + return(PS_SMTP); + } while + (cp = nxtaddr(NULL)); + if ((cp = nxtaddr(bcchdr)) != (char *)NULL) + do { + if (SMTP_rcpt(mboxfd, cp) == SM_UNRECOVERABLE) + return(PS_SMTP); + } while + (cp = nxtaddr(NULL)); #else - /* - * Since we're really only fetching mail for one user - * per host query, we can be simpler - */ - if (SMTP_rcpt(mboxfd, popuser) == SM_UNRECOVERABLE) - return(PS_SMTP); + /* + * Since we're really only fetching mail for one user + * per host query, we can be simpler + */ + if (SMTP_rcpt(mboxfd, popuser) == SM_UNRECOVERABLE) + return(PS_SMTP); #endif /* SMTP_RESEND */ - SMTP_data(mboxfd); - if (outlevel == O_VERBOSE) - fputs("SMTP> ", stderr); - break; - - case TO_FOLDER: - case TO_STDOUT: - if (unixfrom) - (void) strcpy(fromBuf, unixfrom); - else - { - now = time(NULL); - if (fromhdr && (cp = nxtaddr(fromhdr))) - sprintf(fromBuf, - "From %s %s", cp, ctime(&now)); - else - sprintf(fromBuf, - "From POPmail %s",ctime(&now)); - } - - if (write(mboxfd,fromBuf,strlen(fromBuf)) < 0) { - perror("gen_readmsg: writing From header"); - return(PS_IOERR); - } - break; - - case TO_MDA: - break; - } + SMTP_data(mboxfd); + if (outlevel == O_VERBOSE) + fputs("SMTP> ", stderr); /* change continuation markers back to regular newlines */ for (cp = headers; cp < headers + oldlen; cp++) @@ -482,43 +452,15 @@ int rewrite; if (outlevel == O_VERBOSE) fputc('\n', stderr); - /* write message terminator, if any */ - switch (output) - { - case TO_SMTP: - if (SMTP_eom(mboxfd) != 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: writing terminator"); - 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: writing terminator"); - return(PS_IOERR); - } -#endif /* BINMAIL_TERM */ - break; - } + /* write message terminator */ + if (SMTP_eom(mboxfd) != SM_OK) + return(PS_SMTP); /* 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); } @@ -614,34 +556,22 @@ struct method *proto; if (count > 0) { - /* - * We expect the open of the output sink to always succeed. - * Therefore, defer it until here so the typical case (no - * mail waiting) is just a bit cheaper and faster. - */ - if (queryctl->output == TO_FOLDER || queryctl->output == TO_STDOUT) { - if ((mboxfd = openuserfolder(queryctl)) < 0) { - ok = PS_IOERR; - goto cleanUp; - } - } else if (queryctl->output == TO_SMTP) { - ok = PS_SMTP; - if ((mboxfd = Socket(queryctl->smtphost, SMTP_PORT)) < 0) - goto cleanUp; - - /* eat the greeting message */ - if (SMTP_ok(mboxfd, NULL) != SM_OK) { - close(mboxfd); - mboxfd = -1; - goto cleanUp; - } + ok = PS_SMTP; + if ((mboxfd = Socket(queryctl->smtphost, SMTP_PORT)) < 0) + goto cleanUp; + + /* eat the greeting message */ + if (SMTP_ok(mboxfd, NULL) != SM_OK) { + close(mboxfd); + mboxfd = -1; + goto cleanUp; + } - /* make it look like mail is coming from the server */ - if (SMTP_helo(mboxfd,queryctl->servername) != SM_OK) { - close(mboxfd); - mboxfd = -1; - goto cleanUp; - } + /* make it look like mail is coming from the server */ + if (SMTP_helo(mboxfd,queryctl->servername) != SM_OK) { + close(mboxfd); + mboxfd = -1; + goto cleanUp; } /* read, forward, and delete messages */ @@ -657,7 +587,7 @@ struct method *proto; continue; /* request a message */ - (*protocol->fetch)(socket, num, linelimit, &len); + (*protocol->fetch)(socket, num, &len); if (outlevel == O_VERBOSE) if (protocol->delimited) fprintf(stderr, @@ -668,14 +598,6 @@ struct method *proto; "fetching message %d (%d bytes)\n", num, len); - /* open the mail pipe now if we're using an MDA */ - if (queryctl->output == TO_MDA) - { - ok = (mboxfd = openmailpipe(queryctl)) < 0 ? -1 : 0; - if (ok != 0) - goto cleanUp; - } - /* read the message and ship it to the output sink */ ok = gen_readmsg(socket, mboxfd, @@ -683,17 +605,8 @@ struct method *proto; protocol->delimited, queryctl->localname, queryctl->servername, - queryctl->output, !queryctl->norewrite); - /* close the mail pipe, we'll reopen before next message */ - if (queryctl->output == TO_MDA) - { - ok = closemailpipe(mboxfd); - if (ok != 0) - goto cleanUp; - } - /* tell the server we got it OK and resynchronize */ if (protocol->trail) (*protocol->trail)(socket, queryctl, num); @@ -749,18 +662,8 @@ cleanUp: #endif /* HAVE_RRESVPORT_H */ closeUp: - if (queryctl->output == TO_FOLDER) - { - if (closeuserfolder(mboxfd) < 0 && ok == 0) - { - perror("fetchmail, closing output sink"); - ok = PS_IOERR; - } - } - else if (queryctl->output == TO_SMTP && mboxfd > -1) { - SMTP_quit(mboxfd); - close(mboxfd); - } + SMTP_quit(mboxfd); + close(mboxfd); return(ok); } diff --git a/fetchmail.c b/fetchmail.c index e760c17e..e31a3e49 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -44,7 +44,6 @@ #ifdef HAVE_PROTOTYPES /* prototypes for internal functions */ int showoptions (struct hostrec *queryctl); -int parseMDAargs (struct hostrec *queryctl); int showversioninfo (void); int dump_options (struct hostrec *queryctl); int query_host(struct hostrec *queryctl); @@ -62,12 +61,8 @@ int quitmode; /* if --quit was set */ /* miscellaneous global controls */ char *rcfile; /* path name of rc file */ char *idfile; /* path name of id file */ -int linelimit; /* limit # lines retrieved per site */ int versioninfo; /* emit only version info */ -/* args for the MDA, parsed out in the usual fashion by parseMDAargs() */ -char *mda_argv [32]; - /********************************************************************* function: main description: main driver routine @@ -127,8 +122,6 @@ char **argv; prc_mergeoptions(servername, &cmd_opts, &def_opts, hostp); strcpy(hostp->servername, servername); - parseMDAargs(hostp); - hostp->next = hostlist; hostlist = hostp; } @@ -359,7 +352,7 @@ int showversioninfo() return value: none. calls: none. - globals: linelimit, outlimit. + globals: outlimit. *********************************************************************/ int dump_params (queryctl) @@ -399,254 +392,7 @@ struct hostrec *queryctl; printf(" Rewrite of server-local addresses is %sabled (--norewrite %s)\n", queryctl->norewrite ? "dis" : "en", queryctl->norewrite ? "on" : "off"); - - - switch(queryctl->output) - { - case TO_SMTP: - printf(" Messages will be SMTP-forwarded to '%s'\n", queryctl->smtphost); - break; - case TO_FOLDER: - printf(" Messages will be appended to '%s'\n", queryctl->userfolder); - break; - case TO_MDA: - printf(" Messages will be delivered with"); - for (cp = queryctl->mda; *cp; cp += strlen(cp) + 1) { - printf(" %s", cp); - } - putchar('\n'); - break; - case TO_STDOUT: - printf(" Messages will be dumped to standard output\n"); - default: - printf(" Message destination unknown?!?\n"); - } - if (outlevel == O_VERBOSE) - { - if (queryctl->smtphost[0] != '\0' && queryctl->output != TO_SMTP) - printf(" (SMTP host would have been '%s')\n", queryctl->smtphost); - if (queryctl->output != TO_FOLDER) - printf(" (Mail folder would have been '%s')\n", queryctl->userfolder); - if (queryctl->output != TO_MDA) - { - printf(" (MDA would have been"); - for (cp = queryctl->mda; *cp; cp += strlen(cp) + 1) { - printf(" %s", cp); - } - printf(")\n"); - } - } - - if (linelimit == 0) - printf(" No limit on retrieved message length.\n"); - else - printf(" Text retrieved per message will be at most %d bytes.\n", - linelimit); -} - -/********************************************************************* - function: openuserfolder - description: open the file to which the retrieved messages will - be appended. Write-lock the folder if possible. - - arguments: - queryctl fully-determined options (i.e. parsed, defaults invoked, - etc). - - return value: file descriptor for the open file, else -1. - calls: none. - globals: none. - *********************************************************************/ - -int openuserfolder (queryctl) -struct hostrec *queryctl; -{ - int fd; - - if (queryctl->output == TO_STDOUT) - return(1); - else /* queryctl->output == TO_FOLDER */ - if ((fd = open(queryctl->userfolder,O_CREAT|O_WRONLY|O_APPEND,0600)) >= 0) { -#ifdef HAVE_FLOCK - if (flock(fd, LOCK_EX) == -1) - { - close(fd); - fd = -1; - } -#endif /* HAVE_FLOCK */ - return(fd); - } - else { - perror("fetchmail: openuserfolder: open()"); - return(-1); - } - -} - - - -/********************************************************************* - function: openmailpipe - description: open a one-way pipe to the mail delivery agent. - arguments: - queryctl fully-determined options (i.e. parsed, defaults invoked, - etc). - - return value: open file descriptor for the pipe or -1. - calls: none. - globals: reads mda_argv. - *********************************************************************/ - -int openmailpipe (queryctl) -struct hostrec *queryctl; -{ - int pipefd [2]; - int childpid; - char binmailargs [80]; - - if (pipe(pipefd) < 0) { - perror("fetchmail: openmailpipe: pipe"); - return(-1); - } - if ((childpid = fork()) < 0) { - perror("fetchmail: openmailpipe: fork"); - return(-1); - } - else if (childpid == 0) { - - /* in child process space */ - close(pipefd[1]); /* close the 'write' end of the pipe */ - close(0); /* get rid of inherited stdin */ - if (dup(pipefd[0]) != 0) { - fputs("fetchmail: openmailpipe: dup() failed\n",stderr); - exit(1); - } - - execv(queryctl->mda, mda_argv+1); - - /* if we got here, an error occurred */ - perror("fetchmail: openmailpipe: exec"); - return(-1); - - } - - /* in the parent process space */ - close(pipefd[0]); /* close the 'read' end of the pipe */ - return(pipefd[1]); -} - - - -/********************************************************************* - function: closeuserfolder - description: close the user-specified mail folder. - arguments: - fd mail folder descriptor. - - return value: zero if success else -1. - calls: none. - globals: none. - *********************************************************************/ - -int closeuserfolder(fd) -int fd; -{ - int err; - - if (fd != 1) { /* not stdout */ - err = close(fd); - } - else - err = 0; - - if (err) - perror("fetchmail: closeuserfolder: close"); - - return(err); + printf(" Messages will be SMTP-forwarded to '%s'\n", queryctl->smtphost); } - -/********************************************************************* - function: closemailpipe - description: close pipe to the mail delivery agent. - arguments: - queryctl fully-determined options record - fd pipe descriptor. - - return value: 0 if success, else -1. - calls: none. - globals: none. - *********************************************************************/ - -int closemailpipe (fd) -int fd; -{ - int err; - int childpid; - - if (outlevel == O_VERBOSE) - fprintf(stderr, "about to close pipe %d\n", fd); - - err = close(fd); -#if defined(STDC_HEADERS) - childpid = wait(NULL); -#else - childpid = wait((int *) 0); -#endif - if (err) - perror("fetchmail: closemailpipe: close"); - - if (outlevel == O_VERBOSE) - fprintf(stderr, "closed pipe %d\n", fd); - - return(err); -} - - - -/********************************************************************* - function: parseMDAargs - description: parse the argument string given in agent option into - a regular *argv[] array. - arguments: - queryctl fully-determined options record pointer. - - return value: none. - calls: none. - globals: writes mda_argv. - *********************************************************************/ - -int parseMDAargs (queryctl) -struct hostrec *queryctl; -{ - int argi; - char *argp; - - /* first put the last segment of the MDA pathname in argv[0] */ - argp = strrchr(queryctl->mda, '/'); - mda_argv[0] = argp ? (argp + 1) : queryctl->mda; - - argp = queryctl->mda; - while (*argp != '\0' && isspace(*argp)) /* skip null first arg */ - argp++; - - /* now punch nulls into the delimiting whitespace in the args */ - for (argi = 1; - *argp != '\0'; - argi++) { - - mda_argv[argi] = argp; /* store pointer to this argument */ - - /* find end of this argument */ - while (!(*argp == '\0' || isspace(*argp))) - argp++; - - /* punch in a null terminator */ - if (*argp != '\0') - *(argp++) = '\0'; - } - mda_argv[argi] = (char *) 0; - -} - diff --git a/fetchmail.h b/fetchmail.h index 1f29c921..fe3e2a3b 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -27,7 +27,6 @@ #define PASSWORDLEN MAX_PASSWORD_LENGTH #define FOLDERLEN 256 /* max folder name length */ #define DIGESTLEN 33 /* length of MD5 digest */ -#define MDALEN 256 /* length of delivery agent command */ #define IDLEN 128 /* length of UIDL message ID */ /* exit code values */ @@ -37,8 +36,8 @@ #define PS_AUTHFAIL 3 /* user authorization failed */ #define PS_PROTOCOL 4 /* protocol violation */ #define PS_SYNTAX 5 /* command-line syntax error */ -#define PS_IOERR 6 /* local folder I/O woes */ -#define PS_ERROR 7 /* some kind of POP3 error condition */ +#define PS_IOERR 6 /* bad permissions on rc file */ +#define PS_ERROR 7 /* protocol error */ #define PS_EXCLUDE 8 /* exclusion error */ #define PS_SMTP 9 /* SMTP error */ #define PS_UNDEFINED 10 /* something I hadn't thought of */ @@ -48,12 +47,6 @@ #define O_NORMAL 1 /* user-friendly */ #define O_VERBOSE 2 /* excessive */ -/* output sink type */ -#define TO_SMTP 1 /* use SMTP forwarding */ -#define TO_FOLDER 2 /* use a mailbox */ -#define TO_STDOUT 3 /* use stdout */ -#define TO_MDA 4 /* use agent */ - #define SIZETICKER 1024 /* print 1 dot per this many bytes */ struct hostrec @@ -63,15 +56,12 @@ struct hostrec char localname [USERNAMELEN+1]; char remotename [USERNAMELEN+1]; char password [PASSWORDLEN+1]; - char userfolder [FOLDERLEN+1]; char remotefolder [FOLDERLEN]; char smtphost[HOSTLEN+1]; - char mda [MDALEN+1]; int protocol; int port; /* control flags */ - int output; int keep; int fetchall; int flush; @@ -80,9 +70,7 @@ struct hostrec /* internal use */ struct hostrec *next; /* next host in chain */ -#if defined(HAVE_APOP_SUPPORT) char digest [DIGESTLEN]; -#endif }; struct method @@ -133,10 +121,6 @@ int doIMAP (struct hostrec *); int parsecmdline (int, char **, struct hostrec *); int setdefaults (struct hostrec *); char *getnextserver (int argc, char **, int *); -int openuserfolder (struct hostrec *); -int closeuserfolder (int); -int openmailpipe (struct hostrec *); -int closemailpipe (int); char *MD5Digest (char *); void append_server_names(int *, char **, int); int daemonize(const char *, void (*)(int)); diff --git a/fetchmail.man b/fetchmail.man index a6278d8e..817b06e0 100644 --- a/fetchmail.man +++ b/fetchmail.man @@ -22,6 +22,18 @@ program can gather mail from servers supporting POP2 (as specified in RFC program), and IMAP4 (RFC1730). It can use (but does not require) the RPOP and LAST facilities removed from later POP3 versions. .PP +.I fetchmail +delivers mail via SMTP to port 25 on the machine it is running on +(localhost), just as though it were being passed in over a normal TCP/IP link. +This normally results in the mail being delivered locally via your +system's default MDA (Mail Delivery Agent, usually +.I /usr/lib/sendmail +but your system may use a different MDA). All the delivery-control +mechanisms (such as +.I .forward +files) normally available with your system MDA will therefore work on +received mail. +.PP The behavior of .I fetchmail is controlled by comand-line options and a run control file, @@ -63,23 +75,6 @@ is running on (this simulates the way mail would be delivered to the client by a normal Internet TCP/IP connection). With this option you can specify another host to deliver to. .TP -.B \-m mda, --mda mda -Specify a mail delivery agent to use. See OUTPUT OPTIONS below for a -complete description. -.TP -.B \-o folder, --local folder -Causes retrieved messages to be appended to file named by the folder -argument. See OUTPUT OPTIONS below for a complete description. -.TP -.B \-c, --stdout -Causes retrieved messages to be written to stdout instead of a mail folder. -See OUTPUT OPTIONS below for a complete description. You may not specify -both the -.B \-c -and -.B \-o -options on the same command line. -.TP .B \-F, --flush POP3/IMAP only. Delete old (previously retrieved) messages from the mailserver before retrieving new messages. @@ -103,17 +98,6 @@ is compiled with the KEEP_IS_DEFAULT option, the .B kill option forces retrieved mail to be deleted. .TP -.B \-l lines, --limit lines -POP3 and IMAP only. Retrieve no more than the specified number of -lines (POP3) or characters (IMAP) of each message body (plus message -headers). The -.B keep -option is implied by the -.B limit -option -- i.e. messages downloaded with the -.B limit -option remain on the remote mailserver. -.TP .B \-p, \--protocol proto Specify the protocol to used when communicating with the remote mailserver. If no protocol is specified, @@ -194,7 +178,7 @@ Instead, for each server specified, all option information that would be computed if .I fetchmail. were connecting to that server is displayed. -.TP +.PP .SH USER AUTHENTICATION User authentication in .I fetchmail @@ -223,7 +207,7 @@ fetchmail -u jsmith mailgrunt .PP The default behavior of .I fetchmail -is to prompt you for your mailserver password before the POP connection is +is to prompt you for your mailserver password before the connection is established. This is the safest way to use .I fetchmail and ensures that your password will not be compromised. You may also specify @@ -262,89 +246,6 @@ logs in, it sends a cryptographically secure hash of your password and the server greeting time to the server, which can verify it by checking its authorization database. .PP -.SH OUTPUT OPTIONS -The default behavior of -.I fetchmail -is to ship mail via SMTP to port 25 on the machine it is running on -(localhost), just as though it were being passed in over a normal TCP/IP link. -This normally results in the mail being delivered locally via your -system's default MDA (Mail Delivery Agent, usually -.I /usr/lib/sendmail -but your system may use a different MDA). -.PP -You can force mail to be passed to an MDA directly with the -mda or -m -option. Some possible MDAs are "/usr/lib/sendmail -oem %s", -"/usr/formail", and "/usr/bin/deliver %s" (if the MDA string contains -%s, that escape will be expanded into your username on the client -machine). This shouldn't be necessary unless for some reason you -want to bypass your system's default MDA. -.PP -Using the -.B \-o -option, you can specify a mail folder to which retrieved -messages will be appended; -.I fetchmail -always writes the retrieved messages using Unix mail folder format so -the folder will be parsed correctly by Unix mail programs such as -.I elm -or -.I pine. -.PP -If you prefer, for example, to have your POP -mail from a machine called 'mailgrunt' stored in the -.I mbox -file in your home directory, you would start -.I fetchmail -as follows: -.IP -fetchmail \-o $HOME/mbox mailgrunt -.PP -Note that the folder specified with -.B \-o -is write-locked while fetchmail is writing to it, -.PP -.I fetchmail -can be used in a shell pipeline by using the -.B \-c -option. In this mode, -.I fetchmail -writes the retrieved messages to stdout, instead of a mail folder. This would -allow you, for instance, to pass the incoming mail through a filter that -discards mail marked as 'Precedence: junk'. Suppose you've written an AWK -script called 'dumpjunk.awk' to implement a junk mail filter. The appropriate -syntax to retrieve your mail from 'mailgrunt', pass it through the filter, -and write it to a folder called 'realmail' in your home directory would be: - -.nf - fetchmail -c mailgrunt | awk -f dumpjunk.awk >$HOME/realmail -.fi -.PP -The progress/status messages written to stderr when the -.B \-s -option has not been specified, do not interfere with the message stream, which -is written to stdout. You may even use -.B \-v -and -.B \-c -together without corrupting the message stream. It is a good idea to use the -.B \-k -option when using -.B \-c -to insure that your messages will not be lost if part of the shell pipeline -does not function incorrectly. The safest bet would be something like: - -.nf - fetchmail -k -c mailgrunt | myfilter >$HOME/filtered.mail -.fi -.PP -followed by - -.nf - fetchmail -c mailgrunt > /dev/null -.fi -.PP -when you're sure the messages were correctly processed by 'myfilter'. -.PP .SH DAEMON MODE The .B --daemon @@ -403,7 +304,6 @@ Legal keywords are: username (or user) password (or pass) remotefolder (or remote) - localfolder (or local) mda smtphost (or smtp) keep @@ -418,7 +318,7 @@ Legal keywords are: noskip port .PP -All these correspond to the obvuious command-line arguments except +All these correspond to the obvious command-line arguments except two: \fBpassword\fR and \fBskip\fR. .PP The \fBpassword\fR option requires a string argument, which is the password @@ -474,8 +374,7 @@ one server definition. proto pop3 \e port 3111 \e user jsmith \e - pass secret1 \e - localfolder ~/mbox + pass secret1 .fi If you need to include whitespace in a parameter string, enclose the string in double quotes. Thus: @@ -484,9 +383,9 @@ string in double quotes. Thus: server mail.provider.net \e proto pop3 \e user jsmith \e - pass secret1 \e - mda "/bin/mail %s" + pass "u can't krak this" .fi + Finally, you may have an initial server description headed by the keyword `defaults' instead of `server' followed by a name. Such a record is interpreted as defaults for all quries to use. It may be overwritten @@ -496,36 +395,17 @@ by individual server descriptions. So, you could write: defaults \e proto pop3 \e user jsmith \e - mda "/bin/mail %s" server pop.provider.net \e pass secret1 \e server mail.provider.net \e - pass secret2 \e + pass secret2 .fi + .SH EXIT CODES To facilitate the use of .I fetchmail -in shell scripts and the like, an exit code is returned to give an indication -of what occured during a given POP connection. The exit code can be tested -by the script and appropriate action taken. -.PP -A simple example follows. This Bourne shell script executes -.I fetchmail -and, if some messages were successfully retrieved from a mailserver retrieved -from the command line, it starts the -.I mail -utility to read those messages. Otherwise, it prints a brief message, and -exits. -.EX 0 -#!/bin/sh - -if fetchmail $1 -then - mail -else - echo "No mail to read." -fi -.EE +in shell scripts, an exit code is returned to give an indication +of what occurred during a given connection. .PP The exit codes returned by .I fetchmail @@ -547,7 +427,7 @@ Some sort of fatal protocol error was detected. There was a syntax error in the arguments to .I fetchmail. .IP 6 -Some kind of I/O woes occurred when writing to the local folder. +The run control file had bad permissions. .IP 7 There was an error condition reported by the server (POP3 only). .IP 8 @@ -568,10 +448,11 @@ When .I fetchmail queries more than one host, the returned status is that of the last host queried. -.SH AUTHOR +.SH AUTHORS .I fetchmail was originated (under the name `popclient') by Carl Harris at Virginia Polytechnic Institute and State University (a.k.a. Virginia Tech). +.PP Version 3.0 of popclient was extensively rewritten and improved by Eric S. Raymond <esr@snark.thyrsus.com>. The program's name was then changed to @@ -605,7 +486,7 @@ on the same mailbox may cause messages to be lost or remain unfetched. (This is a design problem of the POP2, POP3 and IMAP2bis protocols.) .PP If, using POP3, you find that messages you've already read on the -server are being fetched, blame RFC1725. That late version pf the +server are being fetched, blame RFC1725. That late version of the POP3 protocol specification ill-advisedly removed the LAST command, and some servers (including the one distributed with at least some versions of SunOS) follow it (you can verify this by invoking @@ -622,6 +503,15 @@ This program used to be called `popclient' (the name was changed because it supports IMAP now and may well support more remote-fetch protocols such as DMSP in the future). .PP +The --stdout, --local, --mda and --limit arguments of previous versions have +been removed. Those features did jobs that belonged to your local MDA. +The job of +.I popclient +is to forward local mail to your MDA. Saint-Exupery said, "Perfection +[in design] is achieved not when there is nothing more to add, but +rather when there is nothing more to take away." This program isn't +perfect, but it's trying. +.PP The --password option of previous (popclient) versions has been removed -- it encouraged people to expose passwords in scripts. Passwords must now be specified either interactively or in your @@ -639,4 +529,4 @@ itself to get it. All encryption would do in this context is give a false sense of security to people who don't think very hard. .SH SEE ALSO mail(1), binmail(1), sendmail(8), popd(8), imapd(8) -RFC 937, RFC 1081, RFC 1082, RFC 1225, RFC 1460, RFC 1725. +RFC 937, RFC 1081, RFC 1082, RFC1176, RFC 1225, RFC 1460, RFC 1725. @@ -160,24 +160,16 @@ int *firstp; return(0); } -static int imap_fetch(socket, number, limit, lenp) +static int imap_fetch(socket, number, lenp) /* request nth message */ int socket; int number; -int limit; int *lenp; { char buf [POPBUFSIZE+1]; int num; - if (limit) - gen_send(socket, - "PARTIAL %d RFC822 0 %d", - number, limit); - else - gen_send(socket, - "FETCH %d RFC822", - number); + gen_send(socket, "FETCH %d RFC822", number); /* looking for FETCH response */ do { @@ -25,23 +25,20 @@ #define LA_VERBOSE 5 #define LA_SILENT 6 #define LA_STDOUT 7 -#define LA_LIMIT 8 -#define LA_FLUSH 9 -#define LA_PROTOCOL 10 -#define LA_DAEMON 11 -#define LA_RCFILE 12 -#define LA_USERNAME 13 -#define LA_REMOTEFILE 14 -#define LA_LOCALFILE 15 -#define LA_MDA 16 -#define LA_PORT 17 -#define LA_SMTPHOST 18 -#define LA_LOGFILE 19 -#define LA_QUIT 20 -#define LA_NOREWRITE 21 -#define LA_YYDEBUG 22 - -static char *shortoptions = "23PVaKkvS:scl:Fd:f:u:r:o:m:L:qN"; +#define LA_FLUSH 8 +#define LA_PROTOCOL 9 +#define LA_DAEMON 10 +#define LA_RCFILE 11 +#define LA_USERNAME 12 +#define LA_REMOTEFILE 13 +#define LA_PORT 14 +#define LA_SMTPHOST 15 +#define LA_LOGFILE 16 +#define LA_QUIT 17 +#define LA_NOREWRITE 18 +#define LA_YYDEBUG 19 + +static char *shortoptions = "23PVaKkvS:sFd:f:u:r:L:qN"; static struct option longoptions[] = { {"version", no_argument, (int *) 0, LA_VERSION }, {"all", no_argument, (int *) 0, LA_ALL }, @@ -49,8 +46,6 @@ static struct option longoptions[] = { {"keep", no_argument, (int *) 0, LA_KEEP }, {"verbose", no_argument, (int *) 0, LA_VERBOSE }, {"silent", no_argument, (int *) 0, LA_SILENT }, - {"stdout", no_argument, (int *) 0, LA_STDOUT }, - {"limit", required_argument, (int *) 0, LA_LIMIT }, {"flush", no_argument, (int *) 0, LA_FLUSH }, {"protocol", required_argument, (int *) 0, LA_PROTOCOL }, {"proto", required_argument, (int *) 0, LA_PROTOCOL }, @@ -59,8 +54,6 @@ static struct option longoptions[] = { {"user", required_argument, (int *) 0, LA_USERNAME }, {"username", required_argument, (int *) 0, LA_USERNAME }, {"remote", required_argument, (int *) 0, LA_REMOTEFILE }, - {"local", required_argument, (int *) 0, LA_LOCALFILE }, - {"mda", required_argument, (int *) 0, LA_MDA }, {"port", required_argument, (int *) 0, LA_PORT }, {"smtphost", required_argument, (int *) 0, LA_SMTPHOST }, {"logfile", required_argument, (int *) 0, LA_LOGFILE }, @@ -88,7 +81,7 @@ static struct option longoptions[] = { syntax errors. calls: none. globals: writes outlevel, versioninfo, yydebug, logfile, - poll_interval, quitmode, rcfile, idfile, linelimit. + poll_interval, quitmode, rcfile, idfile. *********************************************************************/ int parsecmdline (argc,argv,queryctl) @@ -144,23 +137,6 @@ struct hostrec *queryctl; case LA_SILENT: outlevel = O_SILENT; break; - case 'c': - case LA_STDOUT: - if (fflag) - errflag++; - else { - fflag++; - queryctl->output = TO_STDOUT; - } - break; - case 'l': - case LA_LIMIT: - linelimit = atoi(optarg); - if (linelimit < 0) { - fprintf(stderr,"Line count limit must be non-negative"); - errflag++; - } - break; case 'F': case LA_FLUSH: queryctl->flush = !0; @@ -196,25 +172,10 @@ struct hostrec *queryctl; case LA_USERNAME: strncpy(queryctl->remotename,optarg,sizeof(queryctl->remotename)-1); break; - case 'o': - case LA_LOCALFILE: - if (fflag) - errflag++; - else { - fflag++; - queryctl->output = TO_FOLDER; - strncpy(queryctl->userfolder,optarg,sizeof(queryctl->userfolder)-1); - } - break; case 'r': case LA_REMOTEFILE: strncpy(queryctl->remotefolder,optarg,sizeof(queryctl->remotefolder)-1); break; - case 'm': - case LA_MDA: - queryctl->output = TO_MDA; - strncpy(queryctl->mda,optarg,sizeof(queryctl->mda)-1); - break; case 'P': case LA_PORT: queryctl->port = atoi(optarg); @@ -225,7 +186,6 @@ struct hostrec *queryctl; errflag++; else { fflag++; - queryctl->output = TO_SMTP; strncpy(queryctl->smtphost,optarg,sizeof(queryctl->smtphost)-1); } break; @@ -261,8 +221,6 @@ struct hostrec *queryctl; fputs(" -F, --flush delete old messages from server\n", stderr); fputs(" -K, --kill delete new messages after retrieval\n", stderr); 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); @@ -271,19 +229,12 @@ struct hostrec *queryctl; fputs(" -f, --fetchmailrc specify alternate run control file\n", stderr); fputs(" -i, --idfile specify alternate ID database\n", stderr); fputs(" -u, --username specify server user ID\n", stderr); - fputs(" -c, --stdout write received mail to stdout\n", stderr); - fputs(" -o, --local specify filename for received mail\n", stderr); fputs(" -r, --remote specify remote folder name\n", stderr); fputs(" -L, --logfile specify logfile name\n", stderr); return(-1); } - else { - if (linelimit && !got_kill) - queryctl->keep = !0; - else - ; - return(optind); - } + + return(optind); } @@ -325,7 +276,7 @@ struct hostrec *queryctl; } } - queryctl->protocol = DEF_PROTOCOL; + queryctl->protocol = P_AUTO; #if defined(KEEP_IS_DEFAULT) queryctl->keep = 1; @@ -336,14 +287,10 @@ struct hostrec *queryctl; strcpy(queryctl->localname, user); strcpy(queryctl->remotename, user); - sprintf(queryctl->userfolder, USERFOLDER, user); strcpy(queryctl->smtphost, "localhost"); - queryctl->output = TO_SMTP; - (void) sprintf(queryctl->mda, DEF_MDA, queryctl->localname); rcfile = (char *) xmalloc(strlen(home)+strlen(RCFILE_NAME)+2); - strcpy(rcfile, home); strcat(rcfile, "/"); strcat(rcfile, RCFILE_NAME); @@ -99,11 +99,10 @@ int *firstp; return(0); } -static int pop2_fetch(socket, number, limit, lenp) +static int pop2_fetch(socket, number, lenp) /* request nth message */ int socket; int number; -int limit; int *lenp; { int ok; @@ -149,11 +148,7 @@ int doPOP2 (queryctl) struct hostrec *queryctl; { /* check for unsupported options */ - if (linelimit) { - fprintf(stderr,"Option --limit is not supported with POP2\n"); - return(PS_SYNTAX); - } - else if (queryctl->flush) { + if (queryctl->flush) { fprintf(stderr,"Option --flush is not supported with POP2\n"); return(PS_SYNTAX); } @@ -64,7 +64,6 @@ char *greeting; { char buf [POPBUFSIZE+1]; -#if defined(HAVE_APOP_SUPPORT) /* build MD5 digest from greeting timestamp + password */ if (queryctl->protocol == P_APOP) { @@ -96,7 +95,6 @@ char *greeting; strcpy(queryctl->digest, MD5Digest(msg)); free(msg); } -#endif /* HAVE_APOP_SUPPORT */ switch (queryctl->protocol) { case P_POP3: @@ -119,13 +117,11 @@ char *greeting; goto badAuth; break; -#if defined(HAVE_APOP_SUPPORT) case P_APOP: gen_send(socket,"APOP %s %s", queryctl->remotename, queryctl->digest); if (pop3_ok(buf,socket) != 0) goto badAuth; break; -#endif /* HAVE_APOP_SUPPORT */ default: fprintf(stderr,"Undefined protocol request in POP3_auth\n"); @@ -182,18 +178,14 @@ int *firstp; return(0); } -static int pop3_fetch(socket, number, limit, lenp) +static int pop3_fetch(socket, number, lenp) /* request nth message */ int socket; int number; -int limit; int *lenp; { *lenp = 0; - if (limit) - return(gen_transact(socket, "TOP %d %d", number, limit)); - else - return(gen_transact(socket, "RETR %d", number)); + return(gen_transact(socket, "RETR %d", number)); } static pop3_delete(socket, queryctl, number) @@ -30,9 +30,7 @@ proto(col)? { return KW_PROTOCOL; } 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; } fetchall { yylval.flag = TRUE; return KW_FETCHALL; } @@ -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_SMTPHOST KW_MDA KW_EOL KW_DEFAULTS +%token KW_REMOTEFOLDER KW_SMTPHOST 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 KW_PORT KW_SKIP @@ -67,9 +67,7 @@ serv_option_clause: | KW_USERNAME PARAM_STRING {prc_remotename($2);} | 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);} | KW_FETCHALL {prc_setfetchall($1);} |