#if defined(HAVE_SYS_ITIMER_H)
#include <sys/itimer.h>
#endif
-#include <sys/time.h>
#include <signal.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
#ifdef HAVE_NET_SOCKET_H
#include <net/socket.h>
#endif
-#ifdef HESIOD
+#ifdef HAVE_PKG_hesiod
#include <hesiod.h>
#endif
+#include <langinfo.h>
+
#if defined(HAVE_RES_SEARCH) || defined(HAVE_GETHOSTBYNAME)
#include <netdb.h>
#include "mx.h"
flag peek_capable; /* can we peek for better error recovery? */
int mailserver_socket_temp = -1; /* socket to free if connect timeout */
-static int timeoutcount; /* count consecutive timeouts */
-static int idletimeout; /* timeout occured in idle stage? */
+static volatile int timeoutcount = 0; /* count consecutive timeouts */
+static volatile int idletimeout = 0; /* timeout occured in idle stage? */
static jmp_buf restart;
return idletimeout;
}
+void resetidletimeout(void)
+{
+ idletimeout = 0;
+}
+
void set_timeout(int timeleft)
/* reset the nonresponse-timeout */
{
if (timeleft == 0)
timeoutcount = 0;
- idletimeout = 1;
-
ntimeout.it_interval.tv_sec = ntimeout.it_interval.tv_usec = 0;
ntimeout.it_value.tv_sec = timeleft;
ntimeout.it_value.tv_usec = 0;
krb5_auth_context auth_context = NULL;
krb5_init_context(&context);
- krb5_init_ets(context);
krb5_auth_con_init(context, &auth_context);
if (retval = krb5_cc_default(context, &ccdef)) {
*/
if (open_warning_by_mail(ctl, (struct msgblk *)NULL))
return;
- stuff_warning(ctl,
- GT_("Subject: Fetchmail oversized-messages warning.\n"
- "\n"
- "The following oversized messages remain on the mail server %s:"),
- ctl->server.pollname);
-
+ stuff_warning(iana_charset, ctl,
+ GT_("Subject: Fetchmail oversized-messages warning"));
+ stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl,
+ GT_("The following oversized messages remain on the mail server %s:"),
+ ctl->server.pollname);
+
+ stuff_warning(NULL, ctl, "");
+
if (run.poll_interval == 0)
max_warning_poll_count = 0;
else
{
nbr = current->val.status.mark;
size = atoi(current->id);
- stuff_warning(ctl,
- GT_("\t%d msg %d octets long skipped by fetchmail.\n"),
+ stuff_warning(NULL, ctl,
+ GT_(" %d msg %d octets long skipped by fetchmail."),
nbr, size);
}
current->val.status.num++;
current->val.status.num = 0;
}
+ stuff_warning(NULL, ctl, "");
+
close_warning_by_mail(ctl, (struct msgblk *)NULL);
}
int cnt;
/* convert size to string */
-#ifdef HAVE_SNPRINTF
- snprintf(sizestr, sizeof(sizestr),
-#else
- sprintf(sizestr,
-#endif /* HAVE_SNPRINTF */
- "%d", size);
+ snprintf(sizestr, sizeof(sizestr), "%d", size);
/* build a list of skipped messages
* val.id = size of msg (string cnvt)
}
static int fetch_messages(int mailserver_socket, struct query *ctl,
- int count, int *msgsizes, int *msgcodes, int maxfetch,
+ int count, int *msgsizes, int maxfetch,
int *fetches, int *dispatches, int *deletions)
/* fetch messages in lockstep mode */
{
- int num, err, len;
+ flag force_retrieval;
+ int num, firstnum = 1, lastnum = 0, err, len;
+ int fetchsizelimit = ctl->fetchsizelimit;
+ int msgsize;
+
+ if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit))
+ {
+ /* for POP3, we can get the size of one mail only! Unfortunately, this
+ * protocol specific test cannot be done elsewhere as the protocol
+ * could be "auto". */
+ switch (ctl->server.protocol)
+ {
+ case P_POP3: case P_APOP: case P_RPOP:
+ fetchsizelimit = 1;
+ }
+
+ /* Time to allocate memory to store the sizes */
+ xalloca(msgsizes, int *, sizeof(int) * fetchsizelimit);
+ }
+
+ /*
+ * What forces this code is that in POP2 and
+ * IMAP2bis you can't fetch a message without
+ * having it marked `seen'. In POP3 and IMAP4, on the
+ * other hand, you can (peek_capable is set by
+ * each driver module to convey this; it's not a
+ * method constant because of the difference between
+ * IMAP2bis and IMAP4, and because POP3 doesn't peek
+ * if fetchall is on).
+ *
+ * The result of being unable to peek is that if there's
+ * any kind of transient error (DNS lookup failure, or
+ * sendmail refusing delivery due to process-table limits)
+ * the message will be marked "seen" on the server without
+ * having been delivered. This is not a big problem if
+ * fetchmail is running in foreground, because the user
+ * will see a "skipped" message when it next runs and get
+ * clued in.
+ *
+ * But in daemon mode this leads to the message
+ * being silently ignored forever. This is not
+ * acceptable.
+ *
+ * We compensate for this by checking the error
+ * count from the previous pass and forcing all
+ * messages to be considered new if it's nonzero.
+ */
+ force_retrieval = !peek_capable && (ctl->errcount > 0);
for (num = 1; num <= count; num++)
{
flag suppress_forward = FALSE;
flag suppress_readbody = FALSE;
flag retained = FALSE;
+ int msgcode = MSGLEN_UNKNOWN;
- if (msgcodes[num-1] < 0)
+ /* check if the message is old
+ * Note: the size of the message may not be known here */
+ if (ctl->fetchall || force_retrieval)
+ ;
+ else if (ctl->server.base_protocol->is_old && (ctl->server.base_protocol->is_old)(mailserver_socket,ctl,num))
+ msgcode = MSGLEN_OLD;
+ if (msgcode == MSGLEN_OLD)
{
- if ((msgcodes[num-1] == MSGLEN_TOOLARGE) && !check_only)
- mark_oversized(ctl, num, msgsizes[num-1]);
/* 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 being old.
+ * 2) fetchmail does not use syslog
*/
if ( (outlevel >= O_VERBOSE) ||
- (outlevel > O_SILENT && (!run.use_syslog || msgcodes[num-1] != MSGLEN_OLD))
+ (outlevel > O_SILENT && !run.use_syslog)
)
{
+ report_build(stdout,
+ GT_("skipping message %s@%s:%d"),
+ ctl->remotename, ctl->server.truename, num);
+ }
+
+ goto flagthemail;
+ }
+
+ if (ctl->server.base_protocol->getpartialsizes && NUM_NONZERO(fetchsizelimit) &&
+ lastnum < num)
+ {
+ /* Instead of getting the sizes of all mails at the start, we get
+ * the sizes in blocks of fetchsizelimit. This leads to better
+ * performance when there are too many mails (say, 10000) in
+ * the mailbox and either we are not getting all the mails at
+ * one go (--fetchlimit 100) or there is a frequent socket
+ * error while just getting the sizes of all mails! */
+
+ int i;
+ int oldstage = stage;
+ firstnum = num;
+ lastnum = num + fetchsizelimit - 1;
+ if (lastnum > count)
+ lastnum = count;
+ for (i = 0; i < fetchsizelimit; i++)
+ msgsizes[i] = 0;
+
+ stage = STAGE_GETSIZES;
+ err = (ctl->server.base_protocol->getpartialsizes)(mailserver_socket, num, lastnum, msgsizes);
+ if (err != 0)
+ return err;
+ stage = oldstage;
+ }
+
+ msgsize = msgsizes ? msgsizes[num-firstnum] : 0;
+
+ /* check if the message is oversized */
+ if (NUM_NONZERO(ctl->limit) && (msgsize > ctl->limit))
+ msgcode = MSGLEN_TOOLARGE;
+/* else if (msgsize == 512)
+ msgcode = MSGLEN_OLD; (hmh) sample code to skip message */
+
+ if (msgcode < 0)
+ {
+ if ((msgcode == MSGLEN_TOOLARGE) && !check_only)
+ {
+ mark_oversized(ctl, num, msgsize);
+ suppress_delete = TRUE;
+ }
+ if (outlevel > O_SILENT)
+ {
+ /* old messages are already handled above */
report_build(stdout,
GT_("skipping message %s@%s:%d (%d octets)"),
ctl->remotename, ctl->server.truename, num,
- msgsizes[num-1]);
- switch (msgcodes[num-1])
+ msgsize);
+ switch (msgcode)
{
case MSGLEN_INVALID:
/*
else
{
flag wholesize = !ctl->server.base_protocol->fetch_body;
+ flag separatefetchbody = (ctl->server.base_protocol->fetch_body) ? TRUE : FALSE;
/* request a message */
err = (ctl->server.base_protocol->fetch_headers)(mailserver_socket,ctl,num, &len);
report(stdout,
GT_("couldn't fetch headers, message %s@%s:%d (%d octets)\n"),
ctl->remotename, ctl->server.truename, num,
- msgsizes[num-1]);
+ msgsize);
continue;
}
else if (err != 0)
/* -1 means we didn't see a size in the response */
if (len == -1)
{
- len = msgsizes[num - 1];
+ len = msgsize;
wholesize = TRUE;
}
num, count);
if (len > 0)
- report_build(stdout, GT_(" (%d %soctets)"),
- len, wholesize ? "" : GT_("header "));
+ report_build(stdout, wholesize ? GT_(" (%d octets)")
+ : GT_(" (%d header octets)"), len);
if (outlevel >= O_VERBOSE)
report_complete(stdout, "\n");
else
* Read the message headers and ship them to the
* output sink.
*/
- err = readheaders(mailserver_socket, len, msgsizes[num-1],
- ctl, num);
+ err = readheaders(mailserver_socket, len, msgsize,
+ ctl, num,
+ /* pass the suppress_readbody flag only if the underlying
+ * protocol does not fetch the body separately */
+ separatefetchbody ? 0 : &suppress_readbody);
if (err == PS_RETAINED)
- {
suppress_forward = suppress_delete = retained = TRUE;
- /* do not read the body only if the underlying protocol
- * allows the body to be fetched separately */
- if (ctl->server.base_protocol->fetch_body)
- suppress_readbody = TRUE;
- }
else if (err == PS_TRANSIENT)
- {
suppress_delete = suppress_forward = TRUE;
- if (ctl->server.base_protocol->fetch_body)
- suppress_readbody = TRUE;
- }
else if (err == PS_REFUSED)
- {
suppress_forward = TRUE;
- if (ctl->server.base_protocol->fetch_body)
- suppress_readbody = TRUE;
- }
else if (err == PS_TRUNCATED)
- {
- if (ctl->server.base_protocol->fetch_body)
- suppress_readbody = TRUE;
- len = 0; /* suppress body processing */
- }
+ suppress_readbody = TRUE;
else if (err)
return(err);
- /*
- * If we're using IMAP4 or something else that
- * can fetch headers separately from bodies,
- * it's time to request the body now. This
- * fetch may be skipped if we got an anti-spam
- * or other PS_REFUSED error response during
- * readheaders.
- */
- if (ctl->server.base_protocol->fetch_body && !suppress_readbody)
+ /* tell server we got it OK and resynchronize */
+ if (separatefetchbody && ctl->server.base_protocol->trail)
{
if (outlevel >= O_VERBOSE && !isafile(1))
{
if ((err = (ctl->server.base_protocol->trail)(mailserver_socket, ctl, num)))
return(err);
- len = 0;
- if (!suppress_forward)
+ }
+
+ /* do not read the body which is not being forwarded only if
+ * the underlying protocol allows the body to be fetched
+ * separately */
+ if (separatefetchbody && suppress_forward)
+ suppress_readbody = TRUE;
+
+ /*
+ * If we're using IMAP4 or something else that
+ * can fetch headers separately from bodies,
+ * it's time to request the body now. This
+ * fetch may be skipped if we got an anti-spam
+ * or other PS_REFUSED error response during
+ * readheaders.
+ */
+ if (!suppress_readbody)
+ {
+ if (separatefetchbody)
{
+ len = -1;
if ((err=(ctl->server.base_protocol->fetch_body)(mailserver_socket,ctl,num,&len)))
return(err);
/*
* string. This violates RFC2060.
*/
if (len == -1)
- len = msgsizes[num-1] - msgblk.msglen;
+ len = msgsize - msgblk.msglen;
if (outlevel > O_SILENT && !wholesize)
report_complete(stdout,
GT_(" (%d body octets) "), len);
}
- }
- /* process the body now */
- if (len > 0)
- {
- if (suppress_readbody)
- {
- err = PS_SUCCESS;
- }
- else
- {
- err = readbody(mailserver_socket,
- ctl,
- !suppress_forward,
- len);
- }
+ /* process the body now */
+ err = readbody(mailserver_socket,
+ ctl,
+ !suppress_forward,
+ len);
if (err == PS_TRANSIENT)
suppress_delete = suppress_forward = TRUE;
else if (err)
* QUALCOMM server (at least) seems to be
* reporting the on-disk size correctly.
*/
- if (msgblk.msglen != msgsizes[num-1])
+ if (msgblk.msglen != msgsize)
{
if (outlevel >= O_DEBUG)
report(stdout,
GT_("message %s@%s:%d was not the expected length (%d actual != %d expected)\n"),
ctl->remotename, ctl->server.truename, num,
- msgblk.msglen, msgsizes[num-1]);
+ msgblk.msglen, msgsize);
}
/* end-of-message processing starts here */
(*fetches)++;
}
+flagthemail:
/*
* At this point in flow of control, either
* we've bombed on a protocol error or had
}
else if (ctl->server.base_protocol->delete
&& !suppress_delete
- && ((msgcodes[num-1] >= 0) ? !ctl->keep : ctl->flush))
+ && ((msgcode >= 0 && !ctl->keep)
+ || (msgcode == MSGLEN_OLD && ctl->flush)))
{
(*deletions)++;
if (outlevel > O_SILENT)
* 3) the message was skipped for some other
* reason than just being old.
*/
- (outlevel > O_SILENT && (!run.use_syslog || msgcodes[num-1] != MSGLEN_OLD))
+ (outlevel > O_SILENT && (!run.use_syslog || msgcode != MSGLEN_OLD))
)
report_complete(stdout, GT_(" not flushed\n"));
/* maybe we mark this message as seen now? */
if (ctl->server.base_protocol->mark_seen
&& !suppress_delete
- && (msgcodes[num-1] >= 0 && ctl->keep))
+ && (msgcode >= 0 && ctl->keep))
{
err = (ctl->server.base_protocol->mark_seen)(mailserver_socket, ctl, num);
if (err != 0)
}
/* perhaps this as many as we're ready to handle */
- if (maxfetch && maxfetch <= *fetches && *fetches < count)
+ if (maxfetch && maxfetch <= *fetches && num < count)
{
- report(stdout, GT_("fetchlimit %d reached; %d messages left on server %s account %s\n"),
+ report(stdout,
+ ngettext("fetchlimit %d reached; %d message left on server %s account %s\n",
+ "fetchlimit %d reached; %d messages left on server %s account %s\n", count - *fetches),
maxfetch, count - *fetches, ctl->server.truename, ctl->remotename);
return(PS_MAXFETCH);
}
return(PS_SUCCESS);
}
-static int do_session(ctl, proto, maxfetch)
/* retrieve messages from server using given protocol method table */
-struct query *ctl; /* parsed options with merged-in defaults */
-const struct method *proto; /* protocol method table */
-const int maxfetch; /* maximum number of messages to fetch */
+static int do_session(
+ /* parsed options with merged-in defaults */
+ struct query *ctl,
+ /* protocol method table */
+ const struct method *proto,
+ /* maximum number of messages to fetch */
+ const int maxfetch)
{
- int js;
-#ifdef HAVE_VOLATILE
+ static int *msgsizes;
volatile int err, mailserver_socket = -1; /* pacifies -Wall */
-#else
- int err, mailserver_socket = -1;
-#endif /* HAVE_VOLATILE */
+ int deletions = 0, js;
const char *msg;
SIGHANDLERTYPE pipesave;
SIGHANDLERTYPE alrmsave;
ctl->server.base_protocol = proto;
+ msgsizes = NULL;
pass = 0;
err = 0;
init_transact(proto);
if ((js = setjmp(restart)))
{
+ /* exception caught */
#ifdef HAVE_SIGPROCMASK
/*
* Don't rely on setjmp() to restore the blocked-signal mask.
if (timeoutcount > MAX_TIMEOUTS
&& !open_warning_by_mail(ctl, (struct msgblk *)NULL))
{
- stuff_warning(ctl,
- GT_("Subject: fetchmail sees repeated timeouts\n"));
- stuff_warning(ctl,
+ stuff_warning(iana_charset, ctl,
+ GT_("Subject: fetchmail sees repeated timeouts"));
+ stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl,
GT_("Fetchmail saw more than %d timeouts while attempting to get mail from %s@%s.\n"),
MAX_TIMEOUTS,
- ctl->remotename,
- ctl->server.truename);
- stuff_warning(ctl,
+ ctl->remotename, ctl->server.truename);
+ stuff_warning(NULL, ctl,
GT_("This could mean that your mailserver is stuck, or that your SMTP\n" \
"server is wedged, or that your mailbox file on the server has been\n" \
"corrupted by a server error. You can run `fetchmail -v -v' to\n" \
}
else
{
+ /* setjmp returned zero -> normal operation */
char buf[MSGBUFSIZE+1], *realhost;
- int count, new, bytes, deletions = 0;
- int *msgsizes = (int *)NULL;
- int *msgcodes = (int *)NULL;
-#if INET6_ENABLE
+ int count, new, bytes;
+#ifdef INET6_ENABLE
int fetches, dispatches, oldphase;
#else /* INET6_ENABLE */
int port, fetches, dispatches, oldphase;
oldphase = phase;
phase = OPEN_WAIT;
set_timeout(mytimeout);
-#if !INET6_ENABLE
+#ifndef INET6_ENABLE
#ifdef SSL_ENABLE
port = ctl->server.port ? ctl->server.port : ( ctl->use_ssl ? ctl->server.base_protocol->sslport : ctl->server.base_protocol->port );
#else
#endif
#endif /* !INET6_ENABLE */
-#ifdef HESIOD
+#ifdef HAVE_PKG_hesiod
/* If either the pollname or vianame are "hesiod" we want to
lookup the user's hesiod pobox host */
if (!strcasecmp(ctl->server.queryname, "hesiod")) {
}
else
{
+#ifdef INET6_ENABLE
+ struct addrinfo hints, *res;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_CANONNAME;
+
+ error = getaddrinfo(ctl->server.queryname, NULL, &hints, &res);
+ if (error)
+ {
+ report(stderr,
+ GT_("couldn't find canonical DNS name of %s (%s)\n"),
+ ctl->server.pollname, ctl->server.queryname);
+ err = PS_DNS;
+ set_timeout(0);
+ phase = oldphase;
+ goto closeUp;
+ }
+ else
+ {
+ ctl->server.truename=xstrdup(res->ai_canonname);
+ ctl->server.trueaddr=xmalloc(res->ai_addrlen);
+ memcpy(ctl->server.trueaddr, res->ai_addr, res->ai_addrlen);
+ }
+#else
struct hostent *namerec;
-
+
/*
* Get the host's IP, so we can report it like this:
*
if (namerec == (struct hostent *)NULL)
{
report(stderr,
- GT_("couldn't find canonical DNS name of %s\n"),
- ctl->server.pollname);
+ GT_("couldn't find canonical DNS name of %s (%s)\n"),
+ ctl->server.pollname, ctl->server.queryname);
err = PS_DNS;
set_timeout(0);
phase = oldphase;
namerec->h_addr_list[0],
namerec->h_length);
}
+#endif
}
}
#endif /* HAVE_GETHOSTBYNAME */
/* allow time for the port to be set up if we have a plugin */
if (ctl->server.plugin)
(void)sleep(1);
-#if INET6_ENABLE
+#ifdef INET6_ENABLE
if ((mailserver_socket = SockOpen(realhost,
ctl->server.service ? ctl->server.service : ( ctl->use_ssl ? ctl->server.base_protocol->sslservice : ctl->server.base_protocol->service ),
ctl->server.netsec, ctl->server.plugin)) == -1)
#endif /* INET6_ENABLE */
{
char errbuf[BUFSIZ];
-#if !INET6_ENABLE
+#ifndef INET6_ENABLE
int err_no = errno;
#ifdef HAVE_RES_SEARCH
if (err_no != 0 && h_errno != 0)
else if (h_errno == TRY_AGAIN)
strcpy(errbuf, GT_("temporary name server error."));
else
-#ifdef HAVE_SNPRINTF
- snprintf(errbuf, sizeof(errbuf),
-#else
- sprintf(errbuf,
-#endif /* HAVE_SNPRINTF */
- GT_("unknown DNS error %d."), h_errno);
+ snprintf (errbuf, sizeof(errbuf),
+ GT_("unknown DNS error %d."), h_errno);
}
else
#endif /* HAVE_RES_SEARCH */
/* warn the system administrator */
if (open_warning_by_mail(ctl, (struct msgblk *)NULL) == 0)
{
- stuff_warning(ctl,
- GT_("Subject: Fetchmail unreachable-server warning.\n"
- "\n"
- "Fetchmail could not reach the mail server %s:")
+ stuff_warning(iana_charset, ctl,
+ GT_("Subject: Fetchmail unreachable-server warning."));
+ stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl, GT_("Fetchmail could not reach the mail server %s:"),
ctl->server.pollname);
- stuff_warning(ctl, errbuf, ctl->server.pollname);
+ stuff_warning(NULL, ctl, errbuf, ctl->server.pollname);
close_warning_by_mail(ctl, (struct msgblk *)NULL);
}
#endif
}
#ifdef SSL_ENABLE
- /* Save the socket opened. Usefull if Fetchmail hangs on SSLOpen
- * because the socket can be closed
+ /* Save the socket opened. Useful if Fetchmail hangs on SSLOpen
+ * because the socket can be closed.
*/
mailserver_socket_temp = mailserver_socket;
set_timeout(mytimeout);
ctl->sslcertpath,ctl->sslfingerprint,realhost,ctl->server.pollname) == -1)
{
report(stderr, GT_("SSL connection failed.\n"));
- goto closeUp;
+ err = PS_AUTHFAIL;
+ goto cleanUp;
}
/* Fetchmail didn't hang on SSLOpen,
&& !open_warning_by_mail(ctl, (struct msgblk *)NULL))
{
ctl->wehavesentauthnote = 1;
- stuff_warning(ctl,
- GT_("Subject: fetchmail authentication failed on %s@%s\n"),
+ stuff_warning(iana_charset, ctl,
+ GT_("Subject: fetchmail authentication failed on %s@%s"),
ctl->remotename, ctl->server.truename);
- stuff_warning(ctl,
+ stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl,
GT_("Fetchmail could not get mail from %s@%s.\n"),
ctl->remotename,
ctl->server.truename);
if (ctl->wehaveauthed)
- stuff_warning(ctl, GT_("\
+ stuff_warning(NULL, ctl, GT_("\
The attempt to get authorization failed.\n\
Since we have already succeeded in getting authorization for this\n\
connection, this is probably another failure mode (such as busy server)\n\
at each cycle. No future notifications will be sent until service\n\
is restored."));
else
- stuff_warning(ctl, GT_("\
+ stuff_warning(NULL, ctl, GT_("\
The attempt to get authorization failed.\n\
This probably means your password is invalid, but some servers have\n\
other failure modes that fetchmail cannot distinguish from this\n\
ctl->server.truename);
if (!open_warning_by_mail(ctl, (struct msgblk *)NULL))
{
- stuff_warning(ctl,
- GT_("Subject: fetchmail authentication OK on %s@%s\n"),
+ stuff_warning(iana_charset, ctl,
+ GT_("Subject: fetchmail authentication OK on %s@%s"),
ctl->remotename, ctl->server.truename);
- stuff_warning(ctl,
+ stuff_warning(NULL, ctl, "");
+ stuff_warning(NULL, ctl,
GT_("Fetchmail was able to log into %s@%s.\n"),
ctl->remotename,
ctl->server.truename);
- stuff_warning(ctl,
+ stuff_warning(NULL, ctl,
GT_("Service has been restored.\n"));
close_warning_by_mail(ctl, (struct msgblk *)NULL);
/* show user how many messages we downloaded */
if (idp->id)
-#ifdef HAVE_SNPRINTF
(void) snprintf(buf, sizeof(buf),
-#else
- (void) sprintf(buf,
-#endif /* HAVE_SNPRINTF */
GT_("%s at %s (folder %s)"),
- ctl->remotename, ctl->server.truename, idp->id);
+ ctl->remotename, ctl->server.pollname, idp->id);
else
-#ifdef HAVE_SNPRINTF
- (void) snprintf(buf, sizeof(buf),
-#else
- (void) sprintf(buf,
-#endif /* HAVE_SNPRINTF */
- GT_("%s at %s"),
- ctl->remotename, ctl->server.truename);
+ (void) snprintf(buf, sizeof(buf), GT_("%s at %s"),
+ ctl->remotename, ctl->server.pollname);
if (outlevel > O_SILENT)
{
if (count == -1) /* only used for ETRN */
else if (count != 0)
{
if (new != -1 && (count - new) > 0)
- report_build(stdout, GT_("%d %s (%d seen) for %s"),
- count, count > 1 ? GT_("messages") :
- GT_("message"),
- count-new, buf);
+ report_build(stdout, ngettext("%d message (%d %s) for %s", "%d messages (%d %s) for %s", (unsigned long)count),
+ count,
+ count-new,
+ ngettext("seen", "seen", (unsigned long)count-new),
+ buf);
else
- report_build(stdout, GT_("%d %s for %s"),
- count, count > 1 ? GT_("messages") :
- GT_("message"), buf);
+ report_build(stdout, ngettext("%d message for %s",
+ "%d messages for %s",
+ count),
+ count, buf);
if (bytes == -1)
report_complete(stdout, ".\n");
else
}
else if (count > 0)
{
- flag force_retrieval;
- int i, num;
-
- /*
- * What forces this code is that in POP2 and
- * IMAP2bis you can't fetch a message without
- * having it marked `seen'. In POP3 and IMAP4, on the
- * other hand, you can (peek_capable is set by
- * each driver module to convey this; it's not a
- * method constant because of the difference between
- * IMAP2bis and IMAP4, and because POP3 doesn't peek
- * if fetchall is on).
- *
- * The result of being unable to peek is that if there's
- * any kind of transient error (DNS lookup failure, or
- * sendmail refusing delivery due to process-table limits)
- * the message will be marked "seen" on the server without
- * having been delivered. This is not a big problem if
- * fetchmail is running in foreground, because the user
- * will see a "skipped" message when it next runs and get
- * clued in.
- *
- * But in daemon mode this leads to the message
- * being silently ignored forever. This is not
- * acceptable.
- *
- * We compensate for this by checking the error
- * count from the previous pass and forcing all
- * messages to be considered new if it's nonzero.
- */
- force_retrieval = !peek_capable && (ctl->errcount > 0);
+ int i;
/*
* Don't trust the message count passed by the server.
return(PS_PROTOCOL);
}
- /* OK, we're going to gather size info next */
- xalloca(msgsizes, int *, sizeof(int) * count);
- xalloca(msgcodes, int *, sizeof(int) * count);
- for (i = 0; i < count; i++) {
- msgsizes[i] = 0;
- msgcodes[i] = MSGLEN_UNKNOWN;
- }
-
/*
* We need the size of each message before it's
* loaded in order to pass it to the ESMTP SIZE
* option. If the protocol has a getsizes method,
* we presume this means it doesn't get reliable
* sizes from message fetch responses.
+ *
+ * If the protocol supports getting sizes of subset of
+ * messages, we skip this step now.
*/
- if (proto->getsizes)
+ if (proto->getsizes &&
+ !(proto->getpartialsizes && NUM_NONZERO(ctl->fetchsizelimit)))
{
+ xalloca(msgsizes, int *, sizeof(int) * count);
+ for (i = 0; i < count; i++)
+ msgsizes[i] = 0;
+
stage = STAGE_GETSIZES;
err = (proto->getsizes)(mailserver_socket, count, msgsizes);
if (err != 0)
}
}
- /* mark some messages not to be retrieved */
- for (num = 1; num <= count; num++)
- {
- if (NUM_NONZERO(ctl->limit) && (msgsizes[num-1] > ctl->limit))
- msgcodes[num-1] = MSGLEN_TOOLARGE;
- else if (ctl->fetchall || force_retrieval)
- continue;
- else if (ctl->server.base_protocol->is_old && (ctl->server.base_protocol->is_old)(mailserver_socket,ctl,num))
- msgcodes[num-1] = MSGLEN_OLD;
-/* else if (msgsizes[num-1] == 512)
- msgcodes[num-1] = MSGLEN_OLD; (hmh) sample code to skip message */
- }
-
/* read, forward, and delete messages */
stage = STAGE_FETCH;
/* fetch in lockstep mode */
err = fetch_messages(mailserver_socket, ctl,
- count, msgsizes, msgcodes,
+ count, msgsizes,
maxfetch,
&fetches, &dispatches, &deletions);
if (err)
* If no expunge limit or we do expunges within the driver,
* then just do one session, passing in any fetchlimit.
*/
- if (proto->retry || !NUM_SPECIFIED(ctl->expunge))
+ if ((ctl->keep && !ctl->flush) ||
+ proto->retry || !NUM_SPECIFIED(ctl->expunge))
return(do_session(ctl, proto, NUM_VALUE_OUT(ctl->fetchlimit)));
/*
* There's an expunge limit, and it isn't handled in the driver itself.