Commit a1612b96 a1612b96fc4592af50cb65caff5b54e74f437b09 by Sergey Poznyakoff

Document changes to Sieve

* NEWS: Update.
* doc/texinfo/libmu_sieve.texi: Update.
* doc/texinfo/sieve.texi: Document extensions

* libmu_sieve/comparator.c (mu_sieve_match_part_checker): Check
the type of the 2nd argument.
* sieve/sieve.c: Define "location" and "phase" environment items.
* sieve/tests/pipetest.at: Use "pipe" as the capability string.
1 parent 98011160
GNU mailutils NEWS -- history of user-visible changes. 2016-12-07
GNU mailutils NEWS -- history of user-visible changes. 2016-12-13
Copyright (C) 2002-2016 Free Software Foundation, Inc.
See the end of file for copying conditions.
......@@ -7,8 +7,34 @@ Please send mailutils bug reports to <bug-mailutils@gnu.org>.
Version 3.0.90 (Git)
Sieve library essentially rewritten. It now inludes support for
the "variables" extension (RFC 5229).
* Sieve
The Sieve library essentially rewritten. The following new extensions
are implemented:
encoded-character - RFC 5228, 2.4.2.4
variables - RFC 5229
environment - RFC 5183
The tools define the Sieve environment "location", and
"phase" as follows:
Utility | "location" | "phase"
--------+-------------+--------
maidag | "MDA" | "during"
inc | "MUA" | "post"
sieve | "MS" | "post"
The "sieve" utility provides new option: --environment, for
manipulating the environment.
* Bugfixes
** Fix program name duplicate in the output of "mailutils help COMMAND"
** Fix several bugs in mhn
** Fix expansion of #, &, %, etc. in mail "copy" and "file" commands.
** Fix improper permissions after delivery to MH and Maildir mailboxes.
** Fix stream flushing code
** Fix the implementation of -nowhatnowproc option in mh
Version 3.0 - 2016-11-06
......
......@@ -44,6 +44,8 @@ Sieve Library.
* Sieve Data Types::
* Manipulating the Sieve Machine::
* Logging and Diagnostic Functions::
* String Accessors::
* Argument Accessors::
* Symbol Space Functions::
* Memory Allocation::
* Compiling and Executing the Script::
......@@ -53,13 +55,13 @@ Sieve Library.
@node Sieve Data Types
@subsection Sieve Data Types
@deftp {Data Type} sieve_machine_t
@deftp {Data Type} mu_sieve_machine_t
This is an opaque data type representing a pointer to an instance of
sieve machine. The @code{sieve_machine_t} keeps all information necessary
sieve machine. The @code{mu_sieve_machine_t} keeps all information necessary
for compiling and executing the script.
It is created by @code{sieve_machine_create()} and destroyed by
@code{sieve_machine_destroy()}. The functions for manipulating this data
It is created by @code{mu_sieve_machine_create()} and destroyed by
@code{mu_sieve_machine_destroy()}. The functions for manipulating this data
type are described in @ref{Manipulating the Sieve Machine}.
@end deftp
......@@ -77,16 +79,13 @@ Numeric type.
Character string.
@item SVT_STRING_LIST
A @code{mu_list_t}. Each item in this list represents a character string.
A list of strings.
@item SVT_TAG
A sieve tag. See @code{mu_sieve_runtime_tag_t} below.
@item SVT_IDENT
A character string representing an identifier.
@item SVT_POINTER
An opaque pointer.
A sieve tag. This data type is available only during the
compilation. On runtime, all tags are converted to one of the above
types, depending on their arguments. Tags without arguments are
converted to SVT_VOID.
@end table
@end deftp
......@@ -96,18 +95,23 @@ as follows:
@smallexample
@group
typedef struct
@{
mu_sieve_data_type type; /* Type of the data */
union @{
char *string; /* String value or identifier */
size_t number; /* Numeric value */
mu_list_t list; /* List value */
mu_sieve_runtime_tag_t *tag; /* Tag value */
void *ptr; /* Pointer value */
@} v;
@}
mu_sieve_value_t;
typedef struct
@{
union mu_sieve_value_storage
@{
char *string;
size_t number;
struct mu_sieve_slice list;
@};
typedef struct
@{
mu_sieve_data_type type;
char *tag;
union mu_sieve_value_storage v;
@} mu_sieve_value_t;
@}
mu_sieve_value_t;
@end group
@end smallexample
......@@ -116,25 +120,48 @@ union @code{v} keep the actual value:
@table @code
@item SVT_VOID
Never appears.
No associated value.
@item SVT_NUMBER
The numeric value is kept in @code{number} member.
@item SVT_STRING
The string is kept in @code{string} member.
The numeric value is kept in the @code{number} member.
@item SVT_STRING_LIST
The list itself is pointed to by @code{list} member
@itemx SVT_STRING
The list is identified by the @code{list} member of the union
@code{mu_sieve_value_storage}. This member is defined as follows:
@item SVT_TAG
The tag value is pointed to by @code{tag} member.
@example
struct mu_sieve_slice
@{
size_t first; /* Index of the first string */
size_t count; /* Number of strings */
@};
@end example
The @code{first} member identifies the first string in the list.
The @code{count} member gives the number of strings in the list. If
the data type is @code{SVT_STRING}, @code{count} is guaranteed to be
1.
@item SVT_IDENT
The @code{string} member points to the identifier name.
The string itself can be accessed using the @code{mu_sieve_string}
function (@pxref{String Accessors}). For example, the following code
fragment iterates over all strings in the list:
@item SVT_POINTER
The data are pointed to by @code{ptr} member.
@example
size_t i;
mu_sieve_value_t *val;
for (i = 0; i < val->v.list.count; i++)
@{
char *string;
string = mu_sieve_string (mach, &val->v.list, i);
...
@}
@end example
@item SVT_TAG
Never appears.
@end table
@end deftp
......@@ -159,131 +186,39 @@ colon}. The @code{argtype} is set to @code{SVT_VOID} if the tag does
not take argument, or to the type of the argument otherwise.
@end deftp
@deftp {Data Type} mu_sieve_runtime_tag_t
This structure represents the tagged (optional) argument at a runtime.
It is defined as:
@smallexample
@group
struct mu_sieve_runtime_tag
@{
char *tag; /* Tag name */
mu_sieve_value_t *arg; /* Tag argument (if any) */
@};
@end group
@end smallexample
The @code{arg} member is @code{NULL} if the tag does not take an argument.
@end deftp
@deftp {Data Type} mu_sieve_locus_t
Objects of this type represent a location in the Sieve source file:
@smallexample
@group
typedef struct
@{
const char *source_file;
size_t source_line;
@}
mu_sieve_locus_t;
@end group
@end smallexample
@end deftp
@deftp {Data Type} mu_sieve_handler_t
This is a pointer to function handler for a sieve action or test.
It is defined as follows:
@smallexample
typedef int (*mu_sieve_handler_t) (mu_sieve_machine_t @var{mach},
mu_list_t @var{args},
mu_list_t @var{tags});
@end smallexample
The arguments to the handler have the following meaning:
@table @var
@item mach
Sieve machine being processed.
@item args
A list of required arguments to the handler
@item tags
A list of optional arguments (tags).
@end table
@end deftp
@deftp {Data Type} mu_sieve_printf_t
A pointer to a diagnostic output function. It is defined as follows:
@smallexample
typedef int (*mu_sieve_printf_t) (void *@var{data},
const char *@var{fmt}, va_list @var{ap});
typedef int (*mu_sieve_handler_t) (mu_sieve_machine_t @var{mach});
@end smallexample
@table @var
@item data
A pointer to application specific data. It is set using
the @code{mu_sieve_set_data} call.
@item fmt
Printf-like format string.
@item ap
Other arguments.
@end table
@end deftp
@deftp {Data Type} mu_sieve_parse_error_t
This data type is declared as follows:
@smallexample
typedef int (*mu_sieve_parse_error_t) (void *@var{data},
const char *@var{filename},
int @var{lineno},
const char *@var{fmt},
va_list @var{ap});
@end smallexample
It is used to declare error handlers for parsing errors. The
application-specific data are passed in the @var{data}
argument. Arguments @var{filename} and @var{line} indicate the location
of the error in the source text, while @var{fmt} and @var{ap} give
verbose description of the error.
@end deftp
The @var{mach} argument is the machine being worked upon. The rest of
data can be obtained from it.
@deftp {Data Type} mu_sieve_action_log_t
A pointer to the application-specific logging function:
@smallexample
typedef void (*mu_sieve_action_log_t) (void *@var{data},
const mu_sieve_locus_t *@var{locus},
size_t @var{msgno},
mu_message_t @var{msg},
const char *@var{action},
const char *@var{fmt},
typedef void (*mu_sieve_action_log_t) (mu_sieve_machine_t @var{mach},
const char *@var{action},
const char *@var{fmt},
va_list @var{ap});
@end smallexample
@table @var
@item data
Application-specific data.
@item locus
Location in the Sieve source file.
@item script
Name of the sieve script being executed.
@item msgno
Ordinal number of the message in mailbox, if appropriate. When execution
is started using @code{sieve_message()}, this argument is zero.
@item msg
The message this action is executed upon.
@item nach
The sieve machine.
@item action
The name of the action.
@item fmt
@itemx var
These two arguments give the detailed description of the action.
A @code{printf}-style format string.
@item ap
Arguments for the format.
@end table
@end deftp
......@@ -329,25 +264,11 @@ associated with @code{data}. See the description of
@deftp {Data Type} mu_sieve_tag_checker_t
@smallexample
typedef int (*mu_sieve_tag_checker_t) (const char *@var{name},
mu_list_t @var{tags},
mu_list_t @var{args})
typedef int (*mu_sieve_tag_checker_t) (const char *@var{name})
@end smallexample
A pointer to tag checker function. The purpose of the function is to
perform compilation-time consistency test on tags. Its arguments are:
@table @var
@item name
Name of the test or action whose tags are being checked.
@item tags
A list of @code{mu_sieve_runtime_tag_t} representing tags.
@item args
A list of @code{mu_sieve_value_t} representing required arguments to
@var{name}.
@end table
perform compilation-time consistency test on tags.
The function is allowed to make any changes in @var{tags} and
@var{args}. It should return 0 if the syntax is correct and non-zero
......@@ -386,33 +307,7 @@ 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{mu_sieve_machine_destroy()}. Here's a short example of the use
of this function:
@smallexample
@group
static void
free_regex (void *data)
@{
regfree ((regex_t*)data);
@}
int
match_part_checker (const char *name, list_t tags, list_t args)
@{
regex_t *regex;
/* Initialise the regex: */
regex = mu_sieve_malloc (mach, sizeof (*regex));
/* Make sure it will be freed when necessary */
mu_sieve_machine_add_destructor (sieve_machine, free_regex, regex);
.
.
.
@}
@end group
@end smallexample
@end deftypefun
@code{mu_sieve_machine_destroy()}.
@deftypefun {void *} mu_sieve_get_data (mu_sieve_machine_t @var{mach})
This function returns the application-specific data associated with
......@@ -433,15 +328,12 @@ with @code{mu_sieve_message}, this function returns 1.
Returns the debug level set for this instance of sieve machine.
@end deftypefun
@deftypefun mu_ticket_t mu_sieve_get_ticket (mu_sieve_machine_t @var{mach})
Returns the authentication ticket for this machine.
@end deftypefun
@deftypefun mu_mailer_t mu_sieve_get_mailer (mu_sieve_machine_t @var{mach})
Returns the mailer.
@end deftypefun
@deftypefun int mu_sieve_get_locus (mu_sieve_machine_t @var{mach}, mu_sieve_locus_t *@var{locus})
@deftypefun int mu_sieve_get_locus (mu_sieve_machine_t @var{mach}, @
struct mu_locus *@var{locus})
Returns the locus in the Sieve source file corresponding to the code pointer
where the Sieve machine currently is.
@end deftypefun
......@@ -453,70 +345,30 @@ envelope from addresses of automatic reply messages. By default its local
part is @samp{<MAILER-DAEMON>} and the domain part is the machine name.
@end deftypefun
@deftypefun void mu_sieve_set_error (mu_sieve_machine_t @var{mach}, mu_sieve_printf_t @var{error_printer})
This function sets the error printer function for the machine. If it is
not set, the default error printer will be used. It is defined as
follows:
@smallexample
int
_sieve_default_error_printer (void *unused, const char *fmt,
va_list ap)
@{
return mu_verror (fmt, ap);
@}
@end smallexample
@deftypefun void mu_sieve_get_diag_stream (mu_sieve_machine_t @var{mach}, @
mu_stream_t *@var{pstr})
Get a reference to the machine's diagnostic stream. The obtained
stream must be dereferenced by using @code{mu_stream_unref} or
@code{mu_stream_destroy}, when no longer needed.
@end deftypefun
@deftypefun void mu_sieve_set_parse_error (mu_sieve_machine_t @var{mach}, mu_sieve_parse_error_t @var{p})
This function sets the parse error printer function for the machine. If it is
not set, the default parse error printer will be used. It is defined as
follows:
@smallexample
@group
int
_sieve_default_parse_error (void *unused,
const char *filename, int lineno,
const char *fmt, va_list ap)
@{
if (filename)
fprintf (stderr, "%s:%d: ", filename, lineno);
vfprintf (stderr, fmt, ap);
fprintf (stderr, "\n");
return 0;
@}
@end group
@end smallexample
@deftypefun void mu_sieve_set_diag_stream (mu_sieve_machine_t @var{mach},
mu_stream_t @var{stream}
Register @var{stream} as the diagnostic stream for this machine. The
reference count of @var{stream} is increased.
@end deftypefun
@deftypefun void mu_sieve_set_debug (mu_sieve_machine_t @var{mach}, mu_sieve_printf_t @var{debug});
This function sets the debug printer function for the machine. If it is
not set, the default debug printer is @code{NULL} which means no
debugging information will be displayed.
@deftypefun void mu_sieve_get_dbg_stream (mu_sieve_machine_t @var{mach}, @
mu_stream_t *@var{pstr})
Get a reference to the machine's debug output stream. The obtained
stream must be dereferenced by using @code{mu_stream_unref} or
@code{mu_stream_destroy}, when no longer needed.
@end deftypefun
@deftypefun void mu_sieve_set_debug_level (mu_sieve_machine_t @var{mach}, mu_debug_t @var{dbg}, int @var{level})
This function sets the debug level for the given instance of sieve
machine. The @var{dbg} argument is the @code{mu_debug_t} object to be
used with mailutils library, the @var{level} argument specifies the
debugging level for the sieve library itself. It is a bitwise or of
the following values:
@table @code
@item MU_SIEVE_DEBUG_TRACE
Trace the execution of the sieve script.
@item MU_SIEVE_DEBUG_INSTR
Print the sieve machine instructions as they are executed.
@item MU_SIEVE_DEBUG_DISAS
Dump the disassembled code of the sieve machine. Do not run it.
@item MU_SIEVE_DRY_RUN
Do not executed the actions, only show what would have been done.
@end table
@deftypefun void mu_sieve_set_dbg_stream (mu_sieve_machine_t @var{mach},
mu_stream_t @var{stream})
Register @var{stream} as the debug output stream for this machine. The
reference count of @var{stream} is increased.
@end deftypefun
@deftypefun void mu_sieve_set_logger (mu_sieve_machine_t @var{mach}, mu_sieve_action_log_t @var{logger})
......@@ -524,10 +376,6 @@ This function sets the logger function. By default the logger function
is @code{NULL}, which means that the executed actions are not logged.
@end deftypefun
@deftypefun void mu_sieve_set_ticket (mu_sieve_machine_t @var{mach}, mu_ticket_t @var{ticket})
This function sets the authentication ticket to be used with this machine.
@end deftypefun
@deftypefun void mu_sieve_set_mailer (mu_sieve_machine_t @var{mach}, mu_mailer_t @var{mailer})
This function sets the mailer. The default mailer is @code{"sendmail:"}.
@end deftypefun
......@@ -569,6 +417,115 @@ Log a sieve action using logger function associated with the machine @var{mach}.
Immediately abort the execution of the script.
@end deftypefun
@node String Accessors
@subsection String Accessors
Strings are stored in a special memory area within the Sieve machine,
which is called @dfn{string space}. A string is identified by its
index in the string space. Array of strings is represented internally
as a contiguous area within the string space that holds one or more
strings. An array is identified by the index of its first element and
number of elements in it:
@example
struct mu_sieve_slice
@{
size_t first; /* Index of the first object */
size_t count; /* Number of objects */
@};
@end example
A single sieve string is represented by an array of strings with
zero @code{count}.
To obtain actual value of a string, use the @code{mu_sieve_string}
function:
@deftypefun {char *} mu_sieve_string (mu_sieve_machine_t @var{mach}, @
mu_sieve_slice_t @var{slice}, @
size_t @var{n})
Return actual textual value of the @var{n}th string in the array
@var{slice} of the Sieve machine @var{mach}.
If the @code{variables} extension is required, the returned value will
have variables expanded.
@end deftypefun
Two functions are provided for manipulating raw string values. Each
string in the string space is kept in the following structure:
@example
typedef struct mu_sieve_string
@{
unsigned constant:1; /* String is constant */
unsigned changed:1; /* String value has changed */
char *orig; /* String original value */
char *exp; /* Actual string value after expansion */
void *rx; /* Pointer to the corresponding regular expr */
@} mu_sieve_string_t;
@end example
All fields in this structure shall be deemed constant. Sieve code
(such as new actions or tests) should never try to change any of them.
The meaning of its fields is:
@deftypecv Field {struct mu_sieve_string} unsigned constant
Zero if the string is subject to variable expansion and 1 otherwise.
This field is defined when compiling the Sieve script.
@end deftypecv
@deftypecv Field {struct mu_sieve_string} unsigned changed
This field is @samp{1} if the expanded value of the string has changed
since it was retrieved for the last time. This is used by the Sieve
machine to determine whether the associated regular expression (if
any) needs to be recompiled.
This field is modified by the string accessor functions. Obviously,
if @code{constant == 1}, then @code{changed == 0}.
@end deftypecv
@deftypecv Field {struct mu_sieve_string} {char *} orig
A pointer to the original string value, as it appeared in the Sieve
script source file.
@end deftypecv
@deftypecv Field {struct mu_sieve_string} {char *} exp
A pointer to the string value after expansion. Valid only if
@code{constant == 0}.
@end deftypecv
@deftypecv Field {struct mu_sieve_string} {void *} rx
Points to the memory area containig the compiled regular expression
corresponding to that string. This member is valid, e.g. if the
string represents the second argument of a test used with
@code{:match} or @code{:regex} tag.
@end deftypecv
The raw string values are accessed via the following two functions:
@deftypefun {mu_sieve_string_t *} mu_sieve_string_raw (mu_sieve_machine_t @var{mach}, @
mu_sieve_slice_t @var{slice}, @
size_t @var{n})
Returns pointer to the structure representing @var{n}th string in
slice @var{slice}. A runtime exception is raised if @var{n} is out of
range represented by @var{slice}.
Extension writers should treat this as a constant object.
@end deftypefun
@deftypefun {char *} mu_sieve_string_get (mu_sieve_machine_t @var{mach}, @
mu_sieve_string_t *@var{string})
Evaluate @var{string} and return its textual representation. If the
@code{variables} extension is required, this function performs
variable substitution.
@end deftypefun
@node Argument Accessors
@subsection Argument Accessors
@node Symbol Space Functions
@subsection Symbol Space Functions
......
......@@ -15,6 +15,7 @@ is a superset of the Sieve language as described in RFC 3028.
* Comparators::
* Tests::
* Actions::
* Extensions::
* GNU Extensions::
@end menu
......@@ -1562,6 +1563,409 @@ message regardless of whether the user email is listed as a recipient
for the message.
@end deftypefn
@node Extensions
@section Extensions
The following extensions are implemented
@menu
* encoded-character::
* relational::
* variables::
* environment::
* numaddr::
* editheader::
* list::
* moderator::
* pipe::
* spamd::
* timestamp::
* vacation::
@end menu
@node encoded-character
@subsection The encoded-character extension
The @samp{encoded-character} extension complies with @cite{RFC 5228},
part 2.4.2.4. It provides a way of incorporating multibyte sequences
in a Sieve script using only ASCII characters. This is a built-in
extension. It is enabled using the following statement:
@example
require "encoded-character";
@end example
When this extension is enabled, the sequences @samp{$@{hex: ...@}},
and @samp{$@{unicode: ...@}} can appear inside of quoted strings.
The sequence
@example
$@{hex: @var{XX}@}
@end example
@noindent
where @var{XX} is a sequence of one or two-digit hex numbers separated
by any amount of whitespace, is replaced with the octets with the
hexadecimal values given by each hex number. For example,
@example
"$@{hex: 24 24@}" @result{} "$$"
@end example
Thus, the following script will discard any message containing three
contiguous dollar signs in its @samp{Subject} header:
@example
require "encoded-character";
if header :contains "Subject" "$$@{hex:24 24@}" @{
discard;
@}
@end example
The @samp{hex:} keyword is case-insensitive. If @var{XX} contains
invalid hex numbers, the entire sequence is left verbatim. This is
illustrated by the following example:
@example
"$$@{hex:40@}" @result{} "$@@"
"$@{hex: 40 @}" @result{} "@@"
"$@{HEX: 40@}" @result{} "@@"
"$@{hex:40" @result{} "$@{hex:40"
"$@{hex:400@}" @result{} "$@{hex:400@}"
"$@{hex:4$@{hex:30@}@}" @result{} "$@{hex:40@}"
@end example
The sequence
@example
$@{unicode: @var{HEXNUM}@}
@end example
@noindent
where @var{HEXNUM} is a list of hexadecimal numbers separated with
whitespace, will be replaced by the UTF-8 encoding of the specified
Unicode characters, which are identified by the hexadecimal value of
@var{HEXNUM}. For example, the following string represents a single
@samp{@@} sign:
@example
"$@{UNICODE:40@}"
@end example
Similarly to @samp{hex:}, the @samp{unicode:} indicator is case
insensitive. The following examples demonstrate the handling of
several valid and invalid encodings:
@example
"$@{unicode:40@}" @result{} "@@"
"$@{ unicode:40@}" @result{} "$@{ unicode:40@}"
"$@{UNICODE:40@}" @result{} "@@"
"$@{UnICoDE:0000040@}" @result{} "@@"
"$@{Unicode:40@}" @result{} "@@"
"$@{Unicode:Cool@}" @result{} "$@{Unicode:Cool@}"
"$@{unicode:200000@}" @result{} error
"$@{Unicode:DF01@} @result{} error
@end example
@node relational
@subsection The relational extension
The @samp{relational} extension complies with @cite{RFC 3431}. It is
a built-in extension. When enabled, the two new match types become
available: @code{:count} and @code{:value}. Both keywords take a
single argument defining the relational operator to use:
@multitable @columnfractions 0.2 0.8
@item @samp{"gt"} @tab greater than (@samp{>})
@item @samp{"ge"} @tab greater than or equal (@samp{>=})
@item @samp{"lt"} @tab less than (@samp{<})
@item @samp{"le"} @tab less than or equal (@samp{<=})
@item @samp{"eq"} @tab equal to (@samp{==})
@item @samp{"ne"} @tab not equal to (@samp{!=})
@end multitable
The @code{:value} keyword requires a relational comparison between
strings. The left side of the relation is formed by the value from
the message. The right side of the relation is the value from the
test expression. If there are multiple values on either side or both
sides, the test is considered true if any pair is true. For example,
@example
require ["relational", "fileinto"];
if header :value "gt" :comparator "i;ascii-numeric"
["x-spam-level] ["5"]
@{
fileinto "spam";
@}
@end example
The @code{:count} keyword counts the specified entities in the message
and compares their number with the value given in the test
expression. The latter must be a list of one element. This match
type can only be used with numeric comparators. For example, the
following script will discard any message with 10 or more recipient
addresses in the @samp{To} and @samp{Cc} headers:
@example
require "relational";
if address :count "ge" :comparator "i;ascii-numeric"
["to", "cc"] ["10"]
@{
discard;
@}
@end example
@node variables
@subsection The variables extension
The @samp{variables} extension is defined in @cite{RFC 5229}. It is
a built-in extension. It introduces support for variables in Sieve
scripts.
There are two kind of variables: user-defined and match variables.
A @dfn{user-defined} variable is initialized using the @code{set}
action:
@deftypefn Action {} set [@var{modifiers}] @var{name}(string) @var{value}(string)
Stores the specified @var{value} in the variable identified by
@var{name}. Optional @var{modifiers} are applied on @var{value} before it
is stored in the variable.
The following modifiers are available:
@table @code
@item :lower
Convert value to lower case letters.
@item :upper
Convert value to upper case letters.
@item :lowerfirst
Convert the first character in value to lower case.
@item :upperfirst
Convert the first character in value to upper case.
@item :quotewildcard
Quote wildcard characters (@samp{*}, @samp{?}, @samp{\}) by prefixing
each occurrence with a backslash (@samp{\}). This can be used to
ensure that the variable will only match a literal occurrence if used
as a parameter to @code{:matches}.
@item :length
The value is the decimal number of characters in the expansion,
converted to a string.
@end table
When several modifiers are present, they are applied in the following
order of precedence (largest value first):
@multitable @columnfractions 0.2 0.8
@headitem precedence @tab modifiers
@item 40 @tab @code{:lower} or @code{:upper}
@item 30 @tab @code{:lowerfirst} or @code{:upperfirst}
@item 20 @tab @code{:quotewildcard}
@item 10 @tab @code{:length}
@end multitable
Modifiers having the same precedence (i.e. listed on the same row in
the above table) cannot be used together.
@end deftypefn
Variables are referenced within text strings using the construct
@samp{$@{@var{name}@}}, where @var{name} is the name of the variable
as it appeared in the first parameter to the @code{set} statement.
For example:
@example
require "variables";
set "sender" "root@*":
if envelope :matches "$@{sender@}"
@{
...
@}
@end example
@dfn{Match variables} refer to parts of the most recently evaluated
successful match of type @code{:matches} or @code{:regex}. They have
names consisting entirely of decimal digits. The variable
@samp{$@{0@}} refers to the entire matched expression. The variable
@samp{$@{1@}} refers to the substring matching the first occurrence of
the wildcard (@samp{?} and @samp{*}), @samp{$@{2@}} refers to the
second occurrence and so on. The wildcards match as little as possible
(non-greedy matching). For example:
@example
require ["variables", "fileinto"];
if header :matches "List-ID" "*<*@*" @{
fileinto "INBOX.lists.$@{2@}";
stop;
@}
@end example
If @code{:regex} match is used, the match variables starting from
@samp{$@{1@}} refer to the substrings of the argument value matching
subsequent parenthesized groups of the regular expression.
@deftypefn Test {} string [@var{comparator}] @
[@var{match-type}] @
@var{source}(string-list) @var{keys}(string-list)
The @code{string} test compares two strings according to the selected
comparator and match type. The test evaluates to @samp{true} if any
two strings from @var{source} and @var{keys} match.
The @samp{:count} match used in @samp{string} counts each empty string
as 0, and each non-empty one as 1. The count of a string list is the
sum of the counts of the member strings.
@end deftypefn
@node environment
@subsection environment
The @samp{environment} extension complies with @cite{RFC 5183}. It is
a built-in extension. It introduces the following test:
@deftypefn Test {} environment [@var{comparator}] @
[@var{match-type}] @
@var{name}(string) @var{keys}(string-list)
The @code{environment} test evaluates to @samp{true} if the value of
the environment items @var{name} matches any string from @var{keys}.
@end deftypefn
The following environment items are defined:
@table @asis
@item domain
The primary DNS domain of the machine where the Sieve script is
executing.
@item host
The fully-qualified domain name of the host where the Sieve script is
executing.
@item location
Type of service that is evaluating the script. Depending on the
utility that is evaluating the script it is:
@multitable @columnfractions 0.6 0.4
@headitem Utility @tab Location
@item sieve @tab @samp{"MUA"}, or set with the @option{--environment} option.
@item maidag @tab @samp{"MDA"}
@item inc @tab @samp{"MUA"}
@end multitable
@item name
The string @samp{GNU Mailutils}
@item phase
The point relative to final delivery where the Sieve script is being
evaluated. Depending on the utility that is evaluating the script it is:
@multitable @columnfractions 0.6 0.4
@headitem Utility @tab Location
@item sieve @tab @samp{post} unless set with the @option{--environment} option.
@item maidag @tab @samp{"during"}
@item inc @tab @samp{"post"}
@end multitable
@item version
Mailutils version string (e.g. @samp{@value{VERSION}}).
@end table
@node numaddr
@subsection The numaddr extension
This is an example loadable extension. @ref{External Tests, numaddr}.
@node editheader
@subsection The editheader extension
The @code{editheader} extension complies with @cite{RFC 5293}. It
provides the following actions:
@deftypefn Action {} addheader [:last] @var{field-name}(string) @var{value}(string
Adds a header field to the existing message header. By default the
header is inserted at the beginning of the header list. If the tag
@code{:last} is specified, it is appended at the end.
@end deftypefn
@deftypefn Action {} deleteheader" [:index @var{fieldno}(number) :last] @
[@var{comparator}] @
[@var{match-type}] @
@var{field-name}(string) @
[@var{value-patterns}(string-list)]
Deletes occurrences of the header field matching the criteria.
The @var{value-patterns}, if specified, determines which occurrences
of the header fielde to delete. If not supplied, @var{comparator} and
@var{match-type} are silently ignored.
If @samp{:index @var{fieldno}} is specified, only the numbered
occurrence of the named header field will be matched (header numbering
begins at 1), If @code{:last} is specified, the count is backwards; 1
denotes the last named header field, 2 the second to last, and so on.
The counting happens before the @var{value-patterns} match, if any.
Thus, e.g. the action
@example
deleteheader :index 1 :contains "Delivered-To" "bob@@example.com";
@end example
@noindent
would delete the first @samp{Delivered-To} header field if it contains
the string @samp{bob@@example.com}.
@end deftypefn
@node list
@subsection The list extension
@ref{External Tests, list}.
@node moderator
@subsection The moderator extension
A loadable extension implementing a moderator robot for Mailman-driven
mail archives. @ref{External Actions, moderator}.
@node pipe
@subsection The pipe extension
A loadable extension for external command execution. It provides the
@code{pipe} action (@pxref{External Actions, pipe}) and test
(@pxref{External Tests, pipe}).
@node spamd
@subsection The spamd extension
Implements a test which interfaces to SpamAssassin filter. This is a
loadable extension. @pxref{External Tests, spamd}.
@node timestamp
@subsection The timestamp extension
The loadable extension @code{timestamp} implements a test for
comparing the value of a structured date header field with the given
date.
Note: this extension will probably phase away in favor of the
@code{date} Sieve extension (@cite{RFC 5260}).
@node vacation
@subsection The vacation extension
The loadable extension @code{vacation} provides the action intended to
inform the sender that the recipient is not currently reading his mail.
@xref{External Actions,vacation}.
@node GNU Extensions
@section GNU Extensions
......
......@@ -225,12 +225,18 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
compfun = comp_false;
val = mu_sieve_get_arg_untyped (mach, 1);
/* NOTE: Type of val is always SVT_STRING_LIST */
if (val->type != SVT_STRING_LIST)
abort ();
if (val->v.list.count > 1)
switch (val->type)
{
case SVT_STRING:
break;
case SVT_STRING_LIST:
if (val->v.list.count == 1)
break;
/* fall through */
default:
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
_("second argument must be a list of one element"));
_(":count requires second argument to be a list of one element"));
mu_i_sv_error (mach);
return 1;
}
......
......@@ -484,6 +484,8 @@ main (int argc, char *argv[])
mu_error (_("cannot initialize sieve machine: %s"), mu_strerror (rc));
return EX_SOFTWARE;
}
sieve_setenv ("phase=post", mach);
mu_list_foreach (env_list, sieve_setenv, mach);
mu_list_destroy (&env_list);
......
......@@ -17,7 +17,7 @@
m4_pushdef([MUT_SIEVE_EXT_NAME],[pipe test])
MUT_SIEVE_EXT_TEST([],[pipetest00],
[require "test-pipe";
[require "pipe";
if pipe :header "$cwd/ckmsg"
{
discard;
......