diff options
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | conf.c | 7 | ||||
-rw-r--r-- | fetchmail.c | 12 | ||||
-rw-r--r-- | fetchmail.h | 3 | ||||
-rw-r--r-- | fetchmail.man | 12 | ||||
-rwxr-xr-x | fetchmailconf.py | 10 | ||||
-rw-r--r-- | options.c | 17 | ||||
-rw-r--r-- | rcfile_l.l | 4 | ||||
-rw-r--r-- | rcfile_y.y | 3 | ||||
-rw-r--r-- | transact.c | 5 |
10 files changed, 74 insertions, 5 deletions
@@ -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 @@ -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:', @@ -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")); @@ -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; } @@ -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();} @@ -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; |