Commit 75e3a3eb 75e3a3ebde7a363bf65e6c51a179508a3a1b3e62 by Sergey Poznyakoff

Updated

1 parent f1cbdaab
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?
......
......@@ -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
......
......@@ -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
......
......@@ -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] @var{header-names} @var{number}
@noindent
This test is provided as an example of loadable extension tests. You
must use @samp{require "test-numaddr"} statement before actually using
it.
......@@ -1156,7 +1496,7 @@ if header :contains ["from"] ["idiot@@example.edu"]
@deffn Action fileinto @var{folder}
@noindent
@sp 1
Required arguments:
@table @var
......@@ -1256,6 +1596,8 @@ if header :mime :matches "Content-Type"
@end deffn
@deffn Action redirect @var{address}
@noindent
The @code{redirect} action is used to send the message to another user at
a supplied @var{address}, as a mail forwarding feature does. This action
makes no changes to the message body or existing headers, but it may add
......
......@@ -24,7 +24,7 @@ The API is still changing.
@deftypefun int mailer_send_message (mailer_t @var{mailer}, message_t @var{msg}, address_t @var{from}, address_t @var{to});
If from is not @var{NULL}, it must containg a single fully qualified
If from is not @var{NULL}, it must contain a single fully qualified
RFC2822 email address which will be used as the envelope from
address. This is the address to which delivery status notifications
are sent, so it never matters what it is set to until it REALLY matters.
......@@ -101,7 +101,7 @@ Some possible use cases the API must support are:
2 - mailer_deliver(mailer, msg, address_t( "<>" ), to)
Don't want mail loops, so the nul but valid SMTP address of <> is
Don't want mail loops, so the null but valid SMTP address of <> is
the envelope from.
@subheading The sendmail mailer.
......
......@@ -118,10 +118,10 @@ Mailutils.
@end ifinfo
@menu
* Introduction:: GNU Mailutils
@comment * Concrete API:: Concrete API.
* Framework:: Framework.
* Authentication Library:: Auxiliary library for authenticating users.
* Sieve Library:: GNU implementation of Sieve mail filtering.
* libmailbox:: Main library
* libmuauth:: Auxiliary library for authenticating users.
* libmu_scm:: Interface with Guile
* libsieve:: GNU implementation of Sieve mail filtering.
* Programs:: Programs.
* Reporting Bugs:: How to report a bug.
* News:: Where to get information about @sc{gnu} Mailutils
......@@ -134,7 +134,7 @@ Indices
@end menu
@node Introduction, Framework, Top, Top
@node Introduction, libmailbox, Top, Top
@comment node-name, next, previous, up
@chapter Introduction
@cindex Introduction
......@@ -257,34 +257,34 @@ Notifications}
@end itemize
@comment @node Concrete API, Framework, Introduction, Top
@comment @comment node-name, next, previous, up
@comment @chapter Concrete API
@comment @cindex Concrete API
@comment @include c-api.texi
@node Framework, Authentication Library, Introduction, Top
@node libmailbox, libmuauth, Introduction, Top
@comment node-name, next, previous, up
@chapter Framework
@cindex Framework
@include framework.texi
@node Authentication Library, Sieve Library, Framework, Top
@node libmuauth, libmu_scm, libmailbox, Top
@chapter Authentication Library
@cindex Authentication Library
@cindex libmuauth
@include libmuauth.texi
@node Sieve Library, Programs, Authentication Library, Top
@node libmu_scm, libsieve, libmuauth, Top
@chapter Mailutils to Scheme interface
@cindex Scheme
@cindex libmu_scm
@include libmu_scm.texi
@node libsieve, Programs, libmu_scm, Top
@chapter Sieve Library
@cindex Sieve Library
@cindex libsieve
@include libsieve.texi
@node Programs, Reporting Bugs, Sieve Library, Top
@node Programs, Reporting Bugs, libsieve, Top
@comment node-name, next, previous, up
@chapter Programs
@cindex Programs
......
......@@ -310,7 +310,7 @@ of seconds.
@cindex :auth
These options control the authorization and authentication module
lists. For a description of auhtentication concepts, refer to
lists. For a description of authentication concepts, refer to
@xref{authentication}.
@table @option
......@@ -351,7 +351,7 @@ The hashed value of the user password is retrieved from the @acronym{sql}
database using query supplied by @option{--sql-getpass} option
(see below).
@item pam
The user is authenicated via pluggable authentication module
The user is authenticated via pluggable authentication module
(@acronym{pam}). The @acronym{pam} service name to be used is
configured via @option{--pam-service} option (see below)
@end table
......@@ -455,7 +455,7 @@ be run either as a standalone program or from @file{inetd.conf} file.
@sc{gnu} imap4d supports a notion of @dfn{namespaces} defined in RFC 2342. A
namespace is a set of directories upon which the user has certain
permissions. It should be understood that these persmissions apply
permissions. It should be understood that these permissions apply
only if the underlying filesystem allows them.
The three namespaces supported by @command{imap4d} are:
......@@ -1306,7 +1306,7 @@ Prints out the messages from @var{msglist}. The variable @code{crt}
determines the minimum number of lines the body of the message must
contain in order to be piped through pager command specified
by environment variable @code{PAGER}. If @code{crt} is set to a numeric
value, this value is taken as the mininmum number of lines. Otherwise,
value, this value is taken as the minimum number of lines. Otherwise,
if @code{crt} is set without a value then the height of the terminal
screen is used to compute the threshold. The number of lines on
screen is controlled by @code{screen} variable.
......@@ -2028,7 +2028,7 @@ Enable network protocol traces (MU_DEBUG_PROT)
Enable sieve trace (MU_SIEVE_DEBUG_TRACE)
@item l
Enble sieve action logs
Enable sieve action logs
@end table
The digits in the range @samp{0} -- @samp{9} used in @var{flags} set
......@@ -2209,7 +2209,7 @@ by default only the first one is presented.
@item -d
@itemx --debug
Display mailbox debuging information.
Display mailbox debugging information.
@item -f @var{MAILBOX}
@itemx --folder=@var{MAILBOX}
......@@ -2513,7 +2513,6 @@ The program uses following option groups: @xref{mailbox}.
* Specifying Mailboxes to Operate Upon::
* Passing Options to Scheme::
* Guimb Invocation Summary::
* Scheme Procedures and Variables::
@end menu
@node Specifying Scheme Program to Execute
......@@ -2596,7 +2595,7 @@ lines to the beginning of your script to allow for its immediate execution:
@noindent
(replace @samp{/usr/local/bin/} with the actual path to the @command{guimb}).
Otherwise, if you use @option{--file} or @option{--expression} oprions,
Otherwise, if you use @option{--file} or @option{--expression} options,
the additional arguments may be passed to the Scheme program @option{-g}
(@option{--guile-arg}) command line option. For example:
......@@ -2656,213 +2655,6 @@ Display help message.
Display program version.
@end table
@node Scheme Procedures and Variables
@subsection Scheme Procedures and Variables
@menu
* Address Functions::
* Mailbox Functions::
* Message Functions::
* MIME Functions::
* Log Functions::
@end menu
@node Address Functions
@subsubsection Address Functions
@deffn Function mu-address-get-personal ADDRESS NUM
Return personal part of an email address.
@end deffn
@deffn Function mu-address-get-comments ADDRESS NUM
@end deffn
@deffn Function mu-address-get-email ADDRESS NUM
Return email part of an email address.
@end deffn
@deffn Function mu-address-get-domain ADDRESS NUM
Return domain part of an email address
@end deffn
@deffn Function mu-address-get-local ADDRESS NUM
Return local part of an email address.
@end deffn
@deffn Function mu-address-get-count ADDRESS
Return number of parts in email address.
@end deffn
@node Mailbox Functions
@subsubsection Mailbox Functions
@deffn Function mu-mailbox-open URL MODE
Opens a mailbox specified by URL.
@end deffn
@deffn Function mu-mailbox-close MBOX
Closes mailbox MBOX
@end deffn
@deffn Function mu-mailbox-get-url MBOX
Returns the URL of the mailbox.
@end deffn
@deffn Function mu-mailbox-get-port MBOX MODE
Returns a port associated with the contents of the MBOX.
MODE is a string defining operation mode of the stream. It may
contain any of the two characters: @samp{r} for reading, @samp{w} for
writing.
@end deffn
@deffn Function mu-mailbox-get-message MBOX MSGNO
Retrieve from MBOX message # MSGNO.
@end deffn
@deffn Function mu-mailbox-messages-count MBOX
Returns number of messages in the mailbox.
@end deffn
@deffn Function mu-mailbox-expunge MBOX
Expunges deleted messages from the mailbox.
@end deffn
@deffn Function mu-mailbox-url MBOX
Returns the URL of the mailbox
@end deffn
@deffn Function mu-mailbox-append-message MBOX MESG
Appends the message to the mailbox
@end deffn
@node Message Functions
@subsubsection Message Functions
@deffn Function mu-message-copy MESG
Creates the copy of the given message.
@end deffn
@deffn Function mu-message-set-header MESG HEADER VALUE REPLACE
Sets new VALUE to the header HEADER of the message MESG.
If the HEADER is already present in the message its value
is replaced with the supplied one if the optional REPLACE is
#t. Otherwise new header is created and appended.
@end deffn
@deffn Function mu-message-get-size MESG
Returns the size of the given message.
@end deffn
@deffn Function mu-message-get-lines MESG
Returns number of lines in the given message.
@end deffn
@deffn Function mu-message-get-sender MESG
Returns the sender email address for the message MESG.
@end deffn
@deffn Function mu-message-get-header MESG HEADER
Returns the header value of the HEADER in the MESG.
@end deffn
@deffn Function mu-message-get-header-fields MESG HEADERS
Returns the list of headers in the MESG. If optional HEADERS is
specified it should be a list of header names to restrict return
value to.
@end deffn
@deffn Function mu-message-set-header-fields MESG LIST REPLACE
Set the headers in the message MESG from LIST
LIST is a list of (cons HEADER VALUE)
Optional parameter REPLACE specifies whether the new header
values should replace the headers already present in the
message.
@end deffn
@deffn Function mu-message-delete MESG FLAG
Mark given message as deleted. Optional FLAG allows to toggle deleted mark
The message is deleted if it is #t and undeleted if it is #f
@end deffn
@deffn Function mu-message-get-flag MESG FLAG
Return value of the attribute FLAG.
@end deffn
@deffn Function mu-message-set-flag MESG FLAG VALUE
Set the given attribute of the message. If optional VALUE is #f, the
attribute is unset.
@end deffn
@deffn Function mu-message-get-user-flag MESG FLAG
Returns value of the user attribute FLAG.
@end deffn
@deffn Function mu-message-set-user-flag MESG FLAG VALUE
Set the given user attribute of the message. If optional VALUE is
#f, the attribute is unset.
@end deffn
@deffn Function mu-message-get-port MESG MODE FULL
Returns a port associated with the given MESG. MODE is a string
defining operation mode of the stream. It may contain any of the
two characters: @samp{r} for reading, @samp{w} for writing.
If optional FULL argument specified, it should be a boolean value.
If it is #t then the returned port will allow access to any
part of the message (including headers). If it is #f then the port
accesses only the message body (the default).
@end deffn
@deffn Function mu-message-get-body MESG
Returns the message body for the message MESG.
@end deffn
@deffn Function mu-message-send MESG MAILER
Sends the message MESG. Optional MAILER overrides default
mailer settings in mu-mailer.
@end deffn
@node MIME Functions
@subsubsection MIME Functions
@deffn Function mu-mime-create FLAGS MESG
Creates a new MIME object.
@end deffn
@deffn Function mu-mime-multipart? MIME
Returns #t if MIME is a multipart object.
@end deffn
@deffn Function mu-mime-get-num-parts MIME
Returns number of parts in a MIME object.
@end deffn
@deffn Function mu-mime-get-part MIME PART
Returns part number PART from a MIME object.
@end deffn
@deffn Function mu-mime-add-part MIME MESG
Adds MESG to the MIME object.
@end deffn
@deffn Function mu-mime-get-message MIME
Converts MIME object to a message.
@end deffn
@node Log Functions
@subsubsection Log Functions
@deffn Function mu-openlog IDENT OPTION FACILITY
Opens a connection to the system logger for Guile program.
@end deffn
@deffn Function mu-logger PRIO TEXT
Generates a log message to be distributed via syslogd.
@end deffn
@deffn Function mu-closelog
Closes the channel to the system logger open by mu-openlog.
@end deffn
@page
@node comsatd
......
......@@ -44,45 +44,44 @@ ENVELOPE TO: <coyote@desert.example.org>
11: I don't want to read these messages.
12:
13: Regards.
14: .
15:
-re
16: [0-9:=-]+
17: Content-Type: message/delivery-status
18:
-re
19: Reporting-UA: sieve; GNU Mailutils [0-9][0-9.]*
-re
20: Arrival-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
21: Final-Recipient: RFC822; foobar@nonexistent.net
22: Action: deleted
23: Disposition: automatic-action/MDN-sent-automatically;deleted
-re
24: Last-Attempt-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
25:
-re
26: [0-9:=-]+
27: Content-Type: message/rfc822
28:
29: From: coyote@desert.example.org
30: To: roadrunner@acme.example.com
31: Subject: I have a present for you
32: X-Caffeine: C8H10N4O2
33:
34: Look, I'm sorry about the whole anvil thing, and I really
35: didn't mean to try and drop it on you from the top of the
36: cliff. I want to try to make it up to you. I've got some
37: great birdseed over here at my place--top of the line
38: stuff--and if you come by, I'll have it all wrapped up
39: for you. I'm really sorry for all the problems I've caused
40: for you over the years, but I know we can work this out.
41:
42: --
43: Wile E. Coyote "Super Genius" coyote@desert.example.org
44:
-re
45: [0-9:=-]+
46:
14:
-re
15: [0-9:=-]+
16: Content-Type: message/delivery-status
17:
-re
18: Reporting-UA: sieve; GNU Mailutils [0-9][0-9.]*
-re
19: Arrival-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
20: Final-Recipient: RFC822; foobar@nonexistent.net
21: Action: deleted
22: Disposition: automatic-action/MDN-sent-automatically;deleted
-re
23: Last-Attempt-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
24:
-re
25: [0-9:=-]+
26: Content-Type: message/rfc822
27:
28: From: coyote@desert.example.org
29: To: roadrunner@acme.example.com
30: Subject: I have a present for you
31: X-Caffeine: C8H10N4O2
32:
33: Look, I'm sorry about the whole anvil thing, and I really
34: didn't mean to try and drop it on you from the top of the
35: cliff. I want to try to make it up to you. I've got some
36: great birdseed over here at my place--top of the line
37: stuff--and if you come by, I'll have it all wrapped up
38: for you. I'm really sorry for all the problems I've caused
39: for you over the years, but I know we can work this out.
40:
41: --
42: Wile E. Coyote "Super Genius" coyote@desert.example.org
43:
-re
44: [0-9:=-]+
45:
END OF MESSAGE
ENVELOPE FROM: MAILER-DAEMON@nonexistent.net
ENVELOPE TO: <b1ff@de.res.example.com>
......@@ -104,43 +103,42 @@ ENVELOPE TO: <b1ff@de.res.example.com>
11: I don't want to read these messages.
12:
13: Regards.
14: .
15:
-re
16: [0-9:=-]+
17: Content-Type: message/delivery-status
18:
-re
19: Reporting-UA: sieve; GNU Mailutils [0-9][0-9.]*
-re
20: Arrival-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
21: Final-Recipient: RFC822; foobar@nonexistent.net
22: Action: deleted
23: Disposition: automatic-action/MDN-sent-automatically;deleted
-re
24: Last-Attempt-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
25:
-re
26: [0-9:=-]+
27: Content-Type: message/rfc822
28:
29: From: youcouldberich!@reply-by-postal-mail.invalid
30: To: rube@landru.example.edu
31: Subject: $$$ YOU, TOO, CAN BE A MILLIONAIRE! $$$
32: Date: TBD
33: X-Number: 0015
34:
35: YOU MAY HAVE ALREADY WON TEN MILLION DOLLARS, BUT I DOUBT
36: IT! SO JUST POST THIS TO SIX HUNDRED NEWSGROUPS! IT WILL
37: GUARANTEE THAT YOU GET AT LEAST FIVE RESPONSES WITH MONEY!
38: MONEY! MONEY! COLD HARD CASH! YOU WILL RECEIVE OVER
39: $20,000 IN LESS THAN TWO MONTHS! AND IT'S LEGAL!!!!!!!!!
40: !!!!!!!!!!!!!!!!!!111111111!!!!!!!11111111111!!1 JUST
41: SEND $5 IN SMALL, UNMARKED BILLS TO THE ADDRESSES BELOW!
42:
-re
43: [0-9:=-]+
44:
14:
-re
15: [0-9:=-]+
16: Content-Type: message/delivery-status
17:
-re
18: Reporting-UA: sieve; GNU Mailutils [0-9][0-9.]*
-re
19: Arrival-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
20: Final-Recipient: RFC822; foobar@nonexistent.net
21: Action: deleted
22: Disposition: automatic-action/MDN-sent-automatically;deleted
-re
23: Last-Attempt-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
24:
-re
25: [0-9:=-]+
26: Content-Type: message/rfc822
27:
28: From: youcouldberich!@reply-by-postal-mail.invalid
29: To: rube@landru.example.edu
30: Subject: $$$ YOU, TOO, CAN BE A MILLIONAIRE! $$$
31: Date: TBD
32: X-Number: 0015
33:
34: YOU MAY HAVE ALREADY WON TEN MILLION DOLLARS, BUT I DOUBT
35: IT! SO JUST POST THIS TO SIX HUNDRED NEWSGROUPS! IT WILL
36: GUARANTEE THAT YOU GET AT LEAST FIVE RESPONSES WITH MONEY!
37: MONEY! MONEY! COLD HARD CASH! YOU WILL RECEIVE OVER
38: $20,000 IN LESS THAN TWO MONTHS! AND IT'S LEGAL!!!!!!!!!
39: !!!!!!!!!!!!!!!!!!111111111!!!!!!!11111111111!!1 JUST
40: SEND $5 IN SMALL, UNMARKED BILLS TO THE ADDRESSES BELOW!
41:
-re
42: [0-9:=-]+
43:
END OF MESSAGE
ENVELOPE FROM: MAILER-DAEMON@nonexistent.net
ENVELOPE TO: <bar@dontmailme.org>
......@@ -162,40 +160,39 @@ ENVELOPE TO: <bar@dontmailme.org>
11: I don't want to read these messages.
12:
13: Regards.
14: .
15:
-re
16: [0-9:=-]+
17: Content-Type: message/delivery-status
18:
-re
19: Reporting-UA: sieve; GNU Mailutils [0-9][0-9.]*
-re
20: Arrival-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
21: Final-Recipient: RFC822; foobar@nonexistent.net
22: Action: deleted
23: Disposition: automatic-action/MDN-sent-automatically;deleted
-re
24: Last-Attempt-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
25:
-re
26: [0-9:=-]+
27: Content-Type: message/rfc822
28:
29: Received: (from bar@dontmailme.org)
30: by dontmailme.org id fERKR9N16790
31: for foobar@nonexistent.net; Fri, 28 Dec 2001 22:18:08 +0200
32: Date: Fri, 28 Dec 2001 23:28:08 +0200
33: From: Bar <bar@dontmailme.org>
34: To: Foo Bar <foobar@nonexistent.net>
35: Message-Id: <200112232808.fERKR9N16790@dontmailme.org>
36: Subject: Coffee
37:
38: How about some coffee?
39:
-re
40: [0-9:=-]+
41:
14:
-re
15: [0-9:=-]+
16: Content-Type: message/delivery-status
17:
-re
18: Reporting-UA: sieve; GNU Mailutils [0-9][0-9.]*
-re
19: Arrival-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
20: Final-Recipient: RFC822; foobar@nonexistent.net
21: Action: deleted
22: Disposition: automatic-action/MDN-sent-automatically;deleted
-re
23: Last-Attempt-Date: [A-Z][a-z][a-z], [A-Z][a-z][a-z] [ 0-3][0-9] [ 0-2][0-9]:[0-6][0-9]:[0-6][0-9] [0-9][0-9][0-9][0-9] [a-zA-Z0-9]*
24:
-re
25: [0-9:=-]+
26: Content-Type: message/rfc822
27:
28: Received: (from bar@dontmailme.org)
29: by dontmailme.org id fERKR9N16790
30: for foobar@nonexistent.net; Fri, 28 Dec 2001 22:18:08 +0200
31: Date: Fri, 28 Dec 2001 23:28:08 +0200
32: From: Bar <bar@dontmailme.org>
33: To: Foo Bar <foobar@nonexistent.net>
34: Message-Id: <200112232808.fERKR9N16790@dontmailme.org>
35: Subject: Coffee
36:
37: How about some coffee?
38:
-re
39: [0-9:=-]+
40:
END OF MESSAGE
FILE END
TEST END
......