1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
# Rspamd composite symbols
## Introduction
Rspamd composites are used to combine rules and create more complex rules.
Composite rules are defined by `composite` keys. The value of this key should be
an object that defines composite's name and value, which is the combination of rules
in a joint expression.
For example, you can define a composite that is added when two of symbols are found:
~~~ucl
composite {
name = "TEST_COMPOSITE";
expression = "SYMBOL1 and SYMBOL2";
}
~~~
In this case, if a message has `SYMBOL1` and `SYMBOL2` simultaneously then they are replaced by
symbol `TEST_COMPOSITE`. The weights of `SYMBOL1` and `SYMBOL2` are substracted from the metric
accordingly.
## Composite expression
You can use the following operations in a composite expression:
* `AND` `&` - matches true only if both of operands are true
* `OR` `|` - matches true if any of operands are true
* `NOT` `!` - matches true if operand is false
You also can use braces to define priorities. Otherwise operators are evaluated from left to right.
For example:
~~~ucl
composite {
name = "TEST";
expression = "SYMBOL1 and SYMBOL2 and ( not SYMBOL3 | not SYMBOL4 | not SYMBOL5 )";
}
~~~
Composite rule can include other composites in the body. There is no restriction of definition order:
~~~ucl
composite {
name = "TEST1";
expression = "SYMBOL1 AND TEST2";
}
composite {
name = "TEST2";
expression = "SYMBOL2 OR NOT SYMBOL3";
}
~~~
Composites should not be recursive and it is normally detected by rspamd.
## Composite weights rules
Composites can leave the symbols in a metric or leave their weights. That could 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`.
* If `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`.
* If `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`.
* If `C` is `~A & B`, then rule `A` is *removed* but its weight is *preserved*,
leading to a single symbol `C` with weight `W_a + W_c`
When you have multiple composites which include the same symbol and some
composites want to remove symbol and other want to preserve it then a symbol is
preserved by default. Here are some more examples:
~~~ucl
composite "COMP1" {
expression = "BLAH || !DATE_IN_PAST";
}
composite "COMP2" {
expression = "!BLAH || DATE_IN_PAST";
}
composite "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 `-` to `~` then `DATE_IN_PAST`
will be removed (however, its weight won't be removed):
~~~ucl
composite "COMP1" {
expression = "BLAH || !DATE_IN_PAST";
}
composite "COMP2" {
expression = "!BLAH || DATE_IN_PAST";
}
composite "COMP3" {
expression = "!BLAH || ~DATE_IN_PAST";
}
~~~
When we want to remove symbol despite of other composites combinations it is
also possible to add prefix '^' to this symbol:
~~~ucl
composite "COMP1" {
expression = "BLAH || !DATE_IN_PAST";
}
composite "COMP2" {
expression = "!BLAH || ^DATE_IN_PAST";
}
composite "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`.
## Composites with symbol groups
It is also possible to include the whole group of symbols to a composite rule. This
efficiently means **any** symbol of the specified group:
~~~ucl
composite {
name = "TEST2";
expression = "SYMBOL2 && !g:mua";
}
~~~
|