X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=driver.c;h=a6a18754efd550628d292c444ffa767bcb5a5752;hb=24ab4a608c8ee1613698a1a312a7b30d138a241e;hp=e4c2638a9b2cd4e275a5f81991e3c1f2edd6fb8a;hpb=c4148424b71a25ec79005361dc2363b800b10ada;p=~andy%2Ffetchmail diff --git a/driver.c b/driver.c index e4c2638a..a6a18754 100644 --- a/driver.c +++ b/driver.c @@ -33,7 +33,7 @@ extern "C" { #include "kerberos.h" -#include "i18n.h" +#include "gettext.h" #include "socket.h" #include "fetchmail.h" @@ -352,7 +352,8 @@ static int eat_trailer(int sock, struct query *ctl) static int fetch_messages(int mailserver_socket, struct query *ctl, int count, int **msgsizes, int maxfetch, - int *fetches, int *dispatches, int *deletions) + int *fetches, int *dispatches, int *deletions, + int *transient_errors) /* fetch messages in lockstep mode */ { flag force_retrieval; @@ -368,7 +369,7 @@ static int fetch_messages(int mailserver_socket, struct query *ctl, * could be "auto". */ switch (ctl->server.protocol) { - case P_POP3: case P_APOP: + case P_POP3: fetchsizelimit = 1; } @@ -425,14 +426,11 @@ static int fetch_messages(int mailserver_socket, struct query *ctl, } if (msgcode == MSGLEN_OLD) { - /* To avoid flooding the syslog when using --keep, - * report "Skipped message" only when: - * 1) --verbose is on, or - * 2) fetchmail does not use syslog - */ - if ( (outlevel >= O_VERBOSE) || - (outlevel > O_SILENT && !run.use_syslog) - ) + /* + * To avoid flooding the logs when using --keep, report + * skipping for old messages only when --flush is on. + */ + if (outlevel > O_SILENT && ctl->flush) { report_build(stdout, GT_("skipping message %s@%s:%d"), @@ -529,6 +527,7 @@ static int fetch_messages(int mailserver_socket, struct query *ctl, GT_("couldn't fetch headers, message %s@%s:%d (%d octets)\n"), ctl->remotename, ctl->server.truename, num, msgsize); + (*transient_errors)++; continue; } else if (err != 0) @@ -570,7 +569,10 @@ static int fetch_messages(int mailserver_socket, struct query *ctl, if (err == PS_RETAINED) suppress_forward = suppress_delete = retained = TRUE; else if (err == PS_TRANSIENT) + { suppress_delete = suppress_forward = TRUE; + (*transient_errors)++; + } else if (err == PS_REFUSED) suppress_forward = TRUE; else if (err) @@ -602,8 +604,44 @@ static int fetch_messages(int mailserver_socket, struct query *ctl, if (separatefetchbody) { len = -1; - if ((err=(ctl->server.base_protocol->fetch_body)(mailserver_socket,ctl,num,&len))) + if ((err=(ctl->server.base_protocol->fetch_body)(mailserver_socket,ctl,num,&len))) { + if (err == PS_ERROR && ctl->server.retrieveerror) { + /* + * Mark a message with a protocol error as seen. + * This can be used to see which messages we've attempted + * to download, but failed. + */ + if (ctl->server.retrieveerror == RE_MARKSEEN) { + if ((ctl->server.base_protocol->mark_seen)(mailserver_socket,ctl,num)) { + return(err); + } + } + + if (ctl->server.retrieveerror != RE_ABORT) { + /* + * Do not abort download session. Continue with the next message. + * + * Prevents a malformed message from blocking all other messages + * behind it in the mailbox from being downloaded. + * + * Reconnect to SMTP to force this incomplete message to be dropped. + * Required because we've already begun the DATA portion of the + * interaction with the SMTP server (commands are ignored/ + * considered part of the message data). + */ + abort_message_sink(ctl); + + // Ensure we don't delete the failed message from the server. + suppress_delete = TRUE; + + // Bookkeeping required before next message can be downloaded. + goto flagthemail; + } + } + return(err); + } + /* * Work around a bug in Novell's * broken GroupWise IMAP server; @@ -631,7 +669,10 @@ static int fetch_messages(int mailserver_socket, struct query *ctl, len); if (err == PS_TRANSIENT) + { suppress_delete = suppress_forward = TRUE; + (*transient_errors)++; + } else if (err) return(err); @@ -724,16 +765,11 @@ flagthemail: } else { - if ( (outlevel >= O_VERBOSE) || - /* To avoid flooding the syslog when using --keep, - * report "Skipped message" only when: - * 1) --verbose is on, or - * 2) fetchmail does not use syslog, or - * 3) the message was skipped for some other - * reason than just being old. - */ - (outlevel > O_SILENT && (!run.use_syslog || msgcode != MSGLEN_OLD)) - ) + /* + * To avoid flooding the logs when using --keep, report + * skipping of new messages only. + */ + if (outlevel > O_SILENT && msgcode != MSGLEN_OLD) report_complete(stdout, GT_(" not flushed\n")); /* maybe we mark this message as seen now? */ @@ -862,7 +898,7 @@ static int do_session( /* sigsetjmp returned zero -> normal operation */ char buf[MSGBUFSIZE+1], *realhost; int count, newm, bytes; - int fetches, dispatches, oldphase; + int fetches, dispatches, transient_errors, oldphase; struct idlist *idp; /* execute pre-initialization command, if any */ @@ -1019,6 +1055,7 @@ static int do_session( ctl->sslcommonname : realhost, ctl->server.pollname, &ctl->remotename) == -1) { + set_timeout(0); report(stderr, GT_("SSL connection failed.\n")); err = PS_SOCKET; goto cleanUp; @@ -1206,6 +1243,7 @@ is restored.")); pass = 0; do { dispatches = 0; + transient_errors = 0; ++pass; /* reset timeout, in case we did an IDLE */ @@ -1335,10 +1373,20 @@ is restored.")); err = fetch_messages(mailserver_socket, ctl, count, &msgsizes, maxfetch, - &fetches, &dispatches, &deletions); + &fetches, &dispatches, &deletions, + &transient_errors); if (err != PS_SUCCESS && err != PS_MAXFETCH) goto cleanUp; + if (transient_errors > MAX_TRANSIENT_ERRORS) + { + if (outlevel > O_SILENT) + { + report(stderr, GT_("Too many mails skipped (%d > %d) due to transient errors for %s\n"), + transient_errors, MAX_TRANSIENT_ERRORS, buf); + } + } + if (!check_only && ctl->skipped && run.poll_interval > 0 && !nodetach) { @@ -1438,7 +1486,7 @@ is restored.")); msg = GT_("socket"); break; case PS_SYNTAX: - msg = GT_("missing or bad RFC822 header"); + msg = GT_("missing or bad RFC822 header or command line option"); break; case PS_IOERR: msg = GT_("MDA");