phpgroupware-developers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Phpgroupware-developers] hello to Sieve


From: Dan Kuykendall (Seek3r)
Subject: Re: [Phpgroupware-developers] hello to Sieve
Date: Sun, 25 Nov 2001 09:52:31 -0800

Sieve looks like a good plan. I have read a bit thru the html summary
and it looks like it should work.

Im looking forward to this very much.

Seek3r

Tony (Angles) Puglisi wrote:
> 
> Welcome to your new proposed filtering scheme: Sieve.
> (no code committed yet - don't worry :)
> 
> Sieve has been in development for at least 6 years and describes a common 
> scheme for
> filtering mail. I don't  like to write docs nor reinvent the wheel, so I 
> choose
> Sieve, as much has already been written about it (ex. rfc3028).
> 
> Grabbing headers, unfolding them, and examining them is relatively easy, even 
> the
> regex is not that big of a deal. Writing a hard coded filter system is, 
> therefor,
> not that hard. However, writing something that is portable, flexible, and
> standardized is hard.
> 
> Sieve scripts can be used as is on the server side if Sieve is supported 
> there, such
> as with Cyrus Imap. Additionally, since it is standardized, it should provide 
> as
> some sort of lingua franca that can be translated into other filtering 
> schemes,
> server side or not (maildrop, procmail, etc...).
> 
> Sieve is extensible, as my summary shows my intent to include php's POSIX and 
> perl
> regex in our implementation.
> 
> I'll probably start with a small subset of Sieve, so that if you'all decide 
> that
> Sieve blows, the code will still be applicable. For example, instead of 
> "discard"
> I'll probably make you "fileto" some sort of trash folder, we don't want to 
> delete
> important mail during the beta phase, do we :)
> 
> Sieve docs are long on words and short on "action" so I paste my summary 
> below. If
> you like to read, you may find some Sieve docs at:
> 
> Sieve Home Page
> http://www.cyrusoft.com/sieve
> 
> Sieve Whitepaper
> http://www.cyrusoft.com/sieve/sievewhitepaper.pdf
> 
> RFC 3028
> http://www.ietf.org/rfc/rfc3028.txt
> 
> BEGIN SUMMARY: (you may wish to use the "view unformatted" option for this)
> 
> =====  String Comparison  =====
> 
> Three kinds
>         :is                     exact match
> 
>         :contains       substring match
>                 :comparator "i;ascii-casemap"   case-insensitive comparison
>                         (which treats uppercase and lowercase characters in
>                         the ASCII subset of UTF-8 as the same)
> 
>                 :comparator "i;octet"           case-sensitive comparison
>                         (simply compares octets)
> 
>                         NOTES:
>                         - default comparator if unspecified is 
> "i;ascii-casemap"
>                         - when specifying a name of a header line (ex. 
> "From"),
>                                 the comparator is always "i;ascii-casemap" 
> case insensitive
>                         - Comparators other than i;octet and i;ascii-casemap 
> must
>                                 be declared with require, as they are 
> extensions.
> 
>         :matches        wildcard glob-style match
>                 using the characters "*" and "?".  "*" matches zero or more
>                 characters, and "?" matches a single character.
> 
>         ANGLES PLANNED EXTNSIONS:
>         :ereg           php POSIX regex
>         :preg           php Perl regex
> 
> =====  Addresses Comparisons  =====
> 
>         :localpart              acts on the local-part (left-side of the @ 
> sign)
>         :domain                 acts on the domain part (right-side of the @ 
> sign)
>         :all                    acts on the whole address
> 
> =====  Blocks  =====
> 
> Blocks are sets of commands enclosed within curly braces.  Blocks are
> supplied to commands so that the commands can implement control
> commands.
> 
> A control structure is a command that happens to take a test and a
> block as one of its arguments; depending on the result of the test
> supplied as another argument, it runs the code in the block some
> number of times.
> 
> With the commands supplied in this memo, there are no loops.  The
> control structures supplied--if, elsif, and else--run a block either
> once or not at all.  So there are two arguments, the test and the
> block.
> 
> =====  Control Structures: If, Require, Stop  =====
> 
> Syntax:   if
> Syntax:   elsif
> Syntax:   else
> 
>         There is no sub if-then blocks, just linear if--else(if)*--(end)
> 
> Syntax:   stop
> 
>    The "stop" action ends all processing.  If no actions have been
>    executed, then the keep action is taken.
> 
> Syntax:   require
> 
>    The require command, if present, MUST be used before anything other
>    than a require can be used.  An error occurs if a require appears
>    after a command other than require.
> 
>    Example:  require ["fileinto", "reject"];
> 
>    Example:  require "fileinto";
>              require "vacation";
> 
> =====  Action Commands  =====
> 
> Five available: keep, fileinto, redirect, reject, discard
> 
> Syntax:   keep  =========================================
> 
>    The "keep" action is whatever action is taken in lieu of all other
>    actions, if no filtering happens at all; generally, this simply means
>    to file the message into the user's main mailbox.  This command
>    provides a way to execute this action without needing to know the
>    name of the user's main mailbox, providing a way to call it without
>    needing to understand the user's setup, or the underlying mail
>    system.
> 
> Syntax:   fileinto   =========================================
> 
>    The "fileinto" action delivers the message into the specified folder.
>    Implementations SHOULD support fileinto, but in some environments
>    this may be impossible.
> 
>    The capability string for use with the require command is "fileinto".
> 
>    In the following script, message A is filed into folder
>    "INBOX.harassment".
> 
>    Example:  require "fileinto";
>              if header :contains ["from"] "coyote" {
>                 fileinto "INBOX.harassment";
>              }
> 
> Syntax:   redirect   =========================================
> 
>    The "redirect" action is used to send the message to another user at
>    a supplied address, as a mail forwarding feature does.  The
>    "redirect" action makes no changes to the message body or existing
>    headers, but it may add new headers.  The "redirect" modifies the
>    envelope recipient.
> 
>    The redirect command performs an MTA-style "forward"--that is, what
>    you get from a .forward file using sendmail under UNIX.  The address
>    on the SMTP envelope is replaced with the one on the redirect command
>    and the message is sent back out.  (This is not an MUA-style forward,
>    which creates a new message with a different sender and message ID,
>    wrapping the old message in a new one.)
> 
>    A simple script can be used for redirecting all mail:
> 
>    Example:  redirect "address@hidden";
> 
>    Implementations SHOULD take measures to implement loop control,
>    possibly including adding headers to the message or counting received
>    headers.  If an implementation detects a loop, it causes an error.
> 
> Syntax:   reject  =========================================
> 
>    The optional "reject" action refuses delivery of a message by sending
>    back an [MDN] to the sender.  It resends the message to the sender,
>    wrapping it in a "reject" form, noting that it was rejected by the
>    recipient.  In the following script, message A is rejected and
>    returned to the sender.
> 
>    Example:  if header :contains "from" "address@hidden" {
>                 reject "I am not taking mail from you, and I don't want
>                 your birdseed, either!";
>              }
> 
>    A reject message MUST take the form of a failure MDN as specified  by
>    [MDN].    The  human-readable  portion  of  the  message,  the  first
>    component of the MDN, contains the human readable message  describing
>    the  error,  and  it  SHOULD  contain  additional  text  alerting the
>    original sender that mail was refused by a filter.  This part of  the
>    MDN might appear as follows:
> 
>    ------------------------------------------------------------
>    Message was refused by recipient's mail filtering program.  Reason
>    given was as follows:
> 
>    I am not taking mail from you, and I don't want your birdseed,
>    either!
>    ------------------------------------------------------------
> 
>    The MDN action-value field as defined in the MDN specification MUST
>    be "deleted" and MUST have the MDN-sent-automatically and automatic-
>    action modes set.
> 
>    Because some implementations can not or will not implement the reject
>    command, it is optional.  The capability string to be used with the
>    require command is "reject".
> 
> Syntax:   discard  =========================================
> 
>    Discard is used to silently throw away the message.  It does so by
>    simply canceling the implicit keep.  If discard is used with other
>    actions, the other actions still happen.  Discard is compatible with
>    all other actions.  (For instance fileinto+discard is equivalent to
>    fileinto.)
> 
>    Discard MUST be silent; that is, it MUST NOT return a non-delivery
>    notification of any kind ([DSN], [MDN], or otherwise).
> 
>    In the following script, any mail from "address@hidden" is thrown
>    out.
> 
>    Example:  if header :contains ["from"] ["address@hidden"] {
>                 discard;
>              }
> 
>    While an important part of this language, "discard" has the potential
>    to create serious problems for users: Students who leave themselves
>    logged in to an unattended machine in a public computer lab may find
>    their script changed to just "discard".  In order to protect users in
>    this situation (along with similar situations), implementations MAY
>    keep messages destroyed by a script for an indefinite period, and MAY
>    disallow scripts that throw out all mail.
> 
> =====  Test Commands  =====
> 
>    Tests are used in conditionals to decide which part(s) of the
>    conditional to execute.
> 
> Available tests:
>         address
>         allof
>         anyof
>         envelope
>         exists
>         false
>         header
>         not
>         size
>         true
> 
> Syntax:   address [ADDRESS-PART] [COMPARATOR] [MATCH-TYPE]
> 
>    The address test matches Internet addresses in structured headers
>    that contain addresses.  It returns true if any header contains any
>    key in the specified part of the address, as modified by the
>    comparator and the match keyword.
> 
> Syntax:   allof   =========================================
> 
>    The allof test performs a logical AND on the tests supplied to it.
> 
>    Example:  allof (false, false)  => false
>              allof (false, true)   => false
>              allof (true,  true)   => true
> 
>    The allof test takes as its argument a test-list.
> 
> Syntax:   anyof   =========================================
> 
>    The anyof test performs a logical OR on the tests supplied to it.
> 
>    Example:  anyof (false, false)  => false
>              anyof (false, true)   => true
>              anyof (true,  true)   => true
> 
> Syntax:   envelope [COMPARATOR] [ADDRESS-PART] [MATCH-TYPE]
> 
>    The "envelope" test is true if the specified part of the SMTP (or
>    equivalent) envelope matches the specified key.
> 
>    If one of the envelope-part strings is (case insensitive) "from",
>    then matching occurs against the FROM address used in the SMTP MAIL
>    command.
> 
> NOTE (ANGLES):
>         I THINK THIS IS ONLY AVAILABLE IN CERTAIN SITUATIONS,
>         SUCH AS DURING AN SMTP TRANSACTION, THIS IS TH ONLY
>         TIME WHEN THIS SPECIFIC "RCPT TO" DATUM IS EXPOSED,
>         I.E. A CLIENT FEEDING AN OUTGOING MESSAGE TO A SMTP SERVER,
>         PERHAPS OTHER OCCASIONS SUCH AS DURING SMTP DESTINATION
>         FINAL DELIVERY. I MAY BE WORNG, THOUGH.
> 
> Syntax:   exists   =========================================
> 
>    The "exists" test is true if the headers listed in the header-names
>    argument exist within the message.  All of the headers must exist or
>    the test is false.
> 
>    The following example throws out mail that doesn't have a From header
>    and a Date header.
> 
>    Example:  if not exists ["From","Date"] {
>                 discard;
>              }
> 
> Syntax:   false   =========================================
> 
>    The "false" test always evaluates to false.
> 
> Syntax:   header [COMPARATOR] [MATCH-TYPE]   =============
> 
>    The "header" test evaluates to true if any header name matches any
>    key.  The type of match is specified by the optional match argument,
>    which defaults to ":is" if not specified, as specified in section
>    2.6.
> 
>    Like address and envelope, this test returns true if any combination
>    of the string-list and key-list arguments match.
> 
>    If a header listed in the header-names argument exists, it contains
>    the null key ("").  However, if the named header is not present, it
>    does not contain the null key.  So if a message contained the header
> 
>            X-Caffeine: C8H10N4O2
> 
>    these tests on that header evaluate as follows:
> 
>            header :is ["X-Caffeine"] [""]         => false
>            header :contains ["X-Caffeine"] [""]   => true
> 
> Syntax:   not    =========================================
> 
>    The "not" test takes some other test as an argument, and yields the
>    opposite result.  "not false" evaluates to "true" and "not true"
>    evaluates to "false".
> 
> Syntax:   size <":over" / ":under">    =============================
> 
>    The "size" test deals with the size of a message.  It takes either a
>    tagged argument of ":over" or ":under", followed by a number
>    representing the size of the message.
> 
>    If the argument is ":over", and the size of the message is greater
>    than the number provided, the test is true; otherwise, it is false.
> 
>    If the argument is ":under", and the size of the message is less than
>    the number provided, the test is true; otherwise, it is false.
> 
>    Exactly one of ":over" or ":under" must be specified, and anything
>    else is an error.
> 
>    The size of a message is defined to be the number of octets from the
>    initial header until the last character in the message body.
> 
>    Note that for a message that is exactly 4,000 octets, the message is
>    neither ":over" 4000 octets or ":under" 4000 octets.
> 
> Syntax:   true   =========================================
> 
>    The "true" test always evaluates to true.
> 
> ======   Extended Example   ======
> 
>    The following is an extended example of a Sieve script.  Note that it
>    does not make use of the implicit keep.
> 
>     #
>     # Example Sieve Filter
>     # Declare any optional features or extension used by the script
>     #
>     require ["fileinto", "reject"];
> 
>     #
>     # Reject any large messages (note that the four leading dots get
>     # "stuffed" to three)
>     #
>     if size :over 1M
>             {
>             reject text:
>     Please do not send me large attachments.
>     Put your file on a server and send me the URL.
>     Thank you.
>     .... Fred
>     .
>     ;
>             stop;
>             }
>     #
>     # Handle messages from known mailing lists
>     # Move messages from IETF filter discussion list to filter folder
>     #
>     if header :is "Sender" "address@hidden"
>             {
>             fileinto "filter";  # move to "filter" folder
>             }
>     #
>     # Keep all messages to or from people in my company
>     #
>     elsif address :domain :is ["From", "To"] "example.com"
>             {
>             keep;               # keep in "In" folder
>             }
> 
>     #
>     # Try and catch unsolicited email.  If a message is not to me,
>     # or it contains a subject known to be spam, file it away.
>     #
>     elsif anyof (not address :all :contains
>                    ["To", "Cc", "Bcc"] "address@hidden",
>                  header :matches "subject"
>                    ["*make*money*fast*", "*university*dipl*mas*"])
>             {
>             # If message header does not contain my address,
>             # it's from a list.
>             fileinto "spam";   # move to "spam" folder
>             }
>     else
>             {
>             # Move all other (non-company) mail to "personal"
>             # folder.
>             fileinto "personal";
>             }
> 
> ======  Example: hillen-sieve-script-001.txt   ======
> 
> require "fileinto";
>         if header :is "X-Mailinglist" "suse-linux" {
>                 fileinto "INBOX.Listen.suse-linux";}
>         elsif header :contains "Mailing-List" "reiserfs" {
>                 fileinto "INBOX.Listen.reiserfs";}
>         elsif address :contains :all ["to", "cc", "bcc"] "free-clim" {
>                 fileinto "INBOX.Listen.free-clim";}
>         elsif header :contains "List-Id" "gnupg-users.gnupg.org" {
>                 fileinto "INBOX.Listen.gnupg";}
>         elsif header :is "X-loop" "isdn4linux" {
>                 fileinto "INBOX.Listen.isdn4linux";}
>         elsif header :contains  "Mailing-list" "address@hidden"{
>                 fileinto "INBOX.Listen.qmail";}
>         elsif allof (header :contains "Sender" "address@hidden",
>                      address :contains :localpart ["to", "cc", "bcc"] 
> "info-cyrus"){
>                 fileinto "INBOX.Listen.info-cyrus";}
>         elsif header :contains "Sender" "address@hidden"{
>                 fileinto "INBOX.Listen.ntbugtraq";}
>         elsif header :is "list-id" "<ietf-mta-filters.imc.org>"{
>                 fileinto "INBOX.Listen.sieve";}
>         elsif header :contains "From" "address@hidden"{
>                 fileinto "INBOX.Newsletter.securityportal";}
>         elsif address :contains :all ["from"] "address@hidden"{
>                 fileinto "INBOX.Newsletter.ebay";}
>         elsif address :contains :all ["to", "cc", "bcc"] "address@hidden"{
>                         fileinto "INBOX.Listen.allegro-cl";}
>         elsif address :contains :all ["to", "cc", "bcc"] "address@hidden"{
>                        fileinto "INBOX.Listen.plob";}
>                 else {
>                          fileinto "INBOX";
> 
> ======  Example: maro-sieve-script-001.txt   ======
> 
> ##############################################
> # Submitted by Tony Maro
> # http://www.maro.net/tony
> # Use and abuse this script as you will
> # I'm not responsible for what it does...
> #
> # Save this script in your home directory.
> # Install this script with the following command,
> # replacing "thisfile" and "yourname" with the appropriate
> # information:
> #
> # installsieve -i thisfile -m PLAIN -u yourname localhost
> #
> #
> require "fileinto";
> require "reject";
> #
> # Circle MUD mailing list list
> # All mail from the list has "[CIRCLE]" in the subject
> # Place all these in the "Circle List" folder
> # I could filter on the mail list senders e-mail as it's always
> # the same, but this way I even catch personal replies that come
> # directly from a user to me
> if header :contains "Subject" "[CIRCLE]" {
>         fileinto "INBOX.Circle List";
> }
> #
> # "shockwave" e-mail virus - just reject it
> #
> if header :contains "Subject" "A great Shockwave flash movie" {
>         reject "Possible virus?  Check your system!";
> }
> #
> # Get a lot of junk from dial-up uu.net accounts
> # Make sure you create a Junk folder under your INBOX
> # I like this one because it catches them even if they
> # relay their crap through some international open
> # mail relay
> #
> if header :contains "Received" ".da.uu.net" {
>         fileinto "INBOX.Junk";
> }
> #
> # If the mail is listed as TO someone at bigfoot.com
> # Then just reject it because it's spam (my experience anyway)
> #
> if header :contains "To:" "@bigfoot.com" {
>         reject "Yeah, right.  Bugoff, hosier!";
> }
> #
> # If the mail is not directed to me put in the junk folder
> # be sure to replace address@hidden with the
> # appropriate information
> # Took me a while to figure out how to do NOT statements... :-}
> #
> if anyof ( not address :all :contains ["To", "Cc", "Bcc"] "address@hidden" ) {
>         fileinto "INBOX.Junk";
> }
> #
> # Everything that makes it to here ends up in the INBOX
> ########################################################
> --
> that's "angle" as in geometry
> 
> _______________________________________________
> Phpgroupware-developers mailing list
> address@hidden
> http://mail.gnu.org/mailman/listinfo/phpgroupware-developers



reply via email to

[Prev in Thread] Current Thread [Next in Thread]