|
Sieve is a simplistic language for filtering email. It is easy to understand and simple to use. Have you ever received an out of office after sending someone an email? It could very well have been sent by a Sieve script.
In Sieve it's all about actions. When evaluating (or not evaluating) an email, what action do you want to take. The action can be based on a condition like a from address, header, etc... but doesn't have to be.
Actions come in three flavors. Must haves, Should haves and extentions. Must have actions are free to use on the fly but you need to declare should haves and extentions before you use them.
Must have actions are actions the Internet Engineering Task Force... a.k.a. The Force... has mandated that all implimentations of sieve MUST support in RFC 5228 which describes the Sieve mail filtering languge. Those actions are keep, discard and redirect. Since these actions are Must haves they don't need to be imported before they are used.
Should haves - the only Should have defined by The Force is fileinto. This action files a message into a mailbox/folder. It's a Should have because not all mailbox heirarchy is the same. Therefore, this action needs to be imported.
Extentions as defined by The Force are those actions designed outside of the original language. There is a list maintained by iana although, I'm not sure how accurate it is. All of these need to be imported also.
Now, how do we import the Should haves and extentions? That's where the Require statement comes in. The first part of the script.
|
|
CREATED 2021-10-28 09:17:51.0
|
012-00-02-2E
|
UPDATED 2021-10-28 09:18:08.0
|
|
|
|
Require is fairly straight forward... it's a type of forward declaration. It announces the action(s) you wish to take in the following rule(s). This is like a C include or a java import statement. It comes before the rule so the action is known before it's used. The Require statement is required for any action that is not a Must have .
Require goes like this:
Require "fileinto"
fileinto is the action that will be used. If there is more than one action or extention to import use square brackets and delimit (separate) the quoted strings with a comma.
Require [ "fileinto", "copy" ]
Now in the following rule(s) we can use the fileinto action that files our email into a folder and the copy action which makes a copy of the email like in a redirect.
|
|
CREATED 2021-10-28 09:29:54.0
|
012-00-02-3B
|
UPDATED 2021-10-28 10:11:44.0
|
|
|
|
The Action is what you want to do with the email. For example: discard.
There is one action that is implied. keep . Since it is implied you don't neet to say it. In other words: if we are still executing the script when all processing is finished... the keep action is executed, even if it isn't there.
As we have already discussed there are 3 internal commands that The Force has mandated Must be supported.
In addition to these there are a few dozen extentions past the fileinto that The Force indicates. Copy, envelope, environment, etc., etc.
So, let's look at an example of how an action would be implemented. Suppose you wanted to forward all your mail to jimbob in Accounting. It would look somthing like this...
redirect jimbob@example.com
That would forward all of your mail to jimbob. In other words, when you activate this script... you would no longer get any mail. Although, this illustrates how an action would be implemented, it isn't a good example because all your mail would go to jimbob@example.com
So how would be forward email to jimbob on a conditional basis? In other words how would we send some mail to Jim and still maintain our dignity?
The Answer is the control structures...
|
|
CREATED 2021-10-28 11:42:08.0
|
012-00-02-4A
|
UPDATED 2021-10-28 11:42:20.0
|
|
|
|
Control structures are necessary when you need to execute several actions OR you only want to execute an action if a condition is true.
There are three types of controls...
- require - This is how you delcare what actions you want to take (we already talked about this).
- if/elsif/else - This is a boolean logic structure
- stop - control to end all processing.
if/elsif/else - if is a conditional control statement also known as boolean logic. It specifies a condition and that condition must evaluate to be true or the action is not completed i.e. the block is skipped.
An example:
if ("a" equals "b"){ Shout "A has slipped a spot" } }
This condition will never be true becase a will never be equal to b. However, if the condition ever was true, the action within the curly braces known as "The Block" will be executed. That's how boolean logic works.
On the other hand, if we wanted to test for the opposite value i.e. if the condition was NOT true...
if ("a" equals "b"){ Shout "A has slipped a spot" } }else{ Shout "A is maintaining the top spot" }
In this case the second block of code, that after the else statement, will always execute because a will never equal b... but you get the picture.
Stop - The Stop control stops all processing period. Whatever happened, happened and what ever was going to happen will not. Pretty simple.
|
|
CREATED 2021-10-28 12:07:28.0
|
012-00-02-4B
|
UPDATED 2021-10-28 12:07:41.0
|
|
|
|
That's all fine a well, but how do we apply this to Sieve and mail filtering?
We use test commands as defined by The Force. Once again we return to the Must haves, and Should haves. These are the Must haves (tests that implementations MUST support)...
- address - one of the addresses. This one can be tricky because it only looks at email addresses. Not phrases as can be defined in an address header like From or To.
- allof - an inclusive group. Example allof(a, b, c) would return true if all of those were true. Comparable to a logical AND
- anyof - one of a group. Example anyof(a, b, e) would return true if either of these items were true. A logical OR
- exists - returns true if a header exists in the message. Example exists [ "from", "date" ]
- false - use this to force a false. Like a = b or 1 = 2. It always evaluates to false.
- header - used to evaluate a specific header. Example
header "From" would be used to evaluate the from header.
- not - negates a test. That is, it revereses the order.
not a = b would be true since a is not equal to b.
- size - Test for the size of the email being evaluated.
- true - use this to force a true. Like 1=1 or a=a. It always returns true.
And the Should haves (tests that implimentations SHOULD support:
- envelope - tests envelop information
What does this mean? It means to use envelope in a statement, you need require it because it's a Should Have while the top list can be used without requiring them becasue they are MUST haves..
|
|
CREATED 2021-10-28 12:24:57.0
|
012-00-02-4D
|
UPDATED 2021-10-28 12:26:15.0
|
|
|
|
There are two types of strings. Strings and String Lists
Strings - are individual strings that are enclosed in quotes. Example example.com or From
String Lists - an array of quotes strings enclosed in square brackets and delimited with a comma. Example [ example.com , From ]
|
|
CREATED 2021-10-28 13:36:45.0
|
012-00-02-52
|
UPDATED 2021-10-28 13:36:55.0
|
|
|
|
Thes are the =, <, > signs in a boolean logic statement. Except in Sieve they are a little different.
- :contains - partial match type. Matches on substrings.
header :contains "From" "example.com" . Does the From header contain the domain example.com
- :is - exact match type.
header :is "From" "jimbob@example.com" Is the value of the From header "jimbob@example.com"
- :matches same as
is but used with wildcard matching. header :matches "From" "*.example.com" will match all local parts from example.com OR header :matches "j??bob@example.com will mach on jimbob or jebbob.
Let us start using some of this stuff...
if header :contains "From" "example.com" { discard; <-- all actions must be terminated with a semicolon. }
If the from address contains the domain example.com, quietly toss this email into the bit bucket (that's the trash in programmereze).
|
|
CREATED 2021-10-28 12:58:36.0
|
012-00-02-4E
|
UPDATED 2021-10-28 13:36:58.0
|
|
|