Provided by: mailagent_3.1-106-1_amd64 bug

NAME

       mailagent - an automatic mail-processing tool

SYNOPSIS

       mailagent  [  -dhilqtFIVU  ]  [  -s{umaryt}  ] [ -f file ] [ -e rule ] [ -c config ] [ -L loglevel ] [ -r
       rulefile ] [ -o override ] [ mailfile ]

DESCRIPTION

       Mailagent allows you to process your mail automatically. Given a set of lex-like rules, you are  able  to
       fill  mails  to specific folders, forward messages to a third person, pipe a message to a command or even
       post the message to a newsgroup. It is also possible to process messages containing some  commands.   The
       mailagent  is  not usually invoked manually but is rather called via the filter program, which is in turn
       invoked by sendmail.  That means you must have sendmail on your system to use this.  You also  must  have
       perl to run the mailagent scripts.

       There  is  a  set  of  options  which may be used when you invoke mailagent yourself. Please refer to the
       OPTIONS section for a complete description. You may use the -h option to get a cryptic usage reminder.

   Product Overview
       Mailagent has actually four distinct set of features, which can be used simultaneously or one at a  time.
       This involves:

       •    An  @SH  command  processor,  to  remain compatible with the first implementation.  In this simplest
            usage, all the mail messages are left in your mailbox (or the catch all folder  required  on  Debian
            systems:  Please  see /usr/share/doc/mailagent/SECURITY for details), with special processing raised
            on messages whose subject is Command.  Please refer to the section entitled USING THE DEFAULT  RULES
            if you wish to use this feature.

       •    A  complete  mail  filter,  which  helps  you  sort  your mail based on various sorting criteria and
            actions. Filtering is specified in a rule file and supersedes the default  Command  mail  processing
            (which  may  be  turned  on  again  by explicitly setting up a rule for it). This should be the most
            common use of mailagent and is fully documented under the section entitled USING  THE  FILTER.   You
            may deliver mail to plain Unix-style folders but also to MMDF and MH ones.

       •    A  replacement for the vacation program, which will automatically answer your mail while you are not
            there. You only need to supply a message to be sent back and the frequency at which this will occur.
            Some simple macro substitutions allow you to re-use some parts of the mail header into your vacation
            message, for a more personalized reply. See the VACATION MODE section for more details.

       •    A generic mail server, which will let you implement a real mail server without  the  hassle  of  the
            lower-level  concerns like error recovery, logging or command parsing. The full documentation can be
            found in the section GENERIC MAIL SERVER at the end of this manual page.

       It is possible to extend the mailagent filtering commands by implementing them in perl  and  then  having
       them  automagically  loaded when used. Those extended commands will behave exactly like built in ones, as
       documented in the EXTENDING FILTERING COMMANDS section.

   Learning From Examples
       It is quite possible that you will find this manual page too complex for you.  Unfortunately, it  is  not
       really  meant  to be a tutorial but rather a reference material. If you wish, you may start by looking at
       the examples held in the distribution source tree  under  agent/examples.  This  directory  contains  two
       examples of rule files (look at the README file first) and are verbosely commented.

