return "unknown action";
}
+static double
+get_specific_action_score (const ucl_object_t *metric,
+ struct metric_action *action)
+{
+ const ucl_object_t *act, *sact;
+ double score;
+
+ if (metric) {
+ act = ucl_object_find_key (metric, "actions");
+ if (act) {
+ sact = ucl_object_find_key (act, str_action_metric (action->action));
+ if (sact != NULL && ucl_object_todouble_safe (sact, &score)) {
+ return score;
+ }
+ }
+ }
+
+ return action->score;
+}
+
gint
-check_metric_action (double score, double required_score, struct metric *metric)
+check_metric_action (struct rspamd_task *task,
+ double score, double *rscore, struct metric *metric)
{
struct metric_action *action, *selected_action = NULL;
double max_score = 0;
+ const ucl_object_t *ms = NULL;
int i;
- if (score >= required_score) {
- return METRIC_ACTION_REJECT;
- }
- else if (metric->actions == NULL) {
- return METRIC_ACTION_NOACTION;
- }
- else {
+ if (metric->actions != NULL) {
+ if (task->settings) {
+ ms = ucl_object_find_key (task->settings, metric->name);
+ }
+
for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) {
+ double sc;
+
action = &metric->actions[i];
- if (action->score < 0) {
+ sc = get_specific_action_score (ms, action);
+
+ if (sc < 0) {
continue;
}
- if (score >= action->score && action->score > max_score) {
+ if (score >= sc && sc > max_score) {
selected_action = action;
- max_score = action->score;
+ max_score = sc;
+ }
+
+ if (rscore != NULL && i == METRIC_ACTION_REJECT) {
+ *rscore = sc;
}
- }
- if (selected_action) {
- return selected_action->action;
- }
- else {
- return METRIC_ACTION_NOACTION;
}
}
+ if (selected_action) {
+ return selected_action->action;
+ }
+
+ return METRIC_ACTION_NOACTION;
}
gboolean
/*
* Get action for specific metric
*/
-gint check_metric_action (double score,
- double required_score,
+gint check_metric_action (struct rspamd_task *task,
+ double score,
+ double *rscore,
struct metric *metric);
#endif
struct metric *m;
gboolean is_spam;
enum rspamd_metric_action action = METRIC_ACTION_NOACTION;
- ucl_object_t *obj = NULL, *sobj;
- gdouble required_score;
+ ucl_object_t *obj = NULL, *sobj;;
gpointer h, v;
+ double required_score;
const gchar *subject;
gchar action_char;
m = mres->metric;
/* XXX: handle settings */
- required_score = m->actions[METRIC_ACTION_REJECT].score;
- is_spam = (mres->score >= required_score);
- action = check_metric_action (mres->score, required_score, m);
+ action = check_metric_action (task, mres->score, &required_score, m);
+ is_spam = (action == METRIC_ACTION_REJECT);
if (task->is_skipped) {
action_char = 'S';
}
/* Update stat for default metric */
metric_res = g_hash_table_lookup (task->results, DEFAULT_METRIC);
if (metric_res != NULL) {
- required_score =
- metric_res->metric->actions[METRIC_ACTION_REJECT].score;
- action = check_metric_action (metric_res->score, required_score,
+ action = check_metric_action (task, metric_res->score, &required_score,
metric_res->metric);
if (action <= METRIC_ACTION_NOACTION) {
task->worker->srv->stat->actions_stat[action]++;
}
else {
row->score = metric_res->score;
- row->required_score =
- metric_res->metric->actions[METRIC_ACTION_REJECT].score;
- row->action = check_metric_action (metric_res->score,
- metric_res->metric->actions[METRIC_ACTION_REJECT].score,
+ row->action = check_metric_action (task, metric_res->score,
+ &row->required_score,
metric_res->metric);
cbdata.pos = row->symbols;
cbdata.remain = sizeof (row->symbols);
if (task && metric_name) {
if ((metric_res =
g_hash_table_lookup (task->results, metric_name)) != NULL) {
- action = check_metric_action (metric_res->score,
- metric_res->metric->actions[METRIC_ACTION_REJECT].score,
+ action = check_metric_action (task, metric_res->score,
+ NULL,
metric_res->metric);
lua_pushstring (L, str_action_metric (action));
}