388 lines
9.9 KiB
Sieve
388 lines
9.9 KiB
Sieve
# Sieve syntax highlighting test
|
|
# see RFC 5228
|
|
|
|
# comments §2.3.
|
|
|
|
# Single line with alerts TODO ###
|
|
/*
|
|
Multiline comment with alerts FIXME
|
|
this also should be folding region
|
|
*/
|
|
|
|
# literal data §2.4.
|
|
# numbers §2.4.1.
|
|
42
|
|
100K
|
|
10M
|
|
3G
|
|
|
|
# strings §2.4.2.
|
|
"string"
|
|
"string\nwith\"special chars"
|
|
# not a string
|
|
"multi \
|
|
line \
|
|
#with\a \
|
|
continuation"
|
|
# not a string
|
|
text:
|
|
Multiline
|
|
string\" "with quotes"
|
|
or # comments
|
|
this should also be a folding region
|
|
.dot
|
|
..dot
|
|
dotstuffed dot:
|
|
..
|
|
ending with a single .
|
|
.
|
|
|
|
# encoded characters §2.4.2.4.
|
|
# valid
|
|
"$${hex:24 24}"
|
|
"${unicode:40}"
|
|
"$${hex:40}"
|
|
"${hex: da }"
|
|
"${hex:FE }"
|
|
"${HEX: 40}"
|
|
"${unicode:40}"
|
|
"${UNICODE:40}"
|
|
"${UnICoDE:0000040}"
|
|
"${Unicode:ff}"
|
|
#invalid
|
|
"${hex:40"
|
|
"${hex:4${hex:30}}"
|
|
"${ unicode:40}"
|
|
"${Unicode:Cool}"
|
|
# semantic errors, syntactically correct
|
|
"${hex:400}"
|
|
"${unicode:200000}"
|
|
"${Unicode:DF01}"
|
|
|
|
# test lists §2.5.1
|
|
if anyof (not exists ["From", "Date"],
|
|
header :contains "from" "fool@example.com") {
|
|
discard;
|
|
}
|
|
if allof (not exists ["From", "Date"],
|
|
header :contains "from" "fool@example.com") {
|
|
discard;
|
|
}
|
|
|
|
# match types §2.7.1.
|
|
:contains
|
|
:matches
|
|
:is
|
|
|
|
# comparators §2.7.3.
|
|
if header :contains :comparator "i;octet" "Subject" "MAKE MONEY FAST" {
|
|
discard;
|
|
}
|
|
|
|
# comparison against addresses §2.7.4.
|
|
:localpart
|
|
:domain
|
|
:all
|
|
|
|
# commands §2.9.
|
|
keep;
|
|
fileinto "inbox.bla";
|
|
redirect "test@kde.org";
|
|
discard;
|
|
|
|
# control if §3.1.
|
|
# this also should create folding regions
|
|
if header :contains "from" "foo" {
|
|
discard;
|
|
} elsif header :contains ["subject"] ["$$$"] {
|
|
discard;
|
|
} else {
|
|
fileinto "INBOX";
|
|
}
|
|
|
|
# control require §3.2.
|
|
require "fileinto";
|
|
require ["vacation", "imapflags"];
|
|
|
|
# control stop §3.3.
|
|
stop;
|
|
|
|
# test commands §5.
|
|
address
|
|
allof
|
|
anyof
|
|
exists
|
|
false
|
|
header
|
|
not
|
|
size
|
|
true
|
|
|
|
# test address §5.1.
|
|
if address :is :all "from" "kde@example.com" {
|
|
discard;
|
|
} elsif address :domain :is ["From", "To"] "example.com" { # comment
|
|
keep; # comment
|
|
}
|
|
|
|
# test envelope §5.4.
|
|
if envelope :all :is "from" "kde@example.com" {
|
|
discard;
|
|
}
|
|
|
|
# test exists §5.5.
|
|
if not exists ["From","Date"] {
|
|
discard;
|
|
}
|
|
|
|
# test header §5.7.
|
|
not header :matches "Cc" "?*"
|
|
|
|
# test size §5.9.
|
|
if size :over 500K { discard; }
|
|
if size :under 1M { keep; } else { discard; }
|
|
|
|
|
|
/*
|
|
* Extensions
|
|
* see https://www.iana.org/assignments/sieve-extensions/sieve-extensions.xhtml
|
|
*/
|
|
|
|
# Body RFC5173
|
|
:raw
|
|
:content
|
|
:text
|
|
if body :raw :contains "MAKE MONEY FAST" {
|
|
discard;
|
|
}
|
|
if body :content "text" :contains ["bla", "blub"] {
|
|
fileinto "inbox.foo";
|
|
}
|
|
|
|
# Convert RFC6558
|
|
require ["convert"];
|
|
convert "image/tiff" "image/jpeg" ["pix-x=320","pix-y=240"];
|
|
|
|
# Copy RFC3894
|
|
require ["copy", "fileinto"];
|
|
fileinto :copy "incoming";
|
|
|
|
# Date RFC5260
|
|
require ["date", "relational", "fileinto"];
|
|
if allof(header :is "from" "boss@example.com",
|
|
date :value "ge" :originalzone "date" "hour" "09",
|
|
date :value "lt" :originalzone "date" "hour" "17")
|
|
{ fileinto "urgent"; }
|
|
if anyof(date :is "received" "weekday" "0",
|
|
date :is "received" "weekday" "6")
|
|
{ fileinto "weekend"; }
|
|
if anyof(currentdate :is "weekday" "0",
|
|
currentdate :is "weekday" "6",
|
|
currentdate :value "lt" "hour" "09",
|
|
currentdate :value "ge" "hour" "17")
|
|
{ redirect "pager@example.com"; }
|
|
if allof(currentdate :value "ge" "date" "2007-06-30",
|
|
currentdate :value "le" "date" "2007-07-07")
|
|
{ vacation :days 7 "I'm away during the first week in July."; }
|
|
|
|
require ["date", "variables", "fileinto"];
|
|
if currentdate :matches "month" "*" { set "month" "${1}"; }
|
|
if currentdate :matches "year" "*" { set "year" "${1}"; }
|
|
fileinto "${month}-${year}";
|
|
|
|
require ["variables", "date", "editheader"];
|
|
if currentdate :matches "std11" "*" {addheader "Processing-date" "${0}";}
|
|
|
|
require ["date", "relational", "index"];
|
|
if date :value "gt" :index 2 :zone "-0500" "received" "iso8601" "2007-02-26T09:00:00-05:00"
|
|
{ redirect "aftercutoff@example.org"; }
|
|
|
|
if header :index 1 :matches "received" "*(* [*.*.*.*])*" {}
|
|
|
|
# Duplicate RFC7352
|
|
require ["duplicate", "variables"];
|
|
if duplicate { discard; }
|
|
if duplicate :header "message-id" { discard; }
|
|
if header :matches "message-id" "*" {
|
|
if duplicate :uniqueid "${0}" { discard; }
|
|
}
|
|
|
|
# Editheader RFC5293
|
|
addheader "X-Hello" "World";
|
|
deleteheader :index 1 "X-Hello";
|
|
|
|
# Enclose RFC5703
|
|
:mime
|
|
:anychild
|
|
:type
|
|
:subtype
|
|
:contenttype
|
|
:param
|
|
replace
|
|
enclose
|
|
extracttext
|
|
if header :mime :type "Content-Type" "image" {}
|
|
replace "Executable attachment removed by user filter";
|
|
foreverypart {
|
|
if header :mime :param "filename" :matches ["Content-Type", "Content-Disposition"]
|
|
["*.com", "*.exe", "*.vbs", "*.scr", "*.pif", "*.hta", "*.bat", "*.zip" ] {
|
|
# these attachment types are executable
|
|
enclose :subject "Warning" text:
|
|
WARNING! The enclosed message contains executable attachments.
|
|
These attachment types may contain a computer virus program
|
|
that can infect your computer and potentially damage your data.
|
|
.
|
|
;
|
|
break;
|
|
}
|
|
}
|
|
extracttext :first 100 "msgcontent";
|
|
|
|
# Notify RFC5435
|
|
notify :importance "1" :message "This is probably very important" "mailto:kde@example.com";
|
|
notify :message "${from_addr}${env_from}: ${subject}" "mailto:kde@example.com";
|
|
if not valid_notify_method ["mailto:", "http://gw.example.net/notify?test"] { stop; }
|
|
if notify_method_capability "xmpp:tim@example.com?message;subject=SIEVE" "Online" "yes" {}
|
|
set :encodeurl "body_param" "stuff";
|
|
|
|
# Envelope DSN RFC6009
|
|
if envelope "notify" "SUCCESS" {}
|
|
if allof (envelope "notify" "FAILURE", envelope :comparator "i;ascii-numeric" :count "eq" "notify" "1") {}
|
|
if envelope :matches "orcpt" "rfc822;*@example.com" {}
|
|
if anyof (envelope :contains "bytimerelative" "-", envelope :value "eq" :comparator "i;ascii-numeric" "bytimerelative" "0") {}
|
|
redirect :copy :notify "NEVER" "elsewhere@example.com";
|
|
redirect :copy :bytimerelative 600 "cellphone@example.com";
|
|
redirect :copy :bytimeabsolute "${date}T20:00:00${zone}" :bymode "return" "cellphone@example.com";
|
|
|
|
# Environment RFC5183
|
|
if environment :contains "item" "" {}
|
|
|
|
# Reject RFC5429
|
|
ereject "I no longer accept mail from this address";
|
|
reject text:
|
|
Your message is too big. If you want to send me a big attachment,
|
|
put it on a public web site and send me a URL.
|
|
.
|
|
;
|
|
|
|
# External Lists RFC6134
|
|
if envelope :list "from" ":addrbook:default" {}
|
|
if currentdate :list "date" "tag:example.com,2011-01-01:localHolidays" {}
|
|
if allof (envelope :detail "to" "mylist", header :list "from" "tag:example.com,2010-05-28:mylist") {
|
|
redirect :list "tag:example.com,2010-05-28:mylist";
|
|
}
|
|
if string :list "${ip}" "tag:example.com,2011-04-10:DisallowedIPs" {}
|
|
if header :mime :param "filename" :list ["Content-Type", "Content-Disposition"] "tag:example.com,2011-04-10:BadFileNameExts" {}
|
|
|
|
# ihave RFC5463
|
|
if ihave "fileinto" {}
|
|
error "failed!";
|
|
|
|
# IMAP Sieve RFC6785
|
|
if anyof (environment :is "imap.cause" "APPEND", environment :is "imap.cause" "COPY") {
|
|
if environment :is "imap.mailbox" "ActionItems" {
|
|
redirect :copy "actionitems@example.com";
|
|
}
|
|
}
|
|
|
|
# IMAP4 Flags RFC5232
|
|
setflag "\\Deleted";
|
|
setflag "flagvar" "\\Flagged";
|
|
addflag "flagvar" "\\Deleted";
|
|
addflag "flagvar" ["\\Deleted", "\\Answered"];
|
|
removeflag "flagvar" "$MDNRequired";
|
|
hasflag :contains "MyVar" "Junk"
|
|
hasflag :contains "${MyVar}" ["label", "forward"]
|
|
hasflag :count "ge" :comparator "i;ascii-numeric" "MyFlags" 2
|
|
fileinto :flags "\\Deleted" "INBOX.bla";
|
|
|
|
# Include RFC6609
|
|
include :personal "always_allow";
|
|
include :global "spam_tests";
|
|
return;
|
|
global "i_am_on_vacation";
|
|
set "global.i_am_on_vacation" "1";
|
|
|
|
# Mailbox RFC5490
|
|
if mailboxexists "bla" {}
|
|
fileinto :create "inbox.bla";
|
|
if metadata :is "INBOX" "/private/vendor/vendor.isode/auto-replies" "on" {}
|
|
if metadataexists "INBOX" "/private/vendor/foo" {}
|
|
if servermetadata :matches "/private/vendor/vendor.isode/notification-uri" "*" {}
|
|
if servermetadataexists "/private/vendor/foo" {}
|
|
|
|
# Regexp (draft)
|
|
if not address :regex ["to", "cc", "bcc"] "me(\\+.*)?@company\\.com" {}
|
|
|
|
# Relational RFC5231
|
|
if address :count "ge" :comparator "i;ascii-numeric" ["to", "cc"] ["3"] {}
|
|
if header :value "lt" :comparator "i;ascii-numeric" ["x-priority"] ["3"] {}
|
|
|
|
# Spamtest RFC5235
|
|
if spamtest :value "eq" :comparator "i;ascii-numeric" "0" {}
|
|
elsif spamtest :value "ge" :comparator "i;ascii-numeric" "3" {}
|
|
elsif spamtest :percent :value "lt" :comparator "i;ascii-numeric" "37" {}
|
|
if virustest :value "eq" :comparator "i;ascii-numeric" "4" {}
|
|
|
|
# Subaddress RFC5233
|
|
if envelope :user "to" "postmaster" {}
|
|
if envelope :detail "to" "mta-filters" {}
|
|
|
|
# Vacation RFC5230
|
|
vacation "I'm out";
|
|
vacation :subject "Automatic response to: ${1}"
|
|
"I'm away -- send mail to foo in my absence";
|
|
vacation :handle "ran-away" "I'm out";
|
|
vacation :mime text:
|
|
Content-Type: multipart/alternative; boundary=foo
|
|
|
|
--foo
|
|
|
|
Hello ${sender}, I'm at the beach relaxing.
|
|
|
|
--foo
|
|
Content-Type: text/html; charset=us-ascii
|
|
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
|
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
<HTML><HEAD><TITLE>How to relax</TITLE>
|
|
<BASE HREF="http://home.example.com/pictures/"></HEAD>
|
|
<BODY><P>I'm at the <A HREF="beach.gif">beach</A> relaxing.
|
|
</BODY></HTML>
|
|
|
|
--foo--
|
|
.
|
|
;
|
|
vacation :days 23 :addresses ["kde@example.edu"] "I'm away until October 19.";
|
|
|
|
# Vacation Seconds RFC6131
|
|
vacation :addresses ["kde@example.edu"] :seconds 1800
|
|
"I am in a meeting, and do not have access to email.";
|
|
|
|
# Variables RFC5229
|
|
"&%${}!" # invalid
|
|
"${doh!}" #invalid
|
|
"${company}"
|
|
"bla ${var42} blub"
|
|
"${1}"
|
|
"${BAD${Company}" # second one is the variable
|
|
"${President, ${Company} Inc.}" # inner one is the variable
|
|
set "var" "value";
|
|
set "var2" "${var}";
|
|
|
|
set "a" "juMBlEd lETteRS";
|
|
set :length "b" "${a}";
|
|
set :lower "b" "${a}";
|
|
set :upperfirst "b" "${a}";
|
|
set :upperfirst :lower "b" "${a}";
|
|
set :quotewildcard "b" "Rock*";
|
|
set :lowerfirst "b" "${a}";
|
|
|
|
if string :matches " ${state} " "* pending *" {}
|
|
|
|
# Dovecot debug extension
|
|
require "vnd.dovecot.debug";
|
|
if header :contains "subject" "hello" {
|
|
debug_log "Subject header contains hello!";
|
|
}
|