Gitweb:
http://git.exim.org/exim.git/commitdiff/dc7b3d368017727e9438fc7463b0841df1e4aa41
Commit: dc7b3d368017727e9438fc7463b0841df1e4aa41
Parent: 6c54be6459b83b955fbd2fd6d6a844f80c98427a
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Sun Feb 15 16:50:27 2015 +0000
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Sun Feb 15 16:50:27 2015 +0000
SpamAssassin: replace "backup" option on server spec with "pri=<N>". Bug 670
---
doc/doc-docbook/spec.xfpt | 22 ++++++---
doc/doc-txt/ChangeLog | 2 +-
src/src/spam.c | 93 +++++++++++++++++++--------------------
src/src/spam.h | 2 +-
test/confs/4009 | 4 +-
test/log/4009 | 5 ++
test/scripts/4000-scanning/4009 | 63 +++++++++++++++++++++++++-
test/stdout/4009 | 55 +++++++++++++++++++++++
8 files changed, 185 insertions(+), 61 deletions(-)
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index a112ec7..411eb98 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -30829,20 +30829,29 @@ Elements after the first for Unix sockets, or second for TCP socket,
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.
@@ -30851,9 +30860,6 @@ The default value is two minutes.
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
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 0548674..cff7f44 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -54,7 +54,7 @@ JH/14 Bug 1573: The spam= ACL condition now additionally supports Rspamd.
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@???>.
JH/16 The spamd_address main option now supports a mixed list of local
diff --git a/src/src/spam.c b/src/src/spam.c
index 4b99aca..05a51f6 100644
--- a/src/src/spam.c
+++ b/src/src/spam.c
@@ -27,12 +27,12 @@ static const uschar * loglabel = US"spam acl condition:";
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;
}
@@ -44,16 +44,11 @@ static int timesinceday = -1;
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 */
@@ -61,7 +56,6 @@ if (sscanf(param, "weight=%u", &spamd->weight))
return 0; /* OK */
}
-/* check time parameter */
if (Ustrncmp(param, "time=", 5) == 0)
{
unsigned int start_h = 0, start_m = 0, start_s = 0;
@@ -136,46 +130,50 @@ badval:
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);
@@ -251,7 +249,7 @@ if (*spamd_address == '$')
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
@@ -280,12 +278,13 @@ start = time(NULL);
{
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)
{
@@ -294,7 +293,7 @@ start = time(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);
@@ -302,7 +301,7 @@ start = time(NULL);
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;
diff --git a/src/src/spam.h b/src/src/spam.h
index 0e3acfc..e7da49b 100644
--- a/src/src/spam.h
+++ b/src/src/spam.h
@@ -28,10 +28,10 @@ typedef struct spamd_address_container
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
diff --git a/test/confs/4009 b/test/confs/4009
index 573aa6a..2799575 100644
--- a/test/confs/4009
+++ b/test/confs/4009
@@ -1,7 +1,7 @@
# Exim test configuration 4009
# Content-scan: spamassassin interface
-OPT=
+OPT= 127.0.0.1 7833
exim_path = EXIM_PATH
host_lookup_order = bydns
@@ -12,7 +12,7 @@ gecos_pattern = ""
gecos_name = CALLER_NAME
log_selector = +subject
-spamd_address = 127.0.0.1 7833 OPT
+spamd_address = OPT
# ----- Main settings -----
diff --git a/test/log/4009 b/test/log/4009
index 4522ddb..612744e 100644
--- a/test/log/4009
+++ b/test/log/4009
@@ -10,3 +10,8 @@
1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@??? U=CALLER P=local-esmtp S=sss
1999-03-02 09:44:33 10HmaZ-0005vi-00 => :blackhole: <userx@???> 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@??? U=CALLER P=local-esmtp S=sss
+1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: <userx@???> R=r
+1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
diff --git a/test/scripts/4000-scanning/4009 b/test/scripts/4000-scanning/4009
index 4c2ab81..50f5ff9 100644
--- a/test/scripts/4000-scanning/4009
+++ b/test/scripts/4000-scanning/4009
@@ -105,7 +105,7 @@ server 7833
>
*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@???>
@@ -163,7 +163,66 @@ server -i 2 7833
>
*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@???>
+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@???>
diff --git a/test/stdout/4009 b/test/stdout/4009
index 9220c7d..cdc7677 100644
--- a/test/stdout/4009
+++ b/test/stdout/4009
@@ -31,6 +31,17 @@
354 Enter message, ending with "." on a line by itself
250 OK id=10HmaZ-0005vi-00
221 myhost.test.ex closing connection
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+250-myhost.test.ex Hello CALLER at test.ex
+250-SIZE 52428800
+250-8BITMIME
+250-PIPELINING
+250 HELP
+250 OK
+250 Accepted
+354 Enter message, ending with "." on a line by itself
+250 OK id=10HmbA-0005vi-00
+221 myhost.test.ex closing connection
******** SERVER ********
Listening on port 7833 ...
@@ -166,3 +177,47 @@ Connection request from [127.0.0.1]
>
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@???>
+<X-Envelope-To: userx@???
+<Received: from CALLER (helo=test.ex)
+< by myhost.test.ex with local-esmtp (Exim x.yz)
+< (envelope-from <CALLER@???>)
+< id 10HmbA-0005vi-00
+< for userx@???; Tue, 2 Mar 1999 09:44:33 +0000
+<Content-type: text/plain
+<Message-Id: <E10HmbA-0005vi-00@???>
+<From: CALLER_NAME <CALLER@???>
+<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