Filter rules can be limited to a period: the rule dialog takes a start
and an end on the user's clock, the rule list shows whether a rule is
planned, active or expired, and the script tests the moment of
delivery with RFC 5260 currentdate in UTC. A rule is never written
without its period.
The vacation card becomes an out of office page: the period on top,
then the automatic reply and forwarding, each with its own switch.
Forwarding runs with or without the auto-reply, within the period,
never for spam, and keeps a copy here or not. Against the server's
redirect limit it counts as a rule ahead of all others, one that stops
the message unless it keeps a copy. The auto-reply can go to
internal or external senders only, told apart by the envelope sender
against the account's own domains. Both run from the filters script
that includes Stalwart's vacation script, which is put back in charge
when the server's own script takes over.
A script that uses any of this says metadata version 2, which older
builds leave alone instead of writing it back without these fields.
"Stop processing further rules" wrote no stop when the rule's last action
was "Delete silently" or "Reject". Both only cancel the implicit keep
(RFC 5228 4.4, RFC 5429): the script goes on, so a later rule still
filed the deleted or rejected message into a folder. Such a rule now
always writes a stop, unless its block has one already; rules below it
no longer run on its messages, which is what the option says.
Since 1.11.1 the "# Rule:" line carries the rule name with its runs of
whitespace collapsed, but the parser compared it with the name as
stored. A name like "Foo Bar", one with a tab or a trailing space, or
an empty one came back as someone else's block on every read, and every
save added one more copy. Both sides are now compared collapsed, and the
name is read from its own line only. That also drops the copies earlier
saves left, as long as the rule still exists under that name.
The rule metadata is JSON inside a Sieve bracket comment, so a `*/` in a
rule name, a value or the vacation text ended the comment early and
broke the script. A line break in a rule name escaped the `# Rule:`
comment line. And a header name outside `[A-Za-z0-9_-]` made Stalwart
(0.16 and 1.0) refuse the whole script, every other rule with it.
- `*/` in the metadata JSON is written as `*\/`, which `JSON.parse`
reads back as `/`, so older versions still parse it.
- Line breaks in a rule name are flattened on the `# Rule:` line, and
the parser matches its own blocks the same way.
- The rule editor refuses to save an invalid header name, with a
translated message. The generator skips such a rule (it stays in the
metadata, so it can be fixed) instead of writing a script the server
refuses.