[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Phpgroupware-developers] hello to Sieve
From: |
Tarjei Huse |
Subject: |
Re: [Phpgroupware-developers] hello to Sieve |
Date: |
Sun, 25 Nov 2001 19:13:52 +0100 |
I think there's a few interfaces already to sive written in php. Check the cyrus
maillinglistarchives.
TH
"Dan Kuykendall (Seek3r)" wrote:
>
> 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
>
> _______________________________________________
> Phpgroupware-developers mailing list
> address@hidden
> http://mail.gnu.org/mailman/listinfo/phpgroupware-developers