diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2002-12-14 23:51:25 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2002-12-14 23:51:25 +0000 |
commit | 75e3a3ebde7a363bf65e6c51a179508a3a1b3e62 (patch) | |
tree | 8a669768414347f8d1058b1bb51b59efe57af981 | |
parent | f1cbdaabade082b13a2994f52b3ec4f7f41026be (diff) | |
download | mailutils-75e3a3ebde7a363bf65e6c51a179508a3a1b3e62.tar.gz mailutils-75e3a3ebde7a363bf65e6c51a179508a3a1b3e62.tar.bz2 |
Updated
-rw-r--r-- | ChangeLog | 31 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | TODO | 22 | ||||
-rw-r--r-- | doc/texinfo/imap4.texi | 4 | ||||
-rw-r--r-- | doc/texinfo/libmuauth.texi | 331 | ||||
-rw-r--r-- | doc/texinfo/libsieve.texi | 378 | ||||
-rw-r--r-- | doc/texinfo/mailer.texi | 4 | ||||
-rw-r--r-- | doc/texinfo/mailutils.texi | 32 | ||||
-rw-r--r-- | doc/texinfo/programs.texi | 222 | ||||
-rw-r--r-- | sieve/testsuite/Reject | 217 |
10 files changed, 881 insertions, 364 deletions
@@ -1,3 +1,34 @@ +2002-12-14 Sergey Poznyakoff + + * mail/previous.c: Skip deleted messages + * mail/next: Likewise. + + * auth/sql.c (mu_auth_sql_by_uid): Fixed typo. + + * include/mailutils/libsieve.h: Changed type of `number' + to size_t. + * libsieve/sieve.y (union): Likewise + * include/mailutils/mu_auth.h: Removed duplicate declaration + of mu_auth_data_free. + * libsieve/actions.c (build_mime): To improve readability, + output additional newline before reporting the reason. + * libsieve/sieve.l: Allow backslashes in quoted strings. + * sieve/testsuite/Reject: Updated + + * doc/texinfo/libmu_scm.texi: New file. Documents libmu_scm + library. + * doc/texinfo/Makefile.am: Added libmu_scm.texi + * doc/texinfo/libmuauth.texi: Updated + * doc/texinfo/libsieve.texi: Updated + * doc/texinfo/mailutils.texi: Updated + * doc/texinfo/programs.texi: Updated + * doc/texinfo/imap4.texi: Updated + * doc/texinfo/mailer.texi: Updated + + * TODO: Updated + * mh/TODO: New file + * NEWS: Updated + 2002-12-13 Sergey Poznyakoff * mail.local/mail.local.h: Create temporary mailbox instead of @@ -10,6 +10,10 @@ Version 0.2: to disable support for any protocol or mailbox format to reduce the size of the library. +* Added new utility mailutils-config. This utility prints gcc command + line options needed for compiling and linknig an application against + mailutils. + * libsieve: New library. Supports Sieve language as described in RFC 3028 and provides a mechanism for dynamic loading of user-defined actions, tests and comparators. @@ -115,14 +115,34 @@ IMPORTANT: + support AUTH=anonymous (imap://cyrus.andrew.cmu.edu/archive.info-cyrus) +[libmuauth] + +- First argument to mu_auth_fp (and second one to mu_auth_runlist) should + be struct mu_auth_data ** instead of void *. + [examples] - unify the mbox-* and mimetest examples with messages, it would be nice to have a general purpose tool +[mh] + +- see mh/TODO + [sieve] -+ need to deal with the envelope addressing issues +- Implement boolean shortcut evaluation for `allof' and `anyof' + +- Extend the `text:' token. The planned syntax is: + + text:[-][delimiter] + + The meaning of optional flags is the same as in shell "here document" + construct: '-' strips all leading tab characters from the string body, + thus allowing it to be indented in a natural fashion; 'delimiter' + introduces the new end-of-text delimiter instead of the default + dot. If 'delimiter' starts with a backslash, no preprocessing will + be performed within a string. - uid isn't good to identify messages, use message-id? diff --git a/doc/texinfo/imap4.texi b/doc/texinfo/imap4.texi index 2435ad6a8..efe64b363 100644 --- a/doc/texinfo/imap4.texi +++ b/doc/texinfo/imap4.texi @@ -10,8 +10,8 @@ Internet Message Access Protocol - Version (4rev1). In IMAP4, the client must be prepared to accept any responses at all times. The server responses -have three forms: status reponses, server data and command continuation -request. Untaged responses, for hitorical reasons are also call +have three forms: status responses, server data and command continuation +request. Untagged responses, for historical reasons are also call "unsolicited responses". @subsection Commands diff --git a/doc/texinfo/libmuauth.texi b/doc/texinfo/libmuauth.texi index 46d72e519..7cfdacec9 100644 --- a/doc/texinfo/libmuauth.texi +++ b/doc/texinfo/libmuauth.texi @@ -2,3 +2,334 @@ @c Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. @c See file mailutils.texi for copying conditions. @comment ******************************************************************* + +The functions from @file{libmailbox} library get user information from +the system user database. The library @file{libmuauth} extends this +functionality, allowing @file{libmailbox} functions to obtain +information about a user from several places, like @sc{sql} database, +etc. The method used is described in detail in @ref{authentication}. +This chapter contains a very succinct description of the underlying +library mechanism. + +@menu +* Data Types:: +* Initializing the lubmuauth:: +* Module Creation and Destruction:: +* Obtaining Authorization Information:: +* Existing Modules:: +* Using Libmuauth in Your Programs:: +@end menu + +@node Data Types +@section Data Types +@cindex libmuauth, data types + +@deftp {Data Type} mu_auth_fp + +This is a pointer to authentication or authorization data. It +is defined as follows: + +@example +typedef int (*mu_auth_fp) (void *@var{return_data}, + void *@var{key}, + void *@var{func_data}, + void *@var{call_data}); +@end example +@noindent +Its arguments are: + +@table @var +@item return_data +@footnote{Actually it shoud have been @code{struct mu_auth_data** return_data}. +This will be fixed in the next release}. +Upon successful return authorization handler leaves in this memory +location a pointer to the filled @code{mu_auth_data} structure +with the user's information. + +For authentication handlers this argument is always @code{NULL} and +should be ignored. + +@item key +The search key value. Its actual type depends upon type of the handler. + +For authorization handlers it is @code{const char*} if the handler is called by +@code{mu_get_auth_by_name()} and @code{uid_t *} if it is called by +@code{mu_get_auth_by_uid()}. + +For authentication handlers it is always @code{struct mu_auth_data*} +representing the user's data obtained by a previous call to +@code{mu_get_auth_by_@dots{}} call. + +@item func_data +Any data associated with this handler. + +@item call_data +Any call specific data. This argument is not used at the moment. +@end table +@end deftp + +@deftp {Data Type} mu_auth_data + +The @code{mu_auth_data} is used to return the information about the +user. It is similar to system @code{struct passwd}, except that it +is more mailutils-specific. Its definition is: + +@example +@group +struct mu_auth_data @{ + /* These are from struct passwd */ + char *name; /* user name */ + char *passwd; /* user password */ + uid_t uid; /* user id */ + gid_t gid; /* group id */ + char *gecos; /* real name */ + char *dir; /* home directory */ + char *shell; /* shell program */ + /* */ + char *mailbox; /* Path to the user's system mailbox */ + int change_uid; /* Should the uid be changed? */ +@}; +@end group +@end example +@end deftp + +@deftp {Data Type} mu_auth_module + +The @code{mu_auth_module} structure contains full information about a +libmuauth module. It is declared as follows: + +@example +@group +struct mu_auth_module @{ + char *name; /* Module name */ + struct argp *argp; /* Corresponding argp structure */ + mu_auth_fp authenticate; /* Authentication function ... */ + void *authenticate_data; /* ... and its specific data */ + mu_auth_fp auth_by_name; /* Get user info by user name */ + void *auth_by_name_data; /* ... and its specific data */ + mu_auth_fp auth_by_uid; /* Get user info by user id */ + void *auth_by_uid_data; /* ... and its specific data */ +@}; +@end group +@end example +@end deftp + +@node Initializing the lubmuauth +@section Initializing the lubmuauth + +@deftypefn void mu_auth_init (void) + +This function registers the command line capability ``auth''. It must be +called after registering @file{libmuauth} modules and before calling +@code{mu_agrp_parse()}. If an error occurs, this function prints +diagnostic message and aborts the program. +@end deftypefn + +@deftypefn void MU_AUTH_REGISTER_ALL_MODULES (void) + +This macro registers all default modules and calls @code{mu_auth_init()}. +@end deftypefn + +@node Module Creation and Destruction +@section Module Creation and Destruction + +@deftypefn int mu_auth_data_alloc (struct mu_auth_data **ptr, const char *name, const char *passwd, uid_t uid, gid_t gid, const char *gecos, const char *dir, const char *shell, const char *mailbox, int change_uid) + +Create a @code{mu_auth_data} structure and initialize it with the given +values. Returns 0 on success and 1 otherwise. +@end deftypefn + +@deftypefn void mu_auth_data_free (struct mu_auth_data *@var{ptr}) + +Free the @code{mu_auth_data} structure allocated by a call to +@code{mu_auth_data_alloc()}. +@end deftypefn + +@deftypefn void mu_auth_register_module (struct mu_auth_module *@var{mod}) + +Register the module defined by the @var{mod} argument. +@end deftypefn + +@node Obtaining Authorization Information +@section Obtaining Authorization Information +@cindex libmuauth, obtaining authorization information + +@deftypefn int mu_auth_runlist (list_t @var{flist}, void *@var{return_data}, void *@var{key}, void *@var{call_data}); + +The list is expected to contain @code{mu_auth_fp} pointers. Each of them +is dereferenced and executed until either the list is exhausted or any +of the functions returns non-zero, whichever occurs first. The +@var{return_data} and @var{key} arguments are passed as the first two +parameters to the function (see the definition of @code{mu_auth_fp}, +notice the footnote), the @code{call_data} is passed as its last +parameter. + +The function returns 0 if none of the functions from @code{list} +succeeded, i.e. returned non-zero value. Otherwise it returns the +return code from the succeeded function. +@end deftypefn + +@deftypefn {struct mu_auth_data *} mu_get_auth_by_name (const char *@var{username}) + +Search the information about given user by its username. Similar to +system's @code{getpwnam} call). + +@end deftypefn + +@deftypefn {struct mu_auth_data *} mu_get_auth_by_uid (uid_t @var{uid}) +Search the information about given user by its uid. Similar to +system's @code{getpwuid} call). +@end deftypefn + +@deftypefn int mu_authenticate (struct mu_auth_data *@var{auth_data}, char *@var{pass}) + +Authenticate the user whose data are in @var{auth_data} using password +@var{pass}. Return 0 if the user is authenticated. +@end deftypefn + +@node Existing Modules +@section Existing Modules +@cindex libmuauth modules + +@deftypefn int mu_auth_nosupport (void *return_data, void *key, void *func_data, void *call_data); + +The ``not-supported'' module. Always returns @code{ENOSYS}. +@end deftypefn + +@defvar mu_auth_system_module + +This module is always registered even if @file{libmuauth} is not linked. +It performs usual authentication using system user database +(@file{/etc/password} et al.) +@end defvar + +@defvar mu_auth_generic_module + +This module is always registered even if @file{libmuauth} is not linked. +Both its authorization handlers are @code{mu_auth_nosupport}. Its +authentication handler computes the MD5 or DES hash over the supplied +password with the seed taken from @code{passwd} member of its @var{key} +argument. Then it compares the obtained hash with the @code{passwd} +member itself and returns 1 if both strings match. +@end defvar + +@defvar mu_auth_pam_module + +Implements PAM authentication. Both authorization handlers are +@code{mu_auth_nosupport()}. +@end defvar + +@defvar mu_auth_sql_module + +Implements authentication and authorization via MySQL database. The +credentials for accessing the database are taken from global variables +@code{sql_host}, @code{sql_port}, @code{sql_user}, @code{sql_passwd} +and @code{sql_db}. The SQL queries for retrieving user information +from global variables @code{sql_getpwnam_query} and +@code{sql_getpwuid_query}. The variable @code{sql_getpass_query} keeps +the query used for retrieving user's password. @xref{auth}, for +information on command line options used to set these variables. +@end defvar + +@defvar mu_auth_virtual_module + +Implements @code{mu_get_auth_by_name} method using virtual mail domains. +Neither @code{mu_get_auth_by_uid} nor @code{mu_authenticate} is +implemented. This module must be used together with @code{generic} +module. +@end defvar + + +@node Using Libmuauth in Your Programs +@section Using Libmuauth in Your Programs +@cindex using libmuauth +@cindex linking with libmuauth +@cindex libmuauth, linking with + +To link your program against @file{libmuauth}, obtain loader arguments +by running @command{mailutils-config} as follows: + +@example +mailutils-config --link auth +@end example +@noindent + +@xref{mailutils-config}, for more information about this utility. + +Here is a sample Makefile fragment: + +@example +MU_LDFLAGS=`mailutils-config --link auth` +MU_INCLUDES=`mailutils-config --include` + +myprog: myprog.c + $(CC) -omyprog $(CFLAGS) $(MU_INCLUDES) myprog.c $(MU_LDFLAGS) +@end example + +If your program will be using only default modules provided by the +library, then it will suffice to call +@code{MU_AUTH_REGISTER_ALL_MODULES()} somewhere near the start of +your program. As an example, consider the following code fragment +(it is taken from the @command{imap4d} daemon): + +@example +@group +int +main (int argc, char **argv) +@{ + struct group *gr; + int status = EXIT_SUCCESS; + + state = STATE_NONAUTH; /* Starting state in non-auth. */ + + MU_AUTH_REGISTER_ALL_MODULES (); + mu_argp_parse (&argp, &argc, &argv, 0, imap4d_capa, + NULL, &daemon_param); + @dots{} +@end group +@end example + +Otherwise, if you program will use it's own modules, first register +them with @code{mu_auth_register_module} and then call +@code{mu_auth_init()}, e.g.: + +@example +@group +struct mu_auth_module radius_module = @{ + @dots{} +@}; + +struct mu_auth_module ext_module = @{ + @dots{} +@}; + +int +main (int argc, char **argv) +@{ + mu_auth_register_module (&radius_module); + mu_auth_register_module (&ext_module); + mu_auth_init (); + + @dots{} +@end group +@end example + +These two approaches may be combined, allowing you to use both your +modules and the ones provided by Mailutils. Consider the example below: + +@example +@group +int +main (int argc, char **argv) +@{ + mu_auth_register_module (&radius_module); + mu_auth_register_module (&ext_module); + MU_AUTH_REGISTER_ALL_MODULES (); + + @dots{} +@} +@end group +@end example + + + diff --git a/doc/texinfo/libsieve.texi b/doc/texinfo/libsieve.texi index 653a7f225..a7c407132 100644 --- a/doc/texinfo/libsieve.texi +++ b/doc/texinfo/libsieve.texi @@ -15,6 +15,44 @@ This chapter describes @sc{gnu} Sieve library. @node Library Description @section Library Description +@code{Libsieve} is @sc{gnu} implementation of the mail filtering +language Sieve. + +The library is built around a @dfn{Sieve Machine} --- an abstract +computer constructed specially to handle mail filtering tasks. This +computer has two registers: program counter and numeric accumulator; +a runtime stack of unlimited depth and the code segment. A set of +functions is provided for creating and destroying instances of Sieve +Machine, manipulating its internal data, compiling and executing a +sieve program. + +The following is a typical scenario of using @code{libsieve}: + +@enumerate +@item Application program creates the instance of sieve machine. + +@item Then @code{sieve_compile} function is called to translate +the Sieve source into an equivalent program executable by the +Machine + +@item A mailbox is opened and associated with the Machine + +@item The Machine executes the program over the mailbox + +@item When the execution of the program is finished, all messages upon which +an action was executed other than @code{keep} are marked with the delete +flag. Thus, running @code{mailbox_expunge} upon the mailbox finishes +the job, leaving in the mailbox only those messages that were preserved +by the filter. + +@item Finally, the instance of Sieve Machine is destroyed and the +resources allocated for it are reclaimed. + +@end enumerate + +The following sections describe in detail the functions from the +Sieve Library. + @menu * Sieve Data Types:: * Manipulating the Sieve Machine:: @@ -188,7 +226,7 @@ Other arguments. @end table @deftp {Function Type} sieve_parse_error_t -This data type is decalred as follows: +This data type is declared as follows: @example typedef int (*sieve_parse_error_t) (void *@var{data}, const char *@var{filename}, int @var{lineno}, @@ -233,7 +271,7 @@ The name of the action. @item fmt @itemx var -These two arguments give the detaied description of the action. +These two arguments give the detailed description of the action. @end table @deftp {Function Type} sieve_comparator_t @@ -322,14 +360,15 @@ order. @deftypefn int sieve_machine_add_destructor (sieve_machine_t @var{mach}, sieve_destructor_t @var{destr}, void *@var{ptr}); This function registers a destructor function @var{dest}. The purpose -of the destructor is to free any resourses assotiated with the item -@var{ptr}. The desctructor function takes a single argument --- a +of the destructor is to free any resources associated with the item +@var{ptr}. The destructor function takes a single argument --- a pointer to the data being destroyed. All registered destructors are called in reverse order upon execution of @code{sieve_machine_destroy()}. Here's a short example of the use of this function: @example +@group static void free_regex (void *data) @{ @@ -349,6 +388,7 @@ match_part_checker (const char *name, list_t tags, list_t args) . . @} +@end group @end example @end deftypefn @@ -407,8 +447,10 @@ not set, the default parse error printer will be used. It is defined as follows: @example +@group int -_sieve_default_parse_error (void *unused, const char *filename, int lineno, +_sieve_default_parse_error (void *unused, + const char *filename, int lineno, const char *fmt, va_list ap) @{ if (filename) @@ -417,6 +459,7 @@ _sieve_default_parse_error (void *unused, const char *filename, int lineno, fprintf (stderr, "\n"); return 0; @} +@end group @end example @end deftypefn @@ -567,7 +610,7 @@ If @var{ptr} is @code{NULL}, no operation is performed. @subsection Compiling and Executing the Script @deftypefn int sieve_compile (sieve_machine_t @var{mach}, const char *@var{name}) -Compile the seive script from the file @var{name}. +Compile the sieve script from the file @var{name}. @end deftypefn @deftypefn int sieve_mailbox (sieve_machine_t @var{mach}, mailbox_t @var{mbox}) @@ -591,6 +634,7 @@ The input language understood by the @sc{gnu} Sieve Library is a superset of the Sieve language as described in RFC 3028. @menu +* Lexical Structure:: * Syntax:: * Preprocessor:: * Require Statement:: @@ -599,9 +643,307 @@ the Sieve language as described in RFC 3028. * Actions:: @end menu +@node Lexical Structure +@subsection Lexical Structure + +@subheading Whitespace and Comments + +Comments are semantically equivalent to whitespace and can be used +anyplace that whitespace is (with one exception in multi-line strings, +as described below). + +There are two kinds of comments: hash comments, that begin with a +@samp{#} character that is not contained within a string and continue +until the next newline, and C-style or bracketed comments, that are +delimited by @samp{/*} and @samp{*/} tokens. The bracketed comments +may span multiple lines. E.g.: + +@example +if size :over 100K + @{ # this is a comment + discard; + @} + +if size :over 100K + @{ /* this is a comment + this is still a comment */ discard /* this is a comment again + */ ; + @} +@end example + +Like in C, bracketed comments do not nest. + +@subheading Lexical Tokens + +The basic lexical entities are @dfn{identifiers} and @dfn{literals}. + +An @dfn{identifier} is a sequence of letters, digits and underscores, started +with a letter or underscore. For example, @code{header} and +@code{check_822_again} are valid identifiers, whereas @code{1st} is not. +A special form of identifier is @dfn{tag}: it is an identifier prefixed +with a colon (@samp{:}), e.g.: @code{:comparator}. + +A @dfn{literal} is a data that is not executed, merely evaluated ``as +is'', to be used as arguments to commands. There are four kinds of +literals: + +@itemize +@item Number + +@dfn{Numbers} are given as ordinary unsigned decimal numbers. An +optional suffix may be used to indicate a multiple of a power of two. +The suffixes are: @samp{K} specifying ``kibi-'', or 1,024 (2^10) times +the value of the number; @samp{M} specifying ``mebi-'', or 1,048,576 +(2^20) times the value of the number; and @samp{G} specifying ``tebi-'', +or 1,073,741,824 (2^30) times the value of the number. + +The numbers have 32 bits of magnitude. + +@item String + +A @dfn{string} is any sequence of characters enclosed in double quotes +(@samp{"}). A string cannot contain newlines and double quote +characters. This limitation will disappear in future releases. + +@item Multiline Strings + +A @dfn{multiline string} is used to represent large blocks of text +with embedded newlines and special characters. It starts with the +keyword @code{text:} followed by a newline and ends with a dot +(@samp{.}) on a newline by itself. Any characters between these two +markers are taken verbatim. For example: + +@example +text: +**This is an authomatic response from my message filtering program.** + +I can not attend your message right now. However it +will be saved, and I will read it as soon as I am back. + +Regards, +Fred +. +@end example + +Notice that a hashed comment or whitespace may occur between +@code{text:} and the newline. However, when used inside the multiline +string a hash sign looses its special meaning (except in one case, see +below) and is taken as is, as well as bracketed comment delimiters. +In other words, no comments are allowed within a multiline string. E.g.: + +@example +text: # This is a comment + +Sample text +# This line is taken verbatim +/* And this line too */ +. +@end example + +The only exception to this rule is that preprocessor @code{include} +statement is expanded as usual when found within a multiline string +(@pxref{#include}), e.g.: + +@example +text: +#include <myresponse.txt> +. +@end example + +This results in the contents of file @file{myresponse.txt} being read +and interpreted as the contents of the multiline string. + +@item String Lists + +A @dfn{string list} is a comma-delimited list of quoted strings, enclosed +in a pair of square brackets, e.g.: + +@example +["me@@example.com", "me00@@landru.example.edu"] +@end example + +For convenience, in any context where a list of strings is appropriate, +a single string is allowed without being a member of a list: it is +equivalent to a list with a single member. For example, the following +two statements are equivalent: + +@example +exists "To"; +exists ["To"]; +@end example + +@end itemize + @node Syntax @subsection Syntax +Being designed for the sole purpose of filtering mail, Sieve has a very +simple syntax. + +@menu +* Commands:: +* Actions Described:: +* Control Flow:: +* Tests and Conditions:: +@end menu + +@node Commands +@subsubsection Commands + +The basic syntax element is a @dfn{command}. It is defined as follows: + +@example +@var{command-name} [@var{tags}] @var{args} +@end example +@noindent +where @var{command-name} is an identifier representing the name of the +command, @var{tags} is an optional list of @dfn{optional} or +@dfn{tagged arguments} and @var{args} is a list of @dfn{required} or +@dfn{positional arguments}. + +Positional arguments are literals delimited with whitespace. They +provide the command with the information necessary to its proper +functioning. Each command has a fixed number of positional arguments. It +is an error to supply more arguments to the command or to give it fewer +arguments than it accepts. + +Optional arguments allow to modify the behaviour of the command, like +command line options in UNIX do. They are a list of @dfn{tags} +(@pxref{Lexical Structure}) separated by whitespace. An optional +argument may have at most one parameter. + +Each command understands a set of optional arguments. Supplying it tags +that it does not understand results in an error. + +For example, consider the following command + +@example +header :mime :comparator "i;octet" ["to", "from"] "bug-mailutils@@gnu.org" +@end example +@noindent +Here, given that @code{header} takes two positional arguments: +@code{header} is command name, the list @code{["to", "from"]} is first +positional argument and the string @code{"bug-mailutils@@gnu.org"} is second +positional argument. There are two optional arguments: @code{:mime} and +@code{:comparator}. The latter has a string @code{"i;octet"} as its +parameter. + +@node Actions Described +@subsubsection Actions Described + +An @dfn{action} is a Sieve command that performs some operation over +the message. Actions do the main job in any Sieve +program. Syntactically, an action is a command terminated with +semicolon, e.g.: + +@example +keep; + +fileinto "mbox"; +@end example + +@sc{gnu} Sieve provides the full set of actions described in RFC 3028. +It also allows to extend this set using loadable +actions. @xref{Actions}, for detailed discussion of actions. + +@node Control Flow +@subsubsection Control Flow + +The only control flow statement Sieve has is ``if'' statement. In its +simplest form it is: + +@example +if @code{condition} @{ @dots{} @} +@end example + +The effect of this statement is that the sequence of actions between the +curly braces is executed only if the @code{condition} evaluates to +@code{true}. + +The more elaborate form of this statement allows to execute two +different sets of actions depending on whether the condition is +true or not: + +@example +if @code{condition} @{ @dots{} @} else @{ @dots{} @} +@end example + +The most advanced form of the ``if'' statement allows to select an +action depending on what condition from the set of conditions is met. + +@example +if @code{cond1} @{ @dots{} @} elsif @code{cond2} @{ @dots{} @} else @{ @dots{} @} +@end example + +There may be any number of ``elsif'' branches in an ``if'' +statement. However it may have at most one ``else'' branch. +Notes for C programmers: + +@enumerate +@item The braces surrounding each branch of an ``if'' statement are +required. +@item The ``else if'' construct is disallowed. Use ``elsif'' keyword +instead. +@end enumerate + +Here's an example of ``if'' statement: + +@example +if header :contains "from" "coyote" + @{ + discard; + @} +elsif header :contains ["subject"] ["$$$"] + @{ + discard; + @} +else + @{ + fileinto "INBOX"; + @} +@end example + +The following section describes in detail conditions used in ``if'' +statements. + +@node Tests and Conditions +@subsubsection Tests and Conditions + +@dfn{Tests} are Sieve commands that return boolean value. E.g. the +test + +@example +header :contains "from" "coyote" +@end example +@noindent +returns true only if the header ``From'' of the current message contains +substring ``coyote''. + +The tests shipped with the @sc{gnu} Sieve are described in @ref{Tests}. + +@dfn{Condition} is a Sieve expression that evaluates to @code{true} or +@code{false}. In its simplest form, condition is just a Sieve test. + +To reverse the sense of a condition use keyword @code{not}, e.g.: + +@example +not header :contains "from" "coyote" +@end example + +The results of several conditions may be joined together by logical +@code{and} and @code{or} operations. The special form @code{allof} +takes several tests as its arguments and computes the logical @code{and} +of their results. Similarly, the form @code{anyof} performs logical +@code{or} over the results of its arguments. E.g.: + +@example +if anyof (not exists ["From", "Date"], + header :contains "from" "fool@@example.edu") + @{ + discard; + @} +@end example + @node Preprocessor @subsection Preprocessor @cindex Sieve preprocessor statements, a @sc{gnu} extension @@ -609,7 +951,7 @@ the Sieve language as described in RFC 3028. The preprocessor statements are a @sc{gnu} extension to the Sieve language. The syntax for a preprocessor statement is similar to that used in @code{C} programming language, i.e.: a pound character (@samp{#}) -followed by a preprocessor directive and any arguments. Any amount of +followed by a preprocessor directive and its arguments. Any amount of whitespace can be inserted between the @samp{#} and the directive. Currently implemented directives are @code{include} and @code{searchpath}. @@ -677,6 +1019,7 @@ sieve allows the @code{require} and any other statements to be interspersed. By default the following actions and comparators are always required: + @itemize @item stop @item keep @@ -826,7 +1169,6 @@ A @var{comparator} syntax item is defined as follows: :comparator "@var{comparator-name}" @end example @noindent -@sp 1 It instructs sieve to use the given comparator with the test. If @var{comparator-name} is not one of @samp{i;octet}, @samp{i;ascii-casemap} it must be required prior to using it. @@ -866,7 +1208,6 @@ an appropriate error message. For example, the statement: @example if header :matches :comparator "i;ascii-numeric" @end example -@sp 1 @noindent would result in the following error message: @@ -876,15 +1217,18 @@ in call to `header' @end example @deffn Test false + This test always evaluates to ``false''. @end deffn @deffn Test true + This test always evaluates to ``true''. @end deffn @deffn Test address [@var{address-part}][@var{comparator}][@var{match-type}] @var{header-names} @var{key-list} +@noindent Tagged arguments: @table @var @@ -898,7 +1242,6 @@ Specifies the comparator to be used instead of the default @code{i;ascii-casemap @item match-type Specifies the match type to be used instead of the default @code{:is}. @end table -@sp 1 @noindent Required arguments: @@ -909,7 +1252,6 @@ A list of header names. @item key-list A list of address values. @end table -@sp 1 @noindent The @code{address} test matches Internet addresses in structured headers @@ -936,8 +1278,8 @@ if address :is :all "from" "tim@@example.com" @end deffn @deffn Test size [:over|:under] @var{number} -@sp 1 @noindent + The @code{size} test deals with the size of a message. The required argument @var{number} represents the size of the message in bytes. It may be suffixed with the following quantifiers: @@ -968,8 +1310,8 @@ initial header until the last character in the message body. @end deffn @deffn Test envelope [@var{address-part}][@var{comparator}][@var{match-type}] @var{envelope-part} @var{key-list} -@sp 1 @noindent + Tagged arguments: @table @var @@ -983,7 +1325,6 @@ Specifies the comparator to be used instead of the default @code{i;ascii-casemap @item match-type Specifies the match type to be used instead of the default @code{:is}. @end table -@sp 1 @noindent Required arguments: @@ -994,7 +1335,6 @@ A list of envelope parts to operate upon. @item key-list A list of address values. @end table -@sp 1 @noindent The @code{envelope} test is true if the specified part of the @sc{smtp} @@ -1010,8 +1350,8 @@ meaningless. @end deffn @deffn Test exists @var{header-names} -@sp 1 @noindent + Required arguments: @table @var @@ -1091,7 +1431,7 @@ header :contains ["X-Caffeine"] [""] @result{} true @end deffn @deffn Test numaddr [:over|:under] |