Rules for mail
This page shows how to write a rule that sorts the mail that arrives: it marks it read, flags it, moves it to a folder or calls a Lua function. Rules are written in init.lua, in the scripts folder of the root (~/.config/tilde/scripts).
A first rule
Section titled “A first rule”rules.mail("newsletter", { from = "news@example.com", header = { ["List-Unsubscribe"] = true } }, { mark_read = true, move = "Newsletter" })rules.mail(name, conditions, actions) records a rule. The first argument is its name, the second says which mail it is for, the third says what to do. This rule matches a mail from news@example.com that has a List-Unsubscribe header, marks it read and moves it to the folder Newsletter, which Tilde creates when it is missing.
A rule works on the mail that arrives while Tilde runs, in tt or in tcli watch. To try it on the mail that is already there, see tcli rules. To see it fire, see tcli watch.
Conditions
Section titled “Conditions”Every condition that you give must hold. A text matches when the field contains it, ignoring case. A list of texts matches when any element does.
| Key | Tests | Accepts |
|---|---|---|
from |
the sender as Name <address>, or the address when there is no name |
a string or a list |
to |
the To header only; Cc does not count |
a string or a list |
subject |
the subject | a string or a list |
header |
the named headers | a table { [name] = text, list or true }; true only needs the header to be there |
account |
the id of the account, ignoring case | a string or a list |
folder |
the folder the mail arrived in, exactly (INBOX in any case) |
a string or a list |
The body of a message is never matched. to and header need the headers, so the message is read once, and only when some rule uses them. If it cannot be read, the rules that need the headers do not match.
Actions
Section titled “Actions”| Key | Does |
|---|---|
mark_read |
sets the Seen flag |
flag |
sets the Flagged flag |
move |
moves the mail to a folder of the same account; the folder is created when missing, except INBOX |
stop |
no rule after this one is looked at |
run |
calls a Lua function with the message |
A rule needs at least one condition and one action. stop = true alone is an action.
The folder a rule sees
Section titled “The folder a rule sees”A rule with no folder condition sees only the mail that arrives in INBOX. To sort mail that arrives in another folder, name it:
rules.mail("lists", { folder = "Lists", subject = "[tilde]" }, { flag = true })A mail that is already in the target folder is not moved.
Several rules
Section titled “Several rules”Rules are looked at in the order they were defined, and every rule that matches contributes:
mark_readandflagapply when any matching rule asks for them;moveis the one of the first matching rule that has one;- a matching rule with
stop = trueends the walk after its own actions. A rule that does not match contributes nothing, itsstopincluded.
A rule with the name of an existing one replaces it and keeps its place. Names are unique across mail and chat rules, so a mail rule with the name of a chat rule is refused. rules.off("newsletter") removes a rule and returns true, or false for a name that does not exist. rules.list() returns the names: { mail = { "newsletter" }, chat = { } }.
Call a function
Section titled “Call a function”rules.mail("invoices", { subject = "invoice" }, { run = function(msg) log.info("an invoice arrived in {Place}", msg.place) end,})The function gets a table with kind ("mail"), account, id, place (the folder), from, text (the subject), direct, mention and flags (a list of lower case names such as "seen"). place, id and flags are the ones the mail had when it arrived, before the rules moved or marked it.
The function runs after the other steps, in the order of the rules, and the call is queued, so it can run a moment after the mail was moved. A function that fails is a script error and does not stop the next function or the next rule. tcli rules does not call it.
When a rule is refused
Section titled “When a rule is refused”rules.mail refuses a rule that makes no sense and raises an error that names the rule and the key, never the value: an unknown key (the message lists the valid ones), a wrong type, a blank string, an empty list, a rule with no condition or no action. A refused rule is not registered. Run tcli scripts to see the error with its line.
A step that fails is logged and reported, and the next steps still run. The only exception is the move, which does not run when its folder cannot be created.
Two limits
Section titled “Two limits”- There is no
tagaction: the mail stores have flags, not keywords. - A moved mail can arrive again as a new mail in its target folder. A rule that names that folder sees it, so two rules that move mail back and forth between two folders loop.
Rules for chat are on Rules for chat. All the functions of the rules module are in the Lua API.