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.
15 #if defined(STDC_HEADERS)
18 #if defined(HAVE_UNISTD_H)
21 #if defined(HAVE_STDARG_H)
26 #if defined(HAVE_ALLOCA_H)
32 #ifdef HAVE_GETHOSTBYNAME
35 #endif /* HAVE_GETHOSTBYNAME */
40 #include <netinet/in.h>
42 #endif /* KERBEROS_V4 */
44 #include "fetchmail.h"
48 /* BSD portability hack...I know, this is an ugly place to put it */
49 #if !defined(SIGCHLD) && defined(SIGCLD)
50 #define SIGCHLD SIGCLD
53 #define SMTP_PORT 25 /* standard SMTP service port */
55 int batchlimit; /* how often to tear down the delivery connection */
56 int fetchlimit; /* how often to tear down the server connection */
57 int batchcount; /* count of messages sent in current batch */
58 int peek_capable; /* can we peek for better error recovery? */
60 static const struct method *protocol;
61 static jmp_buf restart;
65 #define GENSYM (sprintf(tag, "a%04d", ++tagnum), tag)
67 static char *shroud; /* string to shroud in debug output, if non-NULL */
68 static int mytimeout; /* value of nonreponse timeout */
70 static void vtalarm(int timeleft)
71 /* reset the nonresponse-timeout */
73 struct itimerval ntimeout;
75 ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
76 ntimeout.it_value.tv_sec = timeleft;
77 ntimeout.it_value.tv_usec = 0;
78 setitimer(ITIMER_VIRTUAL, &ntimeout, (struct itimerval *)NULL);
81 static void vtalarm_handler (int signal)
82 /* handle server-timeout SIGVTALARM signal */
87 #ifdef HAVE_RES_SEARCH
90 static int is_host_alias(const char *name, struct query *ctl)
91 /* determine whether name is a DNS alias of the hostname */
94 struct mxentry *mxp, *mxrecords;
97 * The first two checks are optimizations that will catch a good
98 * many cases. (1) check against the hostname the user
99 * specified. Odds are good this will either be the mailserver's
100 * FQDN or a suffix of it with the mailserver's domain's default
101 * host name omitted. Then check the rest of the `also known as'
102 * cache accumulated by previous DNS checks. This cache is primed
103 * by the aka list option.
105 * (2) check against the mailserver's FQDN, in case
106 * it's not the same as the declared hostname.
108 * Either of these on a mail address is definitive. Only if the
109 * name doesn't match either is it time to call the bind library.
110 * If this happens odds are good we're looking at an MX name.
112 if (str_in_list(&ctl->server.lead_server->names, name))
114 else if (strcmp(name, ctl->server.canonical_name) == 0)
118 * We know DNS service was up at the beginning of this poll cycle.
119 * If it's down, our nameserver has crashed. We don't want to try
120 * delivering the current message or anything else from this
121 * mailbox until it's back up.
123 else if ((he = gethostbyname(name)) != (struct hostent *)NULL)
125 if (strcmp(ctl->server.canonical_name, he->h_name) == 0)
133 case HOST_NOT_FOUND: /* specified host is unknown */
134 case NO_ADDRESS: /* valid, but does not have an IP address */
137 case NO_RECOVERY: /* non-recoverable name server error */
138 case TRY_AGAIN: /* temporary error on authoritative server */
140 if (outlevel != O_SILENT)
141 putchar('\n'); /* terminate the progress message */
143 "nameserver failure while looking for `%s' during poll of %s.",
144 name, ctl->server.names->id);
146 longjmp(restart, 2); /* try again next poll cycle */
151 * We're only here if DNS was OK but the gethostbyname() failed
152 * with a HOST_NOT_FOUND or NO_ADDRESS error.
153 * Search for a name match on MX records pointing to the server.
156 if ((mxrecords = getmxrecords(name)) == (struct mxentry *)NULL)
160 case HOST_NOT_FOUND: /* specified host is unknown */
161 case NO_ADDRESS: /* valid, but does not have an IP address */
165 case NO_RECOVERY: /* non-recoverable name server error */
166 case TRY_AGAIN: /* temporary error on authoritative server */
169 "nameserver failure while looking for `%s' during poll of %s.",
170 name, ctl->server.names->id);
172 longjmp(restart, 2); /* try again next poll cycle */
178 for (mxp = mxrecords; mxp->name; mxp++)
179 if (strcmp(ctl->server.canonical_name, mxp->name) == 0)
185 /* add this name to relevant server's `also known as' list */
186 save_str(&ctl->server.lead_server->names, -1, name);
190 static void map_name(name, ctl, xmit_names)
191 /* add given name to xmit_names if it matches declared localnames */
192 const char *name; /* name to map */
193 struct query *ctl; /* list of permissible aliases */
194 struct idlist **xmit_names; /* list of recipient names parsed out */
198 lname = idpair_find(&ctl->localnames, name);
199 if (!lname && ctl->wildcard)
202 if (lname != (char *)NULL)
204 if (outlevel == O_VERBOSE)
205 error(0, 0, "mapped %s to local %s", name, lname);
206 save_str(xmit_names, -1, lname);
210 void find_server_names(hdr, ctl, xmit_names)
211 /* parse names out of a RFC822 header into an ID list */
212 const char *hdr; /* RFC822 header in question */
213 struct query *ctl; /* list of permissible aliases */
214 struct idlist **xmit_names; /* list of recipient names parsed out */
216 if (hdr == (char *)NULL)
222 if ((cp = nxtaddr(hdr)) != (char *)NULL)
226 if ((atsign = strchr(cp, '@')))
231 * Does a trailing segment of the hostname match something
232 * on the localdomains list? If so, save the whole name
235 for (idp = ctl->server.localdomains; idp; idp = idp->next)
239 rhs = atsign + 1 + (strlen(atsign) - strlen(idp->id));
240 if ((rhs[-1] == '.' || rhs[-1] == '@')
241 && strcmp(rhs, idp->id) == 0)
243 if (outlevel == O_VERBOSE)
244 error(0, 0, "passed through %s matching %s",
246 save_str(xmit_names, -1, cp);
252 * Check to see if the right-hand part is an alias
253 * or MX equivalent of the mailserver. If it's
254 * not, skip this name. If it is, we'll keep
255 * going and try to find a mapping to a client name.
257 if (!is_host_alias(atsign+1, ctl))
262 map_name(cp, ctl, xmit_names);
264 ((cp = nxtaddr((char *)NULL)) != (char *)NULL);
267 #endif /* HAVE_RES_SEARCH */
269 static FILE *smtp_open(struct query *ctl)
270 /* try to open a socket to the appropriate SMTP server for this query */
274 lead = ctl->lead_smtp; /* go to the SMTP leader for this query */
276 /* maybe it's time to close the socket in order to force delivery */
277 if (batchlimit && lead->smtp_sockfp && batchcount++ == batchlimit)
279 fclose(lead->smtp_sockfp);
280 lead->smtp_sockfp = (FILE *)NULL;
284 /* if no socket to this host is already set up, try to open one */
285 if (lead->smtp_sockfp == (FILE *)NULL)
287 if ((lead->smtp_sockfp = SockOpen(lead->smtphost, SMTP_PORT)) == (FILE *)NULL)
288 return((FILE *)NULL);
289 else if (SMTP_ok(lead->smtp_sockfp) != SM_OK
290 || SMTP_helo(lead->smtp_sockfp, ctl->server.names->id) != SM_OK)
292 fclose(lead->smtp_sockfp);
293 lead->smtp_sockfp = (FILE *)NULL;
297 return(lead->smtp_sockfp);
300 static int gen_readmsg(sockfp, len, delimited, ctl, realname)
301 /* read message content and ship to SMTP or MDA */
302 FILE *sockfp; /* to which the server is connected */
303 long len; /* length of message */
304 int delimited; /* does the protocol use a message delimiter? */
305 struct query *ctl; /* query control record */
306 char *realname; /* real name of host */
308 char buf [MSGBUFSIZE+1];
309 char *bufp, *headers, *fromhdr,*tohdr,*cchdr,*bcchdr,*received_for,*envto;
310 char *fromptr, *toptr;
312 int inheaders, sizeticker;
314 RETSIGTYPE (*sigchld)();
315 #ifdef HAVE_GETHOSTBYNAME
316 char rbuf[HOSTLEN + USERNAMELEN + 4];
317 #endif /* HAVE_GETHOSTBYNAME */
319 /* read the message content from the server */
321 headers = fromhdr = tohdr = cchdr = bcchdr = received_for = envto = NULL;
324 while (delimited || len > 0)
328 if (!SockGets(buf+strlen(buf), sizeof(buf)-strlen(buf)-1, sockfp))
330 vtalarm(ctl->server.timeout);
332 /* we may need to grab RFC822 continuations */
333 (inheaders && (ch = SockPeek(sockfp)) == ' ' || ch == '\t');
335 /* compute length *before* squeezing out CRs */
338 /* write the message size dots */
342 while (sizeticker >= SIZETICKER)
344 if (outlevel > O_SILENT)
346 sizeticker -= SIZETICKER;
351 if (buf[0] == '\r' && buf[1] == '\n')
353 if (delimited && *bufp == '.') {
356 break; /* end of message */
362 reply_hack(bufp, realname);
366 oldlen = strlen(bufp);
367 headers = xmalloc(oldlen + 1);
368 (void) strcpy(headers, bufp);
375 newlen = oldlen + strlen(bufp);
376 headers = realloc(headers, newlen + 1);
379 strcpy(headers + oldlen, bufp);
380 bufp = headers + oldlen;
384 if (!strncasecmp("From:", bufp, 5))
386 else if (!fromhdr && !strncasecmp("Resent-From:", bufp, 12))
388 else if (!fromhdr && !strncasecmp("Apparently-From:", bufp, 16))
390 else if (!strncasecmp("To:", bufp, 3))
392 else if (!strncasecmp("Apparently-To:", bufp, 14))
394 else if (!strncasecmp(ctl->server.envelope, bufp, 14))
396 else if (!strncasecmp("Cc:", bufp, 3))
398 else if (!strncasecmp("Bcc:", bufp, 4))
400 #ifdef HAVE_RES_SEARCH
401 else if (MULTIDROP(ctl) && !strncasecmp("Received:", bufp, 9))
406 * Try to extract the real envelope addressee. We look here
407 * specifically for the mailserver's Received line.
408 * Note: this will only work for sendmail, or an MTA that
409 * shares sendmail's convention for embedding the envelope
410 * address in the Received line. Sendmail itself only
411 * does this when the mail has a single recipient.
413 if ((ok = strstr(bufp, "by ")) == (char *)NULL)
419 /* extract space-delimited token after "by " */
421 for (sp = ok + 3; !isspace(*sp); sp++)
426 * If it's a DNS name of the mail server, look for the
427 * recipient name after a following "for". Otherwise
430 if (is_host_alias(rbuf, ctl))
431 ok = strstr(sp, "for ");
444 while (*sp && *sp != '>' && *sp != '@' && *sp != ';')
449 /* uh oh -- whitespace here can't be right! */
458 received_for = alloca(strlen(rbuf)+1);
459 strcpy(received_for, rbuf);
460 if (outlevel == O_VERBOSE)
462 "found Received address `%s'",
466 #endif /* HAVE_RES_SEARCH */
470 else if (headers) /* OK, we're at end of headers now */
473 struct idlist *idp, *xmit_names;
474 int good_addresses, bad_addresses;
475 #ifdef HAVE_RES_SEARCH
476 int no_local_matches = FALSE;
477 #endif /* HAVE_RES_SEARCH */
479 /* cons up a list of local recipients */
480 xmit_names = (struct idlist *)NULL;
481 bad_addresses = good_addresses = 0;
482 #ifdef HAVE_RES_SEARCH
483 /* is this a multidrop box? */
486 if (envto) /* We have the actual envelope addressee */
487 find_server_names(envto, ctl, &xmit_names);
488 else if (received_for)
490 * We have the Received for addressee.
491 * It has to be a mailserver address, or we
492 * wouldn't have got here.
494 map_name(received_for, ctl, &xmit_names);
498 * We haven't extracted the envelope address.
499 * So check all the header addresses.
501 find_server_names(tohdr, ctl, &xmit_names);
502 find_server_names(cchdr, ctl, &xmit_names);
503 find_server_names(bcchdr, ctl, &xmit_names);
507 no_local_matches = TRUE;
508 save_str(&xmit_names, -1, user);
509 if (outlevel == O_VERBOSE)
511 "no local matches, forwarding to %s",
515 else /* it's a single-drop box, use first localname */
516 #endif /* HAVE_RES_SEARCH */
517 save_str(&xmit_names, -1, ctl->localnames->id);
519 /* time to address the message */
520 if (ctl->mda) /* we have a declared MDA */
526 * We go through this in order to be able to handle very
527 * long lists of users and (re)implement %s.
529 for (idp = xmit_names; idp; idp = idp->next)
530 length += (strlen(idp->id) + 1);
531 names = (char *)alloca(length);
533 for (idp = xmit_names; idp; idp = idp->next)
535 strcat(names, idp->id);
538 cmd = (char *)alloca(strlen(ctl->mda) + length);
539 sprintf(cmd, ctl->mda, names);
540 if (outlevel == O_VERBOSE)
541 error(0, 0, "about to deliver with: %s", cmd);
545 * Arrange to run with user's permissions if we're root.
546 * This will initialize the ownership of any files the
547 * MDA creates properly. (The seteuid call is available
548 * under all BSDs and Linux)
551 #endif /* HAVE_SETEUID */
553 sinkfp = popen(cmd, "w");
556 /* this will fail quietly if we didn't start as root */
558 #endif /* HAVE_SETEUID */
562 error(0, 0, "MDA open failed");
566 sigchld = signal(SIGCHLD, SIG_DFL);
572 /* build a connection to the SMTP listener */
573 if (!ctl->mda && ((sinkfp = smtp_open(ctl)) == NULL))
575 free_str_list(&xmit_names);
576 error(0, 0, "SMTP connect failed");
581 * Try to get the SMTP listener to take the header
582 * From address as MAIL FROM (this makes the logging
583 * nicer). If it won't, fall back on the calling-user
584 * ID. This won't affect replies, which use the header
585 * From address anyway.
587 if (!fromhdr || !(ap = nxtaddr(fromhdr)))
589 if (SMTP_from(sinkfp, user) != SM_OK)
590 return(PS_SMTP); /* should never happen */
592 else if (SMTP_from(sinkfp, ap) != SM_OK)
593 if (smtp_response == 571)
596 * SMTP listener explicitly refuses to deliver
597 * mail coming from this address, probably due
598 * to an anti-spam domain exclusion. Respect
601 sinkfp = (FILE *)NULL;
604 else if (SMTP_from(sinkfp, user) != SM_OK)
605 return(PS_SMTP); /* should never happen */
607 /* now list the recipient addressees */
608 for (idp = xmit_names; idp; idp = idp->next)
609 if (SMTP_rcpt(sinkfp, idp->id) == SM_OK)
616 "SMTP listener doesn't like recipient address `%s'", idp->id);
618 if (!good_addresses && SMTP_rcpt(sinkfp, user) != SM_OK)
621 "can't even send to calling user!");
625 /* tell it we're ready to send data */
631 /* write all the headers */
633 n = fwrite(headers, 1, oldlen, sinkfp);
635 n = SockWrite(headers, 1, oldlen, sinkfp);
641 error(0, errno, "writing RFC822 headers");
645 signal(SIGCHLD, sigchld);
649 else if (outlevel == O_VERBOSE)
654 /* write error notifications */
655 #ifdef HAVE_RES_SEARCH
656 if (no_local_matches || bad_addresses)
659 #endif /* HAVE_RES_SEARCH */
662 char errhd[USERNAMELEN + POPBUFSIZE], *errmsg;
665 (void) strcpy(errhd, "X-Fetchmail-Warning: ");
666 #ifdef HAVE_RES_SEARCH
667 if (no_local_matches)
669 strcat(errhd, "no recipient addresses matched declared local names");
673 #endif /* HAVE_RES_SEARCH */
677 strcat(errhd, "SMTP listener rejected local recipient addresses: ");
678 errlen = strlen(errhd);
679 for (idp = xmit_names; idp; idp = idp->next)
681 errlen += strlen(idp->id) + 2;
683 errmsg = alloca(errlen+3);
684 (void) strcpy(errmsg, errhd);
685 for (idp = xmit_names; idp; idp = idp->next)
688 strcat(errmsg, idp->id);
690 strcat(errmsg, ", ");
694 strcat(errmsg, "\n");
697 fputs(errmsg, sinkfp);
700 free_str_list(&xmit_names);
703 /* SMTP byte-stuffing */
708 SockWrite(bufp, 1, 1, sinkfp);
710 /* ship out the text line */
712 n = fwrite(bufp, 1, strlen(bufp), sinkfp);
714 n = SockWrite(bufp, 1, strlen(bufp), sinkfp);
718 error(0, errno, "writing message text");
722 signal(SIGCHLD, sigchld);
726 else if (outlevel == O_VERBOSE)
730 if (outlevel == O_VERBOSE)
737 /* close the delivery pipe, we'll reopen before next message */
739 signal(SIGCHLD, sigchld);
742 error(0, 0, "MDA exited abnormally or returned nonzero status");
748 /* write message terminator */
749 if (SMTP_eom(sinkfp) != SM_OK)
751 error(0, 0, "SMTP listener refused delivery");
761 kerberos_auth (socket, canonical)
762 /* authenticate to the server host using Kerberos V4 */
763 int socket; /* socket to server host */
764 const char *canonical; /* server name */
770 Key_schedule schedule;
773 ticket = ((KTEXT) (malloc (sizeof (KTEXT_ST))));
774 rem = (krb_sendauth (0L, socket, ticket, "pop",
776 ((char *) (krb_realmofhost (canonical))),
781 ((struct sockaddr_in *) 0),
782 ((struct sockaddr_in *) 0),
787 error(0, 0, "kerberos error %s", (krb_get_err_text (rem)));
792 #endif /* KERBEROS_V4 */
794 int do_protocol(ctl, proto)
795 /* retrieve messages from server using given protocol method table */
796 struct query *ctl; /* parsed options with merged-in defaults */
797 const struct method *proto; /* protocol method table */
800 char *msg, *sp, *cp, realname[HOSTLEN];
804 if (ctl->server.authenticate == A_KERBEROS)
806 error(0, 0, "Kerberos support not linked.");
809 #endif /* KERBEROS_V4 */
811 /* lacking methods, there are some options that may fail */
814 /* check for unsupported options */
817 "Option --flush is not supported with %s",
821 else if (ctl->fetchall) {
823 "Option --all is not supported with %s",
828 if (!proto->getsizes && ctl->limit)
831 "Option --limit is not supported with %s",
838 tag[0] = '\0'; /* nuke any tag hanging out from previous query */
840 error_init(poll_interval == 0 && !logfile);
842 /* set up the server-nonresponse timeout */
843 sigsave = signal(SIGVTALRM, vtalarm_handler);
844 vtalarm(mytimeout = ctl->server.timeout);
846 if ((js = setjmp(restart)) == 1)
849 "timeout after %d seconds waiting for %s.",
850 ctl->server.timeout, ctl->server.names->id);
855 /* error message printed at point of longjmp */
860 char buf [POPBUFSIZE+1];
861 int *msgsizes, len, num, count, new, deletions = 0;
863 /* execute pre-initialization command, if any */
864 if (ctl->preconnect && (ok = system(ctl->preconnect)))
866 sprintf(buf, "pre-connection command failed with status %d", ok);
872 /* open a socket to the mail server */
873 if (!(sockfp = SockOpen(ctl->server.names->id,
874 ctl->server.port ? ctl->server.port : protocol->port)))
876 if (errno != EHOSTUNREACH)
877 error(0, errno, "connecting to host");
883 if (ctl->authenticate == A_KERBEROS)
885 ok = kerberos_auth(fileno(sockfp), ctl->server.canonical_name);
888 vtalarm(ctl->server.timeout);
890 #endif /* KERBEROS_V4 */
892 /* accept greeting message from mail server */
893 ok = (protocol->parse_response)(sockfp, buf);
896 vtalarm(ctl->server.timeout);
899 * Try to parse the host's actual name out of the greeting
900 * message. We do this so that the progress messages will
901 * make sense even if the connection is indirected through
902 * ssh. *Do* use this for hacking reply headers, but *don't*
903 * use it for error logging, as the names in the log should
904 * correlate directly back to rc file entries.
906 * This assumes that the first space-delimited token found
907 * that contains at least two dots (with the characters on
908 * each side of the dot alphanumeric to exclude version
909 * numbers) is the hostname. The hostname candidate may not
910 * contain @ -- if it does it's probably a mailserver
911 * maintainer's name. If no such token is found, fall back on
912 * the .fetchmailrc id.
915 for (cp = buf; *cp; cp++)
919 case 0: /* skip to end of current token */
924 case 1: /* look for blank-delimited token */
932 case 2: /* look for first dot */
937 else if (*cp == '.' && isalpha(cp[1]) && isalpha(cp[-1]))
941 case 3: /* look for second dot */
946 else if (*cp == '.' && isalpha(cp[1]) && isalpha(cp[-1]))
950 case 4: /* look for trailing space */
971 strcpy(realname, ctl->server.names->id);
973 /* try to get authorized to fetch mail */
974 shroud = ctl->password;
975 ok = (protocol->getauth)(sockfp, ctl, buf);
976 shroud = (char *)NULL;
981 vtalarm(ctl->server.timeout);
983 /* compute number of messages and number of new messages waiting */
984 ok = (protocol->getrange)(sockfp, ctl, &count, &new);
987 vtalarm(ctl->server.timeout);
989 /* show user how many messages we downloaded */
990 if (outlevel > O_SILENT)
992 error(0, 0, "No mail from %s@%s",
997 if (new != -1 && (count - new) > 0)
998 error(0, 0, "%d message%s (%d seen) from %s@%s.",
999 count, count > 1 ? "s" : "", count-new,
1003 error(0, 0, "%d message%s from %s@%s.", count, count > 1 ? "s" : "",
1008 /* we may need to get sizes in order to check message limits */
1009 msgsizes = (int *)NULL;
1010 if (!ctl->fetchall && proto->getsizes && ctl->limit)
1012 msgsizes = (int *)alloca(sizeof(int) * count);
1014 ok = (proto->getsizes)(sockfp, count, msgsizes);
1017 vtalarm(ctl->server.timeout);
1023 if (new == -1 || ctl->fetchall)
1025 ok = ((new > 0) ? PS_SUCCESS : PS_NOMAIL);
1031 * What forces this code is that in POP3 and IMAP2BIS you can't
1032 * fetch a message without having it marked `seen'. In IMAP4,
1033 * on the other hand, you can (peek_capable is set to convey
1036 * The result of being unable to peek is that if there's
1037 * any kind of transient error (DNS lookup failure, or
1038 * sendmail refusing delivery due to process-table limits)
1039 * the message will be marked "seen" on the server without
1040 * having been delivered. This is not a big problem if
1041 * fetchmail is running in foreground, because the user
1042 * will see a "skipped" message when it next runs and get
1045 * But in daemon mode this leads to the message being silently
1046 * ignored forever. This is not acceptable.
1048 * We compensate for this by checking the error count from the
1049 * previous pass and forcing all messages to be considered new
1052 int force_retrieval = !peek_capable && (ctl->errcount > 0);
1056 /* read, forward, and delete messages */
1057 for (num = 1; num <= count; num++)
1059 int toolarge = msgsizes && (msgsizes[num-1] > ctl->limit);
1060 int fetch_it = ctl->fetchall ||
1061 (!toolarge && (force_retrieval || !(protocol->is_old && (protocol->is_old)(sockfp,ctl,num))));
1063 /* we may want to reject this message if it's old */
1066 if (outlevel > O_SILENT)
1068 error_build("skipping message %d", num);
1070 error_build(" (oversized, %d bytes)", msgsizes[num-1]);
1075 /* request a message */
1076 ok = (protocol->fetch)(sockfp, ctl, num, &len);
1079 vtalarm(ctl->server.timeout);
1081 if (outlevel > O_SILENT)
1083 error_build("reading message %d", num);
1085 error_build(" (%d bytes)", len);
1086 if (outlevel == O_VERBOSE)
1087 error_complete(0, 0, "");
1092 /* read the message and ship it to the output sink */
1093 ok = gen_readmsg(sockfp,
1095 protocol->delimited,
1100 vtalarm(ctl->server.timeout);
1102 /* tell the server we got it OK and resynchronize */
1103 if (protocol->trail)
1105 ok = (protocol->trail)(sockfp, ctl, num);
1108 vtalarm(ctl->server.timeout);
1113 * At this point in flow of control, either we've bombed
1114 * on a protocol error or had delivery refused by the SMTP
1115 * server (unlikely -- I've never seen it) or we've seen
1116 * `accepted for delivery' and the message is shipped.
1117 * It's safe to mark the message seen and delete it on the
1121 /* maybe we delete this message now? */
1122 if (protocol->delete
1123 && (fetch_it ? !ctl->keep : ctl->flush))
1126 if (outlevel > O_SILENT)
1127 error_complete(0, 0, " flushed");
1128 ok = (protocol->delete)(sockfp, ctl, num);
1131 vtalarm(ctl->server.timeout);
1132 delete_str(&ctl->newsaved, num);
1134 else if (outlevel > O_SILENT)
1135 error_complete(0, 0, " not flushed");
1137 /* perhaps this as many as we're ready to handle */
1138 if (ctl->fetchlimit && ctl->fetchlimit <= num)
1142 ok = gen_transact(sockfp, protocol->exit_cmd);
1150 ok = gen_transact(sockfp, protocol->exit_cmd);
1159 vtalarm(ctl->server.timeout);
1160 if (ok != 0 && ok != PS_SOCKET)
1161 gen_transact(sockfp, protocol->exit_cmd);
1172 msg = "authorization";
1175 msg = "missing or bad RFC822 header";
1181 msg = "client/server synchronization";
1184 msg = "client/server protocol";
1187 msg = "SMTP transaction";
1190 error(0, 0, "undefined");
1193 if (ok==PS_SOCKET || ok==PS_AUTHFAIL || ok==PS_SYNTAX || ok==PS_IOERR
1194 || ok==PS_ERROR || ok==PS_PROTOCOL || ok==PS_SMTP)
1195 error(0, 0, "%s error while fetching from %s", msg, ctl->server.names->id);
1198 signal(SIGVTALRM, sigsave);
1202 #if defined(HAVE_STDARG_H)
1203 void gen_send(FILE *sockfp, char *fmt, ... )
1204 /* assemble command in printf(3) style and send to the server */
1206 void gen_send(sockfp, fmt, va_alist)
1207 /* assemble command in printf(3) style and send to the server */
1208 FILE *sockfp; /* socket to which server is connected */
1209 const char *fmt; /* printf-style format */
1213 char buf [POPBUFSIZE+1];
1216 if (protocol->tagged)
1217 (void) sprintf(buf, "%s ", GENSYM);
1221 #if defined(HAVE_STDARG_H)
1226 vsprintf(buf + strlen(buf), fmt, ap);
1229 strcat(buf, "\r\n");
1230 SockWrite(buf, 1, strlen(buf), sockfp);
1232 if (outlevel == O_VERBOSE)
1236 if (shroud && (cp = strstr(buf, shroud)))
1237 memset(cp, '*', strlen(shroud));
1238 buf[strlen(buf)-1] = '\0';
1239 error(0, 0, "%s> %s", protocol->name, buf);
1243 #if defined(HAVE_STDARG_H)
1244 int gen_transact(FILE *sockfp, char *fmt, ... )
1245 /* assemble command in printf(3) style, send to server, accept a response */
1247 int gen_transact(sockfp, fmt, va_alist)
1248 /* assemble command in printf(3) style, send to server, accept a response */
1249 FILE *sockfp; /* socket to which server is connected */
1250 const char *fmt; /* printf-style format */
1255 char buf [POPBUFSIZE+1];
1258 if (protocol->tagged)
1259 (void) sprintf(buf, "%s ", GENSYM);
1263 #if defined(HAVE_STDARG_H)
1268 vsprintf(buf + strlen(buf), fmt, ap);
1271 strcat(buf, "\r\n");
1272 SockWrite(buf, 1, strlen(buf), sockfp);
1274 if (outlevel == O_VERBOSE)
1278 if (shroud && (cp = strstr(buf, shroud)))
1279 memset(cp, '*', strlen(shroud));
1280 buf[strlen(buf)-1] = '\0';
1281 error(0, 0, "%s> %s", protocol->name, buf);
1284 /* we presume this does its own response echoing */
1285 ok = (protocol->parse_response)(sockfp, buf);
1291 /* driver.c ends here */