diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | design-notes.html | 44 | ||||
-rw-r--r-- | driver.c | 36 | ||||
-rw-r--r-- | fetchmail.c | 6 | ||||
-rw-r--r-- | fetchmail.h | 1 | ||||
-rw-r--r-- | fetchmail.man | 15 | ||||
-rw-r--r-- | options.c | 27 | ||||
-rw-r--r-- | rcfile_l.l | 1 | ||||
-rw-r--r-- | rcfile_y.y | 7 | ||||
-rw-r--r-- | sample.rcfile | 1 |
10 files changed, 108 insertions, 32 deletions
@@ -8,7 +8,6 @@ * Allow -c -F to work to flush messages without retrieval. * Read from /etc/fetchmailrc before ~/.fetchmailrc? * Do is_host_alias checks by comparing IP addresses rather than names? -* Make the antispam response configurable. * Handle multi-homed hosts correctly. Release Notes: @@ -23,6 +22,7 @@ fetchmail-4.4.0 (): * Ron Kaminsky <kam@Orbotech.Co.IL> sent a patch to RFC1730-encode passwords sent to IMAP servers. This allows them to contain doublequotes and backslashes. +* Made the antispam response configurable. There are 269 people on fetchmail-friends and 144 on fetchmail-announce. diff --git a/design-notes.html b/design-notes.html index 54549ff8..b6ddec2d 100644 --- a/design-notes.html +++ b/design-notes.html @@ -10,7 +10,7 @@ <table width="100%" cellpadding=0><tr> <td width="30%">Back to <a href="index.html">Fetchmail Home Page</a> <td width="30%" align=center>To <a href="/~esr/sitemap.html">Site Map</a> -<td width="30%" align=right>$Date: 1998/03/04 05:45:27 $ +<td width="30%" align=right>$Date: 1998/03/06 04:17:44 $ </table> <HR> <H1 ALIGN=CENTER>Design Notes On Fetchmail</H1> @@ -287,6 +287,46 @@ in a system's libc, but we can just include that source file if the day comes when we want to support IPv6 without the inet6-apps library. It just makes life easier.<P> +<H1>Checklist for Adding Options + +Adding a control option is not complicated in principle, but there are +a lot of fiddly details in the process. You'll need to do the +following minimum steps. + +<UL> +<LI>Add a field to represent the control in <code>struct query</code> or + <code>struct hostdata</code>. + +<LI>Pick a token to declare the option in the .fetchmailrc file. Add + the token to <code>rcfile_l</code>. + +<LI>Go to <code>rcfile_y.y</code>. Add the token to the grammar. Don't + forget the <code>%token</code> declaration. Add proper + <code>FLAG_FORCE</code> and <code>FLAG_MERGE</code> actions. + +<LI>Pick a long-form option name, and a one-letter short option if any + are left. Go to <code>options.c</code>. Pick a new <code>LA_<code> + value. Hack the <code>longoptions</code> table to set up the + association. Hack the big switch statement to set the option. + Hack the `?' message to describe it. + +<LI>If the default is nonzero, set it in <code>def_opts</code> near the top of + <code>load_params</code> in <code>fetchmail.c</code>. + +<LI>Add code to dump the option value in <code>fetchmail.c:dump_params</code>. + +<LI>Document the option in fetchmail.man. This will require at least + two changes; one to the collected table of options, and one full + text description of the option. + +<LI>Add the new token and a brief description to the header comment of + sample.rcfile. + +<LI>Add an entry to NEWS. +</UL> + +There may be other things you have to do in the way of logic, of course.<P> + <H1>Lessons learned</H1> <H3>1. Server-side state is essential</H3> @@ -423,7 +463,7 @@ all shaped the design in one way or another.<P> <table width="100%" cellpadding=0><tr> <td width="30%">Back to <a href="index.html">Fetchmail Home Page</a> <td width="30%" align=center>To <a href="/~esr/sitemap.html">Site Map</a> -<td width="30%" align=right>$Date: 1998/03/04 05:45:27 $ +<td width="30%" align=right>$Date: 1998/03/06 04:17:44 $ </table> <P><ADDRESS>Eric S. Raymond <A HREF="mailto:esr@thyrsus.com"><esr@snark.thyrsus.com></A></ADDRESS> @@ -1232,30 +1232,34 @@ int num; /* index of message */ { int smtperr = atoi(smtp_response); + if (smtperr == ctl->antispam) + { + /* + * SMTP listener explicitly refuses to deliver mail + * coming from this address, probably due to an + * anti-spam domain exclusion. Respect this. Don't + * try to ship the message, and don't prevent it from + * being deleted. Typical values. + * + * 571 = sendmail's "unsolicited email refused" + * 501 = exim's old antispam response + * 550 = exim's new antispam response (temporary) + */ + free(headers); + free_str_list(&xmit_names); + return(PS_REFUSED); + } + /* * Suppress error message only if the response specifically - * means `excluded for policy reasons'. We *should* see + * meant `excluded for policy reasons'. We *should* see * an error when the return code is less specific. */ - if (smtperr >= 400 && smtperr != 571) + if (smtperr >= 400) error(0, -1, "SMTP error: %s", smtp_response); switch (smtperr) { - case 571: /* sendmail's "unsolicited email refused" */ - case 501: /* exim's old antispam response */ - case 550: /* exim's new antispam response (temporary) */ - /* - * SMTP listener explicitly refuses to deliver - * mail coming from this address, probably due - * to an anti-spam domain exclusion. Respect - * this. Don't try to ship the message, and - * don't prevent it from being deleted. - */ - free(headers); - free_str_list(&xmit_names); - return(PS_REFUSED); - case 452: /* insufficient system storage */ /* * Temporary out-of-queue-space condition on the diff --git a/fetchmail.c b/fetchmail.c index 316cd3c5..0f187c68 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -655,6 +655,7 @@ static int load_params(int argc, char **argv, int optind) memset(&def_opts, '\0', sizeof(struct query)); def_opts.smtp_socket = -1; def_opts.smtpaddress = (char *)0; + def_opts.antispam = 571; def_opts.server.protocol = P_AUTO; def_opts.server.timeout = CLIENT_TIMEOUT; @@ -1107,6 +1108,11 @@ void dump_params (struct query *ctl) printf(" Host part of MAIL FROM line will be %s\n", ctl->smtpaddress); } + if (ctl->antispam != -1) + printf(" Listener SMTP reponse %d will be treated as a spam block\n", + ctl->antispam); + else if (outlevel == O_VERBOSE) + printf(" Spam-blocking disabled\n"); if (ctl->preconnect) printf(" Server connection will be brought up with '%s.'\n", visbuf(ctl->preconnect)); diff --git a/fetchmail.h b/fetchmail.h index e4c51f4e..a4cccde0 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -144,6 +144,7 @@ struct query struct idlist *smtphunt; /* list of SMTP hosts to try forwarding to */ char *smtphost; /* actual SMTP host to point to */ char *smtpaddress; /* address we want to force in the delivery messages */ + int antispam; /* listener's antispam response */ char *mda; /* local MDA to pass mail to */ char *preconnect; /* pre-connection command to execute */ char *postconnect; /* post-connection command to execute */ diff --git a/fetchmail.man b/fetchmail.man index deded9db..50c947fd 100644 --- a/fetchmail.man +++ b/fetchmail.man @@ -217,6 +217,12 @@ Specify the domain to be put in RCPT TO lines shipped to SMTP. The name of the SMTP server (as specified by --smtphost, or defaulted to "localhost") is used when this is not specified. .TP +.B \-Z nnn, --antispam nnn +(Keyword: antispam) +Specifies the numeric SMTP error that is to be interpreted as a +spam-block response from the listener. A value of -1 disables +this option. +.TP .B \-m, \--mda (Keyword: mda) You can force mail to be passed to an MDA directly (rather than @@ -719,7 +725,8 @@ move to 550 soon. .PP The .I fetchmail -code recognizes any of these error codes and discards the message. This is the +code recognizes and discards the message on a code that defaults to +sendmail's 571 but can be set with the `antispam' option. This is the .I only circumstance under which fetchmail ever discards mail. .P @@ -866,6 +873,12 @@ T} smtphost -S T{ Specify smtp host(s) to forward to T} +smtpaddress -D T{ +Specify the domain to be put in RCPT TO lines +T} +antispam -Z T{ +Specify what SMTP return is interpreted as a spam-policy block +T} mda -m T{ Specify MDA for local delivery T} @@ -46,14 +46,15 @@ #define LA_FOLDER 28 #define LA_SMTPHOST 29 #define LA_SMTPADDR 30 -#define LA_BATCHLIMIT 31 -#define LA_FETCHLIMIT 32 -#define LA_EXPUNGE 33 -#define LA_MDA 34 -#define LA_NETSEC 35 -#define LA_INTERFACE 36 -#define LA_MONITOR 37 -#define LA_YYDEBUG 38 +#define LA_ANTISPAM 31 +#define LA_BATCHLIMIT 32 +#define LA_FETCHLIMIT 33 +#define LA_EXPUNGE 34 +#define LA_MDA 35 +#define LA_NETSEC 36 +#define LA_INTERFACE 37 +#define LA_MONITOR 38 +#define LA_YYDEBUG 39 /* options still left: CgGhHjJoORUwWxXYzZ */ static const char *shortoptions = @@ -97,6 +98,7 @@ static const struct option longoptions[] = { {"folder", required_argument, (int *) 0, LA_FOLDER }, {"smtphost", required_argument, (int *) 0, LA_SMTPHOST }, {"smtpaddress", required_argument, (int *) 0, LA_SMTPADDR }, + {"antispam", required_argument, (int *) 0, LA_ANTISPAM }, {"batchlimit",required_argument, (int *) 0, LA_BATCHLIMIT }, {"fetchlimit",required_argument, (int *) 0, LA_FETCHLIMIT }, @@ -326,8 +328,12 @@ struct query *ctl; /* option record to be initialized */ break; case 'D': case LA_SMTPADDR: - ctl->smtpaddress = xstrdup(optarg); - break; + ctl->smtpaddress = xstrdup(optarg); + break; + case 'Z': + case LA_ANTISPAM: + c = atoi(optarg); + ctl->antispam = NUM_VALUE(c); case 'b': case LA_BATCHLIMIT: c = atoi(optarg); @@ -434,6 +440,7 @@ struct query *ctl; /* option record to be initialized */ #endif /* NET_SECURITY */ fputs(" -S, --smtphost set SMTP forwarding host\n", stderr); fputs(" -D, --smtpaddress set SMTP delivery domain to use\n", stderr); + fputs(" -Z, --antispam, set antispam response value\n", stderr); fputs(" -b, --batchlimit set batch limit for SMTP connections\n", stderr); fputs(" -B, --fetchlimit set fetch limit for server connections\n", stderr); fputs(" -e, --expunge set max deletions between expunges\n", stderr); @@ -51,6 +51,7 @@ pass(word)? { return PASSWORD; } folder(s)? { return FOLDER; } smtp(host)? { return SMTPHOST; } smtpaddress { return SMTPADDRESS; } +antispam { return SPAMRESPONSE; } mda { return MDA; } pre(connect)? { return PRECONNECT; } post(connect)? { return POSTCONNECT; } @@ -64,7 +64,7 @@ extern char * yytext; %token DEFAULTS POLL SKIP VIA AKA LOCALDOMAINS PROTOCOL %token AUTHENTICATE TIMEOUT KPOP KERBEROS4 KERBEROS5 KERBEROS %token ENVELOPE QVIRTUAL USERNAME PASSWORD FOLDER SMTPHOST MDA SMTPADDRESS -%token PRECONNECT POSTCONNECT LIMIT +%token SPAMRESPONSE PRECONNECT POSTCONNECT LIMIT %token IS HERE THERE TO MAP WILDCARD %token BATCHLIMIT FETCHLIMIT EXPUNGE %token SET LOGFILE DAEMON SYSLOG INVISIBLE NETSEC INTERFACE MONITOR @@ -270,6 +270,7 @@ user_option : TO localnames HERE | FOLDER folder_list | SMTPHOST smtp_list | SMTPADDRESS STRING {current.smtpaddress = xstrdup($2);} + | SPAMRESPONSE NUMBER {current.antispam = $2;} | MDA STRING {current.mda = xstrdup($2);} | PRECONNECT STRING {current.preconnect = xstrdup($2);} | POSTCONNECT STRING {current.postconnect = xstrdup($2);} @@ -486,7 +487,8 @@ static void record_current(void) if (cmd_opts.smtphunt) current.smtphunt = cmd_opts.smtphunt; FLAG_FORCE(mda); - FLAG_FORCE(smtpaddress); + FLAG_FORCE(smtpaddress); + FLAG_FORCE(antispam); FLAG_FORCE(preconnect); FLAG_FORCE(postconnect); @@ -547,6 +549,7 @@ void optmerge(struct query *h2, struct query *h1) FLAG_MERGE(password); FLAG_MERGE(mda); FLAG_MERGE(smtpaddress); + FLAG_MERGE(antispam); FLAG_MERGE(preconnect); FLAG_MERGE(keep); diff --git a/sample.rcfile b/sample.rcfile index facb95c3..da6a967e 100644 --- a/sample.rcfile +++ b/sample.rcfile @@ -45,6 +45,7 @@ # password (or pass) -- must be followed by a password string # smtphost (or smtp) -- must be followed by host names # smtpaddress -- must be followed by a host name +# antispam -- must be followed by a numeric response value # mda -- must be followed by an MDA command string # preconnect (or pre) -- must be followed by an executable command # postconnect (or post) -- must be followed by an executable command |