Hi Cedric, The BayesStore API is designed in such a way that implementing a separate store for this sort of thing would be super easy. I suggest you subclass SQL and make the changes and call it something new.
I'm probably -1 on changing the top level, fairly generic, SQL.pm to do what you're asking, but would have to examine the change a little more before I made a final determination. Michael Cedric Lejeune wrote: > Hi list! > > First, this is my first submission to a project, so please excuse me if > I do something that do not follow the rules. > > I'm in charged with spamassassin (SA) and after an update from 3.0 to > 3.1, users starts to complain about SA improved effectiveness (to more > false positive). After some investigation, the problem seems to come > from bayesian filter. I use a global bayesian database (using > bayes_sql_override_username) but with customers coming from all over the > world, it seems a more fine grain filtering should be better. But it > seems it is currently impossible. I use SQL bayesian database setup and > it should have been great if it has offered the same kind of feature > that user_scores_sql_custom_query. What I wanted to do is make bayesian > filter retrieve database first for the current user, then for the > routing domain to which user belongs to, then fall back to global > database. For instance: > > [EMAIL PROTECTED] -> [EMAIL PROTECTED] -> * > > This way, it is possible for users to have their own personal bayes > database and if they do no want to create one or they do no have one > already, they still can benefit from others' databases. Grouping users > per routing domain is like grouping users per center of interest: if one > declares mail as spam, there is little few chance that others consider > it as ham. > > So this feature was not implemented yet and I have started writing it > myself. I warn you that I did not write a single perl line before and > "my" code is made of doc quotes and cut & paste. I've added the > following configuration option bayes_sql_custom_query to SA > configuration file. It acts the same way bayes_sql_override_username does. > > Please, let me know if this feature could be useful to others and/or if > it requires some rewriting. > > Please, find diff as attachments. They applied against SA 3.1.4 because > it is the SA version shipped with Debian testing at this time. > > Best regards =) > > cedric. > > > ------------------------------------------------------------------------ > > --- SpamAssassin/Conf.pm 2006-08-12 18:08:44.000000000 +0200 > +++ Conf.pm 2006-11-13 10:37:16.000000000 +0100 > @@ -2330,6 +2330,52 @@ > type => $CONF_TYPE_STRING > }); > > +#### Start of modification (last modified on 20061109). > +=item bayes_sql_custom_query query > + > +This option gives you the ability to create a custom SQL query to > +retrieve username. In order to work correctly your query should > +return only one value, the desired username. In addition, there > +are several "variables" that you can use as part of your query, > +these variables will be substituted for the current values right > +before the query is run. The current allowed variables are: > + > +=over 2 > + > +=item _USERNAME_ > + > +The current user's username. > + > +=item _DOMAIN_ > + > +The portion after the @ as derived from the current user's username, this > +value may be null. > + > +=back > + > +The query must be one continuous line in order to parse correctly. > + > +Here is an example query, please note that it is broken up for easy > +reading, in your config it should be one continuous line. > + > +=over 1 > + > +=item Current default query: > + > +C<SELECT username FROM bayes_vars WHERE username = '*' OR Username = > CONCAT('*@',_DOMAIN_) OR Username = _USERNAME_ ORDER BY username ASC> > + > +=back > + > +=cut > + > + push (@cmds, { > + setting => 'bayes_sql_custom_query', > + is_admin => 1, > + type => $CONF_TYPE_STRING > + }); > + > +#### End of modification. > + > =item bayes_sql_username_authorized ( 0 | 1 ) (default: 0) > > Whether to call the services_authorized_for_username plugin hook in BayesSQL. > > > ------------------------------------------------------------------------ > > --- SpamAssassin/BayesStore/SQL.pm 2005-08-11 09:00:37.000000000 +0200 > +++ SQL.pm.bayesstore 2006-11-13 11:15:43.000000000 +0100 > @@ -85,15 +85,70 @@ > if ($self->{bayes}->{conf}->{bayes_sql_override_username}) { > $self->{_username} = > $self->{bayes}->{conf}->{bayes_sql_override_username}; > } > +#### Start of modification (last modified on 20061113). > else { > - $self->{_username} = $self->{bayes}->{main}->{username}; > + if ($self->{bayes}->{conf}->{bayes_sql_custom_query}) { > > - # Need to make sure that a username is set, so just in case there is > - # no username set in main, set one here. > - unless ($self->{_username}) { > - $self->{_username} = "GLOBALBAYES"; > - } > + # Connect to database. > + return 0 unless ($self->_connect_db()); > + > + # Retrieve current username and play with it. > + my $username = $self->{bayes}->{main}->{username}; > + my ($mailbox, $domain) = split('@', $username); > + > + my $quoted_username = $self->{_dbh}->quote($username); > + my $quoted_domain = $self->{_dbh}->quote($domain); > + > + my $custom_query = > $self->{bayes}->{conf}->{bayes_sql_custom_query}; > + $custom_query =~ s/_USERNAME_/$quoted_username/g; > + $custom_query =~ s/_DOMAIN_/$quoted_domain/g; > + > + dbg("bayes: new: quoted_username = ".$quoted_username); > + dbg("bayes: new: quoted_domain = ".$quoted_domain); > + dbg("bayes: new: custom_query = ".$custom_query); > + > + # Prepare query. > + my $sth = $self->{_dbh}->prepare($custom_query); > + unless (defined($sth)) { > + dbg("bayes: new: SQL error: > ".$self->{_dbh}->errstr()); > + return 0; > + } > + > + # Execute query. > + my $rc = $sth->execute(); > + unless ($rc) { > + dbg("bayes: new: SQL error: > ".$self->{_dbh}->errstr()); > + return 0; > + } > + > + # Retrieve _username. > + my $ary_ref = $sth->fetchall_arrayref(); > + $self->{_username} = $ary_ref->[-1]->[-1]; > + > + dbg("bayes: new: _username = ".$self->{_username}); > + > + # Tell database server to free buffer allocated to query. > + $sth->finish(); > + > + # Close database connection. > + $self->{_dbh}->disconnect(); > + > + # Set _dbh to initial state. > + $self->{_dbh} = undef; > + > + } > +#### End of modification. > + else { > + $self->{_username} = $self->{bayes}->{main}->{username}; > + } > + } > + > + # Need to make sure that a username is set, so just in case there is > + # no username set in main, set one here. > + unless ($self->{_username}) { > + $self->{_username} = "GLOBALBAYES"; > } > + > dbg("bayes: using username: ".$self->{_username}); > > return $self;