Rspamd composites are used to combine rules and create more complex rules. Composite rules are defined in the composites
section of the configuration.
You could use local.d/composites.conf
(which effects changes inside the composites
section) to define new composites or to change/override existing composites. Names of keys here define the name of the composite; the value of the key should be an object that defines the composite’s properties & expression, which is a combination of rules.
For example, you can define a composite that fires when two specific symbols are found and replace these symbols weights with its score:
TEST_COMPOSITE {
expression = "SYMBOL1 and SYMBOL2";
score = 5.0;
}
In this case, if a message contains both SYMBOL1
and SYMBOL2
, they will be replaced by the TEST_COMPOSITE
symbol. The weights of SYMBOL1
and SYMBOL2
will be subtracted from the metric accordingly.
You can use the following operations in a composite expression:
AND
&
- matches true only if both operands are trueOR
|
- matches true if any operands are trueNOT
!
- matches true if operand is falseYou can use braces to specify the priority of operations in composite rules. If braces are not used, the operators will be evaluated from left to right. For example:
TEST {
expression = "SYMBOL1 and SYMBOL2 and ( not SYMBOL3 | not SYMBOL4 | not SYMBOL5 )";
score = 10.0;
group = "Some group";
}
Composite rule can include another composites in the body. There is no restriction on the order in which composite rules are defined:
TEST1 {
expression = "SYMBOL1 AND TEST2";
}
TEST2 {
expression = "SYMBOL2 OR NOT SYMBOL3";
}
Composites should not be recursive, but Rspamd usually detects and prevents this automatically.
Note that symbols are removed after composites are applied. Therefore, you cannot rely on one composite to remove a symbol that is used in another composite.
You can also set up policies for composites regarding the symbols that are included in their expression. By default, Rspamd removes the symbols and weights that trigger the composite and replaces them with the symbol and weight of the composite itself. However, you can change this behavior in two ways.
~
: remove symbol only (weight is preserved)-
: do not remove anything (both weight and the symbol itself are preserved)^
: force removing of symbol and weight (by default, Rspamd prefers to leave symbols when some composite wants to remove and another composite wants to leave any of score/name pair)policy
option:
default
: default policy - remove weight and symbolremove_weight
: remove weight onlyremove_symbol
: remove symbol onlyleave
: leave both symbol and scoreE.g.
TEST_COMPOSITE {
expression = "SYMBOL1 and SYMBOL2";
policy = "leave";
}
TEST_COMPOSITE2 {
expression = "SYMBOL3 and SYMBOL4";
policy = "remove_weight";
}
Composites can record symbols in a metric, which can be used to create non-captive composites. For example, you have symbol A
and B
with weights W_a
and W_b
and a composite C
with weight W_c
.
C
is A & B
then if rule A
and rule B
matched then these symbols are removed and their weights are removed as well, leading to a single symbol C
with weight W_c
.C
is -A & B
, then rule A
is preserved, but the symbol C
is inserted. The weight of A
is preserved as well, so the total weight of -A & B
will be W_a + W_c
(weight of B
is still removed).C
is ~A & B
, then rule A
is removed, but it’s weight is preserved,
leading to the total weight of W_a + W_c
If you have multiple composites that include the same symbol, and one composite wants to remove the symbol while another composite wants to preserve it, the symbol will be preserved by default. Here are some more examples:
COMP1 {
expression = "BLAH | !DATE_IN_PAST";
}
COMP2 {
expression = "!BLAH | DATE_IN_PAST";
}
COMP3 {
expression = "!BLAH | -DATE_IN_PAST";
}
Both BLAH
and DATE_IN_PAST
exist in the message’s check results. However, COMP3
wants to preserve DATE_IN_PAST
so it will be saved in the output.
If we rewrite the previous example but replace -
with ~
then DATE_IN_PAST
will be removed (however, its weight won’t be removed):
COMP1 {
expression = "BLAH | !DATE_IN_PAST";
}
COMP2 {
expression = "!BLAH | DATE_IN_PAST";
}
COMP3 {
expression = "!BLAH | ~DATE_IN_PAST";
}
When we want to remove a symbol, despite other composites combinations, it is possible to add the prefix ^
to the symbol:
COMP1 {
expression = "BLAH | !DATE_IN_PAST";
}
COMP2 {
expression = "!BLAH | ^DATE_IN_PAST";
}
COMP3 {
expression = "!BLAH | -DATE_IN_PAST";
}
In this example COMP3
wants to save DATE_IN_PAST
once again, however COMP2
overrides this and removes DATE_IN_PAST
.
It is possible to include a group of symbols in a composite rule. This effectively means any matched symbol of the specified group:
g:<group>
- matches any symbolg+:<group>
- matches any symbol with positive scoreg-:<group>
- matches any symbol with negative scoreRemoval policies are applied only to the matched symbols and not to the entire group.
TEST2 {
expression = "SYMBOL2 & !g:mua & g+:fuzzy";
}
You can disable a composite rule by adding enabled = false
to its definition. For example, to disable the DKIM_MIXED
composite defined in the stock configuration, you can add the following to local.d/composites.conf
:
DKIM_MIXED {
enabled = false;
}
You can also disable composites from the users settings from Rspamd 1.9
.
Starting from version 2.0, it is also possible to augment the conditions of composite rules by adding required symbol options. For example, if a symbol SYM
can insert options opt1
and opt2
, you can create a composite expression that only triggers if the opt2
option is presented:
TEST2 {
expression = "SYM[opt2]";
}
[opt2]
syntax means a list of options allowed for a symbol to match. You can also add multiple options:
[opt1,opt2]
- it means that both opt1
and opt2
must be added by a symbol,
or even regular expressions:
[/opt\d/i]
- this must not include comma, even escaped…
or a mix of both:
[/opt\d/i, foo]
In all cases, all matches are required (not just in a single option, but in an options list for a symbol).
In the future, this feature may be extended to support fully functional expressions if needed.