aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2003-08-06 04:31:11 +0000
committerEric S. Raymond <esr@thyrsus.com>2003-08-06 04:31:11 +0000
commit2cec9def937bc3f3b08ca1afeb9cf80413d8e4b4 (patch)
tree429c386abc29ea48315c00ef69062ca453f2679b
parenta5a7f5681a22b4e3fbdd0c4261af38cb1c064490 (diff)
downloadfetchmail-2cec9def937bc3f3b08ca1afeb9cf80413d8e4b4.tar.gz
fetchmail-2cec9def937bc3f3b08ca1afeb9cf80413d8e4b4.tar.bz2
fetchmail-2cec9def937bc3f3b08ca1afeb9cf80413d8e4b4.zip
Ready to ship.
svn path=/trunk/; revision=3831
-rw-r--r--NEWS7
-rw-r--r--driver.c96
-rw-r--r--fetchmail-FAQ.html11
-rw-r--r--fetchmail.h8
-rwxr-xr-xfetchmailconf7
-rw-r--r--imap.c103
-rw-r--r--pop3.c27
-rw-r--r--rcfile_l.l2
-rw-r--r--sink.c30
-rw-r--r--smtp.c12
-rw-r--r--smtp.h4
-rw-r--r--socket.c7
-rw-r--r--transact.c101
-rw-r--r--uid.c19
14 files changed, 274 insertions, 160 deletions
diff --git a/NEWS b/NEWS
index e9065374..c8745dac 100644
--- a/NEWS
+++ b/NEWS
@@ -2,9 +2,14 @@
(The `lines' figures total .c, .h, .l, and .y files under version control.)
-* Updated German and Turkish translations.
+* Updated German, Spanish, Catalan, and Turkish translations.
* IDLE is now supported using no-ops even if the server doesn't support
the IMAP IDLE extension.
+* Sunil Shetye's patch to do better password shrouding.
+* Sunil Shetye's bug-fix rollup patch.
+* Introduce a translation item for the word "seen".
+* Back out the hack to deal with lack of byte stuffing on some POP3 servers.
+* Thomas Steudten's patch to improve SMTP handling of 550 errors.
fetchmail-6.2.3 (Thu Jul 17 14:53:00 EDT 2003), 22490 lines:
diff --git a/driver.c b/driver.c
index 03f53867..f0946e18 100644
--- a/driver.c
+++ b/driver.c
@@ -69,8 +69,8 @@ int batchcount; /* count of messages sent in current batch */
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? */
+volatile static int timeoutcount = 0; /* count consecutive timeouts */
+volatile static int idletimeout = 0; /* timeout occured in idle stage? */
static jmp_buf restart;
@@ -80,6 +80,11 @@ int isidletimeout(void)
return idletimeout;
}
+void resetidletimeout(void)
+{
+ idletimeout = 0;
+}
+
void set_timeout(int timeleft)
/* reset the nonresponse-timeout */
{
@@ -89,8 +94,6 @@ void set_timeout(int timeleft)
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;
@@ -428,7 +431,10 @@ static int fetch_messages(int mailserver_socket, struct query *ctl,
if (msgcodes[num-1] < 0)
{
if ((msgcodes[num-1] == MSGLEN_TOOLARGE) && !check_only)
+ {
mark_oversized(ctl, num, msgsizes[num-1]);
+ suppress_delete = TRUE;
+ }
/* To avoid flooding the syslog when using --keep,
* report "Skipped message" only when:
* 1) --verbose is on, or
@@ -468,6 +474,7 @@ static int fetch_messages(int mailserver_socket, struct query *ctl,
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);
@@ -509,39 +516,23 @@ static int fetch_messages(int mailserver_socket, struct query *ctl,
* output sink.
*/
err = readheaders(mailserver_socket, len, msgsizes[num-1],
- ctl, num);
+ 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;
- suppress_readbody = TRUE;
- }
else if (err == PS_TRANSIENT)
- {
suppress_delete = suppress_forward = TRUE;
- suppress_readbody = TRUE;
- }
else if (err == PS_REFUSED)
- {
suppress_forward = TRUE;
- suppress_readbody = TRUE;
- }
else if (err == PS_TRUNCATED)
- {
suppress_readbody = TRUE;
- len = 0; /* suppress body processing */
- }
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))
{
@@ -551,9 +542,27 @@ static int fetch_messages(int mailserver_socket, struct query *ctl,
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);
/*
@@ -569,22 +578,12 @@ static int fetch_messages(int mailserver_socket, struct query *ctl,
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)
@@ -669,7 +668,8 @@ static int fetch_messages(int mailserver_socket, struct query *ctl,
}
else if (ctl->server.base_protocol->delete
&& !suppress_delete
- && ((msgcodes[num-1] >= 0) ? !ctl->keep : ctl->flush))
+ && ((msgcodes[num-1] >= 0 && !ctl->keep)
+ || (msgcodes[num-1] == MSGLEN_OLD && ctl->flush)))
{
(*deletions)++;
if (outlevel > O_SILENT)
@@ -704,7 +704,7 @@ static int fetch_messages(int mailserver_socket, struct query *ctl,
}
/* 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"),
maxfetch, count - *fetches, ctl->server.truename, ctl->remotename);
@@ -1260,10 +1260,12 @@ is restored."));
else if (count != 0)
{
if (new != -1 && (count - new) > 0)
- report_build(stdout, GT_("%d %s (%d seen) for %s"),
+ report_build(stdout, GT_("%d %s (%d %s) for %s"),
count, count > 1 ? GT_("messages") :
GT_("message"),
- count-new, buf);
+ count-new,
+ GT_("seen"),
+ buf);
else
report_build(stdout, GT_("%d %s for %s"),
count, count > 1 ? GT_("messages") :
diff --git a/fetchmail-FAQ.html b/fetchmail-FAQ.html
index 20db7abf..21f2346e 100644
--- a/fetchmail-FAQ.html
+++ b/fetchmail-FAQ.html
@@ -16,7 +16,7 @@ content="Frequently asked questions about fetchmail."/>
Page</a></td>
<td width="30%" align="center">To <a href="/~esr/sitemap.html">Site
Map</a></td>
-<td width="30%" align="right">$Date: 2003/07/22 02:09:43 $</td>
+<td width="30%" align="right">$Date: 2003/08/06 04:31:10 $</td>
</tr>
</table>
@@ -2002,9 +2002,12 @@ next cycle.</p>
<h2><a id="I8" name="I8">I8. How can I use fetchmail with comcast.net?</a></h2>
<p>Stock fetchmail will work with a comcast.net server...<em>but</em>
-they seem to have an 80K limit on the length of downloaded messages.
+the Maillennium POP3 server comcat uses seems to have an 80K limit on
+the length of downloaded messages if you use POP3 TOP to retrieve.
Anything larger is silently truncated. Don't mistake this for a
-fetchmail bug.</p>
+fetchmail bug. (Reported July 2003.)</p>
+
+<p>Workaround: use the <tt>fetchall</tt> option.</p>
<hr/>
<h2><a id="K1" name="K1">K1. How can I use fetchmail with SOCKS?</a></h2>
@@ -3473,7 +3476,7 @@ does something like "date >> $HOME/Procmail/fetchmail.log".</p>
Page</a></td>
<td width="30%" align="center">To <a href="/~esr/sitemap.html">Site
Map</a></td>
-<td width="30%" align="right">$Date: 2003/07/22 02:09:43 $</td>
+<td width="30%" align="right">$Date: 2003/08/06 04:31:10 $</td>
</tr>
</table>
diff --git a/fetchmail.h b/fetchmail.h
index 627048f4..edcb57c8 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -94,7 +94,6 @@
#define PS_BSMTP 12 /* output batch could not be opened */
#define PS_MAXFETCH 13 /* poll ended by fetch limit */
#define PS_SERVBUSY 14 /* server is busy */
-#define PS_IDLETIMEOUT 15 /* timeout on imap IDLE */
/* leave space for more codes */
#define PS_UNDEFINED 23 /* something I hadn't thought of */
#define PS_TRANSIENT 24 /* transient failure (internal use) */
@@ -102,6 +101,7 @@
#define PS_RETAINED 26 /* message retained (internal use) */
#define PS_TRUNCATED 27 /* headers incomplete (internal use) */
#define PS_REPOLL 28 /* repoll immediately with changed parameters (internal use) */
+#define PS_IDLETIMEOUT 29 /* timeout on imap IDLE (internal use) */
/* output noise level */
#define O_SILENT 0 /* mute, max squelch, etc. */
@@ -391,7 +391,7 @@ extern int pass; /* number of re-polling pass */
extern flag configdump; /* dump control blocks as Python dictionary */
extern char *fetchmailhost; /* either "localhost" or an FQDN */
extern int suppress_tags; /* suppress tags in tagged protocols? */
-extern char shroud[PASSWORDLEN*2+1]; /* string to shroud in debug output */
+extern char shroud[PASSWORDLEN*2+3]; /* string to shroud in debug output */
#ifdef SDPS_ENABLE
extern char *sdps_envfrom;
extern char *sdps_envto;
@@ -429,6 +429,7 @@ void report_at_line ();
/* driver.c -- main driver loop */
void set_timeout(int);
int isidletimeout(void);
+void resetidletimeout(void);
int do_protocol(struct query *, const struct method *);
/* transact.c: transaction support */
@@ -437,7 +438,8 @@ int readheaders(int sock,
long fetchlen,
long reallen,
struct query *ctl,
- int num);
+ int num,
+ flag *suppress_readbody);
int readbody(int sock, struct query *ctl, flag forward, int len);
#if defined(HAVE_STDARG_H)
void gen_send(int sock, const char *, ... )
diff --git a/fetchmailconf b/fetchmailconf
index 86ab9445..88564c56 100755
--- a/fetchmailconf
+++ b/fetchmailconf
@@ -1236,6 +1236,13 @@ It is strongly recommended that you find a better POP3 server. The fetchmail
FAQ includes pointers to good ones.
"""
+ if string.find(greetline, "comcast.net") > 0:
+ warnings = warnings + """
+The Comcast Maillennium POP3 server only returns the first 80K of a long
+message retrieved with TOP. Its response to RETR is normal, so use the
+`fetchall' option.
+
+"""
# Steve VanDevender <stevev@efn.org> writes:
# The only system I have seen this happen with is cucipop-1.31
# under SunOS 4.1.4. cucipop-1.31 runs fine on at least Solaris
diff --git a/imap.c b/imap.c
index 9154620d..fac7cae0 100644
--- a/imap.c
+++ b/imap.c
@@ -306,6 +306,8 @@ static void capa_probe(int sock, struct query *ctl)
if (outlevel >= O_VERBOSE)
report(stdout, GT_("will idle after poll\n"));
}
+
+ peek_capable = (imap_version >= IMAP4);
}
static int imap_getauth(int sock, struct query *ctl, char *greeting)
@@ -316,6 +318,15 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
flag did_stls = FALSE;
#endif /* SSL_ENABLE */
+ /*
+ * Assumption: expunges are cheap, so we want to do them
+ * after every message unless user said otherwise.
+ */
+ if (NUM_SPECIFIED(ctl->expunge))
+ expunge_period = NUM_VALUE_OUT(ctl->expunge);
+ else
+ expunge_period = 1;
+
capa_probe(sock, ctl);
/*
@@ -327,44 +338,6 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
preauth = FALSE; /* reset for the next session */
return(PS_SUCCESS);
}
- /*
- * Time to authenticate the user.
- * Try the protocol variants that don't require passwords first.
- */
- ok = PS_AUTHFAIL;
-
-#ifdef GSSAPI
- if ((ctl->server.authenticate == A_ANY
- || ctl->server.authenticate == A_GSSAPI)
- && strstr(capabilities, "AUTH=GSSAPI"))
- if(ok = do_gssauth(sock, "AUTHENTICATE", ctl->server.truename, ctl->remotename))
- {
- /* SASL cancellation of authentication */
- gen_send(sock, "*");
- if(ctl->server.authenticate != A_ANY)
- return ok;
- }
- else
- return ok;
-#endif /* GSSAPI */
-
-#ifdef KERBEROS_V4
- if ((ctl->server.authenticate == A_ANY
- || ctl->server.authenticate == A_KERBEROS_V4
- || ctl->server.authenticate == A_KERBEROS_V5)
- && strstr(capabilities, "AUTH=KERBEROS_V4"))
- {
- if ((ok = do_rfc1731(sock, "AUTHENTICATE", ctl->server.truename)))
- {
- /* SASL cancellation of authentication */
- gen_send(sock, "*");
- if(ctl->server.authenticate != A_ANY)
- return ok;
- }
- else
- return ok;
- }
-#endif /* KERBEROS_V4 */
#ifdef SSL_ENABLE
if ((!ctl->sslproto || !strcmp(ctl->sslproto,"tls1"))
@@ -408,16 +381,44 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
}
#endif /* SSL_ENABLE */
- peek_capable = (imap_version >= IMAP4);
-
- /*
- * Assumption: expunges are cheap, so we want to do them
- * after every message unless user said otherwise.
+ /*
+ * Time to authenticate the user.
+ * Try the protocol variants that don't require passwords first.
*/
- if (NUM_SPECIFIED(ctl->expunge))
- expunge_period = NUM_VALUE_OUT(ctl->expunge);
- else
- expunge_period = 1;
+ ok = PS_AUTHFAIL;
+
+#ifdef GSSAPI
+ if ((ctl->server.authenticate == A_ANY
+ || ctl->server.authenticate == A_GSSAPI)
+ && strstr(capabilities, "AUTH=GSSAPI"))
+ if(ok = do_gssauth(sock, "AUTHENTICATE", ctl->server.truename, ctl->remotename))
+ {
+ /* SASL cancellation of authentication */
+ gen_send(sock, "*");
+ if(ctl->server.authenticate != A_ANY)
+ return ok;
+ }
+ else
+ return ok;
+#endif /* GSSAPI */
+
+#ifdef KERBEROS_V4
+ if ((ctl->server.authenticate == A_ANY
+ || ctl->server.authenticate == A_KERBEROS_V4
+ || ctl->server.authenticate == A_KERBEROS_V5)
+ && strstr(capabilities, "AUTH=KERBEROS_V4"))
+ {
+ if ((ok = do_rfc1731(sock, "AUTHENTICATE", ctl->server.truename)))
+ {
+ /* SASL cancellation of authentication */
+ gen_send(sock, "*");
+ if(ctl->server.authenticate != A_ANY)
+ return ok;
+ }
+ else
+ return ok;
+ }
+#endif /* KERBEROS_V4 */
/*
* No such luck. OK, now try the variants that mask your password
@@ -506,7 +507,13 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
imap_canonicalize(remotename, ctl->remotename, NAMELEN);
imap_canonicalize(password, ctl->password, PASSWORDLEN);
- strcpy(shroud, password);
+#ifdef HAVE_SNPRINTF
+ snprintf(shroud, sizeof (shroud), "\"%s\"", password);
+#else
+ strcpy(shroud, "\"");
+ strcat(shroud, password);
+ strcat(shroud, "\"");
+#endif
ok = gen_transact(sock, "LOGIN \"%s\" \"%s\"", remotename, password);
shroud[0] = '\0';
#ifdef SSL_ENABLE
diff --git a/pop3.c b/pop3.c
index 1c06c207..3d894160 100644
--- a/pop3.c
+++ b/pop3.c
@@ -224,6 +224,17 @@ static int capa_probe(sock)
{
int ok;
+#if defined(GSSAPI)
+ has_gssapi = FALSE;
+#endif /* defined(GSSAPI) */
+#if defined(KERBEROS_V4) || defined(KERBEROS_V5)
+ has_kerberos = FALSE;
+#endif /* defined(KERBEROS_V4) || defined(KERBEROS_V5) */
+ has_cram = FALSE;
+#ifdef OPIE_ENABLE
+ has_otp = FALSE;
+#endif /* OPIE_ENABLE */
+
ok = gen_transact(sock, "CAPA");
if (ok == PS_SUCCESS)
{
@@ -270,6 +281,20 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
flag did_stls = FALSE;
#endif /* SSL_ENABLE */
+#if defined(GSSAPI)
+ has_gssapi = FALSE;
+#endif /* defined(GSSAPI) */
+#if defined(KERBEROS_V4) || defined(KERBEROS_V5)
+ has_kerberos = FALSE;
+#endif /* defined(KERBEROS_V4) || defined(KERBEROS_V5) */
+ has_cram = FALSE;
+#ifdef OPIE_ENABLE
+ has_otp = FALSE;
+#endif /* OPIE_ENABLE */
+#ifdef SSL_ENABLE
+ has_ssl = FALSE;
+#endif /* SSL_ENABLE */
+
if (ctl->server.authenticate == A_SSH) {
return PS_SUCCESS;
}
@@ -342,7 +367,7 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
*/
if (ctl->server.authenticate == A_ANY)
{
- if (capa_probe(sock) != PS_SUCCESS)
+ if ((ok = capa_probe(sock)) != PS_SUCCESS)
/* we are in STAGE_GETAUTH! */
if (ok == PS_AUTHFAIL ||
/* Some servers directly close the socket. However, if we
diff --git a/rcfile_l.l b/rcfile_l.l
index bf5379a2..3650ca5a 100644
--- a/rcfile_l.l
+++ b/rcfile_l.l
@@ -199,7 +199,7 @@ options {/* EMPTY */}
(#.*)?\\?\n { prc_lineno++; } /* newline is ignored */
--?[0-9]+/[^a-zA-Z] { yylval.number = atoi(yytext); return NUMBER; }
+-?[0-9]+ { yylval.number = atoi(yytext); return NUMBER; }
[^=;:, \t\r\n]+ {
char buf[MSGBUFSIZE];
diff --git a/sink.c b/sink.c
index a8395661..6f437532 100644
--- a/sink.c
+++ b/sink.c
@@ -73,6 +73,11 @@ int smtp_open(struct query *ctl)
char *parsed_host = NULL;
/* maybe it's time to close the socket in order to force delivery */
+ if (last_smtp_ok > 0 && time((time_t *)NULL) - last_smtp_ok > mytimeout)
+ {
+ smtp_close(ctl, 1);
+ last_smtp_ok = 0;
+ }
if (NUM_NONZERO(ctl->batchlimit)) {
if (batchcount == ctl->batchlimit)
smtp_close(ctl, 1);
@@ -270,7 +275,7 @@ static int send_bouncemail(struct query *ctl, struct msgblk *msg,
strcmp(msg->return_path, "<>") == 0 ||
strcasecmp(msg->return_path, md1) == 0 ||
strncasecmp(msg->return_path, md2, strlen(md2)) == 0)
- return(FALSE);
+ return(TRUE);
bounce_to = (run.bouncemail ? msg->return_path : run.postmaster);
@@ -406,6 +411,8 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg)
{
int smtperr = atoi(smtp_response);
char *responses[1];
+ struct idlist *walk;
+ int found = 0;
xalloca(responses[0], char *, strlen(smtp_response)+1);
strcpy(responses[0], smtp_response);
@@ -430,7 +437,15 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg)
* messages, which are probably in English (none of the
* MTAs I know about are internationalized).
*/
- if (str_find(&ctl->antispam, smtperr))
+ for( walk = ctl->antispam; walk; walk = walk->next )
+ if ( walk->val.status.num == smtperr )
+ {
+ found=1;
+ break;
+ }
+
+ /* if (str_find(&ctl->antispam, smtperr)) */
+ if ( found )
{
/*
* SMTP listener explicitly refuses to deliver mail
@@ -511,10 +526,12 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg)
default:
/* bounce non-transient errors back to the sender */
if (smtperr >= 500 && smtperr <= 599)
- if (send_bouncemail(ctl, msg, XMIT_ACCEPT,
+ {
+ send_bouncemail(ctl, msg, XMIT_ACCEPT,
"General SMTP/ESMTP error.\r\n",
- 1, responses))
- return(run.bouncemail ? PS_REFUSED : PS_TRANSIENT);
+ 1, responses);
+ return(PS_REFUSED);
+ }
/*
* We're going to end up here on 4xx errors, like:
*
@@ -847,6 +864,9 @@ static int open_smtp_sink(struct query *ctl, struct msgblk *msg,
}
else if (strchr(msg->return_path,'@') || strchr(msg->return_path,'!'))
ap = msg->return_path;
+ /* in case Return-Path was "<>" we want to preserve that */
+ else if (strcmp(msg->return_path,"<>") == 0)
+ ap = msg->return_path;
else /* in case Return-Path existed but was local */
{
if (is_dottedquad(ctl->server.truename))
diff --git a/smtp.c b/smtp.c
index c3fdaa68..fd987950 100644
--- a/smtp.c
+++ b/smtp.c
@@ -87,7 +87,7 @@ static void SMTP_auth(int sock, char *username, char *password, char *buf)
SockPrintf(sock, "AUTH CRAM-MD5\r\n");
SockRead(sock, smtp_response, sizeof(smtp_response) - 1);
strncpy(tmp, smtp_response, sizeof(tmp));
- tmp[sizeof(tmp)-1] == '\0';
+ tmp[sizeof(tmp)-1] = '\0';
if (strncmp(tmp, "334 ", 4)) { /* Server rejects AUTH */
SMTP_auth_error(sock, GT_("Server rejected the AUTH command.\n"));
@@ -147,7 +147,7 @@ static void SMTP_auth(int sock, char *username, char *password, char *buf)
SockPrintf(sock, "AUTH LOGIN\r\n");
SockRead(sock, smtp_response, sizeof(smtp_response) - 1);
strncpy(tmp, smtp_response, sizeof(tmp));
- tmp[sizeof(tmp)-1] == '\0';
+ tmp[sizeof(tmp)-1] = '\0';
if (strncmp(tmp, "334 ", 4)) { /* Server rejects AUTH */
SMTP_auth_error(sock, GT_("Server rejected the AUTH command.\n"));
@@ -164,7 +164,7 @@ static void SMTP_auth(int sock, char *username, char *password, char *buf)
SockPrintf(sock, "%s\r\n", b64buf);
SockRead(sock, smtp_response, sizeof(smtp_response) - 1);
strncpy(tmp, smtp_response, sizeof(tmp));
- tmp[sizeof(tmp)-1] == '\0';
+ tmp[sizeof(tmp)-1] = '\0';
p = strchr(tmp, ' ');
if (!p) {
SMTP_auth_error(sock, GT_("Bad base64 reply from server.\n"));
@@ -213,7 +213,7 @@ int SMTP_ehlo(int sock, const char *host, char *name, char *password, int *opt)
*opt |= hp->value;
if (strncmp(hp->name, "AUTH ", 5) == 0)
strncpy(auth_response, smtp_response, sizeof(auth_response));
- auth_response[sizeof(auth_response)-1] == '\0';
+ auth_response[sizeof(auth_response)-1] = '\0';
}
if ((smtp_response[0] == '1' || smtp_response[0] == '2' || smtp_response[0] == '3') && smtp_response[3] == ' ') {
if (*opt & ESMTP_AUTH)
@@ -327,6 +327,8 @@ int SMTP_eom(int sock)
return ok;
}
+time_t last_smtp_ok = 0;
+
int SMTP_ok(int sock)
/* returns status of SMTP connection */
{
@@ -360,6 +362,8 @@ int SMTP_ok(int sock)
return SM_UNRECOVERABLE;
}
+ last_smtp_ok = time((time_t *) NULL);
+
if ((smtp_response[0] == '1' || smtp_response[0] == '2' || smtp_response[0] == '3') &&
smtp_response[3] == ' ')
return SM_OK;
diff --git a/smtp.h b/smtp.h
index 8d27049b..ef5d03d3 100644
--- a/smtp.h
+++ b/smtp.h
@@ -7,6 +7,8 @@
#ifndef _POPSMTP_
#define _POPSMTP_
+#include <time.h>
+
#define SMTPBUFSIZE 256
/* SMTP error values */
@@ -21,6 +23,8 @@
#define ESMTP_ATRN 0x08 /* used with ODMR, RFC 2645 */
#define ESMTP_AUTH 0x10
+extern time_t last_smtp_ok;
+
void SMTP_setmode(char);
int SMTP_helo(int socket,const char *host);
int SMTP_ehlo(int socket,const char *host, char *name, char *passwd, int *opt);
diff --git a/socket.c b/socket.c
index 5f295a04..cc3c679e 100644
--- a/socket.c
+++ b/socket.c
@@ -637,8 +637,10 @@ int SockRead(int sock, char *buf, int len)
} while
(!newline && len);
*bp = '\0';
+
+#ifdef FORCE_STUFFING /* too ugly to live -- besides, there's IMAP */
/* OK, very weird hack coming up here:
- * When POP and IMAP servers send us a message, they're supposed to
+ * When POP3 servers send us a message, they're supposed to
* terminate the message with a line containing only a dot. To protect
* against lines in the real message that might contain only a dot,
* they're supposed to preface any line that starts with a dot with
@@ -675,6 +677,7 @@ int SockRead(int sock, char *buf, int len)
buf[0] = '.';
bp++;
}
+#endif /* FORCE_STUFFING */
return bp - buf;
}
@@ -973,7 +976,7 @@ int SSLOpen(int sock, char *mycert, char *mykey, char *myproto, int certck, char
SSL_set_fd(_ssl_context[sock], sock);
- if(SSL_connect(_ssl_context[sock]) == -1) {
+ if(SSL_connect(_ssl_context[sock]) < 1) {
ERR_print_errors_fp(stderr);
return(-1);
}
diff --git a/transact.c b/transact.c
index 0d6151fe..69053b56 100644
--- a/transact.c
+++ b/transact.c
@@ -40,7 +40,7 @@ extern char *strstr(); /* needed on sysV68 R3V7.1. */
int mytimeout; /* value of nonreponse timeout */
int suppress_tags; /* emit tags? */
-char shroud[PASSWORDLEN*2+1]; /* string to shroud in debug output */
+char shroud[PASSWORDLEN*2+3]; /* string to shroud in debug output */
struct msgblk msgblk;
char tag[TAGLEN];
@@ -352,13 +352,15 @@ int readheaders(int sock,
long fetchlen,
long reallen,
struct query *ctl,
- int num)
+ int num,
+ flag *suppress_readbody)
/* read message headers and ship to SMTP or MDA */
/* sock: to which the server is connected */
/* fetchlen: length of message according to fetch response */
/* reallen: length of message according to getsizes */
/* ctl: query control record */
/* num: index of message */
+/* suppress_readbody: whether call to readbody() should be supressed */
{
struct addrblk
{
@@ -379,13 +381,13 @@ int readheaders(int sock,
int n, linelen, oldlen, ch, remaining, skipcount;
struct idlist *idp;
flag no_local_matches = FALSE;
- flag headers_ok, has_nuls;
+ flag has_nuls;
int olderrs, good_addresses, bad_addresses;
- int retain_mail = 0;
+ int retain_mail = 0, refuse_mail = 0;
flag already_has_return_path = FALSE;
sizeticker = 0;
- has_nuls = headers_ok = FALSE;
+ has_nuls = FALSE;
msgblk.return_path[0] = '\0';
olderrs = ctl->errcount;
@@ -419,7 +421,7 @@ int readheaders(int sock,
for (remaining = fetchlen; remaining > 0 || protocol->delimited; )
{
- char *line;
+ char *line, *rline;
int overlong = FALSE;
line = xmalloc(sizeof(buf));
@@ -446,7 +448,13 @@ int readheaders(int sock,
*/
if ( n && buf[n-1] != '\n' ) {
overlong = TRUE;
- line = realloc(line, linelen);
+ rline = (char *) realloc(line, linelen);
+ if (rline == NULL)
+ {
+ free (line);
+ return(PS_IOERR);
+ }
+ line = rline;
memcpy(line + linelen - n, buf, n);
ch = ' '; /* So the next iteration starts */
continue;
@@ -458,7 +466,13 @@ int readheaders(int sock,
if (ctl->forcecr && buf[n-1] == '\n' && (n == 1 || buf[n-2] != '\r'))
{
char * tcp;
- line = (char *) realloc(line, linelen + 2);
+ rline = (char *) realloc(line, linelen + 2);
+ if (rline == NULL)
+ {
+ free (line);
+ return(PS_IOERR);
+ }
+ line = rline;
memcpy(line + linelen - n, buf, n - 1);
tcp = line + linelen - 1;
*tcp++ = '\r';
@@ -469,15 +483,21 @@ int readheaders(int sock,
}
else
{
- line = (char *) realloc(line, linelen + 1);
+ rline = (char *) realloc(line, linelen + 1);
+ if (rline == NULL)
+ {
+ free (line);
+ return(PS_IOERR);
+ }
+ line = rline;
memcpy(line + linelen - n, buf, n + 1);
}
/* check for end of headers */
if (end_of_header(line))
{
- headers_ok = TRUE;
- has_nuls = (linelen != strlen(line));
+ if (linelen != strlen (line))
+ has_nuls = TRUE;
free(line);
goto process_headers;
}
@@ -489,8 +509,13 @@ int readheaders(int sock,
*/
if (protocol->delimited && line[0] == '.' && EMPTYLINE(line+1))
{
- headers_ok = FALSE;
- has_nuls = (linelen != strlen(line));
+ if (outlevel > O_SILENT)
+ report(stdout,
+ GT_("message delimiter found while scanning headers\n"));
+ if (suppress_readbody)
+ *suppress_readbody = TRUE;
+ if (linelen != strlen (line))
+ has_nuls = TRUE;
free(line);
goto process_headers;
}
@@ -499,17 +524,18 @@ int readheaders(int sock,
* At least one brain-dead website (netmind.com) is known to
* send out robotmail that's missing the RFC822 delimiter blank
* line before the body! Without this check fetchmail segfaults.
- * With it, we treat such messages as though they had the missing
- * blank line.
+ * With it, we treat such messages as spam and refuse them.
*/
- if (!isspace(line[0]) && !strchr(line, ':'))
+ if (!refuse_mail && !isspace(line[0]) && !strchr(line, ':'))
{
- headers_ok = FALSE;
- has_nuls = (linelen != strlen(line));
+ if (linelen != strlen (line))
+ has_nuls = TRUE;
if (outlevel > O_SILENT)
report(stdout,
GT_("incorrect header line found while scanning headers\n"));
- goto process_headers;
+ if (outlevel >= O_VERBOSE)
+ report (stdout, GT_("line: %s"), line);
+ refuse_mail = 1;
}
/* check for RFC822 continuations */
@@ -550,8 +576,16 @@ int readheaders(int sock,
}
+ /* skip processing if we are going to retain or refuse this mail */
+ if (retain_mail || refuse_mail)
+ {
+ free(line);
+ continue;
+ }
+
/* we see an ordinary (non-header, non-message-delimiter line */
- has_nuls = (linelen != strlen(line));
+ if (linelen != strlen (line))
+ has_nuls = TRUE;
/* save the message's ID, we may use it for killing duplicates later */
if (MULTIDROP(ctl) && !strncasecmp(line, "Message-ID:", 11))
@@ -691,6 +725,8 @@ int readheaders(int sock,
if ((already_has_return_path==FALSE) && !strncasecmp("Return-Path:", line, 12) && (cp = nxtaddr(line)))
{
already_has_return_path = TRUE;
+ if (cp[0]=='\0') /* nxtaddr() strips the brackets... */
+ cp="<>";
strncpy(msgblk.return_path, cp, sizeof(msgblk.return_path));
msgblk.return_path[sizeof(msgblk.return_path)-1] = '\0';
if (!ctl->mda) {
@@ -701,9 +737,10 @@ int readheaders(int sock,
if (!msgblk.headers)
{
- oldlen = strlen(line);
+ oldlen = linelen;
msgblk.headers = xmalloc(oldlen + 1);
- (void) strcpy(msgblk.headers, line);
+ (void) memcpy(msgblk.headers, line, linelen);
+ msgblk.headers[oldlen] = '\0';
free(line);
line = msgblk.headers;
}
@@ -712,14 +749,15 @@ int readheaders(int sock,
char *newhdrs;
int newlen;
- newlen = oldlen + strlen(line);
+ newlen = oldlen + linelen;
newhdrs = (char *) realloc(msgblk.headers, newlen + 1);
if (newhdrs == NULL) {
free(line);
return(PS_IOERR);
}
msgblk.headers = newhdrs;
- strcpy(msgblk.headers + oldlen, line);
+ memcpy(msgblk.headers + oldlen, line, linelen);
+ msgblk.headers[newlen] = '\0';
free(line);
line = msgblk.headers + oldlen;
oldlen = newlen;
@@ -831,6 +869,8 @@ int readheaders(int sock,
msgblk.headers = NULL;
return(PS_RETAINED);
}
+ if (refuse_mail)
+ return(PS_REFUSED);
/*
* When mail delivered to a multidrop mailbox on the server is
* addressed to multiple people on the client machine, there will
@@ -1255,14 +1295,6 @@ int readheaders(int sock,
*cp++ = '\0';
stuffline(ctl, buf);
- if (!headers_ok)
- {
- if (outlevel > O_SILENT)
- report(stdout,
- GT_("message delimiter found while scanning headers\n"));
- return(PS_TRUNCATED);
- }
-
return(PS_SUCCESS);
}
@@ -1390,7 +1422,7 @@ static void enshroud(char *buf)
char *sp;
sp = cp + strlen(shroud);
- *cp = '*';
+ *cp++ = '*';
while (*sp)
*cp++ = *sp++;
*cp = '\0';
@@ -1457,7 +1489,10 @@ int size; /* length of buffer */
set_timeout(0);
phase = oldphase;
if(isidletimeout())
+ {
+ resetidletimeout();
return(PS_IDLETIMEOUT);
+ }
else
return(PS_SOCKET);
}
diff --git a/uid.c b/uid.c
index 93fe8d26..afc49678 100644
--- a/uid.c
+++ b/uid.c
@@ -135,19 +135,16 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
* espescially if the POP server returns an X-UIDL header
* instead of a Message-ID, as GMX's (www.gmx.net) POP3
* StreamProxy V1.0 does.
+ *
+ * this is one other trick. The userhost part
+ * may contain ' ' in the user part, at least in
+ * the lotus notes case.
+ * So we start looking for the '@' after which the
+ * host will follow with the ' ' seperator finaly id.
*/
- if ((id = strchr(user, ' ')) != NULL )
+ if ((delimp1 = strchr(user, '@')) != NULL &&
+ (id = strchr(delimp1,' ')) != NULL)
{
-
- /*
- * this is one other trick. The userhost part
- * may contain ' ' in the user part, at least in
- * the lotus notes case.
- * So we start looking for the '@' after which the
- * host will follow with the ' ' seperator finaly id.
- */
- delimp1 = strchr(user, '@');
- id = strchr(delimp1,' ');
for (delimp1 = id; delimp1 >= user; delimp1--)
if ((*delimp1 != ' ') && (*delimp1 != '\t'))
break;