aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Andree <matthias.andree@gmx.de>2010-01-28 00:16:07 +0000
committerMatthias Andree <matthias.andree@gmx.de>2010-01-28 00:16:07 +0000
commit6827f405d1239ba41e62181c88ab6cff51ca44f8 (patch)
treef9214cbdfeb7919d6588e1d378c079c172e0d6b6
parentca66045dfe48faa985f39c0208aded9f93d3da96 (diff)
downloadfetchmail-6827f405d1239ba41e62181c88ab6cff51ca44f8.tar.gz
fetchmail-6827f405d1239ba41e62181c88ab6cff51ca44f8.tar.bz2
fetchmail-6827f405d1239ba41e62181c88ab6cff51ca44f8.zip
Recover from SMTP protocol errors on RSET. (Sunil Shetye)
Apply patch from Sunil Shetye to fix a problem reported by James Moe. Before this fix, fetchmail's SMTP client would not recover from errors such as lost connections that were encountered when fetchmail had sent RSET, for instance, after an anti-spam filter dropped the connection after detecting spam. Fetchmail then tried to send subsequent mail through this broken connection and deferred retrieval until the next poll. Now, if RSET fails, fetchmail closes the connection and reopens it for the next message to be delivered. svn path=/branches/BRANCH_6-3/; revision=5463
-rw-r--r--NEWS3
-rw-r--r--sink.c27
2 files changed, 22 insertions, 8 deletions
diff --git a/NEWS b/NEWS
index 92e130f2..4f057990 100644
--- a/NEWS
+++ b/NEWS
@@ -58,6 +58,9 @@ fetchmail 6.3.14 (not yet released):
Fix by Sunil Shetye (the fix also consolidates IMAP response handling,
improving overall robustness of the IMAP client), bug report and testing by
Matt Doran, with further hints from Timo Sirainen.
+* The SMTP client now recovers from errors (such as servers dropping the
+ connection after errors) when sending an RSET command.
+ Fix by Sunil Shetye. Report by James Moe.
# CHANGES
* Only include gssapi.h if we're not including gssapi/gssapi.h, to fix a FreeBSD
diff --git a/sink.c b/sink.c
index 3db9def4..703bea58 100644
--- a/sink.c
+++ b/sink.c
@@ -65,6 +65,17 @@ void smtp_close(struct query *ctl, int sayquit)
batchcount = 0;
}
+void smtp_rset(struct query *ctl)
+/* reset the mail transaction */
+{
+ if (SMTP_rset(ctl->smtp_socket, ctl->smtphostmode) == SM_UNRECOVERABLE)
+ {
+ /* close the bad connection. fetchmail will reconnect for the
+ * next mail */
+ smtp_close(ctl, 0);
+ }
+}
+
int smtp_open(struct query *ctl)
/* try to open a socket to the appropriate SMTP server for this query */
{
@@ -441,7 +452,7 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg)
* RSET discards the message body and it doesn't get sent to the
* valid recipients.
*/
- SMTP_rset(ctl->smtp_socket); /* stay on the safe side */
+ smtp_rset(ctl); /* stay on the safe side */
if (outlevel >= O_DEBUG)
report(stdout, GT_("Saved error is still %d\n"), smtperr);
#endif /* __UNUSED */
@@ -938,7 +949,7 @@ static int open_smtp_sink(struct query *ctl, struct msgblk *msg,
{
int err = handle_smtp_report(ctl, msg); /* map to PS_TRANSIENT or PS_REFUSED */
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* stay on the safe side */
+ smtp_rset(ctl); /* stay on the safe side */
return(err);
}
@@ -1006,7 +1017,7 @@ transient:
* crap. If one of the recipients returned PS_TRANSIENT,
* we return exactly that.
*/
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* required by RFC1870 */
+ smtp_rset(ctl); /* required by RFC1870 */
goto transient;
}
#ifdef EXPLICIT_BOUNCE_ON_BAD_ADDRESS
@@ -1041,7 +1052,7 @@ transient:
{
if (outlevel >= O_VERBOSE)
report(stderr, GT_("no address matches; no postmaster set.\n"));
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* required by RFC1870 */
+ smtp_rset(ctl); /* required by RFC1870 */
return(PS_REFUSED);
}
if ((smtp_err = SMTP_rcpt(ctl->smtp_socket, ctl->smtphostmode,
@@ -1053,7 +1064,7 @@ transient:
if (smtp_err != SM_OK)
{
report(stderr, GT_("can't even send to %s!\n"), run.postmaster);
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* required by RFC1870 */
+ smtp_rset(ctl); /* required by RFC1870 */
return(PS_REFUSED);
}
@@ -1074,7 +1085,7 @@ transient:
if (smtp_err != SM_OK)
{
int err = handle_smtp_report(ctl, msg);
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* stay on the safe side */
+ smtp_rset(ctl); /* stay on the safe side */
return(err);
}
@@ -1409,13 +1420,13 @@ int close_sink(struct query *ctl, struct msgblk *msg, flag forward)
{
if (handle_smtp_report(ctl, msg) != PS_REFUSED)
{
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* stay on the safe side */
+ smtp_rset(ctl); /* stay on the safe side */
return(FALSE);
}
else
{
report(stderr, GT_("SMTP listener refused delivery\n"));
- SMTP_rset(ctl->smtp_socket, ctl->smtphostmode); /* stay on the safe side */
+ smtp_rset(ctl); /* stay on the safe side */
return(TRUE);
}
}