Reject spam scoring above a certain threshold #4

Closed
opened 2020-06-21 07:20:41 +00:00 by glts · 9 comments
glts commented 2020-06-21 07:20:41 +00:00 (Migrated from gitlab.com)

Users familiar with the alternative milter
spamass-milter may
be missing the -r nn option, which allows rejecting spam that scores
above a threshold. In our project we have -r, but no threshold. This
feature has been left out for reasons to do with scope.

First, the notion of ‘strong spam’ is foreign to SpamAssassin. In
SpamAssassin, the spam/ham distinction is a binary property. Either
something is ham and passes, or it is spam and gets a special treatment.
A threshold would break this apart into three categories, strong spam,
weak spam, and ham. This would weaken the uniformity of the milter and
the SpamAssassin components and complicate their relationship (and the
implementation).

Second, SpamAssassin Milter was designed as a thin glue application,
which does not itself have much logic at all. A threshold would require
introducing parsing and interpretation of SpamAssassin headers,
something which we do not currently do (except X-Spam-Flag: YES).

I would first ask: is it possible to cover the threshold use case
differently, within the existing SpamAssassin framework? Such as relying
on the required_score setting in SpamAssassin to reject spam, and let
downstream components (eg Sieve) instead examine the X-Spam-Level
header and add additional logic on their end?

It is possible to add this feature. I push back against it a little,
because SpamAssassin Milter is also an attempt to break free from
spamass-milter, it is not a clone.

