aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Andree <matthias.andree@gmx.de>2010-02-24 01:54:22 +0100
committerMatthias Andree <matthias.andree@gmx.de>2010-02-24 01:54:22 +0100
commitc1cf83738a260121cf7dcc007af8709d0bc15419 (patch)
tree65b087c9056013f75192a81ce573ebb7014c3321
parent1c10c414e45ccedc8999f7dd95889fce6f6890ff (diff)
downloadfetchmail-c1cf83738a260121cf7dcc007af8709d0bc15419.tar.gz
fetchmail-c1cf83738a260121cf7dcc007af8709d0bc15419.tar.bz2
fetchmail-c1cf83738a260121cf7dcc007af8709d0bc15419.zip
Feature: bad-header {reject|pass}
-rw-r--r--NEWS6
-rw-r--r--conf.c7
-rw-r--r--fetchmail.c12
-rw-r--r--fetchmail.h3
-rw-r--r--fetchmail.man12
-rwxr-xr-xfetchmailconf.py10
-rw-r--r--options.c17
-rw-r--r--rcfile_l.l4
-rw-r--r--rcfile_y.y3
-rw-r--r--transact.c5
10 files changed, 74 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index 44cba404..7ae09a7d 100644
--- a/NEWS
+++ b/NEWS
@@ -49,6 +49,12 @@ removed from a 6.4.0 or newer release.)
fetchmail 6.3.15 (not yet released):
+# FEATURE
+* Fetchmail now supports a bad-header command line or rcfile option that takes
+ exactly one argument, pass or reject (default). If set to pass, fetchmail
+ will pass messages with bad headers on. This has been rejected for a long
+ time, and the right behaviour was disputed for too long.
+
# CHANGES
* The repository has been converted and moved from the Subversion (SVN) format
kindly hosted by Graham Wilson over the past years to Git format hosted on
diff --git a/conf.c b/conf.c
index 60eb3ebb..5b5d8779 100644
--- a/conf.c
+++ b/conf.c
@@ -312,6 +312,13 @@ void dump_config(struct runctl *runp, struct query *querylist)
if (ctl->server.esmtp_password)
stringdump("esmtppassword",ctl->server.esmtp_password);
booldump("tracepolls", ctl->server.tracepolls);
+ indent(0);
+ switch(ctl->server.badheader) {
+ /* this is a hack - we map this to a boolean option for
+ * fetchmailconf purposes */
+ case BHREJECT: puts("'badheader': FALSE,"); break;
+ case BHPASS: puts("'badheader': TRUE,"); break;
+ }
indent(0);
fputs("'users': ", stdout);
diff --git a/fetchmail.c b/fetchmail.c
index cb1bc900..5d02a289 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -944,6 +944,7 @@ static void optmerge(struct query *h2, struct query *h1, int force)
FLAG_MERGE(server.plugin);
FLAG_MERGE(server.plugout);
FLAG_MERGE(server.tracepolls);
+ FLAG_MERGE(server.badheader);
FLAG_MERGE(wildcard);
FLAG_MERGE(remotename);
@@ -1012,6 +1013,7 @@ static int load_params(int argc, char **argv, int optind)
def_opts.server.protocol = P_AUTO;
def_opts.server.timeout = CLIENT_TIMEOUT;
def_opts.server.esmtp_name = user;
+ def_opts.server.badheader = BHREJECT;
def_opts.warnings = WARNING_INTERVAL;
def_opts.remotename = user;
def_opts.listener = SMTP_MODE;
@@ -1949,6 +1951,16 @@ static void dump_params (struct runctl *runp,
else if (outlevel >= O_VERBOSE)
printf(GT_(" No poll trace information will be added to the Received header.\n.\n"));
+ switch (ctl->server.badheader) {
+ case BHREJECT:
+ if (outlevel >= O_VERBOSE)
+ printf(GT_(" Messages with bad headers will be rejected.\n"));
+ break;
+ case BHPASS:
+ printf(GT_(" Messages with bad headers will be passed on.\n"));
+ break;
+ }
+
if (ctl->properties)
printf(GT_(" Pass-through properties \"%s\".\n"),
visbuf(ctl->properties));
diff --git a/fetchmail.h b/fetchmail.h
index d0991386..88f7dd33 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -245,6 +245,8 @@ struct method /* describe methods for protocol state machine */
flag retry; /* can getrange poll for new messages? */
};
+enum badheader { BHREJECT = 0, BHPASS };
+
struct hostdata /* shared among all user connections to given server */
{
/* rc file data */
@@ -270,6 +272,7 @@ struct hostdata /* shared among all user connections to given server */
flag tracepolls; /* if TRUE, add poll trace info to Received */
char *principal; /* Kerberos principal for mail service */
char *esmtp_name, *esmtp_password; /* ESMTP AUTH information */
+ enum badheader badheader; /* bad-header {pass|reject} */
#if defined(linux) || defined(__FreeBSD__)
#define CAN_MONITOR
diff --git a/fetchmail.man b/fetchmail.man
index d2b51197..f63f381f 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -699,6 +699,15 @@ to be written to standard output. Note that fetchmail's
reconstruction of MAIL FROM and RCPT TO lines is not guaranteed
correct; the caveats discussed under THE USE AND ABUSE OF MULTIDROP
MAILBOXES below apply.
+.TP
+.B \-\-bad\-header {reject|pass}
+(Keyword: bad\-header; since v6.3.15)
+.br
+Specify how fetchmail is supposed to treat messages with bad headers,
+i. e. headers with bad syntax. Traditionally, fetchmail has rejected such
+messages, but some distributors modified fetchmail to pass them. You can now
+configure fetchmail's behaviour per server.
+
.SS Resource Limit Control Options
.TP
.B \-l <maxbytes> | \-\-limit <maxbytes>
@@ -1749,6 +1758,9 @@ T}
esmtppassword \& \& T{
Set password for RFC2554 authentication to the ESMTP server.
T}
+bad-header \& \& T{
+How to treat messages with a bad header. Can be reject (default) or pass.
+T}
.TE
Here are the legal user descriptions and options:
diff --git a/fetchmailconf.py b/fetchmailconf.py
index 90a2dea5..4aae48f8 100755
--- a/fetchmailconf.py
+++ b/fetchmailconf.py
@@ -5,7 +5,7 @@
# Matthias Andree <matthias.andree@gmx.de>
# Requires Python with Tkinter, and the following OS-dependent services:
# posix, posixpath, socket
-version = "1.56 $Revision$"
+version = "1.57"
from Tkinter import *
from Dialog import *
@@ -103,6 +103,7 @@ class Server:
self.esmtpname = None # ESMTP 2554 name
self.esmtppassword = None # ESMTP 2554 password
self.tracepolls = FALSE # Add trace-poll info to headers
+ self.badheader = FALSE # Pass messages with bad headers on?
self.users = [] # List of user entries for site
Server.typemap = (
('pollname', 'String'),
@@ -127,7 +128,8 @@ class Server:
('esmtpname', 'String'),
('esmtppassword', 'String'),
('principal', 'String'),
- ('tracepolls','Boolean'))
+ ('tracepolls','Boolean'),
+ ('badheader', 'Boolean'))
def dump(self, folded):
res = ""
@@ -197,6 +199,8 @@ class Server:
if self.interface or self.monitor or self.principal or self.plugin or self.plugout:
if folded:
res = res + "\n"
+ if self.badheader:
+ res = res + "bad-header pass "
if res[-1] == " ": res = res[0:-1]
@@ -1129,6 +1133,8 @@ class ServerEdit(Frame, MyWidget):
ctlwin = Frame(leftwin, relief=RAISED, bd=5)
Label(ctlwin, text="Run Controls").pack(side=TOP)
Checkbutton(ctlwin, text='Poll ' + host + ' normally?', variable=self.active).pack(side=TOP)
+ Checkbutton(ctlwin, text='Pass messages with bad headers?',
+ variable=self.badheader).pack(side=TOP)
LabeledEntry(ctlwin, 'True name of ' + host + ':',
self.via, leftwidth).pack(side=TOP, fill=X)
LabeledEntry(ctlwin, 'Cycles to skip between polls:',
diff --git a/options.c b/options.c
index e85682d5..066a8ab0 100644
--- a/options.c
+++ b/options.c
@@ -53,7 +53,8 @@ enum {
LA_LIMITFLUSH,
LA_IDLE,
LA_NOSOFTBOUNCE,
- LA_SOFTBOUNCE
+ LA_SOFTBOUNCE,
+ LA_BADHEADER
};
/* options still left: CgGhHjJoORTWxXYz */
@@ -93,6 +94,7 @@ static const struct option longoptions[] = {
{"timeout", required_argument, (int *) 0, 't' },
{"envelope", required_argument, (int *) 0, 'E' },
{"qvirtual", required_argument, (int *) 0, 'Q' },
+ {"bad-header",required_argument, (int *) 0, LA_BADHEADER},
{"user", required_argument, (int *) 0, 'u' },
{"username", required_argument, (int *) 0, 'u' },
@@ -310,6 +312,17 @@ int parsecmdline (int argc /** argument count */,
case LA_SOFTBOUNCE:
run.softbounce = TRUE;
break;
+ case LA_BADHEADER:
+ if (strcasecmp(optarg,"pass") == 0) {
+ ctl->server.badheader = BHPASS;
+ } else if (strcasecmp(optarg,"reject") == 0) {
+ ctl->server.badheader = BHREJECT;
+ } else {
+ fprintf(stderr,GT_("Invalid bad-header policy `%s' specified.\n"), optarg);
+ errflag++;
+ }
+ break;
+
case 'p':
/* XXX -- should probably use a table lookup here */
if (strcasecmp(optarg,"auto") == 0)
@@ -635,6 +648,8 @@ int parsecmdline (int argc /** argument count */,
#endif
P(GT_(" --plugin specify external command to open connection\n"));
P(GT_(" --plugout specify external command to open smtp connection\n"));
+ P(GT_(" --bad-header {reject|pass}\n"
+ " specify policy for handling messages with bad headers\n"));
P(GT_(" -p, --protocol specify retrieval protocol (see man page)\n"));
P(GT_(" -U, --uidl force the use of UIDLs (pop3 only)\n"));
diff --git a/rcfile_l.l b/rcfile_l.l
index 67317a6b..679a5b4e 100644
--- a/rcfile_l.l
+++ b/rcfile_l.l
@@ -113,7 +113,9 @@ qvirtual { return QVIRTUAL; }
principal { return PRINCIPAL; }
esmtpname { return ESMTPNAME; }
esmtppassword { return ESMTPPASSWORD; }
-
+bad-header { return BADHEADER; }
+pass { return PASS; }
+reject { return REJECT_; }
user(name)? {SETSTATE(NAME); return USERNAME; }
<INITIAL,NAME>pass(word)? {SETSTATE(NAME); return PASSWORD; }
diff --git a/rcfile_y.y b/rcfile_y.y
index e57973b6..b5765d77 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -70,6 +70,7 @@ extern char * yytext;
%token BATCHLIMIT FETCHLIMIT FETCHSIZELIMIT FASTUIDL EXPUNGE PROPERTIES
%token SET LOGFILE DAEMON SYSLOG IDFILE PIDFILE INVISIBLE POSTMASTER BOUNCEMAIL
%token SPAMBOUNCE SOFTBOUNCE SHOWDOTS
+%token BADHEADER PASS REJECT_
%token <proto> PROTO AUTHTYPE
%token <sval> STRING
%token <number> NUMBER
@@ -231,6 +232,8 @@ serv_option : AKA alias_list
| NO ENVELOPE {current.server.envelope = STRING_DISABLED;}
| TRACEPOLLS {current.server.tracepolls = FLAG_TRUE;}
| NO TRACEPOLLS {current.server.tracepolls = FLAG_FALSE;}
+ | BADHEADER PASS {current.server.badheader = BHPASS;}
+ | BADHEADER REJECT_ {current.server.badheader = BHREJECT;}
;
userspecs : user1opts {record_current(); user_reset();}
diff --git a/transact.c b/transact.c
index c6ea7e35..9d151607 100644
--- a/transact.c
+++ b/transact.c
@@ -583,7 +583,10 @@ eoh:
* message/rfc822 attachment and forward to postmaster (Rob
* MacGregor)
*/
- if (!refuse_mail && !isspace((unsigned char)line[0]) && !strchr(line, ':'))
+ if (!refuse_mail
+ && !ctl->server.badheader == BHPASS
+ && !isspace((unsigned char)line[0])
+ && !strchr(line, ':'))
{
if (linelen != strlen (line))
has_nuls = TRUE;