GETTING STARTED

       First,  you  need  to  install a minimum configuration and see how it works. It would be useless to fully
       install the program and then discover that it does not work as advertised...

       To start the installation, you have to set up a ~/.mailagent file which is the main  configuration  file,
       and choose the right filter program.

   Choosing The Filter Program
       The  distribution  comes  with  two filter programs. One written in shell and one in C. The shell version
       might be the one to use if you can receive  your  mail  on  many  different  platforms  where  your  home
       directory  is  NFS-mounted  (i.e.   shared  among  all  those platforms). The C version is safer and much
       faster, but you need to install it to a fixed location.

       On some platforms, sendmail does not correctly reset its UID when processing mails in its own  queue.  In
       that  case,  you  need  to get a private copy of the C filter program and make it setuid to yourself. The
       filter will then correctly reset its UID if invoked with an effective UID different from  yours  (it  may
       also  require the setgid bit to reset GID as well).  If this is indeed the case on your system, make sure
       you use the path configuration variable to set a proper PATH, as the filter will  spawn  a  perl  process
       with the '-S' option, looking for a mailagent script.

       Even  if  you do not need to get a setuid copy of the filter program, it is wise to set up a proper path:
       someone might break into your account by putting a mailagent Trojan horse in  the  appropriate  location.
       Also  make  sure the mailagent program is protected against writing, as well as the directory which holds
       it, or someone might substitute his own version of the script and break security. I  believe  the  setuid
       filter program to be safe, but overlooking is always possible so please report any security hole to me.

       The filter script can be found in the Lib/mailagent directory. It needs some tailoring so you should copy
       it  into  your  home  directory  and  edit  it  to  suit  your  needs. Comments held in it should be self
       explanatory. There is only a small section at the head of the script which needs to  be  edited.   You'll
       have to delete shell comments in the filter script by yourself if your shell cannot deal with them.

       As  of version 3.0 PL44, I advise you to prefer the C version if you are concerned about security. If you
       are in a position where multiple architectures can process your .forward, then a shell wrapper  selecting
       the proper executable based on the architecture will be required.

   Configuring Mailagent
       If mailagent is in your path, you may automatically configure a default installation by running:

                 mailagent -I

       which  will  create a ~/.mailagent file from an existing template, customize some important variables for
       your site, and make some basic sanity checks. Everything the command does is output  on  the  screen  for
       checking purposes, and any problem found is reported.

       Otherwise,   you   have   to   copy   the   mailagent.cf   file   held  in  the  mailagent  sub-directory
       /usr/share/mailagent (hereafter named Lib) as a .mailagent in your home directory. Edit it  to  configure
       the  whole  processing. In particular, you have to choose a spool directory (hereafter named Spool) and a
       log directory (hereafter named Log).

       Note that using the automatic installation procedure above does not prevent you from  going  through  the
       file  and  modifying  it as you wish.  In fact, you are greatly encouraged to do this, especially for the
       home directory setting, the logging level and the path or p_host variables. Once you are done, rerun  the
       mailagent  -I  command  to  make  sure  everything is fine.  Still, you will have to plug in mailagent by
       creating a ~/.forward file, as explained in a few sections.

       Following is a description of each of the fields you will find in the ~/.mailagent file,  followed  by  a
       suggested value, when applicable. Fields marked as optional may not be present in the configuration file.
       Some fields have a close relationship with others, and that is given too.

       agemax    Period  after  which  an  entry in the database should be removed (suggested: 1y) This field is
                 optional, but needed if autoclean is on.
       authfile  Remote sending authorizations (not implemented yet).
       autoclean Set to ON (case insensitively), mailagent will  perform  automatic  cleaning  of  the  database
                 entries  under  hash  by  removing  all the items older than agemax. This is an optional field,
                 omitting it defaults to OFF.  (suggested: OFF, unless you use ONCE, UNIQUE or RECORD  commands,
                 or activate the vacation mode.)
       biff      Whether  or  not biffing is wanted when mailagent delivers mail to a folder. Set it to ON (case
                 insensitively) to allow local biffing if you are logged in. (optional, defaults to: OFF)
       biffchars The charset to use when biffing on the terminal.  Set it  to  utf-8  if  you  are  using  UTF-8
                 terminals. (optional, defaults to: iso-8859-1).
       biffhead  When  biffing  is  enabled,  this  variable  lists which headers should be printed out. Headers
                 should be given in their normalized format and be separated with  commas.  (optional,  defaults
                 to: From, To, Subject, Date).
       bifflen   The  maximum  length  of  the  message  body  that  should be printed when biffing.  (optional,
                 defaults to 560).
       bifflines The maximum number of lines of the message body that should be printed when biffing.  Actually,
                 mailagent  attempts  to  print  that  amount  of lines, provided the total amount of characters
                 printed is less than bifflen.  (optional, defaults to 7).
       biffmh    When turned ON, the body of the message is compacted before  biffing  by  removing  consecutive
                 spaces  and  replacing  newlines  with  a  single  space.   The  message  itself is not altered
                 physically of course, only the output on the screen is concerned.  Since this may  yield  to  a
                 difficult-to-read  message,  I  suggest  you  also  turn  on  biffnice  when using this option.
                 (optional, defaults to: OFF).
       biffmsg   The path to a file describing the format biffing should use. If not set,  a  default  hardwired
                 format is used. Season to taste. (suggested: ~/.biffmsg).
       biffnice  Whether the message should be reformatted to nicely fit into the terminal.  (optional, defaults
                 to OFF, suggested: ON when biffmh is also ON).
       biffnl    Controls  whether  "blank" body lines should be printed or not. By "blank" lines, we mean lines
                 not containing words. Set it to ON to print such blank lines, to OFF if you wish to get a  more
                 compact  view of the body within the limits fixed by bifflen and bifflines. (optional, defaults
                 to ON).
       biffquote Controls whether the leading attribution line introducing a trimmed quotation should be part of
                 the biff message or not. When turned OFF, the attribution line is trimmed  along  and  this  is
                 reported in the trimming message, when bifftrim is ON. (optional, defaults to ON).
       bifftrim  Controls  whether trimmed lines within the biff message should be replaced by a message stating
                 how many of them were trimmed. Only used  by  the  %-T  biffing  macro.  When  turned  OFF,  it
                 automatically turns off biffquote as well. (optional, defaults to ON).
       bifftrlen States  how  many lines long a leading quotation should be before performing any trimming. Only
                 used by the %-T biffing macro. (optional, defaults to 2).
       callout   The name of the callout queue file where batched jobs are kept. This parameter must be  defined
                 when using the AFTER command.  (suggested: $spool/callout)
       cleanlaps Cleaning  period for database entries. The value of the last clean up is saved into the context
                 file. This is optional, but needed if autoclean is on.  (suggested: 1M)
       comfile   Name of the file containing authorized commands. Needed  when  PROCESS  is  used.   (suggested:
                 $spool/commands).
       compress  Name  of  the  file  containing  the  list  of  compressed  folders.  See  section about folder
                 compression. This is an optional parameter. (suggested: ~/.compress).
       compspecs Name of the file containing specifications for how to handle  different  types  of  compression
                 formats.   See  section  about  folder compression.  This is an optional parameter. (suggested:
                 $spool/compressors).
       comptag   The default compression tag when creating new  folders.   If  not  specified,  the  default  is
                 'gzip'.
       comserver Name  of  the  file  containing  authorized  SERVER  commands and their definition.  This is an
                 optional  parameter  if  you  don't  plan  to  use  the  generic  mail   server.    (suggested:
                 $spool/server).
       context   File holding the mailagent context. The context saves some variables which need to be kept over
                 the life of the process. Needed if auto cleaning is activated. (suggested: $spool/context)
       distlist  A  list  of  all  the  available  distributions. See the sample held in Lib/mailagent/distribs.
                 Needed by PROCESS only. (suggested: $spool/distribs)
       domain    Your domain name, without the leading dot, as in example.com.  The value  is  appended  to  the
                 value  of email when that variable does not have any '@', to construct a fully qualified e-mail
                 address.  See also the hidenet variable.  (optional, defaults to the domain name determined  at
                 build time).
       email     Your electronic mail address. If left unspecified, mailagent will try to guess it. This address
                 is used by mailagent when trying to send something to the user (you!). (suggested: specify your
                 e-mail address).
       emergdir  Name of the directory which should be used for dumps, preferably. This is optional. (suggested:
                 ~/tmp/lost+mail)
       execsafe  Whether  to  be  strict  before  using exec() to launch a new process or not. The value of this
                 variable is used in  place  of  secure  when  checking  executable  files.  (defaults  to  OFF,
                 suggested: ON if possible).
       execskip  Whether  to  skip  the exec() security checks alltogether. Don't turn this ON unless you really
                 trust all the users having access to your machine or file server. (optional,  default  to  OFF,
                 suggested: OFF).
       fromall   Whether  or  not  mailagent  should escape all the From lines in the message, not only those it
                 thinks should appear dangerous (i.e. a From after a blank line). This option only  makes  sense
                 when fromesc is also activated. It is ignored otherwise, and therefore is optional. By default,
                 it  is  assumed  to  be OFF. (suggested: OFF, until you have reasons to believe your mail user-
                 agent is confused in this mode: when it happens,  your  user  agent  will  split  mail  for  no
                 apparent reason).
       fromesc   Whether  or  not  mailagent should escape potentially dangerous From lines in mail messages. If
                 you use MH or if your mail reader does not use those lines to separate messages, then  you  may
                 set it to OFF. (suggested: ON)
       fromfake  Whether  or  not  mailagent should fake a From: line into the message header when it is absent.
                 Naturally, it requires a valid leading  From  line  to  operate!  (optional,  defaults  to  ON,
                 suggested: ON).
       groupsafe If  turned  OFF,  then  group-writable  files  will  be  managed as if they were secure, from a
                 security point of view. Leave it to ON if possible, or you may pass by  a  huge  security  hole
                 without your noticing (optional, defaults to ON, suggested: ON).
       hash      The  directory  used  for name hashing by the built-in database used by ONCE, UNIQUE and RECORD
                 commands. Optional, unless you make use of  those  commands  or  activate  auto  cleaning.  The
                 directory is placed in the spool area.  (suggested: $spool/dbr).
       helpdir   Directory where help files for SERVER commands are kept.  (suggested: $spool/help)
       hidenet   When  set  to ON, the value of the variable domain is the fully qualified name used.  When OFF,
                 the hostname is prepended to the domain.  If the hostname is already fully qualified, then  the
                 value  of  domain is ignored.  Assuuming domain is set to example.com and the hostname is host,
                 then the fully qualified name will be host.example.com if hidenet is OFF,  and  example.com  if
                 ON.  (optional, defaults to whatever was determined at build time)
       home      Defines where the home directory is. This must be accurate.
       level     Log level, see below for a definition of available levels (suggested: 9).
       linkdirs  When  set to ON, carefully checks symbolic links to directories when performing security checks
                 on sensitive files. This will (recursively) check for each symbolic link level that the  target
                 directory  is not world writable or group writable and that the parent directory of each target
                 link is not world writable. If the secure option is OFF, this parameter is ignored.  (optional,
                 defaults to: ON, suggested: ON when secure is also ON).
       lockdekay The delay in seconds between two locking attempts. (optional, defaults to: 2).
       lockhold  The maximum delay in seconds for holding a lock. After that time,  the  lock  will  be  broken.
                 (optional, defaults to: 3600).
       lockmax   Maximum number of locking attempts before giving up. (optional, defaults to: 20).
       locksafe  When  locking a file, mailagent normally makes lockmax attempts separated by lockdelay seconds,
                 and then gives up. When facing a delivery to a mailbox, it may make sense to continue  even  if
                 no  lock  was  grabbed,  or  even  if only a partial locking was done (e.g. one of the .lock or
                 flock()-style locking succeeded). This variable controls how safe you want to be. Set it to OFF
                 to let mailagent continue its mailbox delivery even though no locking was done, to  ON  if  you
                 want  strict  locking, to PARTIAL if you can live with partial locking. Messages not saved in a
                 folder are dumped to an emergency mailbox. (optional, defaults to ON). On Debian systems, since
                 mailagent can not grab locks,it should always be left ON, or else mail garbling may occur.  See
                 /usr/share/doc/mailagent/SECURITY for details.
       lockwarn  This  variable controls the time after which mailagent should start emiting a warning when busy
                 trying to acquire a lock.  It is a comma separated list of values, in seconds.  If  two  values
                 are  given,  the  first  is  the  initial  time threshold, the second is the repeat period. For
                 instance, a value of "15,60" would cause a warning after 15  seconds,  then  every  60  seconds
                 until the lock is taken or the locking attempt time is expired (see lockmax and lockdelay).  If
                 only  one  value  is  given,  it  is  taken as being both the initial threshold and the period.
                 (optional, defaults to: 20,300).
       log       Name of the log file which will be put in Log directory. (suggested: agentlog).
       logdir    Logging directory. (suggested: ~/var/log).
       mailbox   The name of the system mailbox file, which by default is the value of  the  user  configuration
                 variable. This is an optional parameter.
       maildrop  Location  of  the system mail spool directory. If none is provided, then the mailagent will use
                 the value determined by Configure.
       mailopt   Options to be passed to the mailer (see sendmail). (optional, suggested: -odq  -i,  when  using
                 sendmail).
       maxcmds   Maximum  number of commands that are allowed to be executed by a SERVER command before flushing
                 the remaining of the mail message. (suggested: 10).
       maxerrors Maximum number of errors for the SERVER command before  flushing  the  remaining  of  the  mail
                 message. (suggested: 10).
       maxsize   Maximum  size  in  bytes  of files before using kit for sending files. This is used by PROCESS.
                 (suggested: 150000).
       mboxlock  The format to be used for locking mailboxes before delivering to them. This string goes through
                 a small macro substitution mechanism to make it more general. The file name derived after macro
                 substitution is the name of the lock that will be used, given the name of the file that  is  to
                 be locked.  Available macros are:

                      %D: the file directory name
                      %f: the file name to be locked (full path)
                      %F: the file base name (last path component)
                      %p: the current process pid number
                      %%: a plain % character

                 Common  locking  formats  are  "%f.lock"  and  "%D/.%F.lock". Of course, to be able to use this
                 feature, mailagent must not have been configured to use flock()-style locking only.  (optional,
                 defaults to: %f.lock). This has no effect on Debian systems, since mailagent can not get a lock
                 anyway, since it is not sgid mail.
       mhprofile The  name  of  the  MH profile to be used. This is needed only when attempting to save in an MH
                 folder. If this optional parameter is not set, the default value ~/.mh_profile is used.
       mmdf      Set this to ON if you wish to be able to save mail in MMDF-style mailboxes.   (suggested:  OFF,
                 unless you use MMDF or MH). This is invalid on a Debian system.
       mmdfbox   The value of this variable only matters when mmdf is on. If set to ON, then new folders will be
                 created  as  MMDF  ones.  This variable is not used when saving to an existing folder, since in
                 that case the mailagent will automatically determine the type and save the message accordingly.
                 (suggested: OFF, unless you use MMDF or wish to use MH's mshf).
       msgprefix Name of the file to put in directory  folders,  specifying  the  message  prefix  to  be  used.
                 Optional, defaults to .msg_prefix.
       name      First  name of the user, used by mailagent when referring to you. This sets the value of the %U
                 macro.
       newcmd    Name of the file describing new filtering commands. See section  Extending  Filtering  Commands
                 for  more  details.  Leave  this  optional  parameter  out  unless  you are a mailagent expert.
                 (suggested: $spool/newcmd).
       newsopt   Options to be passed to the news posting program (see sendnews).  (optional,  suggested:  leave
                 empty when using inews).
       nfslock   Set  it  to  ON  to  ensure  NFS-secure  locks.  The difference is that the hostname is used in
                 conjunction with the PID to obtain a lock. However, mailagent has to fork/exec to  obtain  that
                 information.  This  is an optional parameter which is set to OFF by default. (suggested: OFF if
                 you deliver mail from only one machine, even though it's via NFS).
       passwd    File where SERVER power passwords are kept -- encrypted usually.  (suggested: $powers/passwd).
       path      Minimum path to be used by C filter program. To set a specific path for a machine host, set  up
                 a  p_host  variable.  This  will  be  prepended  to the default PATH variable supplied by other
                 programs. (suggested: /bin:/usr/bin:/usr/ucb). Note  that  the  host  name  must  be  specified
                 without  any domain name appended to it (e.g. for an host name of lyon.eiffel.com, use variable
                 p_lyon). If your host name contains an '-' in it, you must write it as a '_', since '-' is  not
                 a valid character for a perl variable name.
       perlib    This  variable  may  be  used  to  change the perl search path for required files.  Directories
                 should be separated using a ':' character, just like a shell PATH.  This path is  prepended  to
                 the  default perl search path. Any directory not starting with a '/' (after ~name substitution)
                 is taken relatively to the mailagent private lib directory determined at configuration time.
       plsave    Name of the file used to save the patchlevels for archived distributions.  This is only used by
                 the commands invoked via PROCESS. (suggested: $spool/plsave).
       powerdir  Directory listing user clearances for SERVER powers.  (suggested: $powers/clearance)
       powerlist Name of file containing SERVER power aliases. Since power names can be arbitrary long but  some
                 filesystems  still  have  a  14  character  limitation on filename length, internal aliases are
                 created and maintained by mailagent.  (suggested: $powers/aliases).
       powerlog  File where SERVER power requests are logged, in addition to the agentlog.  Since  those  are  a
                 security  concern,  it is a good idea to log them separately.  If not defined, log them only in
                 agentlog. (suggested: $logdir/powerlog).
       powers    Directory for SERVER power administration. (suggested: $spool/powers)
       proglist  A  small  description   for   the   available   distributions.   See   the   sample   held   in
                 Lib/mailagent/proglist. This is used by PROCESS only.  (suggested: $spool/proglist)
       queue     Queue  directory  (messages  waiting  to  be  processed).  Required,  of  course.   (suggested:
                 $spool/queue)
       queuehold Maximum number of seconds a  mail  can  sit  in  the  mailagent  queue  before  being  actually
                 processed.  During  that  time,  mailagent  will not try to process the message even when -q is
                 used. (optional, defaults to: 1800).
       queuelost Maximum number of seconds after which mailagent should flag messages  still  in  its  queue  as
                 being old. (optional, defaults to: 86400, i.e. a day).
       queuewait Time  in seconds telling the C filter program how long it must wait before launching mailagent.
                 (optional, defaults to: 60, but can be lowered to 0 if you don't want to wait to delay  getting
                 new messages).
       rulecache The  name  of  the  file used to cache the latest compiled rules. Since usually mailagent works
                 mainly with one same rule file, this saves the overhead of recompiling all the rules each time.
                 (optional, suggested: $spool/rulecache).
       rulemac   Set this to ON to enable macro substitutions in rule patterns.  (optional, defaults to: OFF).
       rules     The name of the file holding the filtering rules (optional on non  Debian  systems,  suggested:
                 ~/.rules).  On  Debian  systems,  one  must have a minimal rules file to prevent mailagent from
                 trying to put messages into /var/spool/mail/$USER, since mailagent can't lock that directory to
                 prevent mail from being garbled. This is because Debian policy requires all entities attempting
                 locks on that directory to be sgid mail, and making mailagent sgid anything would be a security
                 loophole.
                     { SAVE incoming };
                  is the suggested minimal rules file.
       runmax    Timeout for RUN commands and friends. (optional, defaults to: 3600).
       scriptcc  Flag indicating whether a copy of the SERVER session transcript should  be  send  to  the  user
                 running mailagent. (suggested: OFF).
       secure    When  set to ON, mailagent and the C filter will perform extensive security checks on sensitive
                 files. This includes checks for group writability, ownerships and  protection  testing  on  the
                 directory  where the file resides, and checks on symbolic links to directories (mailagent only,
                 when linkdirs is ON too). Note that secure is assumed to be ON, whatever its real setting, when
                 running as super-user. (suggested: ON).
       sendmail  The name of the program used to send mail. That program  must  accept  the  mail  message  with
                 headers  on  its standard input and a list of recipients on the command line. If not specified,
                 will use the mailer chosen at configuration time (sendmail usually). The command line  used  to
                 mail a message will be sendmail mailopt address(es).  (optional, suggested: /usr/lib/sendmail).
       sendnews  The  name  of  the  program  used  to post news. That program must accept the news article with
                 headers on its standard input. If not specified, will use the news posting  program  chosen  at
                 configuration  time (inews usually).  The command line used to post an article will be sendnews
                 -h newsopt.  (optional, suggested: /usr/local/bin/inews).
       seq       File used to compute job numbers (suggested: .seq).
       servdir   The directory name where shell and perl server commands are stored. This is the default  lookup
                 place. Optional parameter unless SERVER is used.  (suggested: $spool/cmds).
       servshell This  is  the  name  of the shell used to launch SERVER shell commands (actually to process the
                 wrapper file that will ultimately exec() the command). On some systems like HPUX 10.x, this has
                 to be set to /usr/old/bin/sh to get the plain old Bourne shell, because /bin/sh is a  braindead
                 POSIX  shell  that closes file descriptors greater than 2 upon exec(), whereas the Bourne shell
                 does not. (optional, suggested: /bin/sh unless you're on HPUX 10.x, as explained before).
       spool     Spool directory, required (suggested: ~/var/mailagent).
       statfile  File where statistics should be gathered. If  no  such  file  exists,  no  statistics  will  be
                 recorded (suggested: $spool/mailagent.st).
       tofake    Whether  or  not  mailagent  should  fake a To: line into the message header when it is absent,
                 which will be used for filtering purposes (no physical alteration of the header occur). It uses
                 Alternate-To: headers if found, otherwise it assumes the message was send to the user and takes
                 the value from the user configuration variable.  (optional, defaults to ON, suggested: ON; turn
                 it OFF only if you want to identify missing To: lines to detect SPAM).
       tome      This optional variable may contain a comma separated list of alternate  logins  that  are  also
                 valid  for the user (mail aliases). This is used in vacation mode to check whether the mail was
                 sent to the user or to a mailing list.  Matching is anchored on the login name, so saying "ro*"
                 will match both root and rom.
       track     Set to on (case insensitively), this turns on the -t option which tracks all the  rule  matches
                 and the actions on standard output. This is optional (suggested: OFF).
       timezone  The time zone value for environment variable TZ (optional).
       tmpdir    Directory for temporary files. Required (suggested: /tmp).
       umask     Default  umask  which is reset by mailagent before processing a message.  Assumed to be decimal
                 unless starting with '0' (for octal) or '0x' (for hexadecimal). The octal format is the easiest
                 way to specify it nonetheless.  (optional, defaults to: 077).
       user      Login name of the user who runs mailagent. This sets the value of the %u macro.
       vacation  A flag set to ON or OFF to switch the vacation mode accordingly.
       vacfile   The name of the file to be sent back in vacation mode (suggested: ~/.vacation).
       vacfixed  When ON, all changes to the vacation file (even locally) by means of the VACATION  command  are
                 forbidden.  This  is useful if you usually have many customized vacation messages for different
                 people but temporarily want to force one unique message (optional, defaults to: OFF).
       vacperiod The minimum time elapsed between two vacation messages to a given address (suggested: 1d).

   Available Logging Levels
       The following log levels can be used while running mailagent:

            0    No logging
            1    Major problems only
            2    Failed deliveries
            3    Successful deliveries
            4    Deferred messages
            5    Successful filter actions
            6    Unusual but benign incidents
            7    Informative messages
            8    Non-delivery filter actions
            9    Mail reception
            12   Debug
            19   Verbose
            20   Lot more verbose

   Plugging Mailagent
       Once you have configured mailagent in a ~/.mailagent (where ~ stands for your home directory),  you  must
       tell sendmail how to invoke it.  This is done by setting a ~/.forward file which looks like this (leading
       and trailing double quotes are a mandatory part of it):

            "| exec /users/ram/mail/filter >>/users/ram/.bak 2>&1"

       This will pipe all your mails to the filter program, redirecting all unusual messages to ~/.bak. A sample
       filter shell script may be found in Lib/mailagent, as well as a C filter program. On some systems, it may
       be  necessary  to  move the '|' character before the leading quote, but don't try this unless you have no
       other choice (i.e. only as a last resort).  Also, apparently Exim takes exeption to the  exec,  and  even
       perhaps to the redirection -- which would be a pity.

       It  is  very important to redirect error messages to some file within your home directory. For one thing,
       that will get you out of trouble if strange things start to happen, but more to the point, it makes  your
       .forward  file unique. Older sendmail program, in an heroic attempt to "optimize" delivery, will silently
       remove duplicate recipients, and if a recipient has a .forward, its literal content is used in  place  of
       his  e-mail address. Therefore, two local recipients with the same filtering string will be considered as
       one unique recipient and only one of them will get the message...

       If your system does not allow shell redirection from within the .forward, you can use this instead  (only
       supported by the C filter):

            "| exec /users/ram/mail/filter -o /users/ram/.bak"

       which  in  effect redirects stdout and stderr to the specified file for you, appending data at the end of
       the file.  If the filter runs setuid or setgid, you will not be allowed to create the file, nor to append
       to it unless the owner of the file is the real uid invoking the program (for security reasons).

       Note that the .forward file only pipes the mail to the filter program and does not leave any copy in  the
       mailbox.  It  is up to you to decide in the rule file whether you want to trash the mail away or leave it
       in the mailbox.(Note that on Debian systems mailagent can not lock the spool directory,  and  letting  it
       leave mail in mailbox may cause it to get garbled). If you do not have a rule file (i.e. you left a blank
       entry in your ~/.mailagent, or you named a non-existent file, or your file is simply empty),  the default
       action  is to leave the mail in the mailbox, which is not a good idea for Debian machines. Please onstall
       a minimal rules file in any case,
        { SAVE incoming };
        is the suggested minimal rules file.

   Allowed Commands
       The allowed command file (as specified by the comfile variable in your  ~/.mailagent)  contains  all  the
       recognized  and allowed commands.  The file commands held in directory Lib/mailagent should be copied as-
       is into your Spool directory.

   Testing Your Installation
       Now, assuming you have set a proper ~/.mailagent file and edited the configuration section of the filter,
       it is time to test your installation. Make sure your .forward is world readable and that the  filter  has
       the execution bits set (there is no reason to make the filter world readable).  Set a log-level of 20 and
       disable  vacation  mode  (the vacation entry in the ~/.mailagent should be OFF). Set the name of the rule
       file to an file containing a catch-all rule:
            { SAVE incoming };
        You are ready to proceed...

       Send yourself a mail and give mailagent time to process your mail. The subject of the message  should  be
       'test'  (in  fact,  anything  but  'Command').   You  may  want  to run a "tail -f logfile" to see what's
       happening. At the end of the processing, the logfile should contain something like the  following  (names
       of temporaries may -and will- of course differ; timestamps have been removed):

            got the right to process mail
            building default rules
            parsing mail
            analyzing mail
            in mode 'INITIAL' for ALL
            selector 'All' on '<1,->', pattern '/^Subject: [Cc]ommand/'
            matching '/^Subject: [Cc]ommand/' on 'All' (<1,->) was false
            selector 'All'  on '<1,->'
            matching . on 'All' (<1,->) was true
            saving in folder incoming
            XEQ (LEAVE)
            starting LEAVE
            starting SAVE /home/ram/mail/incoming
            SAVED [qm7831] in folder incoming
            FILTERED [qm7831] from ram (Raphael Manfredi)
            mailagent continues
            mailagent exits

       If  you  do  not get that, there is a problem somewhere. Start by looking at the ~/.bak file (or whatever
       file the .forward uses to redirect output of the filter). If you see something like:

            FATAL no valid queue directory
            DUMPED in ~/mbox.filter

       then it means the queue parameter in your ~/.mailagent does not point to a valid directory. Your mail has
       been dumped in an emergency mailbox.

       The ~/.bak file may also contain error messages stating that perl was not  found.  In  that  case,  there
       should be an error message in the logfile:

            ERROR mailagent failed, [qm7886] left in queue

       In  that case, make sure the mail has correctly been queued in a file qm7886. The queue will be processed
       again when another mail arrives or when the  mailagent  is  invoked  with  -q  (however,  to  avoid  race
       conditions, only mails which have remained for a while will be processed).

       Queuing of mail also happens when another mailagent is running. If the logfile says:

            denied right to process mail

       then  remove the perl.lock file in the Spool directory. Old lock files are automatically discarded by the
       mailagent anyway (after one hour).

       If none of these occurs, then maybe sendmail did not process your ~/.forward at all or  the  file  has  a
       syntax  error.   Check  your mailbox, and if your mail is in there, your .forward has not been processed.
       Otherwise, ask your system administrator to check sendmail's logfile. A correct  entry  would  appear  as
       (with leading timestamps and syslog stamps removed):

            message-id=<9202041919.AA07882@york.eiffel.com>
            from=ram, size=395, class=0, received from local
            to="| /york/ram/mail/filter >>/york/ram/.bak 2>&1", delay=00:00:05, stat=Sent

       If  you  still  cannot  find  why the mail was not correctly processed, you should make sure you normally
       receive mail by removing (or renaming) your ~/.forward and sending yourself another test mail. Also  make
       sure your home directory is world readable and "executable".

       If  you  are using the C filter, make sure it is running on the right platform.  There may be a low-level
       routing of all your mail to a mailhost machine, responsible  for  the  final  delivery,  and  the  filter
       program  will run on that machine, which may be a different platform than the one you compiled filter on.
       Also make sure your home directory is mounted on that machine, or the mail transport agent will be unable
       to locate your .forward file, less process it.

       This kind of centralized mail delivery is good only when a few people have mail  processing  hooks  (i.e.
       .forward  files piping mail to a program); otherwise it's better to route mail to each user's workstation
       or machine, for local processing, to avoid an excessive workload on the mailhost machine,  especially  if
       it  is  a  dedicated  NFS  server. If you are a system administrator installing mailagent and expect many
       people to use it, keep this in mind.

OPTIONS

       There is a limited set of options which may be used when calling the mailagent directly. Only one special
       option at a time may be specified.  Invoking mailagent as mailqueue is equivalent to using the -l option.

       -c file        Specify  an  alternate  configuration  file  (~  substitution  occurs).  The  default   is
                      ~/.mailagent.

       -d             The  mailagent  parses  the  rule  file, compiles the rules and dumps them on the standard
                      output. This option is mainly used to check the syntax of the rule file and make sure  the
                      rules are what the user really thinks they are.

       -e rule        This  option  lets  you  specify some rules on the command line, which will override those
                      specified via the ~/.mailagent, if any. There may be as many  -e  as  necessary,  all  the
                      rules  being concatenated together as one happy array, which is then parsed the same way a
                      rule file is. If only one rule is given and there is no  action  specified  between  {...}
                      braces, then the whole line is enclosed between braces. Hence saying -e 'SAVE foo' will be
                      understood  as  -e  '{SAVE  foo}',  which  will always match and be executed. Using the -d
                      option in conjunction with this one is a convenient way to debug a set of rules.

       -f mailfile    Using mailfile as a UNIX-style mailbox (i.e. one where each mail is preceded by a  special
                      From  line  stating  the  sender  and  the  date  the message was issued), extract all its
                      messages into the queue and process them as if they were freshly  arrived  from  the  mail
                      delivery subsystem.

       -F             Force  processing  on  already seen messages. Usually, mailagent enters the special _SEEN_
                      state when it detects an X-Filter: line issued by itself, but this  option  will  have  it
                      continue  as  usual  (although vacation messages are disabled). Use this option when post-
                      processing mail already filtered. Also look at the -U switch if you are using  the  RECORD
                      or UNIQUE actions in some rules.

       -h             Print out a usage message on the standard error and exit.

       -i             Interactive mode, directs mailagent to print a copy of all the log messages on stderr.

       -I             Install  a  ~/.mailagent  file from template, or merge new configuration variables into an
                      existing file; then perform sanity checks and create mandatory files or directories.  This
                      option  may be viewed as an help into setting up mailagent's environment. In any case, the
                      created/merged ~/.mailagent file should be manually verified before letting mailagent deal
                      with your mail by hooking it into ~/.forward.

       -l             List the mailagent queue. Recently queued mails which are waited for  by  the  filter  are
                      skipped  for about half an hour, to avoid race conditions.  This may be configured via the
                      queuehold variable. Really old messages (more than queuelost seconds old) are flagged with
                      a '#' character.  Messages out of the queue (queue  variable)  are  flagged  with  a  '*',
                      whilst  old  messages  out of the queue are signaled by an '@'. Locked messages have a '*'
                      appended to their status.

       -L level       Override the log level specified in the configuration file.

       -o override    This option lets you override a specific configuration option. The option must be followed
                      by a valid configuration line, which will be parsed after the configuration  file  itself.
                      For  instance,  the  -L  4 option is completely equivalent to -o 'level: 4'. Note that any
                      white space must be protected  against  shell  interpretation  by  using  the  appropriate
                      quoting mechanism. There may be as many -o options on the command line as necessary.

       -q             Force  processing  of  mailagent's  queue.  Only the mails not tagged as skipped by the -l
                      option will be processed.

       -r file        Specify an alternate rule file.

       -s {umaryt}    Build a summary of all the statistics gathered so far. The output  can  be  controlled  by
                      appending one or more letters from the set {umaryt}. Using -summary is a convenient way to
                      get  the  whole  history of the filter actions. The u modifier will print only used rules.
                      The m will merge all the statistics at the end while a reports the mode the filter was  in
                      when  the  command  was executed. The r asks for rule-based statistics and the y is pretty
                      useless and is here only to get a nice mnemonic option. Note  that  specifying  an  option
                      more  than  once  has no effect whatsoever on the option itself (i.e. you may put three Uu
                      and only one m, but you'll still get the summary!). The t letter may be followed by digits
                      specifying how many rule file versions relative to the topmost (most recent) rule file  we
                      should extract from the statistics, that amount defaulting to 1: using -surat will print a
                      complete statistics report for the last version of your rules, while -surt12a would do the
                      same for the last twelve versions of those same rules.

       -t             Put  mailagent  in a special tracking mode where all the rule matches and executed actions
                      are printed on the standard output. This is mostly useful for debugging a rule  file.  See
                      also the track parameter in the configuration file.

       -V             Print version number and exit.

       -U             Prevent  the UNIQUE and RECORD commands from rejecting an already processed Message-ID the
                      first time they are run on a given message.  This is useful when processing messages  that
                      have been dropped in the emergdir directory due to some abnormal (but transient) condition
                      and  you  wish  to  reprocess the message. Also see the -F switch if you are re-processing
                      messages.

       If you invoke mailagent without options and without any arguments, the program waits for a  mail  on  its
       standard  input.  If  an argument is provided, it is the name of a file holding one mail to be processed.
       This is the normal calling procedure from the filter, the argument being the location of the queued mail.

USING THE DEFAULT RULES

       If you do not want to use the filtering feature of mailagent, (NOTE: This may cause mail to be garbled on
       Debian systems, since mailagent can not lock the spol directory under Debian  policy  restrictions)  then
       the default built-in rules will be used.  Those are really simple: all the mails are left in your mailbox
       and  mails  with a line "Subject: Command" anywhere in the message will be processed. Commands are looked
       for on lines starting with "@SH". The remaining of the line is then given to a shell for execution.

       Available commands are read from a file (entry comfile in your configuration file), one command name  per
       line. Only those listed there will be executed, others will produce an error message. The mailagent traps
       the  exit  status  and  will  send an error report if a command fails (provided that the command does not
       issue a message by itself, in which case it should return a zero exit status).

       If you do not want to use the default rules, you may skip the remaining of this section.

   Configuring Help
       The help text mailagent will send to people must be copied from  Lib/mailagent/agenthelp  into  your  own
       spool directory, as specified in your ~/.mailagent. Two macros may be used:

       =DEST=    This  will  be  expanded  to  the  sender's  address  (the  one who sent you the mail currently
                 processed by mailagent).

       =MAXSIZE= This stands for the maximum size set before kit is used to send files back  (parameter  maxsize
                 in your ~/.mailagent file).

       You may use the default help file or design one that will give even more details to the poor user.

   Distribution Files
       The  two files proglist and distribs held in Lib/mailagent describe the distributions your mailagent will
       be able to distribute.  The samples given show the expected syntax. In order to clarify things,  here  is
       what the format should be:

       File  proglist  contains a small description for programs. The name of the program appears after a single
       star. It is followed by lines in free format. An optional  three-dashes  line  separates  each  program's
       description. Note that a leading tab will be added to each line of description.

       The distribs file holds lines of the following form:

            progname version path archived compressed patches

       where:

       progname  is the program name (the same as the one mentioned in proglist).

       version   is the current version number. If none, a three-dashed line may be used.

       path      is  the path where the distribution is stored. The ~ will be expanded into your home directory.
                 Note that if the distribution is stored in archived form, the path  name  is  the  one  of  the
                 archive without the ending extension (which may be .cpio.Z or .tar.Z).

       archived  is either y or n depending on whether the distribution is archived or not.

       compressed
                 is  either  y  or  n  depending on whether the distribution is compressed or not. This could be
                 guessed from the extension's name, but we must think of file systems with short names.

       patches   is y or n depending on whether the distribution is maintained or not by you. If you  put  a  p,
                 this  means  official  patches  are  available,  although you do not maintain the distribution.
                 Finally, an o means that this is an old version, where only patches are available, but maildist
                 will not work. In that case, assuming the version number is 1.0, old patches are expected in  a
                 bugs-1.0 directory.

       You may include comments in both files: all lines starting with a leading # will be ignored.

   Testing Your Mail Agent
       It is now time to make sure your mailagent works. Send yourself the following mail:

            Subject: Command
            @SH mailhelp

       You  should  receive back a mail from yourself with the subject set to: "How to use my mailagent". If you
       don't, check the file ~/.bak (or whatever file you set in your .forward). If it is empty, look at the log
       file. If the log file is not empty, then perhaps the mail has been queued. Check the sendmail queue. Also
       make sure that you removed the '#' comments in the filter  script.  On  some  systems,  they  cause  some
       trouble.  If  you  are  using  the  C filter, maybe your sendmail is broken and you need to make your own
       setuid copy (or perl might complain that you have a kernel bug, etc...).

       If you have done everything right but it still does not work properly,  increase  log  level  to  20  and
       resend your command mail. Then check the log file. The diagnosis should be easier.

       Once  this  works,  you  should  check your distribs and proglist files by sending yourself the following
       mail:

            Subject: Command
            @SH maillist

       If the list you have in return is incorrect, then your distribution files are wrongly written. If you  do
       not  get  the list, there is a problem with your mailagent's configuration. Retry with a log level set to
       20 and look at the issued log messages in your Log directory. Make sure  that  the  file  listed  in  the
       plsave entry of your ~/.mailagent is correctly updated after a maillist has been run.

USING THE FILTER

       The  mailagent  can  also  be used as a filter: mail is parsed and some actions are taken based on simple
       lex-like rules. Actions range from a simple saving in a folder, a forwarding to another person,  or  even
       spawning of a shell command. Before going further, here is a small example of a valid rule file:

            From: root { FORWARD postmaster };
            To: gue@eiffel.fr { POST mail.gue };
            Subject: /metaconfig/ { SAVE dist };
            { SAVE incoming };

       There  are  three  distinct  rules.  Rules  are  applied  in sequence, until one matches (so the order is
       important). Any mail coming from root  will  be  forwarded  to  user  postmaster.  A  mail  addressed  to
       gue@eiffel.fr  is  a  mail  coming from a mailing list. The mail is posted on a local newsgroup mail.gue.
       Mails whose subject contains the word "metaconfig" will be saved in a folder dist for delayed reading and
       will not appear in the main mailbox. If no rule matched, the mail is left in the folder incoming.

   Rule File Syntax
       Here is a non-formal description of the rule file. Parsing of the  file  is  done  lexically,  hence  the
       choice  of non-ambiguous tokens like '{' or ';' which are easily parsed. This introduces some limitations
       which are silently applied: for instance, no '{' may be used as part of an address.

       Comments are introduced by a leading '#' , which must be on the left margin.  Unlike  shell  comments,  a
       '#'  which  is  not left justified will not be understood as a comment, unless there is a space following
       '#'.  Spaces or tabs are allowed in front of '#'.

       All the statements in the rule file must end with a ';'. There are mainly four parts in each line. A list
       of comma separated modes, between '<' and '>', which give the set of modes in which the rule applies. The
       special mode ALL will match everything. The filter begins in the mode INITIAL. Omitting the mode defaults
       to "<ALL>". It is possible to guard a rule against some specific mode by negating it, which  is  done  by
       prefixing  the  mode  with  '!'.   Negated modes take precedence other plain modes, meaning "<!ALL>" will
       never be matched, ever, and that "<MODE, !MODE>" is equivalent to "<!MODE>".

       Then comes a list of selectors. Those selectors must be space separated and end with ':'. They  represent
       the  names  of  header  fields which must be looked at by the forthcoming pattern. An empty selector list
       defaults to "Subject:".  Special selectors "All:", "Body:" and "Head:" apply to the  whole  message,  its
       body  or  its  header.  A commonly used selector list is "To Cc:" which tests the recipient fields of the
       header. If the selector name is preceded by an exclamation mark '!', then the logical value of  the  test
       for that selector is negated.

       The list of selectors may end with an optional range specification, given as <min, max>, before the final
       ':'  character  marking  the end of the selector list. The minimum or the maximum may be given as '-', in
       which case it is replaced with the minimal or maximal possible value. Indices for selection  begin  at  1
       (not  0),  for  instance: <3, 7>. If no range selection is given, then the default <1, -> is used. Ranges
       normally select lines within the matching buffer, unless the selector is expecting a list in  which  case
       it operates on the list items. For instance, Body <3, 5>: would select lines #3 to #5 (included) from the
       mail body, whereas To Cc <1,3>: would focus on the first three addresses on each To: or Cc: header lines.
       Negative  values  refer  to  that many lines or addresses back from the end, i.e.  Cc <-2,->: selects the
       last two addresses on the Cc: line.  A single number such as <2> is understood as <2, 2>, i.e. it  select
       only one item in the list, <-> meaning everything (and being therefore redundant).

       The  selector is then followed by a pattern within '/' or by a single name.  In order to ease the writing
       of the rules, the semantic of a single name varies depending  on  the  selector  used.  For  the  special
       selectors  "From:",  "To:", "Cc:", "Sender:", their associated "Resent-" fields, "Reply-To:", "Envelope:"
       and "Apparently-To:", a single name is understood as a match on the login name of the address. Note  that
       if  no "To:" field is present in the header, one will be forged from the "Apparently-To:" for the purpose
       of filtering only (i.e. no physical modification on the header is done). If the login name of the address
       is a full name of the form First.Last, only the last name is kept, and is lower-cased. If only  a  single
       name is given, only shell metacharacters * and ? are allowed, as well as intervals [].

       If the pattern is preceded by a single exclamation mark '!', then the matching status is negated (i.e. it
       will  succeed if the pattern is not found).  If a single word is used for non-special selectors, the same
       rules apply but the pattern is anchored at the beginning and the end for an exact match. With  a  pattern
       starting  with  '/',  any  regular expression understood by perl may be used and your pattern will not be
       modified in any way. The other special selector "Newsgroups:" works as "To:",  excepted  that  newsgroups
       names  are  expected  and a match is attempted on every item in the list. Every pattern match on a single
       name for an address-type  field  (i.e.  "Newsgroups:"  excluded),  are  made  in  case-insensitive  mode.
       Otherwise, you can force a case-insensitive match by appending a trailing i option, as in /pattern/i.

       There  is also a little magic involved when matching on an address field. Namely, if the pattern is not a
       single word and is anchored at the beginning, then only the address part of the field will be  kept.  For
       instance,  if  we  have  a From: field whose value is Raphael Manfredi <ram@eiffel.com>, then the pattern
       /Raphael/ would match, but not /^Raphael/. Instead, /^ram@.*$/ would match, but this is more easily  done
       with a single word pattern ram, for it only focuses on the login name of the address and would also match
       if the address was written as eiffel.com!ram.  A single address in Internet form, as in ram@eiffel.com is
       implicitely  matching on the address part of the field, and you must not escape the '.' as you would have
       to in a regular expression.

       This may sound a little complex, but this design is meant to make things easier for the  user.  Here  are
       some other examples:

            # Match ram@eiffel.com as well as ram@educ.emse.fr.
            From: ram

            # Match root@eiffel.com, ram but not ribbon@eiffel.com
            From: r[oa]*

            # Match gue@eiffel.fr but not algue@eiffel.fr
            To Cc: /^gue@eiffel\.fr/

            # This will match gue@eiffel.fr as well as algue@eiffel.com
            To Cc: /gue@eiffel/

            # Match comp.lang.perl but not comp.lang.perl.poetry (?)
            Newsgroups: comp.lang.perl

            # Accept anything but messages coming from root
            From: !root

       When  attempting a match on "To:", "Cc:" or "Apparently-To:", a list of addresses separated by a comma is
       expected, whereas only one address is expected after "From:".  If  you  omit  the  pattern,  it  will  be
       understood as * (recall that a single word uses shell meta-characters), which will match anything.

       Then  comes  the  action  to  be taken when a match occurs. There are only a limited set of valid actions
       which will be described soon in detail. The action is enclosed in curly braces '{' and  '}'  and  actions
       are  separated  or  terminated (depending on your taste) by a ';'. Action names are spelled in upper-case
       for readability, but case is irrelevant. If you want to put a ';' within the rule, it must be escaped  by
       preceding  it with a backslash.  A double backslash is translated into a single one, and any other escape
       sequence involving the backslash character is ignored (i.e. \n would be kept verbatim).

       Note that a rule should be ended by a single ';' after the last '}'. It is possible to  omit  this  final
       ';', but that single token is the re-synchronizing point for error recovery. One could argue however that
       there  should  be  no syntax error, and thus the ';' ought to be safely omitted. Whenever in doubt, check
       your rule file with the -d option.

       Here is a prototypical rule (using perl regular expressions;  please  refer  to  the  subsection  Regular
       Expressions for more information):

            <ROOT> From: /^\w+@eiffel.com$/ { SAVE eiffel };

       That rule will only be taken into account when the filter is in the mode ROOT (recall that the processing
       starts  in  mode INITIAL; use BEGIN to change the mode, as in lex). So in mode ROOT, anything which comes
       from a user located in the eiffel.com site is saved in folder eiffel for deferred reading. The mail  will
       not appear in the mailbox.

       It  is possible to have more than one selection for a rule. Identical selectors are logically or'ed while
       different ones are and'ed. The selections are comma separated. For instance,

            From: root, To: ram, From: ram, Subject: /\btest\b/ { DELETE };

       will delete a mail from root or ram if it is sent to ram and has the word test in its subject. It is also
       possible to write the previous rule as:

            From: root, ram, To: ram, Subject: /\btest\b/ { DELETE };

       because if no selector is given, the previous one is used (with the first selector  being  "Subject:"  by
       default).

       Anywhere  in  the rule file, it is possible to define some variables. The list of recognized variables is
       given later. For now, let's say that maildir is the default folder directory. This variable  is  used  by
       the SAVE command when the argument is not an absolute path. Setting

            maildir = ~/mail;

       will direct the filter to use ~/mail as the folder directory (default is ~/Mail). Note the ~ substitution
       and the final ';'. It is not possible (currently) to modify the environment by setting PATH for instance.

       Finally,  there  is a special construct to load patterns from a file. A pattern enclosed in double quotes
       means that the patterns to be applied should be taken from the specified file. The file is expected to be
       in the directory mailfilter if it is not an absolute path (~ substitution occurs). If the variable is not
       set maildir will be used. If by chance (!)  maildir is not set either, the home directory  is  used.  The
       file should contain one pattern per line, shell comments (#) being allowed at the beginning of each line.

       An action may be followed by other rules. Hence the following is perfectly valid:

            From:
                 ram       { SAVE ram }
                 /plc/i         { SAVE plc }
                 root      { SAVE ~/admin }
                 /xyz/          { DELETE }
                 "users"        { LEAVE }
                 ;

       Note  the  use of the file inclusion: all the users listed in file users will have their mail left in the
       system mailbox. The usual rules apply for these loaded patterns.

   Selector Combination
       A single rule may have a various set of selectors. For instance, in the following rule:

            From: ram, To Cc: root, !Subject: /test/, From: raphael

       we have the following set { From, To Cc, !Subject }. The first two selectors are called direct selectors,
       !Subject: is called a negated selector.  The To Cc: selector is a group  selector  decomposing  into  two
       direct  selectors,  while  From:  is  an atomic selector. Finally, From: is also a selector with multiple
       occurrences. The value of a selector is its matching status logical value.

       Let D be the set of direct selectors and N the set of negated selectors, which form a partition of R, the
       set of all the selectors in the rule. That is to say, R is the union of D and N, and D intersected with N
       is the empty set (trivial proof: a selector is either direct or negated). If either D or N is empty, then
       it's not a partition but in that case we have either D = R or else N = R.

       Let's define the logical value of a set S as being the logical value the filter  would  return  if  those
       rules  were  actually written.  Then the logical value of D is the logical value of each of its item with
       the AND logical operator distributed among them, i.e. the logical value of { a, b, c } is the value of (a
       AND b AND c). Let's write it AND(D). The logical value of each of the items is the logical value  of  the
       selector  itself if it is not multiple, or it is the logical value of all the occurrences of the multiple
       selector within the rule, with the logical OR operation distributed among them. That is to  say,  in  the
       above  example, the value of From is true iff the From: fields contains ram OR raphael.  Let's write that
       OR[From].

       To be sound, we have to apply De Morgan's Law on N, hence the following rules: the logical value of N  is
       OR(N) and given a negated selector s, its logical value is AND[s]. And finally, the logical value of R is
       that of D AND N, with by convention having the logical value of the empty set be true.

       For  those  who do not know De Morgan's Law, here it is: given two logical propositions p and q, then the
       following identities occur:

            NOT (p AND q) <=> (NOT p) OR (NOT q)
            NOT (p OR q) <=> (NOT p) AND (NOT q)

       While we are in the logic of the propositions, note also that OR and AND are mutually distributive,  that
       is to say, given three logical propositions p, q and r, we have:

            p AND (q OR r) <=> (p AND q) OR (p AND r)
            p OR (q AND r) <=> (p OR q) AND (p OR r)

       To  be  complete,  OR  and  AND  are associative with themselves and commutative.  And the B set { 0, 1 }
       equipped with the set of operations (NOT, OR, AND) is an algebra (a Boolean one). I will  spare  you  the
       definition  of an algebra, which really has nothing to do in this manual page (which is for a mail agent,
       in case you don't remember :-).

       The attentive reader will certainly have noted that I have not specified the logical  value  of  a  group
       selector. Well, given a group selector G, we decompose it into a DG and NG partition, DG being the subset
       of  (atomic)  direct  selectors  of  G  and  NG being the subset of (atomic) negated selectors.  Then the
       logical value of DG is OR(DG) and the logical value of NG is AND(NG); the global logical value of G being
       that of DG OR NG.  In case either DG or NG is empty, then we don't have a partition,  but  by  convention
       the  value  of  the  empty  set  is  false,  and one of the sets is equal to G.  Note that within a group
       selector, the rules are exactly the dual of the rules within R.

       Now the only rule which is not logical is whether a group selector belongs to D or N.  I've  chosen,  for
       analogy  reasons,  to make the group selector belong to D if it does not start by '!' and to N otherwise.
       That is, !To Cc: belongs to N whilst Cc !To: belongs to D.  Apart  from  that,  order  within  the  group
       selector is irrelevant: To Cc: is equivalent to Cc To:, so the behavior in the quotient set is sound.

       Here are some examples:

            # Match anything: (not from ram OR not from root) is always true.
            From: !ram, !root

            # Match anything but reject mails coming from ram OR root
            !From: ram, root

            # Reject mails whose headers matching /^Re.*/ contain the word test
            !^Re.*: /\btest\b/

            # Keep mails whose subject contains test AND host
            !Subject: !/test/, !/host/

            # Matches if ram is listed in the To OR the Cc line
            To Cc: ram

   Minimal Header
       A minimal set of selectors are guaranteed to be set, regardless of the actual header of the message. This
       is for the purpose of filtering only, no physical alteration is performed.

       Envelope: This  is  the  address  found  in  the  mail envelope, i.e. the address where the mail seems to
                 originate from. This can be different from the From: address field if the mail originates  from
                 a trusted user, in sendmail's terminology. If you don't know what that is, simply ignore it.
       From:     User  who  wrote  the  mail.  If this line is missing, uses the address found in the first From
                 line.
       Length:   The physical length of the body, in bytes, once content-transfer-encoding  (if  any)  has  been
                 removed.
       Lines:    The amount of lines in the body (decoded, if necessary).
       To:       The main recipient(s) of the message. If this line is missing but a set of Apparently-To: lines
                 is  found,  then those addresses are used instead. If no such line exists, then assume the mail
                 was directed to the user (which seems a reasonable assumption :-).
       Sender:   User who sent the mail. This may differ from the From: line. If no such field exists, then  the
                 address in the first From line is used (mail envelope).
       Relayed:  This  computed header is a comma-separated list of all the hosts where the message was relayed,
                 in the proper transmission order. Each item in  this  list  can  be  a  machine  name  such  as
                 mail.hp.com  or  an  IP  address such as [15.125.38.12]. The list is derived from the Received:
                 lines present in the message.
       Reply-To: Where any reply should be sent. If no Reply-To: field is present, then the Return-Path is  used
                 (with  <>  stripped  out),  or  the  From:  line is parsed to extract the e-mail address of the
                 author.

   Variables
       The mailagent supports user-defined variables, which are globals. They are set via the ASSIGN command and
       referred to with the %# macro. Assuming we set a variable host, then %#host  would  be  replaced  by  the
       actual value of the variable. This enables some variable propagation across the rules.

       For  example, let's say the user receives cron outputs from various machines and wishes to save them on a
       per-machine basis, differentiating between daily outputs and weekly ones. Here is a solution:

            Subject: /output for host (\w+)/   { ASSIGN host '%1'; REJECT };
            Subject: /^Daily output/ { SAVE %#host/daily.%D };
            Subject: /^Weekly output/     { SAVE %#host/weekly.%m-%d };

       Besides variable interpolation via the %# escape, it  is  also  possible  to  perform  substitutions  and
       translations  on the content of a variable (or a back-reference, i.e. a number between 1 and 99). The two
       commands SUBST and TR will respectively perform in-place substitutions and  translations.  In  that  case
       however,  the name of the variable must be preceded by a single #. This differentiates the back-reference
       1 from the variable #1, although 1 is a funny name for a variable. The  need  for  #  also  prevents  the
       common  mistake of writing %#, as mailagent will loudly complain if the first parameter of SUBST or TR is
       not a digit between 1 and 99 or does not start with a #.

       Here are some actions to canonicalize the host name into lower case and strip down the  domain  name,  if
       any:

            { TR #host /A-Z/a-z/; SUBST #host /^([^.]*)\..*/$1/ };

       Those  actions  are directly translated into their perl equivalent, and any error in the specification of
       the regular expression will be reported.

       If the variable name begins with a colon ':', then the variable is made persistent. That  is  to  say  it
       will  keep  its  value  across  different  mailagent invocations. The variable is simply stored (with the
       leading ':' removed) in mailagent's database and is thus subject to  the  aging  policy  set  up  in  the
       ~/.mailagent.

       Within PERL commands or mail hooks using perl (see the MAIL HOOKS section), you can manipulate those (so-
       called)  external variables via a set of interface functions located in the extern package (i.e. you must
       prefix each of the function name with its package name, set becoming  extern'set).  The  following  three
       interface functions are provided:

       val(name) Return the value of the variable name (the leading ':' is not part of the name, in any of these
                 three interface functions).

       set(name, value)
                 Set  the external variable name to hold value. No interpretation is done by the function on the
                 actual content of the value you are providing.

       age(name) Returns the age of the variable, i.e. the elapsed time in seconds since the  last  modification
                 made by set.

       There  is  currently  no way for erasing a variable from the database. But if you do not use the variable
       any more, it will be removed when its age becomes greater than the maximum age specified  by  the  agemax
       configuration variable.

   Regular Expressions
       All  the  regular  expressions  follow  the  V8  syntax,  as  in perl, with all the perl extensions. If a
       bracketing construct (...) is used inside a rule, then the %digit macro  matches  the  digit's  substring
       held  inside the bracket. All those back-references are memorized on a per-rule basis, numbered from left
       to right. However, great care must be taken when using a back-reference in multiply present selectors, as
       all the matches will be performed up-to the first match, and back-references  are  computed  on  the  fly
       while doing pattern matching.

       For instance:

            To: /(.*)/, Subject: /Output from (\w+)/ { ASSIGN to '%1'; SAVE %2 };

       will  save  the  To:  field  in  variable  'to'  and save the mail in a folder derived from the host name
       specified in the subject. However, if we say:

            Subject: /host (\w+)/, /from (\w+)/ { ASSIGN match '%1' };

       then there will be only one back-reference set, and it will come from the first pattern  matching  if  it
       succeeds,  or  from  the  second. Should the second or the first pattern have no bracketing construct and
       still match, then the back-reference would not be recorded at all, which means the following is  probably
       not what you want:

            Subject: /from/, /host (\w+)/, To: /(.*)/ { SAVE %1; REJECT };

       as if the /from/ pattern matches then /host (\w+)/ will not be checked (identical selectors are or'ed and
       that is optimized), then %1 would refer to the To: field whereas if /host (\w+)/ matches, then %1 will be
       the host name.

       However,  this behavior can be used to selectively store a news article which has been mailed to you in a
       folder whose name is the newsgroup name in dot form. Assuming we want to give priority to comp.lang.perl,
       we could say:

            Newsgroups:
                 /(comp.lang.perl)/,
                 /(comp.mail.mh)/,
                 /(comp.compilers)/,
                 /([^,]*)/      { SAVE %1 };

       An article cross-posted to both comp.lang.perl and  comp.mail.mh  would  be  saved  in  a  comp.lang.perl
       folder,  since  this  is what would match first.  The last rules takes care of other articles: the folder
       used being whatever newsgroup appears first.

       There is also a special macro %&, which lists (it's a comma separated list) all the  selectors  specified
       via a regular expression which indeed matched.  For instance:

            Re.*: /york/        { ASSIGN which '%&' };

       would  assign  to which the list of all the fields matching the /Re.*/ pattern which contained 'york', be
       it a Received: field or a Resent-From: field (as both match the selector  specification).  Assuming  both
       those  fields  contained  the word york, the value of %& would be 'Received,Resent-From;' (the fields are
       alphabetically sorted).

       Should you have more than one such specified selector within a  single  rule,  then  it  might  be  worth
       knowing that all the set of matching selectors are recorded within %&, each set terminated with a ';'. If
       a  negated  selector  is  used,  then  %&  will  record all the fields which did not contain the pattern,
       assuming the selection succeeded (otherwise nothing is recorded).

   Available Actions
       The following actions are available as filtering commands. Case is irrelevant  although  the  recommended
       style is to spell them upper-cased. As explained later, most of the actions record their exit status in a
       special  variable  which  may be tested via the -t and -f options of ABORT, REJECT and RESTART. For every
       command returning such an exit status, the failure or success conditions are given at  the  end  of  each
       description. If nothing is specified, then the command does not return a meaningful status.

       ABORT [-tf] [mode]
                 Abort  application  of  filtering rules immediately. See REJECT for the meaning of the optional
                 parameters. (Does not modify existing status)

       AFTER [-sanc] (time) action
                 Records a callback for after the specified time, where action will be performed. By default,  a
                 mailagent filtering action is assumed (-a option), on the current mail message. A shell command
                 (-c)  may  be  given  instead, receiving the current mail message as standard input. Finally, a
                 plain shell command may be run (with no input) using the -s option.  The option -n may be  used
                 when the current mail message does not need to be kept for input. For instance:

                      AFTER -an (1 day) DO ~/process:proc'run(%u)

                 would call proc'run defined in the ~/process file in one day from now, without giving any input
                 (the action here does not require any).

                 When  running mailagent commands, the initial working mode is set to _CALLOUT_. This may matter
                 if you call APPLY for instance. If the recorded time is less or equal  than  the  current  time
                 (which  is now), the callback will occur when mailagent is done with the messages in its queue,
                 before exiting. This allows for the following cute trick, found out by Randal Schwartz:

                      AFTER (now)         # fork a copy I can mangle
                           STRIP Reply-To \; RESYNC \;
                           ANNOTATE -du Reply-To %2 \; RESYNC \;
                           NOTIFY message %r \; DELETE \;
                           ;

                 Note that the command is not called AT because the call will only  be  performed  at  the  next
                 mailagent  invocation  after the specified time has elapsed. Dates are specified using the same
                 format as in SELECT.  (Fails if the action cannot be recorded in the callout queue).

       ANNOTATE [-du] field value
                 Annotate message by adding field into the mail header, with the supplied value.  This  is  like
                 the  MH command anno, but the annotation is performed at the end of the header, whereas MH does
                 it at the top. Normally, an extra field is added, with the current date as field value.

                 This can be suppressed by using the -d option. If value is omitted,  only  the  date  field  is
                 generated  (hence  it  is an error to use the -d option without supplying a value). As with all
                 the commands which alter the header, a RESYNC is necessary for the filter part to actually  see
                 the new header.

                 The  -u  option  means "unique", and prevents ANNOTATE from executing if the specified field is
                 already present in the header. Don't forget to  RESYNC  between  successive  ANNOTATE  commands
                 using this option if the field refers to a previous ANNOTATE target.  (Fails when no annotation
                 takes place)

       APPLY rulefile
                 Get the rules held in rulefile and apply them to the current message.  The filter will begin in
                 whatever  mode  you  were  when  using this command, but no feed back will occur, i.e. any mode
                 changing will be lost when returning from the command.

                 Variables (see the %# macro) are propagated back and  forth  through  APPLY,  meaning  you  see
                 variables  set  by  the caller, and you may change their values or create new variables for the
                 caller to later use.

                 If mail is saved during the application of the rules, then the corresponding flag is set in the
                 main filter (the one that started the APPLY command). You may nest them, of course.  (Fails  if
                 mail is not saved by the rules held in rulefile)

       ASSIGN var value
                 Assign the value to the user-defined variable var, which may further be accessed as '%#var' for
                 macro  substitution  or  #var  in the TR and SUBST commands in place of the variable name. Note
                 that there is no leading # in front of the variable name. The value you provide  is  first  ran
                 through perl to see if it contains some arithmetic operations. If the evaluation is successful,
                 the  resulting  value  is used instead. If an error occurs in this evaluation process, then the
                 literal value provided is used.  To avoid the evaluation, you may enclose the  whole  value  in
                 simple  quotes.  Those  will be trimmed before the assignment takes place. If you actually want
                 simple quotes in the first AND last position, you have to  double  each  of  them.   (Does  not
                 modify existing status)

       BACK command
                 Execute  command  and  take  its  output  as  new  actions  to  be performed on the mail (hence
                 performing something analogous to `command` in shell).  If there is no output, nothing is done.
                 BACK commands can be nested, although this may lead to surprises this manpage will not disclose
                 (but I assure you it will be funny, assuming we have the same sense of humor... :-). Note  that
                 both the standard output and the standard error from the command are used.

                 If  the  command  fails,  the  output  is  mailed  back to the user and no action is performed.
                 Furthermore, normal feedback does not occur here: any output  from  the  command  is  taken  as
                 filter  actions,  which means the semantics of PASS, for instance, is changed: we do not take a
                 body back but commands.  (The execution status is that of the command)

       BEEP [-l] count
                 This command may be used to tune the amount of beeps emitted when biffing on the terminal,  for
                 each  %a  expansion.  By default, that amount is set to 1.  Using the -l option alters the beep
                 count locally for the rule.  Otherwise, the default amount is changed.

                 Note that this simply expands %a into the suitable amount of Ctrl-G characters.  Your  terminal
                 must  be  allowed  to  issue  consecutive  bells  for  this to work.  Very often, terminals are
                 configured so that the first bell received disables further beeps for  some  period,  to  avoid
                 cascades of bells.  If you use xterm for instance, you should use:

                      xterm -xrm "XTerm*BellSuppressTime: 0"

                 to enable consecutive bells. Otherwise, xterm will swallow them during 200 ms, hence making the
                 BEEP command ineffective, apparently.  (Does not modify existing status)

       BEGIN [-ft] state
                 Enter  a  new  state. An explicit REJECT or RESTART is necessary to abort the processing of the
                 current rule. The processing begins in the state  INITIAL.   If  the  -f  (resp.  -t)  flag  is
                 specified,  then  the  state  change only occurs if the last command status indicated a failure
                 (resp. a success).  A state name can contain alphanumeric characters  and  underscores.   (Does
                 not modify existing status)

       BIFF [-l] on|off|path
                 Allow  or disallow biffing dynamically. When biffing is turned on via the configuration file or
                 via this command, a message is printed on some of the terminals where the user is  logged  when
                 mail is received, as explained under the section MAIL BIFFING.

                 Instead  of  on or off, you can specify a file name (~ substitution allowed) being the new path
                 to be used for the biffing format template.

                 If you use the -l option, changes are made locally, for the duration of the rule only.  If  you
                 REJECT  to  go  to  some other rule, your changes will be lost. The global value of the altered
                 parameters is changed on the first local usage and restored when a new rule is entered.   (Does
                 not alter execution status)

       BOUNCE address(es)
                 Bounce  the  message to the specified address(es) and acts as if a save had been done. The only
                 difference with FORWARD is that no Resent-like lines are added to the header. If an address  is
                 specified  in  double  quotes,  it is taken as the name of a file to be loaded to get addresses
                 (one address per line, shell comments (#) allowed). The file name resolving is the same as  the
                 one used for pattern loading.  (Fails if mail cannot be resent)

       DO routine [(arg1, arg2, ... , argn)]
                 Calls  the perl routine, with the supplied arguments if any. This is a very low level hook into
                 mailagent's internal. The routine can be specified by itself (package'name, package being  main
                 by  default),  or  identified  by  a  leading  tag, followed by a ':', then the routine name as
                 before. The tag can be a path to a file where the routine is defined, or a  command  name  (for
                 user-defined commands which are loaded dynamically). For instance

                      DO UNKIT:newcmd'unkit('true')

                 would  lookup  the user-defined UNKIT command, load the file where it is defined (in the newcmd
                 package), then call the routine with 'true' as  argument.   The  package  specified  determines
                 where  the  loading  is done, so be sure it is consistent with the definition in the file where
                 the routine is defined.  (Fails if the routine cannot be located and executed)

       DELETE    Delete the current message. Actually, this does not do anything, it  just  marks  the  mail  as
                 saved.  If  no further action involving saving is done, then the mail will never show up in the
                 mailbox.  (Never fails)

       FEED [-be] program
                 Feed the whole message to a program and get the output back  as  the  new  message.  Hence  the
                 program  appears as a filter for the whole message.  It does not tag the message as having been
                 saved.  A RESYNC is automatically done upon return.  (Returns the status of program)

                 WARNING: Your program must be able to  properly  parse  a  MIME  message  and  must  deal  with
                 transfer-encoded  bodies  by  itself.   To make the program task simpler, you can supply the -b
                 switch which will let mailagent decode  the  whole  body  for  you,  suppressing  any  Content-
                 Transfer-Encoding  header  (implying  "binary").  This is an invalid message format for sending
                 the message, but it makes processing easier.  You still have to parse the MIME  parts  yourself
                 though.

                 Using  -b  does  not  prevent your program from outputing a valid message back, one that can be
                 possibly sent on the network so you have two options: either you do  not  supply  any  Content-
                 Transfer-Encoding  in the headers, and mailagent will recode the body for you using the initial
                 transfer encoding present in the message (a relatively safe option if you make only changes  in
                 the body at well-defined spots without introducing 8-bit chars), or you can supply the Content-
                 Transfer-Encoding yourself and perform the body encoding manually.

                 To  be  completely safe and minimize the work in your program, the -e switch will let mailagent
                 analyse  the  message  body  you  are  returning  and  select  the  proper  transfer   encoding
                 automatically.   Since this will cause the whole body to be analysed, and it can be potentially
                 huge, that behaviour must be explicitly asked for. If you need -e then you probably want -b  as
                 well (you can supply both by saying -be naturally).

                 If  you  do  not supply any switch, mailagent will give you the message as-is and will get your
                 message as-is without any additional magic.

       FORWARD address(es)
                 Forward mail to the specified address(es). This acts as if a save had been done,  in  order  to
                 avoid the DELETE. Usually when you forward a mail, you do not wish to keep it. The command adds
                 Resent-like lines in the header. As for BOUNCE, file inclusion is possible (i.e. use an address
                 "forward_list"  to forward a mail to all the users listed in the file forward_list).  (Fails if
                 mail cannot be resent)

       GIVE program
                 Give the body of the message to the specified program by feeding its standard input. Any output
                 is mailed to the user who runs the mailagent.  Note that the message is not  tagged  as  having
                 been saved.  (Returns the status of program)

                 NOTE:  If  the  message  had  a body that was encoded for transport (using one of the base64 or
                 quoted-printable transfer encoding), mailagent  will  transparently  decode  it  and  supply  a
                 version  that can be properly handled.  In other words, the program does not need to care about
                 the body being encoded in the message, as it will get  a  plain  one.  (Since  no  headers  are
                 supplied, this is the only possible option).

                 Caution  though for MIME messages: you should use PIPE for them to give a chance to the program
                 to properly handle the body, but then it needs to be fully MIME-aware.

       KEEP header_fields_list
                 Keeps only the corresponding lines in the header of the mail. For instance, a "KEEP From To  Cc
                 Subject"  will  keep  only  the  principal  fields  from the mail message. This is suitable for
                 archiving mailing lists messages.  You may add a ':' after each header field name if you  wish,
                 but  that  is  not  strictly  necessary.  Headers  may  be  specified using shell-style regular
                 expressions, and file inclusion is allowed to get  headers  from  a  file.   (Does  not  modify
                 existing status)

       LEAVE     Leave  incoming mail in the system mailbox. This is the default action if no rule matched or if
                 no saving occurred. This is not recommended on Debian systems.  (Fails if mail cannot be saved)

       MACRO [-rdp] name [= (value, type)]
                 Lets you specify user-defined macros, of the form %-(name). See the paragraph  on  user-defined
                 macros  for  explanation  about  the available types (SCALAR, EXPR, CONST, FN, PROG, PROGC).  A
                 perl interface to the underlying user macros is available for your perl commands. The -r option
                 is used to replace an existing macro (instead of pushing a new instance on the stack),  the  -d
                 is  to  delete  all  the  instances  of  a  named  macro  (in that case it takes only the first
                 argument), and -p pops the last instance of the  macro  from  the  stack  and  reverts  to  the
                 previous  definition, if any (otherwise, it acts as -d).  If you wish to define a simple SCALAR
                 macro, you may omit the = (value, type) part and simply continue with the macro  value.   (Does
                 not modify existing status)

       MESSAGE file
                 Send  message  file  back  to  the  sender  of  the  message (as derived from the header of the
                 message). The text of the message is run through the macro  substitution  mechanism  (described
                 later on).  (Fails if message cannot be sent)

       NOP [-ft] No operation. If this seems a bit odd, think of it in terms of a ONCE command.  (Does not alter
                 existing  status  unless  -f or -t is used, in which case it forces a false --failure-- or true
                 success status)

       NOTIFY file address(es)
                 Send a notification message file to a given address list.  The  text  of  the  message  is  run
                 through the macro substitution mechanism (described later on).  As with FORWARD, file inclusion
                 for address specification is possible.  (Fails if message cannot be sent)

       ON (day list) command
                 Execute  the  specified  filter  command  only on the specified day list. That list is a space-
                 separated list of days, specified using the English names. Only the first three characters  are
                 taken  into  account,  case-insensitively. Therefore, the shortest valid day specifications are
                 Mon, Tue, Wed, Thu, Fri, Sat and Sun.

                 This command can be used in conjunction with SELECT to  do  time-based  selective  bouncing  of
                 messages to, for instance, your home address:

                      ON (Mon Tue Wed Thu) SELECT (18:30 .. 23:00) BOUNCE me@home.net;
                      ON (Fri) SELECT (18:30 .. 23:59) BOUNCE me@home.net;
                      ON (Sat Sun) BOUNCE me@home.net;

                 That  would bounce messages only on week-ends and during the week, after 18:30, and until 23:00
                 (assuming that's bed time, other messages will be seen at work the  next  day).  Note  that  on
                 Fridays,  we  go  as  far  as  23:59.   (Propagates  status from command. If the command is not
                 executed, always return success)

       ONCE (name, tag, period) command
                 Execute the specified filter command once per period. The name  and  tag  fields  are  used  to
                 record  timestamps  of  the  last  ONCE  command.   More on this later. (Propagates status from
                 command. If the command is not executed, always return success)

       PASS program
                 Feed the body of the message to the specified program and get a new body back from  the  output
                 of the program.  Note that the message is not tagged as having been saved.  (Returns the status
                 of program)

                 NOTE:  If  the  message  had  a body that was encoded for transport (using one of the base64 or
                 quoted-printable transfer encoding), mailagent  will  transparently  decode  it  and  supply  a
                 version  that  can  be  properly  handled.   The  body  generated  by  the program will then be
                 automatically encoded back using the same transfer encoding.

                 Caution though for MIME messages: you should use FEED for them to give a chance to the  program
                 to properly handle the body, but then it needs to be fully MIME-aware.

       PERL script [arguments]
                 Escape to a perl script to perform some actions on the message. This is fully described further
                 in  the  manpage, and is very different from a RUN perl script command. (Returns failure if the
                 script did not compile or returned a non-zero status).

       PIPE [-b] program
                 Pipe the whole message to the specified program, but do not get anything back.  Any  output  is
                 mailed  to  the user who runs the mailagent.  The message is not tagged as having been saved in
                 any case, so you must explicitly DELETE it if piping was enough and it did  not  fail:  "REJECT
                 -f" is your friend here to avoid unwanted deletion.  (Returns the status of program)

                 WARNING:  Your  program  must  be  able  to  properly  parse  a MIME message and must deal with
                 transfer-encoded bodies by itself.  To make the program task simpler, you  can  supply  the  -b
                 switch  which  will  let  mailagent  decode  the  whole  body for you, suppressing any Content-
                 Transfer-Encoding header (implying "binary").  This is an invalid message  format  for  sending
                 the  message,  but it makes processing easier.  You still have to parse the MIME parts yourself
                 though.

       POST [-lb] newsgroup(s)
                 Post the message to the specified newsgroup(s) after having cleaned-up the header: mail-related
                 fields like Received: or In-Reply-To: are  removed,  a  valid  From:  line  is  generated,  the
                 original  To:  and Cc: are renamed with an X- prefix, the References: line is updated/generated
                 if necessary based on existing In-Reply-To, and NNTP-specific fields are stripped so  that  the
                 server can add its own.

                 Running POST successfully acts as a saving.

                 If  the  first  name is -l as in "POST -l comp.mail.mh", then a "Distribution: local" header is
                 added to force a local delivery.  Otherwise,  the  default  inews  distribution  will  be  used
                 (world, usually).

                 When  the  -b  switch  is  given, a successful POST will result in biffing being activated (see
                 section MAIL BIFFING) for the resulting news article.

                 If more than one newsgroup is specified, they should be space separated. It is possible to  get
                 a newsgroup list via file inclusion.  (Fails if message cannot be posted)

       PROCESS   Run the mailagent processing which looks for @SH commands and executes them. This was described
                 before  in  the section dealing with default rules.  The action associated by default to a mail
                 having [Cc]ommand as its subject is PROCESS.  (Always returns success)

       PROTECT [-lu] mode
                 Sets the default protection mode that should be set on created folders (or created  files  when
                 saving  into  an  MH  folder or a directory). By default, permissions are governed by the UMASK
                 command, but this lets you override the default. The specified mode should be preceded by  a  0
                 as  in  0644  to give the familiar octal permissions. Otherwise, it is interpreted as a decimal
                 number, so beware!

                 The -l option may be used to specify a mode locally for one rule.   Otherwise,  the  protection
                 mode  is  set  globally. The -u option unsets the global (or local when combined with -l) mode,
                 reverting to the default behaviour where only the umask is taken into account by the system.

                 Note that when saving into an MH folder, the PROTECT command takes  precedence  over  the  Msg-
                 Protect field from your ~/.mh_profile file.  (Does not alter execution status)

       PURIFY program
                 Feed  the  header  into  a  program  and get new header back. RESYNC is done automatically upon
                 return.  This may be used to indeed purify the header by removing all the verbose  stuff  added
                 by  so  many  mail  transport agents (X-400 like lines for instance).  Obviously, this does not
                 flag the message as having been saved.  (Returns the status of program)

                 If your program removes the Content-Transfer-Encoding header in a MIME message, mailagent  will
                 properly  transform  the  message  to  have a non-encoded body.  If you change the value of the
                 Content-Transfer-Encoding header, mailagent will also correctly recode the body for  you.   The
                 only supported encodings are base64 and quoted-printable.

       QUEUE     Queue  mail again. A successful queuing counts as if mail has been saved.  Mail queued that way
                 will not be processed during the next 30 minutes. Note that unless mailagent is  invoked  on  a
                 regular  basis  by  cron, the mail will remain in the queue until another mail arrives.  (Fails
                 when mail cannot be queued)

       RECORD [-acr] [state] [(tag-list)]
                 Record message in the history and enters state _SEEN_ if the message was already present there.
                 If the message is recorded for the first  time,  processing  continues  normally.  Otherwise  a
                 REJECT  is  performed. This behavior may be somewhat modified by using some options. See UNIQUE
                 for a complete description of the options and arguments. Naturally, when a state is  specified,
                 that  overrides  the  default  _SEEN_.   A  state  name can contain alphanumeric characters and
                 underscores.

                 When a tag-list (comma-separated list of names) is specified, the message is only recorded  and
                 checked  against  all  those  tags,  but  only  them.  Not  specifying  any  tag list means any
                 occurrence, whether it is tagged or not.  See paragraph Using Tags in  Record  and  Unique  for
                 more information.  (Returns a failure status if mail was already recorded)

       REJECT [-tf] [state]
                 Abort  execution  of current action, and continue matching. If -t is specified, the reject will
                 occur only if the previous action was successfully completed (return status of true), whilst -f
                 would cause the reject only when a failure occurred. If a state is  specified,  we  enter  that
                 state  before  rejection. REJECT resets the matching flag, which means that if no further match
                 occurs, the default action will apply.  A state name can contain  alphanumeric  characters  and
                 underscores.  (Does not alter execution status)

       REQUIRE file [package]
                 Behaves like the perl require operator by loading a perl file into memory. By default, the file
                 is  read  in  the  newcmd package, but you may specify whatever package you wish to load it in.
                 This command will only perform the loading once per (file,  package)  tuple.  Unlike  its  perl
                 equivalent,  the  file  "value" is not important, i.e. it does not have to end with a statement
                 returning a true value.  (Fails if file cannot be loaded)

       RESTART [-tf] [state]
                 Abort execution of current action and restart the matching process from the beginning. To avoid
                 loops, each rule may be walked through once in a given state. See REJECT for the meaning of the
                 optional parameters. RESTART resets the matching flag, which means that the default action will
                 apply, should no further match occur.  (Does not alter execution status)

       RESYNC    Re-synchronize header used for matching with the header of the mail. This  is  probably  useful
                 only when a SUBST or ANNOTATE command was run.  (Does not alter execution status)

                 NOTE:  At  RESYNC  time,  mailagent will check whether the Content-Transfer-Encoding header was
                 changed and will transparently recode the body if required, so that the whole  message  remains
                 valid  despite  header mangling. It will also take care of updating Content-Length if required.
                 Whenever you do change these important headers via SUBST or ANNOTATE, be sure  to  call  RESYNC
                 before disposing of the message or you run the risk of saving a corrupted version that will not
                 be properly understood by your mail user agent.

       RUN program
                 Run the specified program and mail any output to the user who runs mailagent.  This action does
                 not flag the message as having been saved.  (Returns the status of program)

       SAVE folder
                 Save message in the specified folder. If folder name starts with a '+', it is handled as an MH-
                 style  folder  and rcvstore is emulated to deliver the message into that folder. If folder is a
                 directory, message is delivered in a  single  file  within  that  directory.  See  the  FOLDERS
                 section.  (Fails if message cannot be saved)

       SELECT (start .. end) command
                 Execute the command only within the time selection period specified.  Dates can be specified in
                 a  wide  range  of  formats.  The  output  of  the  date(1)  command  is  an example of a valid
                 specification. If the date, the year  or  the  month  is  missing,  then  the  current  one  is
                 substituted  in  place  of  it. The following dates are valid specifications: '10:04:25', 'now'
                 ,'April 1 1992', 'Dec 25', 'July 14 1789, 07:40' (err... it's valid according to  the  grammar,
                 but it's before the Epoch so it does not mean anything). Other fancy dates like 'last month - 5
                 minutes'  or  '3  weeks  ago'  are  also enabled.  (Isn't that great to have a real parser? The
                 filtering rules could have been more elaborated if only I had known about  this  Berkeley  yacc
                 producing a perl parser...).  (Returns the status of command, if run, otherwise returns true).

       SERVER [-t] [-d disabled commands]
                 Activate  server  processing.  The  body of the message is interpreted as a list of commands to
                 execute. See section GENERIC MAIL SERVER for more information about the server itself.  The  -t
                 option  turns  the  server into trusted mode, where powers may be gained. The -d option must be
                 followed by a list of disabled commands, separated by commas with no intervening spaces between
                 them.

       SPLIT [-adeiw] folder
                 Split a mail in digest format into the specified folder (same naming conventions as  in  SAVE).
                 If  no folder is specified, each digest item is queued and will be analyzed as a single mail by
                 itself. The -d option deletes the digest header. The -i option means split is done in-place and
                 the original mail is discarded. All the options may be used simultaneously  provided  they  are
                 stuck together at the beginning (option parsing being really rudimentary).

                 If the mail is not in digest format and a folder is specified, then it is saved in that folder.
                 Otherwise,  the  SPLIT  action  fails  and  nothing occurs (the filter continues its processing
                 though). The SPLIT command will correctly burst RFC-934 digest messages and will try to do  its
                 best  otherwise. If the digest was not RFC-934 compliant and there is a chance SPLIT might have
                 produced something incorrect, then the original message is also saved if -i,  otherwise  it  is
                 not  tagged  as  saved  (so  that the default LEAVE command may apply). The -w (watch) requests
                 special care and will detect  every  non  RFC-934  digest,  even  when  the  non-compliance  is
                 otherwise  harmless; furthermore, any trailing garbage longer that 100 bytes will be saved as a
                 digest item by itself.

                 The -a option annotates every digest item with  an  X-Digest-To:  header  line,  which  is  the
                 concatenation  of  the  To: and Cc: fields of the original digest message. This may be used for
                 instance to burst the digest into the queue and then re-process each of its items according  to
                 this  added  field.   Finally, the -e option will discard the digest header only if its body is
                 empty (i.e. the moderator did not include any leading comment).  (Returns success if  mail  was
                 in digest format and correctly split without any error)

       STORE folder
                 Save  message  in  the  specified  folder  and  leave a copy in the system mailbox.  The folder
                 parameter follows the same naming conventions as in SAVE. Again,  because  of  locking  issues,
                 leaving mail in the mailbox is not recommended on Debian machines.  (Fails if message cannot be
                 saved either in the folder or in the mailbox)

       STRIP header_fields_list
                 Remove  the  corresponding  lines  in the header of the mail. For instance, a "STRIP Newsgroups
                 Apparently-To" will remove the appropriate lines to wipe out any Newsgroups: or  Apparently-To:
                 header.  You  may  add a ':' after each header field name if you wish, but that is not strictly
                 necessary. Headers  may  be  specified  via  shell-style  regular  expressions  or  via  "file"
                 inclusion.  (Does not alter execution status)

       SUBST var/header expression
                 Substitutes  the  expression on the specified user-defined variable (name starting with a #) or
                 back-reference (digit), or header field (optionally ending with ':').  For instance

                      SUBST #foo /w/y/g

                 would substitute in user-defined variable foo all the w by y.  See also ASSIGN and TR.

                 For substitutions on header fields, like:

                      SUBST Subject: /\[foo\]\s+//;

                 matching header lines will be reformatted when the substitution  is  successful,  which  likely
                 means  original  continuations  will  not  be preserved.  The target of the substitution is the
                 whole header, with continuations normalized to one space.  You are therefore guaranteed  to  be
                 independent from the actual header formatting in the original.

                 Do  not  forget  to  issue a RESYNC after a header field SUBST, since some routines (like POST)
                 probe into the parsed header hash table to generate the saved message.

                 (Fails if error in expression)

       TR var/header translation
                 Perform the translation on the specified variable, back-reference or header field. For instance

                      TR 1 /A-Z/a-z/

                 would canonicalize content of reference 1 into lowercase.  Successfully transliterated  headers
                 are  reformatted,  even  when  their  overall  size is not changed.  See also ASSIGN and SUBST.
                 (Fails if error in translation)

       UMASK [-l] mode
                 Changes the process's umask to the specified mode, which can be decimal, octal (if preceded  by
                 '0') or hexadecimal (starting with '0x'). The octal notation is the clearest way to specify the
                 umask  anyway.  Aren't rumors saying that octal was invented for that purpose only? ;-) Use the
                 -l option to change the umask for the duration of the current action rule only. Note  that  the
                 default  umask specified in your config file is used to reset mailagent's umask at the start of
                 each mail processing.  (Does not alter execution status)

       UNIQUE [-acr] [state] [(tag-list)]
                 Record message in the history and tag message as saved if it was already present there. If  the
                 message  is  recorded  for the first time, processing continues normally. Otherwise a REJECT is
                 performed. If -r was used, a RESTART is used  instead  whilst  -a  would  run  an  ABORT.   For
                 instance,  to  remove  duplicate messages from mailing lists, run a UNIQUE -a before saving the
                 mail.  The -c option may be used alone to actually prevent  the  command  from  disturbing  the
                 execution  flow,  and  to  later  use  the return status to see what happened: UNIQUE returns a
                 failure status if the message was already recorded.  If an optional state  argument  is  given,
                 then  the automaton will enter that state if the mail was previously in the database.  See also
                 RECORD, and the paragraph entitled Using Tags in Record and Unique for more  information  about
                 the tag-list.  (Fails if mail was already recorded)

       VACATION [-l] on|off|path [period]
                 Allow  or  disallow  a  vacation message. When vacation mode is turned on via the configuration
                 file, a message is sent whenever the  user  receives  a  mail  meeting  some  requirements,  as
                 explained  under  the  section  VACATION MODE.  One of the conditions is that the vacation flag
                 modified by this command be true. This makes it easy to disallow vacation messages, ever, to  a
                 group of people for instance.

                 Instead  of  on or off, you can specify a file name (~ substitution allowed) being the new path
                 to be used for locating the vacation file.  Optionally, you may specify a last parameter, which
                 will be taken as the period to apply  when  sending  the  vacation  message.   Changes  to  the
                 vacation message path are forbidden when the configuration variable vacfixed is set to ON.

                 If  you  use the -l option, changes are made locally, for the duration of the rule only. If you
                 REJECT to go to some other rule, your changes will be lost. The global  value  of  the  altered
                 parameters  is changed on the first local usage and restored when a new rule is entered.  (Does
                 not alter execution status)

       WRITE folder
                 Write the message in the specified folder, removing any pre-existing folder with the same name.
                 Hence, successive WRITE commands will overwrite the previous  one.  This  is  useful  to  store
                 output  of  system  commands  ran by cron. Don't try to use it with an MH folder or a directory
                 folder or it will behave like SAVE.  (Fails if message cannot be written)

   Execution Status
       Almost all the actions modify a variable which keeps track of the execution status (analogous to  the  $?
       variable  in  the  shell).  This variable can be tested via the -t or -f option of the REJECT command for
       instance. To give but a single example, the SAVE action would return failed if it could not save the mail
       in the specified folder. If that SAVE command was followed by a "REJECT -f FAILED", then the execution of
       the current rule would stop and the automaton would continue to analyze the mail in the FAILED state.

       Some of the actions however do not modify this last execution status. Typically, those are actions  which
       make  decisions  based on that status, or simply actions which may never fail. Those special actions are:
       ABORT, ASSIGN, BEGIN, KEEP, MACRO, NOP, REJECT, RESTART, RESYNC, STRIP and VACATION.

       It is unfortunate that ONCE or SELECT commands cannot make the difference between a non-execution  and  a
       successful  execution  of the specified command.  There may be a change in the way this scheme works, but
       it should remain backward compatible.

   Perl Escape
       By using the PERL command, you have the ability to perform  filtering  and  other  sophisticated  actions
       directly  in perl. This is really different from what you could do by feeding your mail to a perl script.
       First of all, no extra process is created: the script is loaded directly into mailagent and compiled in a
       special package called mailhook. Secondly, you have a perl interface to all the filtering commands:  each
       filtering  action  is  associated  to  a  perl  function (spelled lower-cased). Finally, some pre-defined
       variables are set for you by mailagent.

       Before we go any further, please note that as there is no extra process created, you must  not  call  the
       perl  exit  function.  Use  &exit instead, so that the exit may be trapped. &exit takes one argument, the
       exit code.  If you use 0, this is understood as a success, any other value meaning failure (i.e. the PERL
       command will return a failure status). Using the perl exit function directly  would  kill  mailagent  and
       would probably incur some mail losses.

       The  scripts  used should remain simple. In particular, you should avoid the use of the package directive
       or define functions with a package name other than mailhook  (i.e.  the  package  where  your  script  is
       loaded).  Failure  to  do  so  may raise some name clashes with mailagent's own routines.  In particular,
       avoid the main package. Note that since the compilation environment is set-up to mailhook, not specifying
       package names in your variables and subroutine is fine (in fact, it's meant to work that way).

       Your script is free to do whatever it wants to the mail. Most of the time however, you end up  using  the
       mailagent  primitives to save the mail or forward it (but you are free to redesign your own and call them
       instead, of course). The interface is simple: each function takes but one argument, a  string,  which  is
       the arguments to the command, if any. For instance, in a perl escape script, you would express:

            { SAVE list; FORWARD "users"; FEED ~/bin/newmail -tty; REJECT }

       with:

            &save('list');
            &forward('"users"');
            &feed('~/bin/newmail -tty');
            &reject;

       The  rule  is simple: each command is replaced by a function call, with the remaining parameters enclosed
       in a string, if any. Alternatively, you may specify parameters as a list: all the arguments  you  provide
       are  joined  into  a  big  happy  string,  using  a  space character as separator. The macro substitution
       mechanism is then ran on this resulting argument string.

       Each function returns a boolean success status of the command (i.e. 1 means success). For those functions
       which usually do not modify the filter's last execution status variable, a success  is  always  returned.
       This makes it possible to (intuitively) write:

            &exit(0) if &save('uucp');
            &bounce('root') || &save('emergency');

       and  get  the  expected  result.  The mail will be saved in the emergency folder only when saving in uucp
       folder failed and the mail could not be bounced to root.

       It is important to understand that these commands have exactly the same effect on the  filtering  process
       when  they  are run from a perl escape script or from within the rule file as regular actions.  A &reject
       call will simply abandon the execution of the current perl script and the filter  automaton  will  regain
       control  and  attempt  a  new  match.   But  perl brings you much more power, in particular system calls,
       control structures like if and for, raw regular expressions, etc...

       The special perl @INC array (which controls  the  search  path  for  require)  is  slightly  modified  by
       prepending  mailagent's  own private library path. This leaves the door open for future mailagent library
       perl scripts which may be required by the perl script. Furthermore, the following special  variables  are
       set-up by perl before invoking your script:

       @ARGV          The  arguments  of  the script, which were given by the PERL command. This array is set up
                      the exact same way you would expect it to be set up if you invoked  the  command  directly
                      from  the  shell,  excepted  that @ARGV[0] is the name of the script (since you cannot use
                      perl's $0 to get at it; that would give you mailagent's name).
       $address       The address part of the From: line.
       $cc            The raw content of the Cc: line.
       @cc            The list of addresses on the Cc: line, with comments suppressed.
       $envelope      The mail envelope, as computed using the first From line of the message.
       $friendly      The comment part of the From: line, if any.
       $from          The content of the From: line, with address and comment part.
       %header        This table, indexed by field name, returns the raw content  on  the  corresponding  header
                      line. See below.
       $msgpath       The  full  path  name of the folder (or message within an MH folder) where the last saving
                      operation has occurred. This is intended to be used if you wish to construct your own mail
                      reception notification.
       $length        The message length, in bytes.
       $lines         The number of lines in the message.
       $login         The login name of the address on the From: line.
       $precedence    The content of the Precedence: line, if any at all.
       @relayed       The list of host names (possibly raw IP  addresses  if  no  DNS  mapping)  listed  in  the
                      (computed) Relayed: header line.
       $reply_to      The e-mail address where a reply should be sent to, with comment suppressed.
       $sender        The  sender  of the message (may have a comment), derived in the same way the Sender: line
                      is computed by mailagent.
       $subject       The subject of the message.
       $to            The raw content of the To: line.
       @to            The list of addresses on the To: line, with comments suppressed.

       The associative array %header gives you access to all the fields  in  the  header  of  the  message.  For
       instance,  $to  is  really the value of $header{'To'}. The key is specified using a normalized case, i.e.
       the first letter of each word is uppercased, the remaining being lowercased.  This is independent of  the
       actual physical representation in the message itself.

       The  pseudo  keys  Head, Body and All respectively gives you access to the raw header of the message, the
       body and the whole message.  The %header array is really a reference to  the  mailagent's  internal  data
       structure,  so modifying the values will influence the filtering process.  For instance, the SAVE command
       writes the Head, the X-Filter: line, the end of header (a single newline) and then the Body (this  is  an
       example  only,  not  a  documented  feature  :-).  The =Body= key is special: it is a Perl reference to a
       scalar containing the body with any content transfer encoding removed.

       Note that the $msgpath variable holds only a snapshot of the folder path  at  the  time  where  the  PERL
       escape  was  called.  If  you  perform  your  own  savings  in  perl,  then  you  need  to  look  at  the
       $main'folder_saved variable instead to get the up-to-date folder path value.

       As a final note, resist the temptation of reading the internals of the mailagent and directly calling the
       routines you need. If it is not documented in the manual page, it may be changed without  notice  by  any
       further  patch.   (And  this  does not say that documented features may not change also... It's just more
       unlikely, and patches would clearly state that, of course.)

   Program Environment
       All the programs started by mailagent via RUN and friends inherit the  following  environment  variables:
       HOME,  USER  and  NAME,  respectively  set  from the configuration parameters home, user and name. If the
       mailagent is invoked by the filter, then the PATH is also set according to the configuration file (if you
       are using the C filter) or to whatever you set PATH (if you are using the shell filter).

       All the programs are executed from within the home directory. This includes scripts started via the  PERL
       command and mail hooks. The latter will be described in detail further down.

   File inclusion
       Some  commands  like  FORWARD  or KEEP allow you to specify a file name between double quotes to actually
       load parameters from this file. Unless a full path is given, the following method is used to  locate  the
       file:  first  in  the  location  pointed  to  by the mailfilter variable if set, otherwise in maildir and
       finally in the home directory. Note that this is not a search path in the sense  that  if  mailfilter  is
       defined and the file is not there, an error will be reported.

       The file should list each parameter (be it an address, a header or a pattern) on a line by itself. Shell-
       style  comments  (#)  are allowed within that file and leading white spaces are trimmed (but not trailing
       spaces).

   Macros Substitutions
       All the commands go through a macro substitution mechanism before being executed.  The  following  macros
       are available:

       %%        A real percent sign
       %A        The  internet  address extracted out of the From: field (a.b.c in u@a.b.c), converted to lower-
                 case.
       %C        CPU name on which mailagent runs. That is a fully qualified hostname with the domain name, e.g.
                 lyon.eiffel.com.
       %D        Day of the week (0-6)
       %H        Host name (name of the machine on which the mailagent runs), without any domain name. Always in
                 lower-case, regardless of the machine name.
       %I        The internet domain name extracted out of the From: field (b.c in u@a.b.c), converted to lower-
                 case.
       %L        Length of the body part, in bytes, with content-transfer-encoding removed.
       %N        Full name of the sender (login name if none)
       %O        The organization name extracted out of the From: field (b in u@a.b.c), converted to lower-case.
       %R        Subject of the original message with leading Re: suppressed
       %S        Re: subject of original message
       %T        Time of the last modification on mailed file (commands MESSAGE and NOTIFY)
       %U        Full name of the user
       %Y        Full year, with four digits (so-called yyyy format)
       %_        A white space (useful to put white spaces in single patterns)
       %&        List of selectors which incurred match (among those specified via a regular expression such  as
                 'X-*:  /foo/i'.  If we find the foo substring in the X-Mailer: header line, then %& will be set
                 to this value). Values in the list are comma separated.
       %~        A null character, wiped out from the resulting string.
       %digit    Value of the corresponding back reference from the last match.
       %#var     Value of user-defined variable var
       %=var     Value of the mailagent configuration variable var as specified in the ~/.mailagent file.
       %d        Day of the month (01-31)
       %e        The user's e-mail address (yours!).
       %f        Contents of the "From:" line, something like %N <%r> or %r (%N) depending on how the mailer  is
                 configured.
       %h        Hour of the day (00-23)
       %i        Message ID, if available (otherwise, this is a null string)
       %l        Number of lines in the message, once content-transfer-encoding has been removed
       %m        Month of the year (01-12)
       %n        Lower-case login name of sender
       %o        Organization (where mailagent runs)
       %r        Return address of message
       %s        Subject of original message
       %t        Current hour and minute (in HH:MM format)
       %u        Login name of the user
       %y        Year (last two digits)
       %[To]     Value of the header field (here To:)

   User-defined Macros
       The  mailagent lets you define your own macros in two ways: at the filter level via the MACRO command, or
       at the perl level in your own commands or perl actions.

       Once defined, a user macro (say foo) can be substituted by using %-(foo). In the case of a  single-letter
       macro, that can be optimized into %-f for instance, i.e. the parenthesis can be omitted.

       There are six types of macros:

       SCALAR    A  scalar  value  is given, e.g: red. The macro's value is the literal scalar value, no further
                 interpretation is performed on the data.

       EXPR      A perl expression will be evaled to get the value, e.g: $red.  Note that the evaluation will be
                 performed within the usrmac package, so if you are referring to a variable in another  package,
                 it would be wise to specify it, as in $foo'bar.

       CONST     It's  really  the  same  as  EXPR, but the value is known to be a constant. So the first time a
                 substitution is made, the expression will be evaluated, and then its result is cached.

       FN        A perl function name (without the leading &), such  as  main'do_this.   The  function  will  be
                 called  with  a  single  parameter: the name of the macro itself. That leaves the door open for
                 further user-defined conventions by forcing evaluation through one single perl function.

       PROG      A program to run to get the  actual  value.  Only  trailing  newline  is  chopped,  others  are
                 preserved.  The  program  is forked each time. In the argument list given to the program, %n is
                 expanded as the macro name we are trying to evaluate. If you  specify  that  in  the  filtering
                 rules, don't forget to escape the first %.

       PROGC     Same  as  PROG  really,  but  the program is forked only once and the value is cached for later
                 perusal.

       At the perl level, four functions let you manipulate and define your  macros  (all  part  of  the  usrmac
       package):

       new(name, value, type)
                 Replace or create a %-(name) macro. For instance:

                      new('foo', "$mailhook'header{'X-Foo'}", 'EXPR');

                 would create a new macro foo that would expand into the value of an hypothetical X-Foo header.

       delete(name)
                 Delete all values recorded for the macro.

       push(name, value, type)
                 Stack a new macro, creating it if necessary.

       pop(name) Remove last macro definition on the stack.

       One  macro  stack  is  allocated  for  each  macro,  so  that  some  kind of crude dynamic scoping may be
       implemented. Creating a macro via push is like taking a local variable in perl, while creating one by new
       is simply assigning to a variable. Likely, pop is like exiting a block with a local  variable  definition
       and delete frees all the macro bearing that name, i.e. it deletes the whole stack.

       At  the filter level, the MACRO command has three options. By default, the command defines a new macro by
       using push, and the other options each let you access one of the other interface  functions.   Note  that
       macro definitions persist across APPLY commands.

   User-defined Logging
       Most of the time when writing a new mailagent filtering command or an perl hook, you will have a need for
       specific logging, either to report a problem or to keep track of what you are performing.

       Normally,  logs  are  appended  into  the  agentlog file by calling &main'add_log(string) (see subsection
       General Purpose Routines).  For plain mailagent actions, this is fine.

       But mailagent lets you define alternate logging  files,  referred  to  by  name.   This  generic  logging
       interface is defined in the usrlog package:

       new(name, file, flag)
                 Records  a  new log file known as name and done in file. If the pathname given for this file is
                 not absolute, it is rooted under the logdir directory. If flag is set to true, any logging done
                 to this file will also be copied to the default system-wide  logfile.  Nothing  is  done  if  a
                 logfile with the same name has already been defined.

       delete(name)
                 Deletes  the  logfile  known  as  name.  Further logging done to that file is redirected to the
                 default logfile.

       main'usr_log(name, string)
                 Adds an entry to the logfile name. The default logfile  is  known  as  default  and  cannot  be
                 redefined  nor  deleted. Note that this function is available from the main package. Calling it
                 with name set to the string 'default' is mostly equivalent  to  calling  directly  main'add_log
                 with  the notable exception that the -i mailagent option will not be honored in that case. This
                 may or may not be useful to you.

       If you call &main'usr_log with a non-existent logfile name, logging is redirected to the default  system-
       wide logfile defined in your ~/.mailagent.

   Dynamically Loading New Code
       In  you  perl  routines (user-defined commands, perl hooks, etc...), you may feel the need to dynamically
       load some new code into mailagent. You have direct access to the internal routine used  by  mailagent  to
       implement the REQUIRE command or load your new filtering commands for example.

       Using the so-called dynload interface buys you some extra features:

       •    The  mailagent  public  library  path  is  automatically prepended to the @INC array, which lets you
            define your own system-wide or private perl library files (the private library path  is  defined  by
            the perlib configuration variable, the public library path was defined at installation time).

       •    Like  perl's  require, mailagent keeps track of which files were loaded into which packages and will
            not reload the same file in the same package twice.

       •    It is possible to make sure that a specific function be defined in the loaded file,  with  an  error
            reported if this is not the case.

       •    You benefit from the default logging done by dynload when some error occurs.

       In order to do all this, you call:

            &dynload'load(package, file, function)

       specifying  the  package into which you wish to load the file, and optionally the name of a function that
       must be defined once the file has been loaded (leave this field to undef  if  you  do  not  have  such  a
       constraint).   The routine returns undef if the file cannot be loaded (non-existent file, most probably),
       0 if the file was loaded but contained a syntax error or did not define the specified function, and 1 for
       success.

   Using Once Commands
       The ONCE constructs lets you specify a given command to be run once  every  period  (day,  week...).  The
       command is identified by a name and a tag, the combination of the two being unique. Why not just a single
       identifier?  Well,  that  would  be  fine, but assume you want to send a message in reply to someone once
       every week. You could use the e-mail address of the person as the command identifier.  But  what  if  you
       also want to send another message to the same address, this time once a month?

       Here  is  a  prototypical usage of a ONCE, which acts like the vacation program, excepted that it sends a
       reply only once a day for a given address:

            { ONCE (%r, message, 1d) MESSAGE ~/.message };

       This relies on the macro substitution mechanism to send only once a day the message held  in  ~/.message.
       Do  not  use  the  tag  vacation,  unless you know what you are doing: this is the tag used internally by
       mailagent in vacation mode. Recall that no selector nor pattern is understood as "Subject: *", hence  the
       rule is always executed because that pattern always matches.

       The timestamps associated with each commands are kept in files under the Hash directory. The name is used
       as  a  hashing  key  to  compute  the name of the file (the two first letters are used). Inside the file,
       timestamps are sorted by name, then by tag. Of course, you could say (inverting tag and name):

            { ONCE (message, %r, 1d) MESSAGE ~/.message };

       but that would be likely to be less efficient, as the first hashing would be done on a fixed word,  hence
       all  the  timestamps  would  be  located  in  the  file  Hash/m/e (where Hash is the name of your hashing
       directory, which is the hash parameter in the configuration file).

   Using Tags in Record and Unique
       Both the RECORD and UNIQUE commands let you specify a comma-separated tag list between '(' and  ')'.  For
       each  tag  present in the list, there is a separate entry in the database associated with the message ID.
       When the message is recorded for at least one of the tags, the command "fails". Not specifying  any  tags
       means looking for any occurrence of that message ID, whether it is tagged or not.

       This  is  very useful when receiving mail cross-posted to distinct mailing lists and you want to save one
       instance of the message in each folder, but still guard against duplicates. You may say:

            To Cc: unix-wizards {
                 UNIQUE (wizards);
                 SAVE wizards;
                 REJECT;
            };
            To Cc: majordomo-users   {
                 UNIQUE (majordomo);
                 SAVE majordomo;
                 REJECT;
            };

       and only one instance of the message will end up in each folder. When you have folders  with  conflicting
       interests,  you  might use a tag list, instead of a single tag. For instance, assuming you wish to keep a
       single copy for messages cross-posted to both dist-users and agent-users, but have  a  separate  copy  if
       also cross-posted to majordomo-users, then say:

            To Cc: majordomo-users   {
                 UNIQUE (majordomo);
                 SAVE majordomo;
                 REJECT;
            };
            To Cc: dist-users {
                 UNIQUE (dist, agent);
                 SAVE dist-users;
                 REJECT;
            };
            To Cc: agent-users {
                 UNIQUE (dist, agent);
                 SAVE dist-users;
                 REJECT;
            };

       If  you  have  some  rule  using UNIQUE without any tags, it will match when at least one instance of the
       message has been recorded, no matter what tag (if any at all) was used in the first place.

   Specifying A Period
       The period parameter of the ONCE commands or the vacperiod parameter of your configuration file  has  the
       following format: a number followed by a modifier. The modifier is an atomic period like a day or a week,
       the  number  is the number of atomic periods the final period should be equal to. The available modifiers
       are:

       m         minute
       h         hour (60 minutes)
       d         day (24 hours)
       w         week (7 days)
       M         month (30 days)
       y         year (365 days)

       All the periods are converted internally in seconds, although you do not really care... Examples of valid
       periods range from "1m" to "136y" on a 32 bits machine (why ?).

   Timeouts
       In order to avoid having a mailagent waiting for a command forever, a maximum execution time of one  hour
       is  allowed by default.  Past that amount of time, the child is sent a SIGTERM signal. If it does not die
       within the next 30 seconds, a SIGKILL is sent. Output from the program, if any so far, is mailed back  to
       the  user.   This  default  behaviour  may  be  altered  by  setting  a  proper  runmax  variable in your
       configuration file to allow more time for the command to complete.

       There is also a filter queue timeout. In order to moderate system load, the C  filter  program  waits  60
       seconds  by  default (or whatever queuewait was set to in the config file) before launching mailagent. To
       avoid conflicts, messages queued by the first filter (which will then sleep for  queuewait  seconds)  are
       not  processed  by  mailagent's  -q  option until they are at least queuehold seconds old. Another queue-
       related parameter is queuelost, the amount of seconds after which mailagent will flag messages as  "lost"
       when listing the queue.

       Finally,  the  locking timeout policy may also be configured. By default, a lock is broken when it is one
       hour old (configured by the lockhold variable) and mailagent will only make lockmax attempts,  spaced  by
       lockdelay  seconds to acquire the lock. It will then proceed whether or not it got that lock. If you want
       a secure locking policy, make sure lockmax times lockdelay is greater than lockhold, that parameter being
       "large" enough.

   Avoiding Loops
       The mailagent leaves an "X-Filter:" header on each filtered message, which in  turn  is  used  to  detect
       loops.  If  a  message  already filtered is to be processed, the mailagent enters a special state _SEEN_.
       This state is special in the sense it is built-in, it is not matched by ALL, and  some  actions  are  not
       made  available,  namely:  BACK, BOUNCE, FEED, FORWARD, GIVE, NOTIFY, PASS, PIPE, POST, PURIFY, QUEUE and
       RUN. Also note that although the ONCE and SELECT constructs are enabled, they will not  let  you  execute
       disallowed  commands.  Otherwise, the _SEEN_ state behaves like any other state you can select or negate,
       so a <!_SEEN_> guard will not select the rule when we are in state _SEEN_.

       The _SEEN_ state makes it easy to deal with mails which loop because of an alias loop you have no control
       on. If no action is found in the _SEEN_ state, the mail is left in the mailbox, as usual. Moreover, if no
       saving is done, a LEAVE is executed. This is the normal behavior.

       The "X-Filter:" header is only added when the message is saved. Actions such as PIPE or GIVE do not  flag
       the  message as being saved and therefore they do not add that header line.  You can add one via ANNOTATE
       if you wish to prevent loops, in case the program to which you are feeding the message might return it to
       you in some strange way.

   Message Files
       The text of the message to be sent back (for MESSAGE or NOTIFY) is read from a file  and  passed  through
       the  macro  substitution  mechanism. The special macro %T is set to the date of last modification made on
       that file. The format is month/day, and the year is added before the month only if it  differs  from  the
       current year.

       At  the  head  of  the message, you may put header lines. Those lines will overwrite the default supplied
       lines. That may be useful to change the default subject or add some additional fields like  the  name  of
       your  organization.   The end of your header is given by the first blank line encountered.  If the top of
       the message you wish to send looks like a mail header, you may protect it by adding a blank line  at  the
       very top of the file. This dummy line will be removed from the message and the whole file will be sent as
       a body part.

       Here  is  an  example of a vacation file. We add a carbon copy as well as the name of our organization in
       the header:

            Cc: ram
            Organization: %o
            Precedence: bulk

            [Last revision made on %T]

            Dear %N:

            I've received your mail regarding "%R".
            It will be read as soon as I come back from vacation.

            Sincerely,
            --
            %U <%u@%C>

VACATION MODE

       When it's time to take some vacation, it is  possible  to  set  up  mailagent  in  vacation  mode.  Every
       vacperiod,  the  message vacfile will be sent back to the user (with macros substitutions) if the user is
       explicitly listed in the To or Cc field and if the sender is  not  a  special  user  (root,  uucp,  news,
       daemon,  postmaster,  newsmaster,  usenet, Mailer-Daemon, Mailer-Agent or nobody).  Matches are done in a
       case insensitive manner, so MAILER-DAEMON will also be recognized as a special  user.   Furthermore,  any
       message  tagged  with  a Precedence: field set to bulk, list or junk will not trigger a vacation message.
       This built-in behavior can of course be overloaded by suitable rules (by testing and issuing the vacation
       message yourself via MESSAGE).

       Internally, mailagent uses a ONCE command tagged (%r, vacation, $vacperiod). This implies  you  must  not
       use the vacation tag in your own ONCE commands, unless you know what you are doing.

       Besides,  the  vacation  message  is  sent  only if no "VACATION off" commands were issued, or if another
       "VACATION on" overwrote the previous one. Note that whether a rule matched or not is  irrelevant  to  the
       algorithm.  By  default,  of  course,  the  vacation  message  is allowed when the vacation configuration
       parameter is set to on.

       If you are not pleased by the fact that a vacation message is sent to people who addressed you  a  carbon
       copy only, then you may write at the top of your rule file:

            Cc: ram  { VACATION off; REJECT };

       Of course, you have to substitute your own login name in place of ram.  You cannot use the same scheme to
       allow  vacation  messages to special users like root, because the test for "specialness" occurs after the
       vacation mode flag. This is construed as a feature as it prevents stupid mistakes, like using r*  instead
       of ram in the previous rule.

       You may also want to setup a different vacation message, meant only for people in your organization given
       the sensitive nature of the information revealed ;-).  A simple way of doing that is:

            From: /^\w+$/, /^\w+@\w+$/, /^[\w.-]+@.*\.hp\.com$/i
                 { VACATION ~/.hp_vacation 1w; REJECT HP };

       Assuming  the  domain  of  my  organization is .hp.com and that messages not bearing any domain are local
       messages, the above rule sets up the file ~/.hp_vacation, sent once a week, for all HP employees.

       The VACATION command will not let you change the message path (but will allow frequency  changes  anyway)
       when  the vacfixed configuration variable is set to ON. This is meant to be used in emergency situations,
       when only one vacation message will fit. For instance, when you are on a sick  leave,  a  simple  trigger
       message  to  your  mailagent  from  home  could  change  your  ~/.mailagent  configuration  to  force the
       ~/.i_am_sick message, regardless of what the various rules have to say. Actually, this is  precisely  why
       this feature was added, amazing... :-)

VARIABLES

       The  following  variables are paid attention to: they may come from the environment or be set in the rule
       file:

       mailfilter
                 indicates where loaded patterns are to be looked for, if the name of  the  file  is  not  fully
                 qualified.  If  it  is not set, maildir will be used instead. If maildir is not set either, the
                 home directory is used.

       maildir   is the location of your mail folders. Any relative path is understood as starting from maildir.
                 If it is not set, ~/Mail is used.

       Those variables remain active while in the scope of the rule file.  Should an alternate rule file be used
       (via rules hook or the APPLY command), the current values are propagated  to  the  new  rule  set  unless
       overridden  in  the  alternate  rule  file.  In  any case, the previous value is restored when control is
       transferred back to the previous set of rules. That  is,  those  variables  are  dynamically  instead  of
       statically scoped.

AUTOMATIC ACKNOWLEDGMENTS

       Anywhere  in  the mail, there can be an @RR left-justified line which will send back an acknowledgment to
       the sender of the  mail.  The  @RR  may  optionally  be  followed  by  an  address,  in  which  case  the
       acknowledgment  will  be sent to that address instead.  In fact (but let's keep that a secret), this is a
       way for me to be able to see who runs my mailagent program and who doesn't...

       The sendmail program usually implements such a feature via a Return-Receipt-To: header line, which  sends
       the  whole  header  back upon successful delivery. However, this is not implemented on all mail transport
       agents, and @RR is a good alternative :-).

NOTA BENE

       Throughout this manual page, I have always written header fields with  the  first  letter  of  each  word
       uppercased,  as  in Return-Receipt-To. But RFC-822 does not impose this spelling convention, and a mailer
       could legally rewrite the previous field as return-receipt-to (and in fact so does sendmail  in  its  own
       private mail queue files).

       However,  you  must  always  specify  the  headers in what could be called a normalized case (for headers
       anyway). The mailagent will correctly recognize cc:, CC: or Cc: in a mail message and will allow  you  to
       select  those fields via the normalized Cc: selector. In fact, it operates the normalization for you, and
       a cc: selector would not be recognized as such. Of course, no physical alteration is  ever  made  on  the
       header itself.

       This  is  also  true  for  headers specified in the STRIP or KEEP command. If you write STRIP Cc, it will
       correctly remove any cc: line. Likewise, if you use regular expressions  to  specify  a  selector,  Re.*:
       would  match  both  original received: and Return-path: fields, internally known through their normalized
       representation.

MAIL HOOKS

       The mail hooks allow mailagent to transparently invoke some scripts or perform further processing on  the
       message.  Those  hooks  are  activated  via the SAVE, STORE or LEAVE commands. Namely, saving in a folder
       whose executable bit is set will raise a special processing. By default, the folder is taken as a program
       where the mail should be piped to. If the "folder" program returns a zero status,  then  the  message  is
       considered  saved  by  the  mailagent.  Otherwise, all the processing attached to failed save commands is
       started (including emergency saving attempts). Executable folders provide a  transparent  way  (from  the
       rule file point of view) to deal with special kind of messages.

       In  fact,  five  different  types of hooks are available. The first one is the plain executable folder we
       have just spoken about. But in fact, here is what  really  happens  when  a  saving  command  detects  an
       executable  folder:  the  mailagent scans the first line of the folder (in fact, the first 128 bytes) and
       looks for something starting with #: and followed by a single word, describing a special  kind  of  hook.
       This  is  similar in the way the kernel deals with the #! hook in executable programs.  If no #: is found
       or #: is followed by some garbage, then mailagent decides it is a  simple  program  and  feeds  the  mail
       message to this program. End of the story.

       But  if the #: token is followed (spaces allowed, case is irrelevant) by one of the following words, then
       special actions are taken:

       rules     The file holds a set of mailagent rules which are to be applied. A  new  mailagent  process  is
                 created  to  actually  deal  with  those and the exit status is propagated back to the original
                 mailagent.

       audit     This is similar in spirit to what Martin Streicher's audit.pl package does, hence the  name  of
                 this  hook.  The special variables which are set up by the PERL filter commands are initialized
                 and the script is loaded in the special mailhook package name space, which also  gives  you  an
                 interface to the mailagent's own routines.  You may safely use the exit function here, since an
                 extra fork is done. This is the only difference between an audit and a perl hook.

       deliver   Same  thing  as  for  the  audit  hook,  but the standard output of your script is monitored by
                 mailagent and understood as mailagent filtering commands.  Upon successful return, a  mailagent
                 process  will  be  invoked  to  actually  execute those commands on the message. Again, this is
                 similar in spirit to Chip Salzenberg's deliver package and gave the name of this hook.

       perl      This hook is the same as audit but it is executed without forking a new mailagent, and you have
                 the perl interface to mailagent's filtering commands. There is  no  difference  with  the  PERL
                 command,  because  it  is  implemented  that  way,  by calling a mailagent and forcing the PERL
                 command to be executed. This is similar in spirit to Larry Wall's famous perl language  and  it
                 is responsible for the name of this hook :-).

       As  mentioned  earlier in this manual page, the hook is invoked from with the home directory specified in
       your ~/.mailagent (which may differ from your real home directory, as far as mailagent  or  mailhook  are
       concerned).

       For those hooks which are finally ran by perl, the special @INC array has mailagent's own private library
       path prepended to it, so that require first looks in this place.

FOLDERS

       A  folder is a file or a directory which can be the target of a delivery by the mailagent, that is to say
       the argument of SAVE-like commands.

   Folder Format
       By default, mails are written into folders according to the standard UNIX-style mailbox format: each mail
       starts with a leading From line bearing the sender's address and the date. However, by setting  the  mmdf
       parameter  from  the ~/.mailagent to ON, the mailagent will be able to save messages in MMDF format: each
       message is sandwiched between two lines of four Ctrl-A characters (ASCII code 1)  and  the  leading  From
       line is removed.

       When  MMDF  mode  is  activated,  each  folder will be scanned to see if it is a UNIX-style or MMDF-style
       mailbox and the message will be saved accordingly.  When saving to a new folder, the default is to create
       a UNIX-style mailbox, unless the mmdfbox configuration variable was set to ON, in  which  case  the  MMDF
       format prevails.

       Note  that  the MMDF format is also the standard for MH packed folders, so by enabling the MMDF mode, you
       can actually deliver directly to those packed folders. The MH command inc is  able  to  incorporate  mail
       from  either form anyway, i.e. it does not matter whether the folder is in UNIX format (also called UUCP-
       style) or in MMDF format.

       MH-style folders are also supported. It is mainly a directory in which messages are stored in  individual
       files.  To  save directly into an MH folder, simply prefix the folder name with '+', just as you would do
       with MH commands.  The unseen sequences specified in your MH profile (the  mhprofile  parameter  in  your
       ~/.mailagent, default is ~/.mh_profile) will be correctly updated, as rcvstore would.

       When the target folder is a directory, mailagent attempts the delivery in an individual numbered file. If
       a  prefix file is present (config parameter msgprefix, default is .msg_prefix), its first line is used to
       specify the base name of the message, then a number is appended to give the name of the message  file  to
       use. That is, if there is no such file, the folder will look like an MH one, without any MH sequence file
       though.

   Folder Compression
       If  you  have  one or more of the widely available file compression utilities such as compress or gzip in
       your PATH (as set up by ~/.mailagent), then you may wish to use folder  compression  to  save  some  disk
       space,  especially  when  you  are  away  for  some  time  and  do  not want to see your mail fill-up the
       filesystem.

       To achieve folder compression, you have to set up a file,  referred  to  by  the  compress  configuration
       variable.  This  file  must list folder names, one per line, with blank lines ignored and shell-style (#)
       comments allowed. You may use shell-style patterns  to  specify  the  folders,  and  the  match  will  be
       attempted  on  the  full  pathname of the folder (~ substitution occurs). If you do not specify a pattern
       starting with a leading '/' character, then the match will be attempted on the  basename  of  the  folder
       (i.e. the last component of the folder path). If you want to compress all your folders, then simply put a
       single '*' inside this file.

       Mailagent  uses  the  filename  extension  to  determine what compression scheme is used for a particular
       folder.  The file referred to by the compspecs configuration variable (default is $spool/compressors)  is
       used  to  define  the  commands  that  mailagent  will  use  to perform the compress, uncompress, and cat
       operations for a particular extension.

       The compressors file holds lines of the following form:

            tag extension compression_prog uncompress_prog cat_prog

       where:

       tag       is the logical name for the compression scheme.  This is typically the same as the name of  the
                 program  used  to  provide  the compression, but could be different for some unforeseen reason.
                 This must be unique across all records in the file.

       extension is the extension to recognize as belonging to the specified tag.  This must  be  unique  across
                 all records in the file.

       compression_prog
                 is  the  name  of  the  command  to  run  to  compress  a folder.  The program must replace the
                 uncompressed file with the compressed one with the extension appended  to  the  filename  (like
                 compress or gzip).

       uncompression_prog
                 is  the  name  of  the  command  to  run  to uncompress a folder.  The program must replace the
                 compressed file with the uncompressed one without the extension (like uncompress or gunzip).

       cat_prog  is the name of the command to output the uncompressed contents of a compressed folder to stdout
                 (like zcat or gzcat).

       The fields are separated by TABS to allow for the use of space characters in the command fields.

       If the file referred to by the compspecs configuration variable cannot be accessed for whatever reason, a
       default entry is hard-wired into mailagent (knows about both compress and gzip programs):

            compress <TAB> .Z <TAB> compress <TAB> uncompress <TAB> zcat
            gzip <TAB> .gz <TAB> gzip <TAB> gunzip <TAB> gunzip -c

       If you wish to add more compressors, you can copy the default compressors file from  mailagent's  private
       library directory and setup a correct entry for your alternate compressor. Keep in mind that the trailing
       extension  needs  to be unique amongst all the listed programs, since that extension is used to determine
       the type of compression performed on the folder.

       If the folder is created without any existing compressed form around, a default  compressor  is  selected
       for  you,  as defined by the comptag configuration variable. That refers to the tag name of the compspecs
       file, i.e. the first word on the line (usually the name of the compression program, but not necessarily).

       When attempting delivery, mailagent will check the folder name  against  the  list  of  patterns  in  the
       compress  file.  If  there  is  a  match,  the  folder  is flagged as compressed. Then mailagent attempts
       decompression if there is already a compressed form (ie. the file has a  recognized  filename  extension)
       and  if  no uncompressed form is present.  Delivery is then made to the uncompressed folder. However, re-
       compression is not done immediately, since it is still possible to get  messages  to  that  folder  in  a
       single  batch  delivery.  Should  disk  space  become  so  tight  that  decompression of other folders is
       impossible, mailagent will re-compress the folders it has already uncompressed. Otherwise, it waits until
       the last moment.

       If for some reason there is a compressed folder which cannot be decompressed, mailagent will deliver  the
       mail  to  the  plain  folder.  Further delivery to that folder will be faced with both a compressed and a
       plain version of the folder, and that will get you a warning in the log file, but delivery will  be  made
       automatically to the plain file.

       On  newly  created  folders the comptag configuration variable is referenced to determine the compression
       type to use for the folder.

MAIL BIFFING

       If you are receiving and processing mail on your own machine, then you have access to local mail  biffing
       where mailagent can warn you about new messages and tell you about where they have been saved, printing a
       small subset of the header and the first few lines of the body.

       To use biffing, all you need is the setting of the few biff parameters in your ~/.mailagent and make sure
       biff  is  set  to ON. Actually, this is the only parameter you need to set to get minimal default biffing
       behaviour. Don't forget to run the shell command "biff  y"  on  the  terminals  where  you  want  to  get
       notification (you may do that on several ttys, one for each virtual display for instance).

       Upon  mail  reception  and  saving  on a folder or posting to a newsgroup, mailagent locates all the ttys
       where you are logged on, then selects those where biffing was requested, finally emitting a  message  and
       making a beeping sound (if your terminal supports this and you are using the standard format--see below).

   Customizing Biffing Output
       Should  the default format not suit your needs, you may customize the biffing message freely, setting the
       biffmsg parameter to point to the file where the format is stored. Standard macros substitutions will  be
       performed on your message, the following macro set superseding and completing the standard set:

       %-A       Same as writing %-H, new line, %-B
       %-B       The  body  part of the biffing message, with content-transfer-encoding removed.  If the message
                 is a MIME multipart one, the text/plain part is shown.  If only a text/html part is  available,
                 the HTML markup is stripped for biffing.
       %-H       The header part of the biffing message. If shows only From:, To: Subject: and Date: headers, or
                 whatever  you  have  set  the biffhead configuration variable to. All headers are showed as one
                 line of text, regardless of their actual length. There will be three trailing dots at  the  end
                 to  signal that truncation occurred.  For a news article (biffing after a POST -b), the To: and
                 Cc: fields are never shown, even if specified in biffhead.
       %-T       Same as %-B, but trimming is activated. The purpose  of  trimming  is  to  remove  any  leading
                 quotation  in  the  message,  to  get  only the most meaningful part.  This assumes the quoting
                 character is a single non-alphanumeric  character.   The  leading  attribution  line  that  may
                 introduce  the quotation can be also removed, and a minimum length for the quotation can be set
                 in the configuration file.
       %B        The relative path under %d of the message folder, full  path  (%p)  if  not  saved  under  that
                 directory.  The newsgroup name for news articles.
       %D        The  directory  where the message is stored. If an MH folder, this is the folder full path. The
                 home directory is replaced by a ~.  Empty for news articles.
       %F        The base name (last path component) of the message. For an MH  message,  this  is  the  message
                 number.  Empty for news articles.
       %P        The  folder  path. It has the correct semantics for MH and directory folders, i.e. it points to
                 the folder directory itself. Otherwise, the same as %p.
       %a        Alarm characters (^G).  May expand to more than one under the control  of  the  BEEP  filtering
                 command. Use %b if you only want a single bell.
       %b        A beeping character (^G).  As opposed to %a, this only expands to give one bell.
       %d        Full path where folders such as the one being saved into are stored if not qualified (i.e. your
                 MH path for MH folders, of something like ~/Mail for other folders).  Empty for news articles.
       %f        Folder  where  mail  was  saved,  home replaced by ~ for short.  The newsgroup when article was
                 posted for news.
       %m        A '+' sign if the folder is an MH one, empty otherwise.
       %p        The full path name (same as %f) of the message, but without any ~ shortcut.  The newsgroup name
                 for news articles.
       %t        The type of message: usually "mail", but set to "article" for biffing after a POST command.

       You can get the standard macro expansion by using %:f for instance, since the %f macro is superseded. The
       %: form lets you obtain the standard macro definition anyway, no  matter  what,  so  you  don't  have  to
       remember  whether  a  given  macro  is superseded in this context or not.  Besides, it is safer since new
       macros may be added here without notice.  Note that macros related to the message content all start  with
       %- and therefore are not conflicting with standard one.

       Here is the format you need to use to get the same behaviour as the default hardwired format:

            %b
            New %t for %u has arrived in %f:
            ----
            %-A
            ----%b

       Note  that  the  string ...more... appears at the end of the body when it has not been completely printed
       out on the screen and the remaining lines are not blank or similar.

   Trimming Leading Quotation
       It is a standard practice, when replying to a message, to include  an  excerpt  of  the  sentences  being
       replied-to, using a non-alphanumeric character such as '>' to prefix quoted lines. Something like:

            Quoting John Doe:
            > This is quoted material.
            > Another line from John's mail.

            This is part of the reply to John.

       The  leading  "Quoting  ..."  line,  called  the attribution line, is optional and may be missing or take
       another free form.

       However, when biffing, this may be seen as useless noise, especially nowadays where people  freely  quote
       more and more in their replies. Since the biff message only shows the top lines of the message, it may be
       desirable to automatically trim those quoted lines.

       Via  the  %-T  macro  in  the  customized  biff format, you may request trimming of the leading quotation
       material, keeping the attribution line or not, and even replace trimmed material with a notification that
       so many lines have been removed.

       All this customization is done from the ~/.mailagent configuration file, using  the  bifftrim,  bifftrlen
       and biffquote variables.

       You  first  need  to  turn  trimming on by using a customized biff format using the %-T macro. By setting
       bifftrlen to 3, you may request that only quotations of at least 3 lines be trimmed. Turning bifftrim off
       will remove the trimming notification, whilst turning biffquote off will also strip the attribution line,
       when present.

       For instance, assuming the following settings:

            bifftrim : ON
            bifftrlen: 2
            biffquote: OFF

       then the  above  example  would  produce  the  following  biffing  output  (header  of  the  message  not
       withstanding):

            [trimmed 3 lines starting with a leading '>' character & attribution line]
            This is part of the reply to John.

       because  the  blank  line  following  the  quoted material is counted as being part of the quotation. The
       "[trimmed ..]" message can be turned off by setting bifftrim to OFF.

       The trimming algorithm considers the first line of the body to see if it starts with  a  non-alphanumeric
       character.  If it does, then all the following lines starting with that same character, or any blank line
       is removed, up to the first non-blank line starting with another character. Optionally,  the  first  line
       (and that line only) is skipped if the second one starts with a non-alphanumeric character, and the first
       line is taken as being the attribution line.

   Using Compact MH-style Biffing
       The  so-called  MH-style  biffing  is a way of presenting a compacted body where all the lines are joined
       together into a big happy string with successive spaces turned into a single space character.  To  enable
       it, you need to set the biffmh variable to ON.

       Since  this  compacting  is output verbatim on the tty, line breaks will occur randomly and this may make
       reading difficult. You may request an automatic reformatting of the compacted body by turning biffnice to
       ON and the biff output will fit nicely within the terminal.

       To make biffnice really nice, mailagent probes each tty (those where biffing was turned on) for its  size
       and  uses  that  information to drive formatting of the output.  Note that you can set biffnice even when
       biffmh is OFF.  This really helps maximizing the amount of body text displayed.

EXTENDING FILTERING COMMANDS

       Once you've reached the expert level, and provided you have a fair knowledge of perl, you  may  feel  the
       need for more advanced commands which are not part of the standard set. This section explains how you can
       achieve this dynamically, without the need of diving deep inside the source code.

       Once  you  have extended the filtering command set, you may use those commands inside the rule file as if
       they were built-in. You may even choose to redefine the  standard  commands  if  they  do  not  suit  you
       (however,  if  you  wish  to do that, you should know exactly what you are doing, or you may start losing
       some mail or get an unexpected behavior -- this also voids your warranty :-).

       The ability to provide external commands without actually modifying the main source code is, I believe, a
       strong point in favor of having a program written in an interpreted language like perl.  This  of  course
       once  you  have  convinced yourself that it is a Good Thing to customize and extend a program in the same
       language as the one used for the core, meaning usually a  fairly  low-level  language  with  fewer  user-
       friendly hooks.

   Overview
       In order to implement a new command, say FOLD, you will need to do the following:

       •    Write  a  perl  subroutine  to  implement the FOLD action and put that into an external file. Say we
            write the subroutine fold and we store that in a fold.pl file. This is naturally the difficult part,
            where you need to know some basic things about mailagent internals.

       •    Choose where you want to store your fold.pl file. Then check the syntax with perl  -c,  just  to  be
            sure...

       •    Edit the newcmd file (as given by the configuration file) to record your new command. Then make sure
            this  file  is  tightly  protected.  You  must  own  it,  and it should not be writable by any other
            individual but you.

       •    Additionally, you may want to specify whether FOLD is to modify the existing  execution  status  and
            whether or not it will be allowed within the special _SEEN_ state.

       •    Write some rules using the new FOLD command. This is the easy part!  Note that your command may also
            be used within perl hooks as if it were a builtin command (this means there is an interface function
            built for you within the mailhook package).

       In  the following sections, we're going to describe the syntax of the newcmd file, and we'll then present
       some low-level internal variables which may be used when implementing new commands.

   New Command File Format
       The newcmd file consists of a series of lines, each line describing one command. Blank lines are  ignored
       and shell-style comments introduced by the sharp (#) character are allowed.

       Each  line  is  formed by 3 principal fields and 2 optional ones; fields are separated by spaces or tabs.
       Here is a skeleton:

            <cmd_name> <path> <function> <status_flag> <seen_flag>

       The cmd_name is the name of the command you wish to add. In our previous example, it would be  FOLD.  The
       next field, path, tells mailagent where the file containing the command implementation is located. Say we
       store  it  in ~/mail/cmds/fold.pl. The function field is the name of the perl function implementing FOLD,
       which may be found in fold.pl. Here, we named our function fold. Note that if your function has its  name
       within the newcmd package, which is the default behavior if you do not specify any, then there is no need
       to prefix the function name with the package. Otherwise, you must use a fully qualified name.

       The last two fields are optional, and are boolean values which may be specified by true or yes to express
       truth,  and false or no to express falsehood. If status_flag is set to true, then the command will modify
       the last execution status variable.  If seen_flag is true, then the command may be used when  the  filter
       is in _SEEN_ state. The default values are respectively true and false.

       So in our example, we would have written:

            FOLD  ~/mail/cmds/fold.pl  fold  no  yes

       to  allow FOLD even in _SEEN_ state and have it executed without modifying the current value of the last-
       command-status variable.

   Writing An Implementation
       Your perl function will be loaded when needed into the special package newcmd, so that its own name-space
       is protected and does not accidentally conflict with other mailagent routines or variables. When you need
       to call the perl interface of some common mailagent functions, you will have to remember to use the fully
       qualified routine name, for instance &mailhook'leave to actually execute the LEAVE command.

       (Normally, in PERL hooks, there is no need for this prefixing since the perl  script  is  loaded  in  the
       mailhook package. When you are extending your mailagent, you should be extra careful however, and it does
       not  really  hurt  to  use  this  prefixing.  You  are free to use the perl package directive within your
       function, hence switching to the mailhook package in the body of the routine but leaving its name in  the
       newcmd package.)

       Since  mailagent  will  dynamically  load the implementation of your command the first time it is run, by
       loading the specified perl script into  memory  and  evaluating  it,  I  suggest  you  put  each  command
       implementation in a separate file, to avoid storing potentially unneeded code in memory.

       Each  command  is called with one argument, namely the full command string as read from the filter rules.
       Additionally, the special @ARGV array is set by performing a shell-style  parsing  of  the  command  line
       (which  will fail if quotes are mismatched, but then you can do the parsing by yourself since you get the
       command line).  At the end of your routine, you must return a failure status, i.e.  0 for success  and  1
       to signal failure.

       Those  are  your only requirements. You are free to do whatever you want inside the routine. To ease your
       task however, some variables are pre-computed for you, the same ones that are made available within  mail
       hooks,  only they are defined within the newcmd package this time. There are also a few special variables
       which you need to know about, and a set of standard routines you may want to call. Please  avoid  calling
       something  which  is  not documented here, since it may change without prior notice. If you would like to
       use one routine and it is not documented in this manual page, please let me know.

       Each command is called from within an eval construct, so you may safely use die or call external  library
       routines that use die.  If you use require, be aware that mailagent is setting up a special @INC array by
       putting its private library path first, so you may place all your mailagent-related library files in this
       place.

   Special Variables
       The  following  special  variables (some of them marked read-only, meaning you shouldn't modify them, and
       indeed you can't) made available directly within the newcmd package, are pre-set by the filter automaton,
       and are used to control the filtering process:

       $mfile         The base name of the mail file being processed. This variable is read-only.  It is  mainly
                      used in log messages, as in [$mfile] to tag each log, since a single mailagent process may
                      deal with multiple messages.

       $ever_saved    This  is  a  boolean, which should be set to 1 once a successful saving operation has been
                      completed. If at the end of the filtering, this variable is  still  0,  then  the  default
                      LEAVE will be executed.

       $folder_saved  The value of that variable governs the $msgpath convenience variable set for PERL escapes.
                      It  is  updated  whenever  a message is written to a file, to hold the path of the written
                      file.

       $cont          This is the continuation status, a variable of the utmost importance when dealing with the
                      control flow. Four constants from the main package can  be  used  to  specify  whether  we
                      should  continue  with  the  current  rule  ($FT_CONT), abandon current rule ($FT_REJECT),
                      restart filtering from the beginning ($FT_RESTART) or simply abort processing ($FT_ABORT).
                      More on this later.

       $lastcmd       The last failure status recorded by the last command (among  those  which  do  modify  the
                      execution  status).  You  should  not  have  to  update  this  by  yourself unless you are
                      implementing some encapsulation for other commands, like BACK or ONCE,  since  by  default
                      $lastcmd will be set to the value you return at the end of the command.

       $wmode         This records the current state of the filter automaton (working mode), in a literal string
                      form,  typically  modified  by  the  BEGIN  command  or as a side effect, as in REJECT for
                      instance.

       All the special variables set-up for PERL escapes are also installed within the newcmd package. Those are
       $login, %header, etc... You may peruse them at will.

       Other variables you might have a  need  for  are  configuration  parameters,  held  in  the  ~/.mailagent
       configuration  file.  Well,  the rule is simple. The value of each parameter param from the configuration
       file is held in variable $cf'param. Variable $main'loglvl is the copy of  $cf'level,  since  it's  always
       shorter to type in $'loglvl after each call to the logging routine &add_log.

       There  is  one  more variable worth knowing about: $main'FILTER, which is the suitable X-Filter line that
       should be appended in all the mail you send via mailagent, in order to avoid loops. Also  when  you  save
       mails  to  a  folder,  it's  wise  adding  this  line in case a problem arises: you may then identify the
       culprit.

   Rule Environment
       An action might have a legitimate desire of altering the environment for the  scope  of  one  rule  only,
       reverting to the previous value when exiting the rule. Or you might want to change the value forever.

       When  we  speak  about  altering  the environment, we refer to the one set up via the configuration file,
       whose values end-up in the cf package.  Well, some of those variables  are  copied  in  the  env  package
       before filtering of a message starts (under the control of the @env'Env array).

       All  rules  should  then  refer  to  the  version  in  the env package, and not in the cf package, to see
       alterations. Global changes are made by affecting directly to the variable  in  the  env  package,  while
       local changes are requested by calling the &env'local routine.

       For instance, the cf'umask value is copied as env'umask because umask is held in @env'Env. Global changes
       are made by setting that copy directly, while local changes may be made with:

                 &env'local('umask', 0722);

       to  set-up  a  new  local  value.  The  first time &env'local is called on a variable, its value is saved
       somewhere, and will be restored upon exiting the scope of the rule. Then the new value is affected to the
       variable.

       Variables requiring a side effect when their value is changed (such as the umask variable, which requires
       a system call to let the kernel see the change) may specify it by accessing the %env'Spec array, the  key
       being the name of the variable requiring a side effect, the value being interpreted as a bit of perl code
       ran once the original value is restored. For instance, we say somewhere (in &env'init):

                 package env;
                 $Spec{'umask'} = 'umask($umask)';

       to  update  the  kernel view when leaving scope. Note that the side effect is evaluated once the variable
       has recovered its original value, and within the env package.

       Internally, the &analyze_mail routine calls &env'setup before starting its processing to  initialize  the
       env package, and &env'cleanup at the end before returning. Before running the actions specified on a rule
       match,  &apply_rules  calls  &env'restore  to ensure a coherent view of the environment while running the
       actions for that particular rule.

   Altering Control Flow
       When you want to alter control flow to perform a REJECT, a RESTART or an ABORT, you have  three  choices.
       If  you  wish to control that action via an option, the same way the standard UNIQUE does (with -c, -r or
       -a), you may call &main'alter_execution(option, state) giving it two parameters: the  option  letter  and
       the state you wish to change to before altering the control flow.

       You  may  also want to directly alter the $wmode and $cont variables, but then you'll have to do your own
       logging if you want some. Or you  may  call  low-level  routines  &main'do_reject,  &main'do_restart  and
       &main'do_abort to perform the corresponding operation (with logging).

       Remember that the _SEEN_ state is special and directly handled at the filter level, and the filter begins
       in  the  INITIAL state. The default action is to continue with the current rule, which is why there is no
       routine to perform this task.

       The preferred way is to invoke  the  mailhook  interface  functions,  &mailhook'begin,  &mailhook'reject,
       etc...,  and  that  will  work  even  if  you redefine those functions yourself. Besides, that's the only
       interface which is likely not to be changed by new versions.

   General Purpose Routines
       The following is a list of all the general routines you may wish to call when performing  some  low-level
       tasks.  Note  that this information is version-dependent. Since I document them, I'll try to keep them in
       new versions, but I cannot guarantee I will not have to slightly change some of their semantics. There is
       a good chance you will never have to worry about that anyway.

       &header'format(rfc822-field)
                 Return a formatted RFC822 field to fit in 78 columns, with proper continuations  introduced  by
                 eight spaces.

       &header'normalize(rfc822-header-name)
                 Normalize  case  in  RFC822  header  and  return  the  new  header name with every first letter
                 uppercased.

       &header'reset
                 This is part of an RFC822 header validation, mainly used when splitting a digest.  This  resets
                 the recognition automaton (see &header'valid).

       &header'valid(line)
                 Returns  a  boolean status, indicating if all the lines given so far to this function since the
                 last &header'reset are part of a valid RFC822 header.  The function understands the first  From
                 line  which  is  part of UNIX mails.  At any time, the variable $header'maybe may be checked to
                 see if so far we have found at least one essential mail header field.

       &main'acs_rqst(file)
                 Perform a .lock locking on the file, returning 0 on success and -1 on failure.  If an old  lock
                 was  present,  it  is  removed (time limit set to one hour). Use &main'free_file to release the
                 lock.

       &main'add_log(string)
                 Add the string to the logfile. The usual idiom is to postfix that call with the if  $'loglvl  >
                 value,  where  value  is  the  logging  level you wish to have before emitting that kind of log
                 ($'loglvl is a short form for $main'loglvl).

       &main'free_file(file)
                 Remove a .lock on a file, obtained by &main'acs_rqst. It returns 0 if the lock was successfully
                 removed, -1 if it was a stale lock (obtained by someone else).

       &main'header_found(file)
                 Scan the head of a file and try to determine whether there is a mail header at the beginning or
                 not. Return true if a header was found.

       &main'history_record
                 Record the message ID of the current  message  and  return  0  if  the  message  had  not  been
                 previously seen, 1 if it is a duplicate.

       &main'hostname
                 Return  the  value  of the hostname, lowercased, with possible domain name appended to it.  The
                 hostname is cached, since  its  value  must  initially  be  obtained  by  forking.   (see  also
                 &main'myhostname)

       &main'internet_info(email-address)
                 Parse  an  e-mail  internet  address  and return a three-element array containing the host, the
                 domain and the country part of the internet host. For instance, if the address is user@d.c.b.a,
                 it will return (c, b, a).

       &main'login_name(email-address)
                 Parse the e-mail internet address and return the login name.

       &main'macros_subst(*line)
                 Perform in-place macro substitution  (line  passed  as  a  type  glob)  using  the  information
                 currently  held  in  the  %main'Header  array.  Do not pass *_ as a parameter, since internally
                 macros_subst uses a local variable bearing that name to perform the substitutions and you would
                 end up with an unmodified version. If you really want  to  pass  *_,  then  you  must  use  the
                 returned  value from macros_subst which is the substituted text, but that's less efficient than
                 having it modified in place.

       &main'makedir(pathname, mode)
                 Make directory, creating all the intermediate directories  needed  to  make  pathname  a  valid
                 directory.  Has no effect if the directory already exists. The mode parameter is optional, 0700
                 is used (octal number) if not specified.

       &main'myhostname
                 Returns the hostname of the current machine, without any domain name.  The hostname is  cached,
                 since its value must initially be obtained by forking.

       &main'run_command(filter-command)
                 Execute  the  single  filter command specified and return the continuation status, which should
                 normally be affected to the $cont variable. You will need this routine when trying to implement
                 commands which encapsulate other commands, like ONCE or SELECT.

       &main'seconds_in_period(period)
                 Return the number of seconds in the period specified. See section Specifying A  Period  to  get
                 valid period strings.

       &main'shell_command(program, input, feedback)
                 Run  a  shell command and return a failure status (0 for OK). The input parameter may be one of
                 the following constants (defined in the main  package):  $NO_INPUT  to  close  standard  input,
                 $BODY_INPUT  to pipe the body of the current message, $MAIL_INPUT to pipe the whole mail as-is,
                 $MAIL_INPUT_BINARY to pipe the whole mail after having removed  any  content  transfer-encoding
                 and $HEADER_INPUT to pipe the message header. The feedback parameter may be one of $FEEDBACK or
                 $NO_FEEDBACK  depending  whether  or  not  you  wish  to  use  the standard output to alter the
                 corresponding part of the message. If no feedback is wanted,  the  output  of  the  command  is
                 mailed  back  to  the  user.   The  $FEEDBACK_ENCODING  is handled like $FEEDBACK but will tell
                 mailagent to look at the best suitable body encoding when the input is the whole message.

       &main'parse_address(rfc822-address)
                 Parse an RFC822 e-mail address and return a two-elements array containing the internet  address
                 and the comment part of that address.

       &main'xeqte(filter-actions)
                 Execute  a  series  of  actions separated by the ';' character, calling run_command to actually
                 perform the job. Return the continuation status.  Note that $FT_ABORT will never  be  returned,
                 since  mailagent  usually stops after having executed one set of actions, only continuing if it
                 saw an RESTART or a REJECT. What ABORT does is skipping the remaining commands on the line  and
                 exiting  as if all the commands had been run. You could say xeqte is the equivalent of the eval
                 function in perl, since it interprets a little filter script and returns control to the  caller
                 once finished, and ABORT is perl's die.

       You  may  also  use  the  three  functions  from the extern package which manipulate persistent variables
       (already documented in the section dealing with variables) as well as the user-defined macro routines.

   Example
       Writing your own commands is not easy,  since  it  requires  some  basic  knowledge  regarding  mailagent
       internals. However, once you are familiar with that, it should be relatively straightforward.

       Here is a small example. We want to write a command to bounce back a mail message to the original sender,
       the  way  sendmail  does,  with  some  leading  text to explain what happened. The command would have the
       following syntax:

            SENDBACK reason

       and we would like that command to modify the existing status, returning a failure if the mail  cannot  be
       bounced  back.  Since this command actually sends something back, we do not want it to be executed in the
       _SEEN_ state.  Here is my implementation (untested):

            sub sendback {
                 local($cmd_line) = @_;
                 local($reason) = join(' ', @ARGV[1..$#ARGV]);
                 unless (open(MAILER, "|/usr/lib/sendmail -odq -t")) {
                      &'add_log("ERROR cannot run sendmail to send message")
                           if $'loglvl;
                      return 1;
                 }
                 print MAILER <<EOF;
            From: mailagent
            To: $header{'Sender'}
            Subject: Returned mail: Mailagent failure
            $main'FILTER

              --- Transcript Of Session

            $reason

              --- Unsent Message Follows

            $header{'All'}
            EOF
                 close MAILER;
                 $ever_saved = 1;    # Don't want it in mailbox
                 $? == 0 ? 0 : 1;    # Failure status
            }

       Assuming this command is put into ~/mail/cmds/sendback.pl, the line describing  it  in  the  newcmd  file
       would be:

            SENDBACK  ~/mail/cmds/sendback.pl  sendback  yes  no

       Now  this  command  may  be  used freely in any rule, and will be logged as a user-defined command by the
       command dispatcher. Who said it was not easy to do? :-)

       Note the use of the $ever_saved variable to mark the mail as saved once  it  has  been  bounced.  Indeed,
       should  the  SENDBACK action be the only one action to be run, we do not want mailagent to LEAVE the mail
       in the mailbox because it has never been saved (this default behavior being a precaution only  --  better
       safe than sorry).

   Conclusion
       If  along  the way you imagine some useful commands which could be made part of the standard command set,
       please e-mail them to me and I'll consider integrating them. In the future, I would also like to  provide
       a  standard  library  of  perl  scripts to implement some weird commands which could be needed in special
       cases.

       Note that you may also use the information presented here inside the perl escape scripts. Via the require
       operator, it is easy to get the new command implementation into your script and perform  the  same  task.
       You  will  maybe  need  to  set  up  @ARGV  by  yourself  if  you  rely  on  that feature in your command
       implementation.

       Command extension can also be viewed as a way to reuse some other perl code, the  mailagent  providing  a
       fixed and reliable frame and the external program providing the service. One immediate extension would be
       mailing  list  handling,  using  this  mechanism  to interface with some mailing list management software
       written in perl.

GENERIC MAIL SERVER

       One nice thing about mailagent is that it provides you with the basic tools to implement a  generic  mail
       server.  Indeed,  via  the  SERVER command, you can process a mail message, extract and then execute some
       predefined commands.  For instance, you may implement an archive  server,  or  a  mailing  list  manager,
       etc...

       The  major  limitation  currently  is  that  only  plain  commands  are accepted, or commands taking some
       additional info as standard input or equivalent. There is no notion of modes, with separate command  sets
       for  each mode or limited name-space visibility, at least for now, so it is not easy (albeit possible) to
       implement an ftpmail server, for instance, since this implies the notion of mode.

   Overview
       In order to implement a mail server command (say send file, which would send an arbitrary file  from  the
       file system in a separate mail message), you need to do the following:

       •    Think  about  the command from a security point of view. Here, the command we want to implement is a
            potentially dangerous one since it can give access to any file on the machine the individual running
            mailagent has access to.  So we want to restrict that command to a limited number of trusted people,
            who will be granted the power to run this command. More on this later.

       •    Choose whether you want to implement the command in perl or in another programming language. If  you
            do  the latter, your command will be known as a shell command (i.e. a command runnable directly from
            a shell), while in the former case, you have the choice of making it appear as a shell  command,  or
            have it hooked to the mailagent in which case it is known as a perl command. In that last case, your
            command  will be dynamically loaded into mailagent with all the advantages that brings you. Here, we
            are going to write our command as a shell script.

       •    Write the command itself. That's the most difficult part in this scheme.  Later on, we  will  see  a
            straightforward implementation of the send command.

       •    Edit  the  comserver  file (defined in your ~/.mailagent) to record your new command. Then make sure
            this file is tightly protected.  You must own it, and be the only one allowed to modify it.

       •    Additionally, you may want to hide some of the arguments in the session  transcript  (more  on  this
            later),  allow  the  command  to  take  a  flow  of data as its standard input, assign a path to the
            command, etc...  All those parameters take place in your comserver file.

       •    Start using the command... which of course is the nicest part in this scheme!

       In the following sections, we'll learn about the syntax of the comserver file, what powers are,  how  the
       session transcript is built, what the command environment is, etc...

   Builtin Commands Overview
       The  mail  server  has  a  limited  set of builtin commands, dealing with user authentication and command
       environment settings. User authentication is password based and is not extremely strong  since  passwords
       are specified in clear within the mail message itself, which could be easily intercepted.

       The  server  maintains  the notion of powers. One user may have more than one power at a time, each power
       granting only a limited access to some sensitive area. A few powers are hardwired in the server, but  the
       user  may  create  new  ones when necessary. Those powers are software-enforced, meaning the command must
       check for itself whether is has the necessary power(s) to perform correctly.

       Powers are protected by a password and a clearance file. Having the good password is not enough, you have
       to be cleared in order to (ab)use it. The clearance file is a list of e-mail address patterns, using  the
       shell metacharacters scheme, someone being cleared if and only if his e-mail address matches at least one
       of  the  patterns  from the clearance file. The more use you will make of metacharacters, the weaker this
       clearance scheme will be, so be careful.

       Your commands and the output resulting from their execution is normally mailed back to you as  a  session
       transcript.  For security reasons, passwords are hidden from the command line. Likewise, failure to get a
       power will not indicate whether you lacked authorization or whether your password was bad.

       A user with the system power is  allowed  to  create  new  powers,  delete  other  powers,  change  power
       passwords,  and  list, remove or change power clearances. This is somehow an important power which should
       be detained by a small number of users with very strict clearance (no meta-characters in the address,  if
       possible). A good password should also protect that power.

       However, a user with the system power is not allowed to directly get another power without specifying its
       password and being allowed to do so by the associated clearance file. But it would be possible to achieve
       that  indirectly  by removing the power and creating a new one bearing the same name. In order to control
       people with the system power and also for some tricky situation, there is another  more  god-like  power:
       the root power.

       A  user  with the root power can do virtually anything, since it instantly grants that individual all the
       powers available on the server (but security). The only limitation is that root cannot  remove  the  root
       power  alone.  One  needs to specify the security password (another hardwired power) in order to proceed.
       Needless to say, only one individual  should  have  both  root  and  security  clearance,  and  only  one
       individual should know the security password and be listed in the clearance file. The system power cannot
       harm  any of those two powers. Eventually, more than one user could have the root power, but do not grant
       that lightly...

       Getting the root power is necessary when system has messed with the system configuration in  an  hopeless
       way,  or  when  a  long  atomic sequence of commands has to be issued: root is not subject to the maximum
       number of command that can be issued in one single message.

       In case you think this mailagent feature is dangerous for your  account,  do  not  create  the  root  and
       security powers, and do not write any sensitive commands.

   Builtin Commands Definition
       Now let's have a look at those builtin commands. Passwords of sensitive commands will be concealed in the
       session transcript. Some commands accept input by reading the mail message up to the EOF marker, which is
       a simple EOF string on a line by itself (analogous with shell's here documents).

       addauth power password
                 Add  users  to  clearance  file  for power. If the power password is given, no special power is
                 needed, otherwise the system power is required.  For root or security powers, the corresponding
                 power is required, or the password must be specified. The command reads the standard  input  up
                 to the EOF marker to get the new users.

       approve password command
                 Records  the  password  in  the  command environment, then executes the command.  If a power is
                 required and not yet obtained, the command will look for the password in  the  environment  and
                 try  to  get  the  relevant  power  using  that  password. Hence, approved command (with proper
                 password) will transparently execute without the hassle of requesting the  power,  issuing  the
                 command  and  then releasing the power. It is up to the command to perform the approve password
                 test by looking at the approve variable in the command environment (see below). Since clearance
                 checks (such as those performed when requesting  a  power)  are  not  performed,  no  sensitive
                 command should ever deal with the approve construct.

       delpower power password [security]
                 Delete a power from the system, and its associated clearance list. The system power is required
                 to  delete  most  powers  except  root  and security. The security power may only be deleted by
                 itself and the root power may only be deleted when the security password is also specified.

       getauth power password
                 Get current clearance file for a given power. No special power  required  if  the  password  is
                 given  or  the  power is already detained. Otherwise, the system power is needed for all powers
                 but root or security where the corresponding power is mandatory.

       newpower power password [alias]
                 Add a new power to the system. The command then reads the standard mail  input  until  the  EOF
                 marker  to  get  the  power clearance list. The system power is required to create a new power,
                 unless it's root or security: The security power is required to create root and the root  power
                 is required to create security.

       passwd power old new
                 Change power password. It does not matter if you already hold the corresponding power, you must
                 give the proper old password. See also the password command.

       password power new
                 Change  power  password.  The  corresponding  power  is required, or you have to get the system
                 power. To change the root or security passwords, you need the corresponding power.

       power name password
                 Ask for a new power. Of course, root does not need to request for any other power but security,
                 less give any password. This command is not honored when the server is  not  in  trusted  mode,
                 unbeknownst  to the user: the error message in the transcript file is no different from the one
                 obtained with an invalid password.

       powers regexp
                 List all the powers matching the perl regular expression, along with their respective clearance
                 file. The system power is required to get the list.  The root or security power are required to
                 get access to the root or security information, respectively.  If no arguments are  given,  all
                 the powers are listed.

       release power
                 Get rid of some power.

       remauth power password
                 Remove users from clearance file, getting the list by reading the standard mail input until the
                 EOF  marker. This command does not require any special power if the proper password is given or
                 if the power is already detained.  Otherwise, the system power is needed. For root and security
                 clearance, the corresponding power is needed as well.

       set variable value
                 Set the variable to the corresponding value. Useful to alter internal variables  like  the  EOF
                 marker  value,  or  change some command environment.  The user may define his own variables for
                 his commands.  For flag-type variable, a value of on, yes or true sets the variable to  1,  any
                 other  string  sets  it  to  0 (false).  Used all by itself as set, the list of all the defined
                 variables along with their respective values is returned.

       setauth power password
                 Replace power clearance file with one obtained from standard mail input up to the EOF mark. The
                 system power is needed unless you specify the proper password or the power is already yours. As
                 usual, root or security clearances can only be changed when the power is detained.

       user [e-mail [command]]
                 Execute command by assuming the e-mail identity specified. Powers are lost while executing  the
                 command.  The  e-mail  identity  may be checked by the command itself, which may impose further
                 restrictions on the execution, like getting user-defined powers. Note that  this  command  only
                 modifies  the global environment, and that it's up to the command implementation to make use of
                 that information. If no command is specified, the new identity  is  assumed  until  changed  by
                 another  user  command and all the powers currently held by the user are released. If no e-mail
                 address is given, the original user ID is restored.

   Command Environment
       There are six types of commands and variables that can be specified in server mode. Two of them, end  and
       help types are special and handled separately. Two types var and flag refer to variables and the last two
       types perl and shell refer to commands.

       Whenever  mailagent  fires a server command, it sets up an environment for that command: if it is a perl-
       type command, then a set of perl variables are set before loading the command;  if  it  is  a  shell-type
       command, some environment variables are initialized and file descriptor #3 is set up to point directly to
       the mailagent session transcript.

       A  shell-type  command  is  forked, whilst a perl-type command is loaded directly in mailagent within the
       cmdenv package. This operates much like the PERL filtering command, only the target package differs and a
       distinct set of variables is preset.

       Some commands collect additional data up to an end-of-file marker (by default the string EOF on a line by
       itself) and those data are fed to shell commands via stdin and to perl commands via the @buffer  variable
       set up in the environment package named cmdenv (in which the command is loaded and run).

       If you define your own variables (types var or flag), you may use the builtin set command to modify their
       values.  Note that no default value can be provided when defining your variable. A suitable default value
       must be set within commands making use of them, with the advantage that different default values  may  be
       used by different commands.

       The  following environment variables are defined. Most are read-only, unless notified otherwise, in which
       case the builtin set command may be used on them.

       approve   The approve password for approve commands, empty if not within a builtin approve construct.

       auth      A flag set to true when a valid envelope was found in the mail  message.   When  this  flag  is
                 false, the server cannot be put in trusted mode.

       cmd       The command line, as written in the message.

       collect   Internal flag set to true while collecting input from a here-document.  It is normally reset to
                 false before calling the command.

       debug     True when debug mode is activated (may be set).

       disabled  A  comma  separated list of disabled commands, with no space between them.  This is initialized
                 when the SERVER command is invoked and the -d option is used.

       eof       The current end-of-file marker for here-document commands. By default  set  to  'EOF'  (may  be
                 changed).

       errors    Number of errors so far.

       jobnum    The job number assigned to the current mailagent.

       log       What was logged in the transcript, with some args possibly concealed.

       name      The command name.

       pack      Packing mode for file sending (may be set).

       path      Destination address for file sending or notification (may be set).

       powers    A colon (:) separated list of powers the user currently has successfully requested and got.

       requests  Number of requests processed so far.

       trace     True when shell commands want to be traced in transcript (may be set).

       trusted   True  when  server  is  in  trust mode, where powers may be gained. This is activated by the -t
                 option of the SERVER command, provided a valid mail envelope was found.

       uid       Address of the sender of the message, where transcript is to be sent. By  extension,  the  real
                 user ID for the server, which is the base of the power clearance mechanism.

       user      The  effective user ID, originally the same as the uid, but may be changed via the user builtin
                 command.

   Session Transcript
       A session transcript is mailed back automatically to  the  user  who  requested  a  server  access.  This
       transcript  shows  the  commands ran by the user and their status: OK or FAILED. Between those two lines,
       the transcript show any output  explicitly  made  by  the  command  to  the  transcript.  Typically,  the
       transcript  may be used to forward error messages back to the user, but even commands executing correctly
       may want to issue an explicit message, stating what has just been done.

       A perl command may access the transcript via the MAILER file  handle,  defined  in  the  cmdenv  package,
       whilst a shell command may access it via its file descriptor #3.

       Note that the session transcript is mailed to the sender of the message, i.e. whoever the envelope header
       line says it is. As far as the server is concerned, this e-mail address is used as the user ID, just like
       a plain login name can be thought of as the user id. For sensitive commands, authentication based on that
       information  is  really  weak.  A more "secure" authentication is provided by the server powers, which is
       password-based. Unfortunately, the clear password has to be transmitted in the message itself  and  could
       be eavesdropped.

   Recording New Commands and Variables
       Server  commands and variables are defined in the comserver file defined in your ~/.mailagent. The format
       of the file is that of a table with items on a row separated by tabs characters. Each  line  defines  one
       command  or  variable.  Any irrelevant field may be entered as a single '-' (minus) character. The format
       allows for shell-style (#) comments.

       Each row has the following fields:

            name type hide collect-data path extra

       where:

       name           is the name of the command or variable as recognized by the server.

       type           is one of perl, shell, var, flag, help or end.

       hide           indicates which arguments in the command are to be hidden (the command name being argument
                      zero) in the session transcript. Use '-' if no arguments need  to  be  hidden.  Typically,
                      this  is  used  to  hide clear passwords in commands.  If more than one argument has to be
                      hidden, then a list of numbers separated by a ',' (comma) may be specified, with no spaces
                      between them. For instance '2,4' would hide arguments 2 and 4 in the transcript.

       collect-data   is a flag (specify as either 'y' or 'n', but you may use complete  words  'yes'  or  'no')
                      indicating  whether  the command collects additional data in a here-document until the EOF
                      marker. Alternatively, you may specify '-' in place of 'n'.

       path           specifies the path of the command (~name substitution allowed). If not relevant (e.g. when
                      defining a variable) or when you want to leave it blank, use '-'.   If  a  blank  path  is
                      specified for a perl or shell command, then the implementation of that command is expected
                      to  be  found  in  servdir,  as  defined  in  ~/.mailagent. If the command name is cmd for
                      instance, then perl command are expected there in a file  named  cmd  of  cmd.pl,  whereas
                      shell  commands  are  expected to be found in a cmd of cmd.sh file. Note that a command is
                      disabled if it cannot be located at the time the comserver file is parsed.

       extra          is any extra parameter needed for the command. Unlike other fields, this  should  be  left
                      blank  if  not  needed.  Anything up to the end of the line is grabbed by this field. Perl
                      commands should specify the name of the perl function to call to execute the  command;  if
                      none  is  specified, the name of the command itself is called. Shell commands may use that
                      field to supply additional options, which will be inserted right after  the  command  name
                      and before any other user-supplied arguments. Others should leave this alone.

   Special Command Types
       There are currently two special command types.

       The  simplest  is  the end type. This is used to specify commands which may end the server processing. By
       default, processing continues until the end of the file is reached  or  a  signature  delimiter  '--'  is
       found.  For  instance,  you may wish to define the command quit and give it the end type.  As soon as the
       server reaches that command, it aborts processing and discards the remaining of the message.

       The help type is usually attached to an help command and prints help on a command basis,  help  for  each
       command being stored under the helpdir variable (defined in your ~/.mailagent) in a file bearing the same
       name  as  the  command  itself. For example, assuming a command shoot, its help file would be expected in
       helpdir/shoot. If no file is found there, mailagent looks in its  public  library  (/usr/share/mailagent)
       for an help file.  Help is provided only when the help file exists and is not zero-sized.

   Creating the Root Power
       In  order  to  bootstrap  the server, you need to create the root power. All the other powers may then be
       created by using the server interface, which ensures consistency and logs your actions. If you don't plan
       using powers at all, you may skip that section.

       First, you need to pick up a good password for the root  power.  Someone  with  the  root  power  can  do
       virtually anything with the server, so be careful. Let's assume you choose root-pass as a password.

       Edit passwd (defined in your ~/.mailagent) and add the following line:

            root:<root-pass>:

       i.e.  enter  the  password in clear between '<' and '>'. It won't stay in that form for long, but this is
       the easiest way to bootstrap it. Protect the passwd file tightly (read-write permissions only  for  you).
       Then create a powerdir/root file, protect it the same way and add your e-mail address to it, on a line by
       itself. That must be the address that will show up in the From: line of your mails. Since clearance files
       support  shell-style  patterns,  you  may  use  login@*domain.top to allow mails from your login from any
       machine in your domain.

       You are almost done. Now simply issue the following command:

            mailagent -i -e 'SERVER -t'

       and feed its standard input with:

            From your e-mail address
            From: your e-mail address

            power root root-pass
            password root root-pass
            ^D

       Note that the first From line is mandatory here, since it's  the  envelope  on  which  authentication  is
       based. Since we're feeding mailagent with an handcrafted message, we must provide a valid envelope or the
       server will not switch into trusted mode...

       The side effect of re-instantiating your password will be to crypt it in the passwd file, so that anybody
       looking at that file cannot guess your root password, hopefully.

       Once  you  have  a valid root power installed, you may create the system power by using newpower. Further
       powers may then be created and deleted using the system power only.

       You should also create the security power and give it a different password than the root  password.  This
       is  really  needed  only  if  you  wish to remotely administrate the server. If you have local access and
       things get corrupted, it's always possible to  change  the  root  password  manually  by  repeating  this
       bootstrapping sequence.

       Note  that  clearance checks are made using the envelope address of the message, which is a little harder
       to forge than plain header fields like Sender:.  The envelope is extracted by looking at the first header
       line, which on Unix systems looks like:

                 From envelope-address send-date

       and is inserted by the mail transport agent (MTA). If you are  using  sendmail  as  the  MTA,  then  only
       trusted  users  declared  in the sendmail.cf file are able to create a "fake" envelope address, a feature
       typically used by mailing list dispatchers, since that address is then used as the bounce target in  case
       the  mail  cannot  be  delivered.   If that first header line is absent, the sender is computed using the
       Sender: field if present, then the From: field, but the auth variable is set to false and the server will
       not switch into trusted mode; in other words, it will not be possible to gain powers in that session.

       Moreover, since the session transcript is sent to that same envelope address  used  to  authenticate  the
       eligibility  for a power, the server feature can hardly be used to retrieve confidential information held
       at the site where the mailagent is run since the information would be sent to one of  the  users  cleared
       for  that  power. It is the responsibility of you, the user, to make sure this cannot happen or you could
       get into legal troubles.

       Finally, sensitive commands should be protected by a proper power, and great  care  should  be  taken  in
       writing  the command implementation to ensure the security cannot be circumvented. But no, this mailagent
       feature is not believed to be dangerous for the system or site it is used on,  since  a  determined  user
       could  implement  one  trivially  via a five line shell script.  If security is really an issue, .forward
       files using the piping feature should be prohibited and access  to  cron  forbidden  in  order  to  avoid
       automatic  mail  processing  (since  it would be possible to have cron invoke a mailagent process -or any
       other program for that matter- to process the incoming mail in a comparable way).

   Example
       Here is an example showing the steps involved in creating a shell command, which would take a  script  by
       collecting lines until an EOF mark and feed it to a real shell for execution. Since allowing this feature
       without  any  safeguards  would  be  a  real security hole, we protect that by requesting the power shell
       before allowing the execution.

       Here is  my  implementation  of  the  shell  command  (available  in  the  mailagent  distribution  under
       misc/shell):

            #!/bin/sh

            # Execute commands from stdin, as transmitted by the mailagent server.
            # File descriptor #3 is a channel to the session transcript.

            # Make sure we have the shell power.
            # Don't even allow the root power to bypass that for security reasons.
            case ":$powers:" in
            *:shell:*) ;;
            *)
                 echo "Permission denied." >&3
                 exit 1
                 ;;
            esac

            # Perhaps a shell was defined... Otherwise, use /bin/sh
            case "$shell" in
            '') shell='/bin/sh';;
            esac

            # Normally, a shell command has its output included in the transcript only in
            # case of error or when the user requests the trace. Here however, we need to
            # see what happened, so everything is redirected to the session transcript.

            exec $shell -x >&3 2>&3

       Note  how we make access to the $powers and $shell environment variable. That last one is user-defined to
       allow dynamic set-up of a shell.

       Assuming we store that command under servdir/shell.sh (don't forget to  add  the  execution  bit  on  the
       file...), here is how we declare it and its variable in the comserver file.

            shell     shell     -    y    -
            shell     var  -    -    -

       This  example shows that there is a separate name-space for variables and commands. Moreover, the command
       bears the same name as its type -- don't let that confuse you :-).

       Now, assuming you have already created a system power and protected it with a password (let's assume sys-
       pass for the purpose of this example), you need to create the shell  power.  Although  you  could  do  it
       manually  (like  when  you  handcrafted the root power), it's better to use the SERVER interface since it
       ensures consistency.

       In order to create the shell power required to use the newly created shell command, you need to  add  the
       following rule to your rule file:

            Subject: Server          { SAVE server; SERVER -t };

       which  will save all server mail in a dedicated folder and process them. Note the -t option, which allows
       trusted mode, in which powers may be gained.  Now send yourself the following mail:

            Subject: Server
            power system sys-pass
            newpower shell shell-pass
            ram@acri.fr
            EOF

       which requests for the system power (needed to created most powers), and then creates a new power  shell,
       assigning  shell-pass as its password and clearing ram@acri.fr for it. Note the here-document fill-in for
       the newpower command, up to the EOF marker. Of course, you need to  replace  the  address  by  your  real
       address.

       You will receive a session transcript along these lines:

                ---- Mailagent session transcript for ram@acri.fr ----

            ----> power system ********
            OK.

            ====> newpower shell ********
            OK.

            ====> --
            End of processing (.signature)

                ---- End of mailagent session transcript ----

       Note  the  concealed  passwords,  and  the prompt change once the system power has been granted. Since my
       mailer automatically appends a signature, the processing stops on it.

       Now let's use this new command... Send yourself the following mail:

            Subject: Server
            set shell /bin/ksh
            set eof END
            shell
            ls -l /etc/passwd
            END
            power shell shell-pass
            shell
            ls -l /etc/passwd
            END

       If you everything is right, you should receive back a transcript looking like this:

                ---- Mailagent session transcript for ram@acri.fr ----

            ----> set shell /bin/ksh
            OK.

            ----> set eof END
            OK.

            ----> shell
            Permission denied.
            Command returned a non-zero status (1).
            FAILED.

            ----> power shell ********
            OK.

            ====> shell
            + ls -l /etc/passwd
            -rw-r--r--   1 root     system       691 Oct 01 14:24 /etc/passwd
            OK.

            ====> --
            End of processing (.signature)

                ---- End of mailagent session transcript ----

       The first invocation of the shell command fails since we lack the shell  power.  The  string  "Permission
       denied." is echoed by the command itself into file descriptor #3 and makes it to the transcript.

   Conclusion
       The  generic mail server implemented in mailagent can be used to implement a mailing list manager, a vote
       server, an archive server, etc...  Unfortunately, it does not currently have the notion of state, with  a
       command set dedicated to each state, so it is not possible to implement an intelligent archive server.

       If  you  implement  new simple server commands and feel they are generic enough to be contributed, please
       send them to me and I will gladly integrate them.

EXAMPLES

       Here are some examples of rule files. First, if you do not specify a rule file or if  it  is  empty,  the
       following built-in rule applies:

            All: /^Subject: [Cc]ommand/ { LEAVE; PROCESS };

       Every  mail  is  left  in  the mailbox. Besides, mail with "Subject: Command" anywhere in the message are
       processed.

       The following rule file is the one I am currently using:

            maildir = ~/mail;

            All: /^Subject: [Cc]ommand/   { SAVE cmds; PROCESS };

            To: /^gue@eiffel.fr/          { POST -l mail.gue };
            Apparently-To: ram,
            Newsgroups: mail.gue          { BOUNCE gue@eiffel.fr };

            <_SEEN_>
                 Apparently-To: ram,
                 Newsgroups: mail.gue     { DELETE };

            From: root, To: root          { BEGIN ROOT; REJECT };
            <ROOT> /^Daily run output/    { WRITE ~/var/log/york/daily.%D };
            <ROOT> /^Weekly run output/   { WRITE ~/var/log/york/weekly };
            <ROOT> /^Monthly run output/  { WRITE ~/var/log/york/monthly };

            From: ram      { BEGIN RAM; REJECT };
            <RAM> To: ram       { LEAVE };
            <RAM> X-Mailer: /mailagent/   { LEAVE };
            <RAM>               { DELETE };

       The folder directory is set to ~/mail. All  command  mails  are  saved  in  the  folder  ~/mail/cmds  and
       processed.  They  do  not  show up in my mailbox. Mails directed to the gue mailing list (French Eiffel's
       Users Group, namely Groupe des Utilisateurs Eiffel) are posted on the local newsgroup mail.gue and do not
       appear in my mailbox either. Any follow-up made on this group is mailed to me by inews (and not  directly
       to the mailing list, because those mails would get back to me again and be fed to the newsgroup, which in
       turn  would  have  them  mailed  back  to  the list, and so on, and so forth).  Hence the next rule which
       catches those follow-ups and bounces them to the mailing list. Those mails will indeed come back, but the
       _SEEN_ rule will simply delete them.

       On my machine, the mails for root are forwarded to me. However, everyday, the  cron  daemon  starts  some
       processes  to  do  some administration clean-up (rotating log files, etc...), and mails the results back.
       They are redirected into specific folders with the WRITE command, to ensure they do not grow  up  without
       limit.  Note the macro substitution for the daily output (on Mondays, the output is stored in daily.1 for
       instance).

       The next group of rules prevents the mail system from sending back mails when  I  am  in  a  group  alias
       expansion.  This is a sendmail option which I disabled on my machine. Care is taken however to keep mails
       coming from the mailagent which I receive as a blind carbon copy.

CAVEAT

       In order to limit the load overhead on the system, only one mailagent  process  is  allowed  to  run  the
       commands.  If  some  new mail arrives while another mailagent is running, that mail is queued and will be
       processed later by the main mailagent.

       For the same reason, messages sent back by mailagent are queued by sendmail, to avoid the  cost  of  mail
       transfer while processing commands.

SECURITY

       First,  let me discuss what security means here. It does not mean system safety against intruder attacks.
       If your system allows .forward hooks and/or cron jobs to be set by regular users, then your system is not
       secure at all. Period. So we're not bothering with security at the system level, but rather at  your  own
       account level where all sort of precious data is held.

       To avoid any pernicious intrusion via Trojan horses, the C filter will refuse to run if the configuration
       file ~/.mailagent or the rule file specified are world writable or not owned by the user. Those tests are
       enforced  even  if  the filter does not run setuid, because they compromise the security of your account.
       The mailagent will also perform some of those checks, in case it is not invoked via the C filter.

       Indeed, if someone can write  into  your  ~/.mailagent  file,  then  he  can  easily  change  your  rules
       configuration  parameter to point to another faked rule file and then send you a mail, which will trigger
       mailagent, running as you. Via the RUN command, this potential intruder could run any command, using your
       privileges, and could set a Trojan horse for later perusal. Applying the same logic, the rule  file  must
       also be protected tightly.

       And, no surprise, the same rules apply for your newcmd file, which is used to describe extended filtering
       commands.  Otherwise  it  would  allow  someone to quietly redefine a commonly used standard command like
       LEAVE and later be able to assume your identity.

       Versions after 3.0 PL44 come with an improved (from a security point of view) C filter that will not only
       perform the aforementionned checks but will also ensure that the perl executable and the mailagent script
       it is about to exec are not loosely protected (when  execsafe  is  ON  or  when  running  with  superuser
       privileges).   Furthermore,  if  the  filter is set up in your .forward as described in this man page, it
       will be able to check itself for safety and will warn you loundly if it can be tampered with, which could
       defeat all security checks.

       Mailagent was also extended so that all programs executed via RUN and friends, as well as mail hooks, are
       checked for obvious protection flaws before being actually run Interpreted scripts (starting with the  #!
       magic  token)  and perl scripts following the magic "exec perl if $under_shell" incantation are specially
       checked for further security of the relevant interpretor. Those checks are performed systematically (when
       execsafe is ON or when running with superuser privileges) even if the secure parameter was not set to ON.
       Also, all files about to be exec()ed are checked using the same extended check method used when secure is
       ON (ownership tests are skipped however when checking for exec()-ness of a file).

FILES

       ~/.mailagent        configuration file for mailagent.
       ~/agent.trace       trace dump from a PROCESS command when error cannot be mailed back.
       ~/mbox.filter       mailbox used by filter in case of error
       ~/mbox.urgent       mailbox used by mailagent in case of error
       ~/mbox.<username>   mailbox used if writing access is denied in the mail spool directory
       /usr/share/mailagent/mailagent
                           directory holding templates and samples.
       Log/agentlog        mailagent's log file.
       Spool/agent.wait    list of mails waiting to  be  processed  and  stored  outside  of  mailagent's  queue
                           directory.  Even  when  logically empty, this file is kept around and still holds one
                           blank line to reserve a block on the filesystem.
       Queue/qmXXXXX       mail spooled by filter.
       Queue/fmXXXXX       mail spooled by mailagent.
       Queue/cmXXXXX       mail spooled by the AFTER command.
       Hash/X/Y            hash files used by RECORD, UNIQUE, ONCE commands and vacation mode.

BUGS

       There is a small chance that mail arrives while the main mailagent is about  to  finish  its  processing.
       That  mail  will  be  queued  and  not  processed  until  another mail arrives (the main mailagent always
       processes the queue after having dealt with the message that invoked it).

       A version number must currently contain a dot. Moreover, an old system (i.e. a system with an  o  in  the
       patches  column)  must  have  a  version  number, so that mailagent can compute the name of the directory
       holding the patches.

       The lock file is deliberately ignored when -q option is used (in fact, it is ignored whenever  an  option
       is specified).  This may result in having mails processed more than once.

       Mailagent  is at the mercy of any perl bug, and there is little I can do about it. Some spurious warnings
       may be emitted by the data-loaded version, although they do not appear with the plain version.

       Parsing of the rule file should be done by a real parser and not lexically.  Or at least,  it  should  be
       possible to escape otherwise meaningful characters like ';' or '}' within the rules.

AUTHOR

       Raphael Manfredi <Raphael_Manfredi@pobox.com>.

SEE ALSO

       maildist(1), mailhelp(1), maillist(1), mailpatch(1), perl(1).

                                                  Version 3.1-                                      MAILAGENT(1)