2 * driver.c -- generic driver for mail fetch method protocols
4 * Copyright 1996 by Eric S. Raymond
6 * For license terms, see the file COPYING in this directory.
14 #if defined(STDC_HEADERS)
17 #if defined(HAVE_UNISTD_H)
20 #if defined(HAVE_STDARG_H)
28 #ifdef HAVE_GETHOSTBYNAME
31 #endif /* HAVE_GETHOSTBYNAME */
36 #include <netinet/in.h> /* must be included before "socket.h".*/
38 #endif /* KERBEROS_V4 */
39 #include "fetchmail.h"
42 #define SMTP_PORT 25 /* standard SMTP service port */
44 static const struct method *protocol;
45 static jmp_buf restart;
49 #define GENSYM (sprintf(tag, "a%04d", ++tagnum), tag)
51 static char *shroud; /* string to shroud in debug output, if non-NULL */
52 static int mytimeout; /* value of nonreponse timeout */
54 static int strcrlf(dst, src, count)
55 /* replace LFs with CR-LF; return length of string with replacements */
56 char *dst; /* new string with CR-LFs */
57 char *src; /* original string with LFs */
58 int count; /* length of src */
75 static void vtalarm(timeleft)
76 /* reset the nonresponse-timeout */
79 struct itimerval ntimeout;
81 ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_sec = 0;
82 ntimeout.it_value.tv_sec = timeleft;
83 ntimeout.it_value.tv_usec = 0;
84 setitimer(ITIMER_VIRTUAL, &ntimeout, (struct itimerval *)NULL);
87 static void vtalarm_handler (int signal)
88 /* handle server-timeout SIGVTALARM signal */
93 static void reply_hack(buf, host)
94 /* hack message headers so replies will work properly */
95 char *buf; /* header to be hacked */
96 const char *host; /* server hostname */
99 int parendepth, state = 0, tokencount = 0;
100 char mycopy[POPBUFSIZE+1];
102 if (strncmp("From: ", buf, 6)
103 && strncmp("To: ", buf, 4)
104 && strncmp("Reply-", buf, 6)
105 && strncmp("Cc: ", buf, 4)
106 && strncmp("Bcc: ", buf, 5)) {
111 for (from = mycopy; *from; from++)
115 case 0: /* before header colon */
120 case 1: /* we've seen the colon, we're looking for addresses */
123 else if (*from == '(')
128 else if (*from == '<' || isalnum(*from))
130 else if (isspace(*from))
134 case 2: /* found a token boundary -- reset without copying */
135 if (*from != ' ' && *from != '\t')
143 case 3: /* we're in a quoted human name, copy and ignore */
148 case 4: /* we're in a parenthesized human name, copy and ignore */
151 else if (*from == ')')
157 case 5: /* the real work gets done here */
159 * We're in something that might be an address part,
160 * either a bare unquoted/unparenthesized text or text
161 * enclosed in <> as per RFC822.
163 /* if the address part contains an @, don't mess with it */
167 /* If the address token is not properly terminated, ignore it. */
168 else if (*from == ' ' || *from == '\t')
173 * The only lookahead case. If we're looking at space or tab,
174 * we might be looking at a local name immediately followed
177 for (cp = from; isspace(*cp); cp++)
189 * On proper termination with no @, insert hostname.
190 * Case '>' catches <>-enclosed mail IDs. Case ',' catches
191 * comma-separated bare IDs.
193 else if (strchr(">,", *from))
202 /* a single local name alone on the line */
203 else if (*from == '\n' && tokencount == 1)
211 /* everything else, including alphanumerics, just passes through */
214 case 6: /* we're in a remote mail ID, no need to append hostname */
215 if (*from == '>' || *from == ',' || isspace(*from))
220 /* all characters from the old buffer get copied to the new one */
226 static char *nxtaddr(hdr)
227 /* parse addresses in succession out of a specified RFC822 header */
228 char *hdr; /* header line to be parsed, NUL to continue in previous hdr */
230 static char *hp, *tp, address[POPBUFSIZE+1];
235 * Note 1: RFC822 escaping with \ is *not* handled. Note 2: it is
236 * important that this routine not stop on \r, since we use \r as
237 * a marker for RFC822 continuations below.
250 case 0: /* before header colon */
260 case 1: /* we've seen the colon, now grab the address */
261 if (*hp == '\n') /* end of address list */
267 else if (*hp == ',') /* end of address */
272 else if (*hp == '"') /* quoted string */
277 else if (*hp == '(') /* address comment -- ignore */
282 else if (*hp == '<') /* begin <address> */
287 else if (isspace(*hp)) /* ignore space */
289 else /* just take it */
296 case 2: /* we're in a quoted string, copy verbatim */
308 case 3: /* we're in a parenthesized comment, ignore */
319 case 4: /* possible <>-enclosed address */
320 if (*hp == '>') /* end of address */
326 else if (*hp == '<') /* nested <> */
328 else if (*hp == '"') /* quoted address */
333 else /* just copy address */
337 case 5: /* we're in a quoted address, copy verbatim */
338 if (*hp == '\n') /* mismatched quotes */
340 if (*hp != '"') /* just copy it if it isn't a quote */
342 else if (*hp == '"') /* end of quoted string */
358 #ifdef HAVE_GETHOSTBYNAME
361 static int is_host_alias(name, ctl)
362 /* determine whether name is a DNS alias of the hostname */
370 * The first two checks are optimizations that will catch a good
371 * many cases. First, check against the hostname the user specified.
372 * Odds are good this will either be the mailserver's FQDN or a
373 * suffix of it with the mailserver's domain's default host name
374 * omitted. Next, check against the mailserver's FQDN, in case
375 * it's not the same as the declared hostname.
377 * Either of these on a mail address is definitive. Only if the
378 * name doesn't match either is it time to call the bind library.
379 * If this happens odds are good we're looking at an MX name.
381 if (strcmp(name, ctl->servername) == 0)
383 else if (strcmp(name, ctl->canonical_name) == 0)
387 * We treat DNS lookup failure as a negative on the theory that
388 * the mailserver's DNS server is `nearby' and should be able
389 * to respond quickly and reliably. Ergo if we get failure,
390 * the name isn't a mailserver alias.
392 else if ((he = gethostbyname(name)) && strcmp(ctl->canonical_name, he->h_name) == 0)
396 * Search for a name match on MX records pointing to the server
397 * site. These may live far away, so allow a couple of retries.
399 for (i = 0; i < MX_RETRIES; i++)
401 struct mxentry *mxrecords, *mxp;
403 mxrecords = getmxrecords(name);
405 if (mxrecords == (struct mxentry *)NULL)
406 if (h_errno == TRY_AGAIN)
414 for (mxp = mxrecords; mxp->name; mxp++)
415 if (strcmp(name, mxp->name) == 0)
422 void find_server_names(hdr, ctl, xmit_names)
423 /* parse names out of a RFC822 header into an ID list */
424 const char *hdr; /* RFC822 header in question */
425 struct query *ctl; /* list of permissible aliases */
426 struct idlist **xmit_names; /* list of recipient names parsed out */
428 if (hdr == (char *)NULL)
434 if ((cp = nxtaddr(hdr)) != (char *)NULL)
438 if ((atsign = strchr(cp, '@')))
441 * Address has an @. Check to see if the right-hand part
442 * is an alias or MX equivalent of the mailserver. If it's
443 * not, skip this name. If it is, we'll keep going and try
444 * to find a mapping to a client name.
446 if (!is_host_alias(atsign+1, ctl))
451 lname = idpair_find(&ctl->localnames, cp);
452 if (lname != (char *)NULL)
454 if (outlevel == O_VERBOSE)
456 "fetchmail: mapped %s to local %s\n",
458 save_uid(xmit_names, -1, lname);
461 ((cp = nxtaddr((char *)NULL)) != (char *)NULL);
464 #endif /* HAVE_GETHOSTBYNAME */
466 static FILE *smtp_open(ctl)
467 /* try to open a socket to the appropriate SMTP server for this query */
470 ctl = ctl->leader; /* go to the SMTP leader for this query */
472 /* if no socket to this host is already set up, try to open one */
473 if (ctl->smtp_sockfp == (FILE *)NULL)
475 if ((ctl->smtp_sockfp = Socket(ctl->smtphost, SMTP_PORT)) == (FILE *)NULL)
476 return((FILE *)NULL);
477 else if (SMTP_ok(ctl->smtp_sockfp, NULL) != SM_OK
478 || SMTP_helo(ctl->smtp_sockfp, ctl->servername) != SM_OK)
480 fclose(ctl->smtp_sockfp);
481 ctl->smtp_sockfp = (FILE *)NULL;
485 return(ctl->smtp_sockfp);
488 static int strip_gets(buf, len, sockfp)
489 /* get a line of input, stripping out \r and \n */
494 if (fgets(buf, len, sockfp) == (char *)NULL)
500 for (tp = sp = buf; *sp; sp++)
501 if (*sp != '\r' && *sp != '\n')
509 static int gen_readmsg (sockfp, len, delimited, ctl)
510 /* read message content and ship to SMTP or MDA */
511 FILE *sockfp; /* to which the server is connected */
512 long len; /* length of message */
513 int delimited; /* does the protocol use a message delimiter? */
514 struct query *ctl; /* query control record */
516 char buf [MSGBUFSIZE+1];
517 char *bufp, *headers, *fromhdr, *tohdr, *cchdr, *bcchdr;
518 int n, oldlen, mboxfd;
519 int inheaders,lines,sizeticker;
522 /* read the message content from the server */
524 headers = fromhdr = tohdr = cchdr = bcchdr = NULL;
528 while (delimited || len > 0)
530 if ((n = strip_gets(buf,sizeof(buf),sockfp)) < 0)
532 vtalarm(ctl->timeout);
534 /* write the message size dots */
538 while (sizeticker >= SIZETICKER)
540 if (outlevel > O_SILENT)
542 sizeticker -= SIZETICKER;
547 if (buf[0] == '\0' || buf[0] == '\r' || buf[0] == '\n')
549 if (delimited && *bufp == '.') {
552 break; /* end of message */
559 reply_hack(bufp, ctl->servername);
563 oldlen = strlen(bufp);
564 headers = malloc(oldlen + 1);
567 (void) strcpy(headers, bufp);
575 * We deal with RFC822 continuation lines here.
576 * Replace previous '\n' with '\r' so nxtaddr
577 * and reply_hack will be able to see past it.
578 * (We know this is safe because SocketGets stripped
579 * out all carriage returns in the read loop above
580 * and we haven't reintroduced any since then.)
581 * We'll undo this before writing the header.
583 if (isspace(bufp[0]))
584 headers[oldlen-1] = '\r';
586 newlen = oldlen + strlen(bufp);
587 headers = realloc(headers, newlen + 1);
590 strcpy(headers + oldlen, bufp);
591 bufp = headers + oldlen;
595 if (!strncasecmp("From:", bufp, 5))
597 else if (!strncasecmp("To:", bufp, 3))
599 else if (!strncasecmp("Cc:", bufp, 3))
601 else if (!strncasecmp("Bcc:", bufp, 4))
606 else if (headers) /* OK, we're at end of headers now */
609 struct idlist *idp, *xmit_names;
611 /* cons up a list of local recipients */
612 xmit_names = (struct idlist *)NULL;
613 #ifdef HAVE_GETHOSTBYNAME
614 /* is this a multidrop box? */
617 /* compute the local address list */
618 find_server_names(tohdr, ctl, &xmit_names);
619 find_server_names(cchdr, ctl, &xmit_names);
620 find_server_names(bcchdr, ctl, &xmit_names);
622 else /* it's a single-drop box, use first localname */
623 #endif /* HAVE_GETHOSTBYNAME */
626 save_uid(&xmit_names, -1, ctl->localnames->id);
629 /* if nothing supplied localnames, default appropriately */
632 save_uid(&xmit_names, -1, ctl->remotename);
634 save_uid(&xmit_names, -1, user);
636 /* time to address the message */
637 if (ctl->mda[0]) /* we have a declared MDA */
643 * We go through this in order to be able to handle very
644 * long lists of users and (re)implement %s.
646 for (idp = xmit_names; idp; idp = idp->next)
648 sp = sargv = (char **)alloca(sizeof(char **) * ctl->mda_argcount+nlocals+2);
649 for (i = 0; i < ctl->mda_argcount; i++)
650 if (strcmp("%s", ctl->mda_argv[i]))
651 *sp++ = ctl->mda_argv[i];
653 for (idp = xmit_names; idp; idp = idp->next)
659 * Arrange to run with user's permissions if we're root.
660 * This will initialize the ownership of any files the
661 * MDA creates properly. (The seteuid call is available
662 * under all BSDs and Linux)
665 #endif /* HAVE_SETEUID */
667 mboxfd = openmailpipe(sargv);
670 /* this will fail quietly if we didn't start as root */
672 #endif /* HAVE_SETEUID */
676 fprintf(stderr, "fetchmail: MDA open failed\n");
682 if (ctl->mda[0] == '\0' && ((sinkfp = smtp_open(ctl)) < 0))
684 free_uid_list(&xmit_names);
685 fprintf(stderr, "fetchmail: SMTP connect failed\n");
691 fprintf(stderr, "fetchmail: I see no From header\n");
695 if (SMTP_from(sinkfp, nxtaddr(fromhdr)) != SM_OK)
697 fprintf(stderr, "fetchmail: SMTP listener is confused\n");
701 for (idp = xmit_names; idp; idp = idp->next)
702 if (SMTP_rcpt(sinkfp, idp->id) != SM_OK)
704 fprintf(stderr, "fetchmail: SMTP listener is upset\n");
709 if (outlevel == O_VERBOSE)
710 fputs("SMTP> ", stderr);
712 free_uid_list(&xmit_names);
714 /* change continuation markers back to regular newlines */
715 for (cp = headers; cp < headers + oldlen; cp++)
719 /* replace all LFs with CR-LF before sending to the SMTP server */
722 char *newheaders = malloc(1 + oldlen * 2);
724 if (newheaders == NULL)
726 oldlen = strcrlf(newheaders, headers, oldlen);
728 headers = newheaders;
731 /* write all the headers */
733 n = write(mboxfd,headers,oldlen);
735 n = fwrite(headers, sizeof(char), oldlen, sinkfp);
741 perror("fetchmail: writing RFC822 headers");
744 else if (outlevel == O_VERBOSE)
750 /* SMTP byte-stuffing */
751 if (*bufp == '.' && ctl->mda[0] == 0)
752 fwrite(".", sizeof(char), 1, sinkfp);
754 /* replace all LFs with CR-LF in the line */
757 char *newbufp = malloc(1 + strlen(bufp) * 2);
761 strcrlf(newbufp, bufp, strlen(bufp));
765 /* ship out the text line */
767 n = write(mboxfd,bufp,strlen(bufp));
769 n = fwrite(bufp, sizeof(char), strlen(bufp), sinkfp);
775 perror("fetchmail: writing message text");
778 else if (outlevel == O_VERBOSE)
787 /* close the delivery pipe, we'll reopen before next message */
788 if (closemailpipe(mboxfd))
793 /* write message terminator */
794 if (SMTP_eom(sinkfp) != SM_OK)
796 fputs("fetchmail: SMTP listener refused delivery\n", stderr);
806 kerberos_auth (socket, canonical)
807 /* authenticate to the server host using Kerberos V4 */
808 int socket; /* socket to server host */
809 char *canonical; /* server name */
815 Key_schedule schedule;
818 ticket = ((KTEXT) (malloc (sizeof (KTEXT_ST))));
819 rem = (krb_sendauth (0L, socket, ticket, "pop",
821 ((char *) (krb_realmofhost (canonical))),
826 ((struct sockaddr_in *) 0),
827 ((struct sockaddr_in *) 0),
832 fprintf (stderr, "fetchmail: kerberos error %s\n", (krb_get_err_text (rem)));
837 #endif /* KERBEROS_V4 */
839 int do_protocol(ctl, proto)
840 /* retrieve messages from server using given protocol method table */
841 struct query *ctl; /* parsed options with merged-in defaults */
842 const struct method *proto; /* protocol method table */
848 if (ctl->authenticate == A_KERBEROS)
850 fputs("fetchmail: Kerberos support not linked.\n", stderr);
853 #endif /* KERBEROS_V4 */
855 /* lacking methods, there are some options that may fail */
858 /* check for unsupported options */
861 "Option --flush is not supported with %s\n",
865 else if (ctl->fetchall) {
867 "Option --all is not supported with %s\n",
872 if (!proto->getsizes && ctl->limit)
875 "Option --limit is not supported with %s\n",
882 tag[0] = '\0'; /* nuke any tag hanging out from previous query */
885 /* set up the server-nonresponse timeout */
886 sigsave = signal(SIGVTALRM, vtalarm_handler);
887 vtalarm(mytimeout = ctl->timeout);
889 if (setjmp(restart) == 1)
891 "fetchmail: timeout after %d seconds waiting for %s.\n",
892 ctl->timeout, ctl->servername);
895 char buf [POPBUFSIZE+1];
896 int *msgsizes, len, num, count, new, deletions = 0;
899 /* open a socket to the mail server */
900 if ((sockfp = Socket(ctl->servername,
901 ctl->port ? ctl->port : protocol->port)) == (FILE *)NULL)
903 perror("fetchmail, connecting to host");
909 if (ctl->authenticate == A_KERBEROS)
911 ok = (kerberos_auth (fileno(sockfp), ctl->canonical_name));
912 vtalarm(ctl->timeout);
916 #endif /* KERBEROS_V4 */
918 /* accept greeting message from mail server */
919 ok = (protocol->parse_response)(sockfp, buf);
920 vtalarm(ctl->timeout);
924 /* try to get authorized to fetch mail */
925 shroud = ctl->password;
926 ok = (protocol->getauth)(sockfp, ctl, buf);
927 vtalarm(ctl->timeout);
928 shroud = (char *)NULL;
934 /* compute number of messages and number of new messages waiting */
935 if ((protocol->getrange)(sockfp, ctl, &count, &new) != 0)
937 vtalarm(ctl->timeout);
939 /* show user how many messages we downloaded */
940 if (outlevel > O_SILENT)
942 fprintf(stderr, "No mail from %s@%s\n",
947 fprintf(stderr, "%d message%s", count, count > 1 ? "s" : "");
948 if (new != -1 && (count - new) > 0)
949 fprintf(stderr, " (%d seen)", count-new);
956 /* we may need to get sizes in order to check message limits */
957 msgsizes = (int *)NULL;
958 if (!ctl->fetchall && proto->getsizes && ctl->limit)
960 msgsizes = (int *)alloca(sizeof(int) * count);
962 if ((ok = (proto->getsizes)(sockfp, count, msgsizes)) != 0)
968 if (new == -1 || ctl->fetchall)
970 ok = ((new > 0) ? PS_SUCCESS : PS_NOMAIL);
975 /* read, forward, and delete messages */
976 for (num = 1; num <= count; num++)
978 int toolarge = msgsizes && msgsizes[num-1]>ctl->limit;
979 int fetch_it = ctl->fetchall ||
980 (!(protocol->is_old && (protocol->is_old)(sockfp,ctl,num)) && !toolarge);
982 /* we may want to reject this message if it's old */
985 if (outlevel > O_SILENT)
987 fprintf(stderr, "skipping message %d", num);
989 fprintf(stderr, " (oversized, %d bytes)", msgsizes[num-1]);
994 /* request a message */
995 (protocol->fetch)(sockfp, num, &len);
996 vtalarm(ctl->timeout);
998 if (outlevel > O_SILENT)
1000 fprintf(stderr, "reading message %d", num);
1002 fprintf(stderr, " (%d bytes)", len);
1003 if (outlevel == O_VERBOSE)
1004 fputc('\n', stderr);
1009 /* read the message and ship it to the output sink */
1010 ok = gen_readmsg(sockfp,
1012 protocol->delimited,
1014 vtalarm(ctl->timeout);
1018 /* tell the server we got it OK and resynchronize */
1019 if (protocol->trail)
1020 (protocol->trail)(sockfp, ctl, num);
1024 * At this point in flow of control, either we've bombed
1025 * on a protocol error or had delivery refused by the SMTP
1026 * server (unlikely -- I've never seen it) or we've seen
1027 * `accepted for delivery' and the message is shipped.
1028 * It's safe to mark the message seen and delete it on the
1032 /* maybe we delete this message now? */
1033 if (protocol->delete
1034 && (fetch_it ? !ctl->keep : ctl->flush))
1037 if (outlevel > O_SILENT)
1038 fprintf(stderr, " flushed\n");
1039 ok = (protocol->delete)(sockfp, ctl, num);
1040 vtalarm(ctl->timeout);
1043 delete_uid(&ctl->newsaved, num);
1045 else if (outlevel > O_SILENT)
1046 fprintf(stderr, " not flushed\n");
1049 /* remove all messages flagged for deletion */
1050 if (protocol->expunge_cmd && deletions > 0)
1052 ok = gen_transact(sockfp, protocol->expunge_cmd);
1057 ok = gen_transact(sockfp, protocol->exit_cmd);
1064 ok = gen_transact(sockfp, protocol->exit_cmd);
1072 if (ok != 0 && ok != PS_SOCKET)
1074 gen_transact(sockfp, protocol->exit_cmd);
1079 signal(SIGVTALRM, sigsave);
1085 #if defined(HAVE_STDARG_H)
1086 void gen_send(FILE *sockfp, char *fmt, ... )
1087 /* assemble command in printf(3) style and send to the server */
1090 void gen_send(sockfp, fmt, va_alist)
1091 /* assemble command in printf(3) style and send to the server */
1092 FILE *sockfp; /* socket to which server is connected */
1093 const char *fmt; /* printf-style format */
1097 char buf [POPBUFSIZE+1];
1100 if (protocol->tagged)
1101 (void) sprintf(buf, "%s ", GENSYM);
1105 #if defined(HAVE_STDARG_H)
1110 vsprintf(buf + strlen(buf), fmt, ap);
1113 strcat(buf, "\r\n");
1116 if (outlevel == O_VERBOSE)
1120 if (shroud && (cp = strstr(buf, shroud)))
1121 memset(cp, '*', strlen(shroud));
1122 fprintf(stderr,"> %s", buf);
1126 #if defined(HAVE_STDARG_H)
1127 int gen_transact(FILE *sockfp, char *fmt, ... )
1128 /* assemble command in printf(3) style, send to server, accept a response */
1131 int gen_transact(sockfp, fmt, va_alist)
1132 /* assemble command in printf(3) style, send to server, accept a response */
1133 FILE *sockfp; /* socket to which server is connected */
1134 const char *fmt; /* printf-style format */
1139 char buf [POPBUFSIZE+1];
1142 if (protocol->tagged)
1143 (void) sprintf(buf, "%s ", GENSYM);
1147 #if defined(HAVE_STDARG_H)
1152 vsprintf(buf + strlen(buf), fmt, ap);
1155 strcat(buf, "\r\n");
1157 if (outlevel == O_VERBOSE)
1161 if (shroud && (cp = strstr(buf, shroud)))
1162 memset(cp, '*', strlen(shroud));
1163 fprintf(stderr,"> %s", buf);
1166 /* we presume this does its own response echoing */
1167 ok = (protocol->parse_response)(sockfp, buf);
1173 /* driver.c ends here */