Users familiar with the alternative milter [spamass-milter](https://savannah.nongnu.org/projects/spamass-milt) may be missing the `-r nn` option, which allows rejecting spam that scores above a threshold. In our project we have `-r`, but no threshold. This feature has been left out for reasons to do with scope. First, the notion of ‘strong spam’ is foreign to SpamAssassin. In SpamAssassin, the spam/ham distinction is a binary property. Either something is ham and passes, or it is spam and gets a special treatment. A threshold would break this apart into three categories, strong spam, weak spam, and ham. This would weaken the uniformity of the milter and the SpamAssassin components and complicate their relationship (and the implementation). Second, SpamAssassin Milter was designed as a thin glue application, which does not itself have much logic at all. A threshold would require introducing parsing and interpretation of SpamAssassin headers, something which we do not currently do (except `X-Spam-Flag: YES`). I would first ask: is it possible to cover the threshold use case differently, within the existing SpamAssassin framework? Such as relying on the `required_score` setting in SpamAssassin to reject spam, and let downstream components (eg Sieve) instead examine the `X-Spam-Level` header and add additional logic on their end? It is possible to add this feature. I push back against it a little, because SpamAssassin Milter is also an attempt to break free from spamass-milter, it is not a clone.
glts commented 2020-06-21 07:21:33 +00:00 (Migrated from gitlab.com)

valuable input from pgnd here: #3

valuable input from pgnd here: #3
pgnd commented 2020-06-29 05:12:34 +00:00 (Migrated from gitlab.com)

now that i've had some time to watch this in production ...

atm, for my use case -- split front & back end postfix servers, with spamassassint-milter running on the front-end -- way too much spam is being sent to the back end.

the intended purpose for SA on the front end is to REJECT above a certain score, and only forward BELOW that score, either tagged as (possible) spam for review, or ham.

for the time being, I've had to switch back to spamass-milter -- for this feature alone.
which is not an ideal solution imo.

now that i've had some time to watch this in production ... atm, for _my_ use case -- split front & back end postfix servers, with spamassassint-milter running on the front-end -- _way_ too much spam is being sent to the back end. the intended purpose for SA on the front end is to REJECT above a certain score, and only forward BELOW that score, either tagged as (possible) spam for review, or ham. for the time being, I've had to switch back to spamass-milter -- for this feature alone. which is not an ideal solution imo.
glts commented 2020-06-29 07:48:22 +00:00 (Migrated from gitlab.com)

I will look into implementing this.

I’m still interested in how you file spam into users’ spam folders. In my setup, I can already implement the reject-with-threshold use case:

  • configure a required_score of 10.0 in SpamAssassin
  • enable the -r option in the milter
  • check whether X-Spam-Level contains ***** in a global Sieve script and file into junk

The result is that spam above 10 gets rejected, spam above 5 goes into the spam folder, and the rest is delivered as ham.

I will look into implementing this. I’m still interested in how you file spam into users’ spam folders. In my setup, I can already implement the reject-with-threshold use case: * configure a `required_score` of 10.0 in SpamAssassin * enable the `-r` option in the milter * check whether `X-Spam-Level` contains `*****` in a global Sieve script and file into junk The result is that spam above 10 gets rejected, spam above 5 goes into the spam folder, and the rest is delivered as ham.
pgnd commented 2020-06-29 13:47:10 +00:00 (Migrated from gitlab.com)

Now that you mention that, I'm juggling my Bayes learning & sieve processing around ... I think that'll 'fix' my issue, so I do not need the reject limits from spamassassin-milter.

If this works -- it should -- it'll be cleaner!

question: why is it the case that

"error: The argument '--preserve-body' cannot be used with '--reject-spam'"

?

if i'm simply milter-rejecting spam with replycode+rejectcode+msg, why is there any modification of msg body?

Now that you mention that, I'm juggling my Bayes learning & sieve processing around ... I think that'll 'fix' my issue, so I do not need the reject limits from spamassassin-milter. If this works -- it should -- it'll be cleaner! question: why is it the case that "error: The argument '--preserve-body' cannot be used with '--reject-spam'" ? ***if i'm simply milter-rejecting spam with replycode+rejectcode+msg, why is there any modification of msg _body_?***
pgnd commented 2020-06-29 14:51:51 +00:00 (Migrated from gitlab.com)

i'm going to rescind this request.

your current reject + code/reply/msg @ >= SA 'required_score', is a simpler/better approach.

on my end, i'm cleaning up / simplifying :
-- rm'ing all afterQ & subsequent delivery A/S processing
-- rm'ing per-user Sieve; using global only
-- implementing quarantine of 'possible' spam -- < SA 'required score', but > 'suspected score', for message sizes > some_threshhold ... before final imap delivery.

with that^, spamassassin-milter should do its job quite nicely.

now, i watch logs for awhile ...

i'm going to rescind this request. your current reject + code/reply/msg @ >= SA 'required_score', is a simpler/better approach. on my end, i'm cleaning up / simplifying : -- rm'ing _all_ afterQ & subsequent delivery A/S processing -- rm'ing per-user Sieve; using global only -- implementing quarantine of 'possible' spam -- < SA 'required score', but > 'suspected score', for message sizes > some_threshhold ... before final imap delivery. with that^, spamassassin-milter should do its job quite nicely. now, i watch logs for awhile ...
glts commented 2020-06-29 15:05:06 +00:00 (Migrated from gitlab.com)

Good to hear. I would like to keep this issue open for a while, probs will think about it a little longer …

question: why is it the case that

"error: The argument '--preserve-body' cannot be used with '--reject-spam'"

?

if i'm simply milter-rejecting spam with replycode+rejectcode+msg, why is there any modification of msg body?

This combination of options is disallowed simply because it doesn’t make sense: if --reject-spam is set, then all spam is rejected, and will never proceed to the stage where the body would be replaced. In other words, the --preserve-body option is never even looked at when --reject-spam is set.

But perhaps forbidding this is confusing … in any case no functional impact whatsoever, just a bit of option validation.

Good to hear. I would like to keep this issue open for a while, probs will think about it a little longer … > question: why is it the case that > > "error: The argument '--preserve-body' cannot be used with '--reject-spam'" > > ? > > if i'm simply milter-rejecting spam with replycode+rejectcode+msg, why is there any modification of msg body? This combination of options is disallowed simply because it doesn’t make sense: if `--reject-spam` is set, then all spam is rejected, and will never proceed to the stage where the body would be replaced. In other words, the `--preserve-body` option is never even looked at when `--reject-spam` is set. But perhaps forbidding this is confusing … in any case no *functional* impact whatsoever, just a bit of option validation.
pgnd commented 2020-06-29 15:18:39 +00:00 (Migrated from gitlab.com)

keep this issue open for a while, probs will think about it a little longer …

+1

But perhaps forbidding this is confusing

it was a bit. as is the need for "--reject-spam" if

--reply-code / --reply-status-code / --reply-text 

are set.

I'd prefer the option to have

--reply-code / --reply-status-code / --reply-text 

set/defined in the .service file, but 'quickly' toggle spam rejection OFF by either

(1) removing the --reject-spam flag

or

(2) setting a boolean

--reject-spam {0,1}

is it necessary? no. more convenient? imo, yes.

i am also wondering if a sa-milter config file,

-C, --config-file

makes sense. as it stands, you have to change/reload the service unit file.

an option is to document/use an ENV file, containing OPTS, in the service file.

> keep this issue open for a while, probs will think about it a little longer … +1 > But perhaps forbidding this is confusing it was a bit. as is the need for "--reject-spam" if --reply-code / --reply-status-code / --reply-text are set. I'd _prefer_ the option to _have_ --reply-code / --reply-status-code / --reply-text set/defined in the .service file, but 'quickly' toggle spam rejection OFF by either (1) removing the --reject-spam flag or (2) setting a boolean --reject-spam {0,1} is it necessary? no. more convenient? imo, yes. i _am_ also wondering if a sa-milter config file, -C, --config-file makes sense. as it stands, you have to change/reload the service unit file. an option is to document/use an ENV file, containing OPTS, in the service file.
glts commented 2020-08-11 06:18:02 +00:00 (Migrated from gitlab.com)

changed title from Reject spam above a certain threshold to Reject spam {+scoring +}above a certain threshold

changed title from **Reject spam above a certain threshold** to **Reject spam {+scoring +}above a certain threshold**
glts commented 2021-08-07 09:35:44 +00:00 (Migrated from gitlab.com)

I’m closing this feature request.

The desired use case can already be implemented using existing options
of SpamAssassin and our milter’s -r option.

First, the header X-Spam-Flag: YES added by SpamAssassin determines if
SpamAssassin Milter will treat a message as spam. So the easiest
solution is to adjust SpamAssassin’s required_score threshold. For
example, with required_score 10.0, messages scoring 10 or above will
be rejected as spam. Messages with a score below 10 are accepted.

Then, if you need to make a further decision about the message coming
through, check the number of stars in the X-Spam-Level header. For
example, you could treat messages where X-Spam-Level contains the
string ***** as spam: such messages have a score >= 5. Where
X-Spam-Level does not contain that string, the score is below 5.

More complex requirements can be implemented via a plugin. An example is
shown below.

Given that ‘reject-with-score’ can be implemented with the facilities
available an additional option in SpamAssassin Milter is not needed.

/etc/spamassassin/local.cf:

loadplugin Mail::SpamAssassin::Plugin::SpammyFlag SpammyFlag.pm
add_header all Spammy-Flag _SPAMMYFLAG_

/etc/spamassassin/SpammyFlag.pm:

package Mail::SpamAssassin::Plugin::SpammyFlag;

use strict;
use warnings;

use Mail::SpamAssassin::Plugin;

our @ISA = qw(Mail::SpamAssassin::Plugin);

sub new {
  my ($class, $mailsa) = @_;

  $class = ref($class) || $class;
  my $self = $class->SUPER::new($mailsa);
  bless ($self, $class);

  return $self;
}

sub check_end {
  my ($self, $opts) = @_;

  my $pms = $opts->{permsgstatus};
  $pms->set_tag("SPAMMYFLAG", $pms->get_score() > 3 ? "YES" : "NO");
}

1;
I’m closing this feature request. The desired use case can already be implemented using existing options of SpamAssassin and our milter’s `-r` option. First, the header `X-Spam-Flag: YES` added by SpamAssassin determines if SpamAssassin Milter will treat a message as spam. So the easiest solution is to adjust SpamAssassin’s `required_score` threshold. For example, with `required_score 10.0`, messages scoring 10 or above will be rejected as spam. Messages with a score below 10 are accepted. Then, if you need to make a further decision about the message coming through, check the number of stars in the `X-Spam-Level` header. For example, you could treat messages where `X-Spam-Level` contains the string `*****` as spam: such messages have a score >= 5. Where `X-Spam-Level` does not contain that string, the score is below 5. More complex requirements can be implemented via a plugin. An example is shown below. Given that ‘reject-with-score’ can be implemented with the facilities available an additional option in SpamAssassin Milter is not needed. /etc/spamassassin/local.cf: ``` loadplugin Mail::SpamAssassin::Plugin::SpammyFlag SpammyFlag.pm add_header all Spammy-Flag _SPAMMYFLAG_ ``` /etc/spamassassin/SpammyFlag.pm: ```perl package Mail::SpamAssassin::Plugin::SpammyFlag; use strict; use warnings; use Mail::SpamAssassin::Plugin; our @ISA = qw(Mail::SpamAssassin::Plugin); sub new { my ($class, $mailsa) = @_; $class = ref($class) || $class; my $self = $class->SUPER::new($mailsa); bless ($self, $class); return $self; } sub check_end { my ($self, $opts) = @_; my $pms = $opts->{permsgstatus}; $pms->set_tag("SPAMMYFLAG", $pms->get_score() > 3 ? "YES" : "NO"); } 1; ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: glts/spamassassin-milter#4
No description provided.