are options.
The supported option are:
.code
-variant=rspamd Use Rspamd rather than SpamAssassin protocol
+pri=<priority> Selection priority
+weight=<value> Selection bias
time=<start>-<end> Use only between these times of day
+retry=<timespec> Retry on connect fail
tmo=<timespec> Connection time limit
-weight=<value> Selection bias
-backup Use only if all non-backup servers fail
-retry=<timespec> Retry on connect fail
+variant=rspamd Use Rspamd rather than SpamAssassin protocol
.endd
+The &`pri`& option specifies a priority for the server within the list,
+higher values being tried first.
+The deafult priority is 1.
+
+The &`weight`& option specifies a selection bias.
+Within a priority set
+servers are queried in a random fashion, weighted by this value.
+The default value for selection bias is 1.
+
Time specifications for the &`time`& option are <hour>.<minute>.<second>
in the local time zone; each element being one or more digits.
Either the seconds or both minutes and seconds, plus the leading &`.`&
characters, may be omitted and will be taken as zero.
-Timeout specifications for the &`tmo`& and &`retry`& options
+Timeout specifications for the &`retry`& and &`tmo`& options
are the usual Exim time interval standard, eg. &`20s`& or &`1m`&.
The &`tmo`& option specifies an overall timeout for communication.
The &`retry`& option specifies a time after which a single retry for
a failed connect is made.
The default is to not retry.
-
-Servers are queried in a random fashion, weighted by the selection bias.
-The default value for selection bias is 1.
.wen
The &%spamd_address%& variable is expanded before use if it starts with
Patch from Andrew Lewis.
JH/15 Bug 670: The spamd_address main option (for the spam= ACL condition)
- now supports optional time-restrictions, weighting, and backup-only
+ now supports optional time-restrictions, weighting, and priority
modifiers per server. Patch originally by <rommer@active.by>.
JH/16 The spamd_address main option now supports a mixed list of local
static int
spamd_param_init(spamd_address_container *spamd)
{
-/* default spamd server weight, time and backup value */
+/* default spamd server weight, time and priority value */
spamd->is_failed = FALSE;
-spamd->is_backup = FALSE;
spamd->weight = SPAMD_WEIGHT;
spamd->timeout = SPAMD_TIMEOUT;
spamd->retry = 0;
+spamd->priority = 1;
return 0;
}
const uschar * s;
const uschar * name;
-/* check backup parameter */
-if (Ustrcmp(param, "backup") == 0)
- {
- spamd->is_backup = TRUE;
- return 0; /* OK */
- }
-
/*XXX more clever parsing could discard embedded spaces? */
-/* check weight parameter */
+if (sscanf(param, "pri=%u", &spamd->priority))
+ return 0; /* OK */
+
if (sscanf(param, "weight=%u", &spamd->weight))
{
if (spamd->weight == 0) /* this server disabled: skip it */
return 0; /* OK */
}
-/* check time parameter */
if (Ustrncmp(param, "time=", 5) == 0)
{
unsigned int start_h = 0, start_m = 0, start_s = 0;
static int
-spamd_get_server(spamd_address_container **spamds, int num_servers)
+spamd_get_server(spamd_address_container ** spamds, int num_servers)
{
unsigned int i;
-long rnd, weights = 0;
-static BOOL srandomed = 0;
-BOOL usebackup = FALSE;
-
-for (;;)
- {
- /* seedup, if we have only 1 server */
- if (num_servers == 1)
- return (spamds[0]->is_failed ? -1 : 0);
+spamd_address_container * sd;
+long rnd, weights;
+unsigned pri;
+static BOOL srandomed = FALSE;
- /* init ranmod */
- if (!srandomed)
- {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- srandom((unsigned int)(tv.tv_usec/1000));
- srandomed = TRUE;
- }
+/* seedup, if we have only 1 server */
+if (num_servers == 1)
+ return (spamds[0]->is_failed ? -1 : 0);
- /* get sum of all weights */
- for (i = 0; i < num_servers; i++)
- if (!spamds[i]->is_failed && spamds[i]->is_backup == usebackup)
- weights += spamds[i]->weight;
+/* init ranmod */
+if (!srandomed)
+ {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ srandom((unsigned int)(tv.tv_usec/1000));
+ srandomed = TRUE;
+ }
- if (weights != 0)
- break;
- if (usebackup) /* all servers failed (backups too) */
- return -1;
- usebackup = TRUE;
+/* scan for highest pri */
+for (pri = 0, i = 0; i < num_servers; i++)
+ {
+ sd = spamds[i];
+ if (!sd->is_failed && sd->priority > pri) pri = sd->priority;
}
-rnd = random() % weights;
+/* get sum of weights */
+for (weights = 0, i = 0; i < num_servers; i++)
+ {
+ sd = spamds[i];
+ if (!sd->is_failed && sd->priority == pri) weights += sd->weight;
+ }
+if (weights == 0) /* all servers failed */
+ return -1;
-for (i = 0; i < num_servers; i++)
- if (!spamds[i]->is_failed && spamds[i]->is_backup == usebackup)
- if ((rnd -= spamds[i]->weight) < 0)
+for (rnd = random() % weights, i = 0; i < num_servers; i++)
+ {
+ sd = spamds[i];
+ if (!sd->is_failed && sd->priority == pri)
+ if ((rnd -= sd->weight) <= 0)
return i;
+ }
log_write(0, LOG_MAIN|LOG_PANIC,
"%s unknown error (memory/cpu corruption?)", loglabel);
else
spamd_address_work = spamd_address;
-HDEBUG(D_acl) debug_printf("spamd: addrlist '%s'\n", spamd_address_work);
+DEBUG(D_acl) debug_printf("spamd: addrlist '%s'\n", spamd_address_work);
/* check if previous spamd_address was expanded and has changed. dump cached results if so */
if ( spam_ok
{
int num_servers = 0;
int current_server;
- uschar *address;
- const uschar *spamd_address_list_ptr = spamd_address_work;
+ uschar * address;
+ const uschar * spamd_address_list_ptr = spamd_address_work;
spamd_address_container * spamd_address_vector[32];
/* Check how many spamd servers we have
and register their addresses */
+ sep = 0; /* default colon-sep */
while ((address = string_nextinlist(&spamd_address_list_ptr, &sep,
NULL, 0)) != NULL)
{
unsigned args;
uschar * s;
- HDEBUG(D_acl) debug_printf("spamd: addr entry '%s'\n", address);
+ DEBUG(D_acl) debug_printf("spamd: addr entry '%s'\n", address);
sd = (spamd_address_container *)store_get(sizeof(spamd_address_container));
for (sublist = address, args = 0, spamd_param_init(sd);
args++
)
{
- HDEBUG(D_acl) debug_printf("spamd: addr parm '%s'\n", s);
+ DEBUG(D_acl) debug_printf("spamd: addr parm '%s'\n", s);
switch (args)
{
case 0: sd->hostspec = s;
uschar * hostspec;
int is_rspamd:1;
int is_failed:1;
- int is_backup:1;
unsigned int weight;
unsigned int timeout;
unsigned int retry;
+ unsigned int priority;
} spamd_address_container;
#endif
# Exim test configuration 4009
# Content-scan: spamassassin interface
-OPT=
+OPT= 127.0.0.1 7833
exim_path = EXIM_PATH
host_lookup_order = bydns
gecos_name = CALLER_NAME
log_selector = +subject
-spamd_address = 127.0.0.1 7833 OPT
+spamd_address = OPT
# ----- Main settings -----
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
1999-03-02 09:44:33 10HmaZ-0005vi-00 => :blackhole: <userx@test.ex> R=r
1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
+1999-03-02 09:44:33 10HmbA-0005vi-00 spam acl condition: spamd: failed to connect to any address for ::1: Connection refused
+1999-03-02 09:44:33 10HmbA-0005vi-00 U=CALLER Warning: no action Spam detection software, running on the system "demo",\n has NOT identified this incoming email as spam. The original\n message has been attached to this so you can view it or label\n similar future email. If you have any questions, see\n @@CONTACT_ADDRESS@@ for details.\n \n Content preview: test [...]\n \n Content analysis details: (4.5 points, 5.0 required)\n \n pts rule name description\n ---- ---------------------- --------------------------------------------------\n -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP\n 1.2 MISSING_HEADERS Missing To: header\n 1.0 MISSING_FROM Missing From: header\n 1.8 MISSING_SUBJECT Missing Subject: header\n 1.4 MISSING_DATE Missing Date: header\n 0.1 MISSING_MID Missing Message-Id: header
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
+1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: <userx@test.ex> R=r
+1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
>
*eof
****
-exim -odi -bs -DOPT='retry=10s'
+exim -odi -bs -DOPT='127.0.0.1 7833 retry=10s'
ehlo test.ex
mail from:<>
rcpt to:<userx@test.ex>
>
*eof
****
-exim -odi -bs -DOPT='retry=4s'
+exim -odi -bs -DOPT='127.0.0.1 7833 retry=4s'
+ehlo test.ex
+mail from:<>
+rcpt to:<userx@test.ex>
+data
+Content-type: text/plain
+
+test
+.
+quit
+****
+#
+#
+#
+# Multiple servers, prioritised, with timeout spec; first one fails
+# List separator changed
+server 7833
+<REPORT SPAMC
+<User:
+<Content-length:
+<
+<From
+<X-Envelope-From
+<X-Envelope-To
+<Received:
+< by
+< (envelope
+< id
+< for
+<Content-type: text/plain
+<Message-Id:
+<From:
+<Date:
+<
+<test
+>SPAMD/1.1 0 EX_OK
+>Spam: False ; 4.5 / 5.0
+>
+>Spam detection software, running on the system "demo",
+>has NOT identified this incoming email as spam. The original
+>message has been attached to this so you can view it or label
+>similar future email. If you have any questions, see
+>@@CONTACT_ADDRESS@@ for details.
+>
+>Content preview: test [...]
+>
+>Content analysis details: (4.5 points, 5.0 required)
+>
+> pts rule name description
+>---- ---------------------- --------------------------------------------------
+>-1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP
+> 1.2 MISSING_HEADERS Missing To: header
+> 1.0 MISSING_FROM Missing From: header
+> 1.8 MISSING_SUBJECT Missing Subject: header
+> 1.4 MISSING_DATE Missing Date: header
+> 0.1 MISSING_MID Missing Message-Id: header
+>
+*eof
+****
+exim -odi -bs -DOPT='<; 127.0.0.1 7833 ; ::1 7834 pri=2 tmo=2s'
ehlo test.ex
mail from:<>
rcpt to:<userx@test.ex>
354 Enter message, ending with "." on a line by itself\r
250 OK id=10HmaZ-0005vi-00\r
221 myhost.test.ex closing connection\r
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-myhost.test.ex Hello CALLER at test.ex\r
+250-SIZE 52428800\r
+250-8BITMIME\r
+250-PIPELINING\r
+250 HELP\r
+250 OK\r
+250 Accepted\r
+354 Enter message, ending with "." on a line by itself\r
+250 OK id=10HmbA-0005vi-00\r
+221 myhost.test.ex closing connection\r
******** SERVER ********
Listening on port 7833 ...
>
Expected EOF read from client
End of script
+Listening on port 7833 ...
+Connection request from [127.0.0.1]
+<REPORT SPAMC/1.2
+<User: nobody
+<Content-length: 479
+<
+<From MAILER-DAEMON Tue Mar 02 09:44:33 1999
+<X-Envelope-From: <CALLER@myhost.test.ex>
+<X-Envelope-To: userx@test.ex
+<Received: from CALLER (helo=test.ex)
+< by myhost.test.ex with local-esmtp (Exim x.yz)
+< (envelope-from <CALLER@myhost.test.ex>)
+< id 10HmbA-0005vi-00
+< for userx@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+<Content-type: text/plain
+<Message-Id: <E10HmbA-0005vi-00@myhost.test.ex>
+<From: CALLER_NAME <CALLER@myhost.test.ex>
+<Date: Tue, 2 Mar 1999 09:44:33 +0000
+<
+<test
+>SPAMD/1.1 0 EX_OK
+>Spam: False ; 4.5 / 5.0
+>
+>Spam detection software, running on the system "demo",
+>has NOT identified this incoming email as spam. The original
+>message has been attached to this so you can view it or label
+>similar future email. If you have any questions, see
+>@@CONTACT_ADDRESS@@ for details.
+>
+>Content preview: test [...]
+>
+>Content analysis details: (4.5 points, 5.0 required)
+>
+> pts rule name description
+>---- ---------------------- --------------------------------------------------
+>-1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP
+> 1.2 MISSING_HEADERS Missing To: header
+> 1.0 MISSING_FROM Missing From: header
+> 1.8 MISSING_SUBJECT Missing Subject: header
+> 1.4 MISSING_DATE Missing Date: header
+> 0.1 MISSING_MID Missing Message-Id: header
+>
+Expected EOF read from client
+End of script