tools/sieve-playground builds the vendored sieve-rs 0.7.3 (vnd.inbuxa.* names included) to WebAssembly, with a static page around it, for inbuxa Admin's Debug button on a Sieve script: until now that button sent the script to an outside site whose interpreter knows only upstream's extension names, so any script that requires vnd.inbuxa.* failed to compile there. Ported from the playground in the upstream sieve-rs repository's web/ directory (commit 549a2d57f7), which targets sieve-rs 1.x: - run.rs and handler.rs drive 0.7's event loop the way the server's delivery does, carrying on after a runtime error; llm_prompt compiles and answers false, as on a server without a model. - The expression functions are the server's own modules, included by path; tests fail if the list, ApplyString or the few functions copied from misc.rs/unicode.rs stop matching crates/common. - Built for wasm32-wasip1 rather than with wasm-bindgen: sieve-rs and mail-builder read the clock, which panics on wasm32-unknown-unknown. The page's worker answers the six WASI calls, giving the module the playground's current-time setting. shim/gethostname stands in for a crate with no WASI build. Nothing in vendor/ or crates/ changes. - The page carries no upstream names or links; storage keys and the samples are renamed to match. build.sh --admin <dir> stages the result into an inbuxa-admin checkout.
106 lines
3.2 KiB
Sieve
106 lines
3.2 KiB
Sieve
# Welcome to the Sieve playground!
|
|
#
|
|
# Sieve (RFC 5228) is the standard language for filtering email on the
|
|
# mail server. This script runs in your browser on the same interpreter
|
|
# your inbuxa server runs.
|
|
#
|
|
# Press Run (Ctrl+Enter or Cmd+Enter) to filter the message in the middle
|
|
# column, then open the Messages tab on the right to see what changed.
|
|
# Hover over any command to read its documentation.
|
|
#
|
|
# Everything runs locally in your browser: scripts and messages are saved
|
|
# in this browser only and are never sent to or stored on a server.
|
|
|
|
require ["envelope", "fileinto", "mailbox", "special-use", "imap4flags",
|
|
"variables", "relational", "comparator-i;ascii-numeric",
|
|
"spamtest", "spamtestplus", "date", "duplicate", "extlists",
|
|
"editheader", "mime", "foreverypart", "extracttext", "replace",
|
|
"vacation"];
|
|
|
|
# Drop the message if the very same one was delivered in the last hour.
|
|
# Press "Run again" to simulate a second delivery.
|
|
if duplicate :seconds 3600 {
|
|
discard;
|
|
stop;
|
|
}
|
|
|
|
# Anything the spam filter scored 80% or higher goes to Junk.
|
|
if spamtest :percent :value "ge" :comparator "i;ascii-numeric" "80" {
|
|
fileinto :specialuse "\\Junk" :create "Junk";
|
|
stop;
|
|
}
|
|
|
|
# Mailing lists get a folder of their own, such as "Lists/rust-users".
|
|
if header :matches "List-Id" "*<*.*>*" {
|
|
set :lower "list" "${2}";
|
|
fileinto :create "Lists/${list}";
|
|
stop;
|
|
}
|
|
|
|
# Capture a few details about the message with variables and wildcard
|
|
# matches. Variables first assigned inside a block only live in that block,
|
|
# so declare the ones used later at the top level.
|
|
set "domain" "unknown";
|
|
set "subject" "";
|
|
set "sender" "there";
|
|
if address :domain :matches "from" "*" {
|
|
set :lower "domain" "${1}";
|
|
}
|
|
if header :matches "Subject" "*" {
|
|
set "subject" "${1}";
|
|
}
|
|
if header :matches "From" "* <*>" {
|
|
set "sender" "${1}";
|
|
}
|
|
|
|
# People in your address book are flagged as important.
|
|
if address :all :list "from" "addrbook:default" {
|
|
addflag "\\Flagged";
|
|
}
|
|
|
|
# Tag messages that carry a PDF anywhere in their MIME structure.
|
|
if header :mime :anychild :contenttype "Content-Type" "application/pdf" {
|
|
addflag "$HasPDF";
|
|
}
|
|
|
|
# Note when the message arrived outside office hours.
|
|
if anyof (currentdate :value "lt" :comparator "i;ascii-numeric" "hour" "08",
|
|
currentdate :value "ge" :comparator "i;ascii-numeric" "hour" "18") {
|
|
addheader "X-After-Hours" "yes";
|
|
}
|
|
|
|
# Stamp the message so you can see it went through the filter.
|
|
addheader :last "X-Sieve-Filter" "inbuxa Sieve playground";
|
|
|
|
# Append a footer to every plain text part.
|
|
foreverypart {
|
|
if header :mime :subtype "Content-Type" "plain" {
|
|
extracttext "body";
|
|
replace text:
|
|
${body}
|
|
--
|
|
Filtered on its way in by a Sieve script.
|
|
.
|
|
;
|
|
}
|
|
}
|
|
|
|
# Let the sender know you are away, at most once a week per sender.
|
|
vacation :days 7 :subject "Away: ${subject}" text:
|
|
Hi ${sender},
|
|
|
|
Thanks for your message. I am out of the office this week and will
|
|
get back to you as soon as I return.
|
|
|
|
--
|
|
This reply was sent by a Sieve script.
|
|
.
|
|
;
|
|
|
|
# Important mail stays in the inbox, the rest is sorted by domain.
|
|
if hasflag "\\Flagged" {
|
|
keep;
|
|
} else {
|
|
fileinto :create "Contacts/${domain}";
|
|
}
|