aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--driver.c113
-rw-r--r--fetchmail.c11
-rw-r--r--fetchmail.h1
4 files changed, 104 insertions, 24 deletions
diff --git a/NEWS b/NEWS
index a728fc9b..da408dc1 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,8 @@
fetchmail-4.6.6 ():
* Fixed a core-dump bug in reply_hack with -v -v on.
-* Fix fetchmailconf to be able to edit proprerties.
+* Fix fetchmailconf to be able to edit properties.
+* Send calling user mail when password authentication fails in daemon mode.
There are 249 people on fetchmail-friends and 309 on fetchmail-announce.
diff --git a/driver.c b/driver.c
index 6d09ff51..6016de51 100644
--- a/driver.c
+++ b/driver.c
@@ -819,7 +819,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl,
}
else
{
- /* set up sinkfp so we can deliver the message body through it */
+ /* set up stuffline() so we can deliver the message body through it */
if ((n = open_sink(ctl, return_path, xmit_names, reallen,
&good_addresses, &bad_addresses)) != PS_SUCCESS)
{
@@ -1229,15 +1229,71 @@ static void clean_skipped_list(struct idlist **skipped_list)
*skipped_list = head;
}
-static void send_warning(struct query *ctl)
+static open_warning_by_mail(struct query *ctl)
+/* set up output sink for a mailed warning to calling user */
+{
+ int good, bad;
+
+ /*
+ * We give a null address list as arg 3 because we actually *want*
+ * this message to go to run.postmaster. The zero length arg 4 means
+ * we won't pass a SIZE option to ESMTP; the message length would
+ * be more trouble than it's worth to compute.
+ */
+ return(open_sink(ctl, "FETCHMAIL-DAEMON", NULL, 0, &good, &bad));
+}
+
+#if defined(HAVE_STDARG_H)
+void stuff_warning_line(struct query *ctl, const char *fmt, ... )
+#else
+void stuff_warning_line(struct query *ctl, fmt, va_alist)
+struct query *ctl;
+const char *fmt; /* printf-style format */
+va_dcl
+#endif
+/* format and ship a warning message line by mail */
+{
+ char buf[POPBUFSIZE];
+ va_list ap;
+
+ /*
+ * stuffline() requires its input to be writeable (for CR stripping),
+ * so we needed to copy the message to a writeable buffer anyway in
+ * case it was a string constant. We make a virtue of that necessity
+ * here by supporting stdargs/varargs.
+ */
+#if defined(HAVE_STDARG_H)
+ va_start(ap, fmt) ;
+#else
+ va_start(ap);
+#endif
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+#else
+ vsprintf(buf, fmt, ap);
+#endif
+ va_end(ap);
+
+ strcat(buf, "\r\n");
+
+ stuffline(ctl, buf);
+}
+
+static close_warning_by_mail(struct query *ctl)
+/* sign and send mailed warnings */
+{
+ stuff_warning_line(ctl, "--\r\n\t\t\t\tThe Fetchmail Daemon\r\n");
+ close_sink(ctl, TRUE);
+}
+
+static void send_size_warnings(struct query *ctl)
/* send warning mail with skipped msg; reset msg count when user notified */
{
int size, nbr;
int msg_to_send = FALSE;
struct idlist *head=NULL, *current=NULL;
int max_warning_poll_count, good, bad;
-#define OVERHD "Subject: Fetchmail WARNING.\r\n\r\nThe following oversized messages remain on the mail server:\n\r\n"
- char buf[sizeof(OVERHD) + 2];
+#define OVERHD "Subject: Fetchmail oversized-messages warning.\r\n\r\nThe following oversized messages remain on the mail server:"
head = ctl->skipped;
if (!head)
@@ -1254,18 +1310,10 @@ static void send_warning(struct query *ctl)
* There's no good way to recover if we can't send notification mail,
* but it's not a disaster, either, since the skipped mail will not
* be deleted.
- *
- * We give a null address list as arg 3 because we actually *want*
- * this message to go to run.postmaster. The zero length arg 4 means
- * we won't pass a SIZE option to ESMTP; the message length would
- * be more trouble than it's worth to compute.
*/
- if (open_sink(ctl, "FETCHMAIL-DAEMON", NULL, 0, &good, &bad))
+ if (open_warning_by_mail(ctl))
return;
-
- /* stuffline() requires its input to be writeable for CR stripping */
- strcpy(buf, OVERHD);
- stuffline(ctl, buf);
+ stuff_warning_line(ctl, OVERHD);
if (run.poll_interval == 0)
max_warning_poll_count = 0;
@@ -1279,10 +1327,9 @@ static void send_warning(struct query *ctl)
{
nbr = current->val.status.mark;
size = atoi(current->id);
- sprintf(buf,
- "\t%d msg %d octets long skipped by fetchmail.\n",
+ stuff_warning_line(ctl,
+ "\t%d msg %d octets long skipped by fetchmail.",
nbr, size);
- stuffline(ctl, buf);
}
current->val.status.num++;
current->val.status.mark = 0;
@@ -1291,7 +1338,7 @@ static void send_warning(struct query *ctl)
current->val.status.num = 0;
}
- close_sink(ctl, TRUE);
+ close_warning_by_mail(ctl);
#undef OVERHD
}
@@ -1510,6 +1557,28 @@ const struct method *proto; /* protocol method table */
error(0, -1, "Authorization failure on %s@%s",
ctl->remotename,
ctl->server.truename);
+
+ /*
+ * If we're running in background, try to mail the
+ * calling user a heads-up about the authentication
+ * failure the first time it happens.
+ */
+ if (run.poll_interval && !nodetach
+ && !ctl->authfailcount && !open_warning_by_mail(ctl))
+ {
+ stuff_warning_line(ctl,
+ "Subject: fetchmail authentication failed\r\n");
+ stuff_warning_line(ctl,
+ "Fetchmail could not get mail from %s@%s.",
+ ctl->remotename,
+ ctl->server.truename);
+ stuff_warning_line(ctl,
+ "The attempt to get authorization failed.");
+ stuff_warning_line(ctl,
+ "This probably means your password is invalid.");
+ close_warning_by_mail(ctl);
+ ctl->authfailcount++;
+ }
}
goto cleanUp;
}
@@ -1925,7 +1994,7 @@ const struct method *proto; /* protocol method table */
if (!check_only && ctl->skipped)
{
clean_skipped_list(&ctl->skipped);
- send_warning(ctl);
+ send_size_warnings(ctl);
}
}
} while
@@ -2011,14 +2080,13 @@ closeUp:
#if defined(HAVE_STDARG_H)
void gen_send(int sock, const char *fmt, ... )
-/* assemble command in printf(3) style and send to the server */
#else
void gen_send(sock, fmt, va_alist)
-/* assemble command in printf(3) style and send to the server */
int sock; /* socket to which server is connected */
const char *fmt; /* printf-style format */
va_dcl
#endif
+/* assemble command in printf(3) style and send to the server */
{
char buf [MSGBUFSIZE+1];
va_list ap;
@@ -2094,14 +2162,13 @@ int size; /* length of buffer */
#if defined(HAVE_STDARG_H)
int gen_transact(int sock, const char *fmt, ... )
-/* assemble command in printf(3) style, send to server, accept a response */
#else
int gen_transact(int sock, fmt, va_alist)
-/* assemble command in printf(3) style, send to server, accept a response */
int sock; /* socket to which server is connected */
const char *fmt; /* printf-style format */
va_dcl
#endif
+/* assemble command in printf(3) style, send to server, accept a response */
{
int ok;
char buf [MSGBUFSIZE+1];
diff --git a/fetchmail.c b/fetchmail.c
index bcad08fb..0e0d3f46 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -367,6 +367,9 @@ int main (int argc, char **argv)
/* pick up interactively any passwords we need but don't have */
for (ctl = querylist; ctl; ctl = ctl->next)
+ {
+ ctl->authfailcount = 0;
+
if (ctl->active && !(implicitmode && ctl->server.skip)&&!ctl->password)
{
if (ctl->server.preauthenticate == A_KERBEROS_V4 ||
@@ -406,6 +409,7 @@ int main (int argc, char **argv)
#undef PASSWORD_PROMPT
}
}
+ }
/*
* Maybe time to go to demon mode...
@@ -481,6 +485,13 @@ int main (int argc, char **argv)
batchcount = 0;
for (ctl = querylist; ctl; ctl = ctl->next)
{
+ if (ctl->authfailcount)
+ {
+ error(0, -1,
+ "poll of %s skipped until authentication is unwedged",
+ ctl->server.pollname);
+ continue;
+ }
if (ctl->active && !(implicitmode && ctl->server.skip))
{
/* check skip interval first so that it counts all polls */
diff --git a/fetchmail.h b/fetchmail.h
index 7558984d..73e0b8ec 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -251,6 +251,7 @@ struct query
flag active; /* should we actually poll this server? */
const char *destaddr; /* destination host for this query */
int errcount; /* count transient errors in last pass */
+ int authfailcount; /* count authentication failures this run */
int smtp_socket; /* socket descriptor for SMTP connection */
unsigned int uid; /* UID of user to deliver to */
struct idlist *skipped; /* messages skipped on the mail server */