diff options
-rw-r--r-- | src/libserver/task.c | 1 | ||||
-rw-r--r-- | src/libstat/stat_api.h | 7 | ||||
-rw-r--r-- | src/libstat/stat_process.c | 68 |
3 files changed, 76 insertions, 0 deletions
diff --git a/src/libserver/task.c b/src/libserver/task.c index 91ed48e86..bee7df22d 100644 --- a/src/libserver/task.c +++ b/src/libserver/task.c @@ -455,6 +455,7 @@ rspamd_task_process (struct rspamd_task *task, guint stages) case RSPAMD_TASK_STAGE_POST_FILTERS: rspamd_lua_call_post_filters (task); + rspamd_stat_check_autolearn (task); break; case RSPAMD_TASK_STAGE_LEARN: diff --git a/src/libstat/stat_api.h b/src/libstat/stat_api.h index a63ee3734..28fbf2429 100644 --- a/src/libstat/stat_api.h +++ b/src/libstat/stat_api.h @@ -68,6 +68,13 @@ rspamd_stat_result_t rspamd_stat_classify (struct rspamd_task *task, /** + * Check if a task should be learned and set the appropriate flags for it + * @param task + * @return + */ +gboolean rspamd_stat_check_autolearn (struct rspamd_task *task); + +/** * Learn task as spam or ham, task must be processed prior to this call * @param task task to learn * @param spam if TRUE learn spam, otherwise learn ham diff --git a/src/libstat/stat_process.c b/src/libstat/stat_process.c index 8d88540aa..6635f8aa7 100644 --- a/src/libstat/stat_process.c +++ b/src/libstat/stat_process.c @@ -26,6 +26,7 @@ #include "rspamd.h" #include "stat_internal.h" #include "libmime/message.h" +#include "libmime/filter.h" #include "libmime/images.h" #include "libserver/html.h" #include "lua/lua_common.h" @@ -642,6 +643,73 @@ rspamd_stat_learn (struct rspamd_task *task, return ret; } +gboolean +rspamd_stat_check_autolearn (struct rspamd_task *task) +{ + struct rspamd_stat_ctx *st_ctx; + struct rspamd_classifier *cl; + const ucl_object_t *obj; + struct metric_result *mres; + guint i; + gboolean ret = FALSE; + + g_assert (RSPAMD_TASK_IS_CLASSIFIED (task)); + st_ctx = rspamd_stat_get_ctx (); + g_assert (st_ctx != NULL); + + for (i = 0; i < st_ctx->classifiers->len; i ++) { + cl = g_ptr_array_index (st_ctx->classifiers, i); + + if (cl->cfg->opts) { + obj = ucl_object_find_key (cl->cfg->opts, "autolearn"); + + /* TODO: support range and lua for this option */ + if (ucl_object_type (obj) == UCL_BOOLEAN) { + if (ucl_object_toboolean (obj)) { + /* + * Default learning algorithm: + * + * - We learn spam if action is ACTION_REJECT + * - We learn ham if score is less than zero + */ + mres = g_hash_table_lookup (task->results, DEFAULT_METRIC); + + if (mres) { + mres->action = rspamd_check_action_metric (task, + mres->score, + &mres->required_score, + mres->metric); + + if (mres->action == METRIC_ACTION_REJECT) { + task->flags |= RSPAMD_TASK_FLAG_LEARN_SPAM; + msg_info_task ("<%s>: autolearn spam for classifier " + "'%s' as message's " + "action is reject, score: %.2f", + task->message_id, cl->cfg->name, + mres->score); + ret = TRUE; + break; + } + else if (mres->score < 0) { + task->flags |= RSPAMD_TASK_FLAG_LEARN_HAM; + msg_info_task ("<%s>: autolearn ham for classifier " + "'%s' as message's " + "score is negative: %.2f", + task->message_id, cl->cfg->name, + mres->score); + + ret = TRUE; + break; + } + } + } + } + } + } + + return ret; +} + /** * Get the overall statistics for all statfile backends * @param cfg configuration |