]> source.dussan.org Git - rspamd.git/commitdiff
* Add ability to assign several actions to one metric
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Thu, 15 Jul 2010 15:20:45 +0000 (19:20 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Thu, 15 Jul 2010 15:20:45 +0000 (19:20 +0400)
* Report action in rspamc protocol
* Mail::Rspamd::Client and rspamc can now understand Action header too
* Write action to log as well

perl/lib/Mail/Rspamd/Client.pm
rspamc.pl.in
src/cfg_xml.c
src/filter.h
src/protocol.c

index ca90b7421fee32bbadc49a6c8bcfe28da70d356d..d74484002d5c8de3a3a0fc2271f595146cfe156f 100644 (file)
@@ -943,6 +943,7 @@ sub _do_rspamc_command {
                        symbols => [],
                        urls => [],
                        messages => [],
+                       action => 'reject',
                };
                foreach my $line (@lines) {
                        if ($line =~ /^Urls: (.+)$/) {
@@ -979,6 +980,9 @@ sub _do_rspamc_command {
                                my $symref = $metrics{$cur_metric}->{'messages'};
                                push(@$symref, $1);
                        }
+                       elsif ($line =~ /^Action: (.+)/ && $cur_metric) {
+                               $metrics{$cur_metric}->{'action'} = $1;
+                       }
                        elsif ($line =~ /^${EOL}$/) {
                                last;
                        }
index a71e061f153d0ab5f4363432f5c9c56033bc227a..b2f6162d809289c92d0dbf3ca1eb00fd71eddef5 100755 (executable)
@@ -178,9 +178,22 @@ sub print_rspamc_result {
                        print "Symbols: ";
                        $terminal->Tputs( 'me', 1, *STDOUT );
                        print join("; ", @{ $result->{symbols} }) . "\n";
-                       print "Urls: " . join(", ", @{ $result->{urls} }) . "\n";
+
+                       $terminal->Tputs( 'md', 1, *STDOUT );
+                       print "Action: ";
+                       $terminal->Tputs( 'me', 1, *STDOUT );
+                       print "$result->{action}\n";
+
+                       $terminal->Tputs( 'md', 1, *STDOUT );
+                       print "Urls: ";
+                       $terminal->Tputs( 'me', 1, *STDOUT );
+                       print join(", ", @{ $result->{urls} }) . "\n";
+
                        foreach my $msg (@{ $result->{messages} }) {
-                               print "Message: $msg\n";
+                               $terminal->Tputs( 'md', 1, *STDOUT );
+                               print "Message: ";
+                               $terminal->Tputs( 'me', 1, *STDOUT );
+                               print "$msg\n";
                        }
                        print "\n\n";
                }
index c88bf60db9475068e6f0baa2b9ebbae2098df719..534bfa961c2be1d56602b83736efda2922bd48c8 100644 (file)
@@ -672,19 +672,20 @@ worker_handle_bind (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GH
        return TRUE;
 }
 
-gboolean 
-handle_metric_action (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+G_INLINE_FUNC gboolean
+check_action (const gchar *data, gint *result)
 {
-       struct metric                  *metric = ctx->section_pointer;
-
-       if (g_ascii_strcasecmp (data, "reject") == 0) {
-               metric->action = METRIC_ACTION_REJECT;
+       if (g_ascii_strncasecmp (data, "reject", sizeof ("reject") - 1) == 0) {
+               *result = METRIC_ACTION_REJECT;
        }
-       else if (g_ascii_strcasecmp (data, "greylist") == 0) {
-               metric->action = METRIC_ACTION_GREYLIST;
+       else if (g_ascii_strncasecmp (data, "greylist", sizeof ("greylist") - 1) == 0) {
+               *result = METRIC_ACTION_GREYLIST;
+       }
+       else if (g_ascii_strncasecmp (data, "add_header", sizeof ("add_header") - 1) == 0) {
+               *result = METRIC_ACTION_ADD_HEADER;
        }
-       else if (g_ascii_strcasecmp (data, "add_header") == 0) {
-               metric->action = METRIC_ACTION_ADD_HEADER;
+       else if (g_ascii_strncasecmp (data, "rewrite_subject", sizeof ("rewrite_subject") - 1) == 0) {
+               *result = METRIC_ACTION_REWRITE_SUBJECT;
        }
        else {
                msg_err ("unknown action for metric: %s", data);
@@ -693,6 +694,42 @@ handle_metric_action (struct config_file *cfg, struct rspamd_xml_userdata *ctx,
        return TRUE;
 }
 
+gboolean
+handle_metric_action (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct metric                  *metric = ctx->section_pointer;
+       gchar                          *p, *errstr;
+       gint                            res;
+       struct metric_action           *action;
+
+       /* First of all check whether we have data with weight (reject:50 for example) */
+       if ((p = strchr (data, ':')) == NULL) {
+               if (check_action (data, &res)) {
+                       metric->action = res;
+                       return TRUE;
+               }
+               return FALSE;
+       }
+       else {
+               if (!check_action (data, &res)) {
+                       return FALSE;
+               }
+               else {
+                       action = memory_pool_alloc (cfg->cfg_pool, sizeof (struct metric_action));
+                       action->action = res;
+                       errno = 0;
+                       action->score = strtod (p + 1, &errstr);
+                       if (errno != 0 || (errstr != NULL && *errstr != '\0')) {
+                               msg_err ("invalid double value: %s", data);
+                               return FALSE;
+                       }
+                       metric->actions = g_list_prepend (metric->actions, action);
+               }
+       }
+
+       return TRUE;
+}
+
 gboolean
 handle_metric_symbol (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
 {
index 24feaae9e93069ba803cf98309e4a6d0519bdd32..7996f16e66e2af4b26157ac4eb2f53d0830a0972 100644 (file)
@@ -33,24 +33,33 @@ struct symbol {
        GList *options;                                                                 /**< list of symbol's options                           */
 };
 
+enum rspamd_metric_action {
+       METRIC_ACTION_REJECT = 0,
+       METRIC_ACTION_SOFT_REJECT,
+       METRIC_ACTION_REWRITE_SUBJECT,
+       METRIC_ACTION_ADD_HEADER,
+       METRIC_ACTION_GREYLIST,
+       METRIC_ACTION_NOACTION
+};
+
+struct metric_action {
+       enum rspamd_metric_action action;
+       gdouble score;
+};
+
 /**
  * Common definition of metric
  */
 struct metric {
-       char *name;                                                                             /**< name of metric                                                     */
-       char *func_name;                                                                /**< name of consolidation function                     */
-       metric_cons_func func;                                                  /**< c consolidation function                           */
-       double grow_factor;                                                             /**< grow factor for metric                                     */
-       double required_score;                                                  /**< required score for this metric                     */
-       double reject_score;                                                    /**< reject score for this metric                       */
-       GHashTable *symbols;                                                    /**< weights of symbols in metric                       */
-       enum {
-               METRIC_ACTION_REJECT = 0,
-               METRIC_ACTION_SOFT_REJECT,
-               METRIC_ACTION_REWRITE_SUBJECT,
-               METRIC_ACTION_ADD_HEADER,
-               METRIC_ACTION_GREYLIST
-       } action;                                                                               /**< action to do by this metric                        */
+       char *name;                                                                             /**< name of metric                                                                     */
+       char *func_name;                                                                /**< name of consolidation function                                     */
+       metric_cons_func func;                                                  /**< c consolidation function                                           */
+       double grow_factor;                                                             /**< grow factor for metric                                                     */
+       double required_score;                                                  /**< required score for this metric                                     */
+       double reject_score;                                                    /**< reject score for this metric                                       */
+       GHashTable *symbols;                                                    /**< weights of symbols in metric                                       */
+       enum rspamd_metric_action action;                               /**< action to do by this metric by default                     */
+       GList *actions;                                                                 /**< actions that can be performed by this metric       */
 };
 
 /**
index 1b349b49e184b624fc3e5661f9abdaeb088c0cf0..f4e95b40f8b595453b983150e4b773b279414905 100644 (file)
@@ -591,18 +591,69 @@ show_metric_symbols (struct metric_result *metric_res, struct metric_callback_da
        return TRUE;
 }
 
+G_INLINE_FUNC const char *
+str_action_metric (enum rspamd_metric_action action)
+{
+       switch (action) {
+       case METRIC_ACTION_REJECT:
+               return "reject";
+       case METRIC_ACTION_SOFT_REJECT:
+               return "soft reject";
+       case METRIC_ACTION_REWRITE_SUBJECT:
+               return "rewrite subject";
+       case METRIC_ACTION_ADD_HEADER:
+               return "add header";
+       case METRIC_ACTION_GREYLIST:
+               return "greylist";
+       case METRIC_ACTION_NOACTION:
+               return "no action";
+       }
+
+       return "unknown action";
+}
+
+G_INLINE_FUNC gint
+check_metric_action (double score, double required_score, struct metric *metric)
+{
+       GList                          *cur;
+       struct metric_action           *action, *selected_action = NULL;
+
+       if (score >= required_score) {
+               return metric->action;
+       }
+       else if (metric->actions == NULL) {
+               return METRIC_ACTION_NOACTION;
+       }
+       else {
+               cur = metric->actions;
+               while (cur) {
+                       action = cur->data;
+                       if (score >= action->score) {
+                               selected_action = action;
+                       }
+                       cur = g_list_next (cur);
+               }
+               if (selected_action) {
+                       return selected_action->action;
+               }
+               else {
+                       return METRIC_ACTION_NOACTION;
+               }
+       }
+}
 
 static void
 show_metric_result (gpointer metric_name, gpointer metric_value, void *user_data)
 {
        struct metric_callback_data    *cd = (struct metric_callback_data *)user_data;
        struct worker_task             *task = cd->task;
-       int                             r;
+       int                             r = 0;
        char                            outbuf[OUTBUFSIZ];
        struct metric_result           *metric_res = (struct metric_result *)metric_value;
        struct metric                  *m;
        int                             is_spam = 0;
        double                          ms = 0, rs = 0;
+       enum rspamd_metric_action       action;
 
        if (! cd->alive) {
                return;
@@ -652,6 +703,7 @@ show_metric_result (gpointer metric_name, gpointer metric_value, void *user_data
                if (metric_res->score >= ms) {
                        is_spam = 1;
                }
+               action = check_metric_action (metric_res->score, ms, metric_res->metric);
                if (task->proto == SPAMC_PROTO) {
                        r = rspamd_snprintf (outbuf, sizeof (outbuf), "Spam: %s ; %.2f / %.2f" CRLF, (is_spam) ? "True" : "False", metric_res->score, ms);
                }
@@ -670,14 +722,15 @@ show_metric_result (gpointer metric_name, gpointer metric_value, void *user_data
                                r = rspamd_snprintf (outbuf, sizeof (outbuf), "Metric: %s; %s; %.2f / %.2f" CRLF, 
                                                (char *)metric_name, (is_spam) ? "True" : "False", metric_res->score, ms);
                        }
+                       r += rspamd_snprintf (outbuf + r, sizeof (outbuf) - r, "Action: %s" CRLF, str_action_metric(action));
                }
         if (!task->is_skipped) {
-                   cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "(%s: %s: [%.2f/%.2f/%.2f] [", 
-                               (char *)metric_name, is_spam ? "T" : "F", metric_res->score, ms, rs);
+                   cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "(%s: %c (%s): [%.2f/%.2f/%.2f] [",
+                               (char *)metric_name, is_spam ? 'T' : 'F', str_action_metric (action), metric_res->score, ms, rs);
         }
         else {
-                   cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "(%s: %s: [%.2f/%.2f/%.2f] [", 
-                               (char *)metric_name, "S", metric_res->score, ms, rs);
+                   cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "(%s: %c (%s): [%.2f/%.2f/%.2f] [",
+                               (char *)metric_name, 'S', metric_res->score, ms, rs);
         
         }
        }