=for comment $Id: avenger.local.pod,v 1.21 2006/01/15 02:54:36 dm Exp $

=head1 NAME

avenger.local - deliver mail for a local user

=head1 SYNOPSIS

avenger.local [-f I<sender>] [-D I<recip>] [-a I<extra>] [-d] I<user>

=head1 DESCRIPTION

avenger.local is a local mail delivery agent that enables users to set
up multiple "extension" email addresses and process mail differently
for each addresses.  The popular qmail MTA (L<http://www.qmail.org/>)
has a mechanism for processing such extension addresses.
avenger.local provides a similar facility for users of other MTAs,
such as sendmail.

To use avenger.local, you should configure your MTA so that it
delivers mail to I<user>B<+>I<extra>B<@>I<host> by executing
B<avenger.local> B<-D> I<user>B<+>I<extra>B<@>I<host> B<-d>
I<user>B<+>I<extra>.  Alternatively, you can execute B<avenger.local>
B<-a> I<extra> B<-d> I<user>, but then you lose information about the
host.  However, the latter syntax has the advantage of being
command-line compatible with procmail; thus, if your MTA has support
for procmail as a local delivery agent, you should be able to use that
by simply substituting avenger.local's path for procmail's.

Note that either way you invoke it, avenger.local rejects recipients
containing the string C<..> in the local part.  Such mailbox names are
not allowed by RFC822, and could potentially lead to security problems
if parts of mailbox names are used as file names.  Out of paranoia,
avenger.local additionally rejects mailbox names containing the C</>
character in the extra portion after the local username.

avenger.local is designed to be unobtrusive for users who do not want
to take advantage of its functionality.  When delivering mail for
I<user>, if I<user>'s home directory does not contain a subdirectory
F<.avenger>, avenger.local simply executes the default mail delivery
agent (usually called F<mail.local>).

For users who do have F<.avenger> directories, mail is delivered
according to rule files called F<.avenger/local*>.  Mail to
I<user>B<@>I<host> is delivered according to rules in
F<.avenger/local>.  Mail to I<user>B<+>I<ext1>B<@>I<host> is delivered
according to rules in F<.avenger/local+ext1> if such a file exists, or
else F<.avenger/local+default> if such a file exists; if neither file
exists, the mail is bounced.  Addresses containing multiple C<+>
characters are handled as expected.  Mail to
I<user>B<+>I<ext1>B<+>I<ext2>B<@>I<host> is governed by, in order of
decreasing precedence, F<.avenger/local+ext1+ext2>,
F<.avenger/local+ext1+default>, or F<.avenger/local+default>; it is
bounced if none of those files exist.

Local rule files can be in one of two formats.  If the first two
characters of the file are C<#!>, then the file is simply executed as
a script, with the message on standard input.  The script's standard
input will be read-only, but seekable, so, for example, the message
can be delivered to multiple mailboxes using the deliver utility.

Otherwise, if the first two characters of a file are not C<#!>,
avenger.local uses a syntax similar to (but not identical to) qmail's,
where each line is one of the following types, depending on the first
character:

=over

=item B<#> I<comment>

Lines starting with C<#> are treated as comments and ignored.  The
exception is that if the first line begins C<#!>, the file is executed
as a script.  Note that if the first two characters of a file are
C<#!> but the file's execute permission bits are not set, then mail
sent to that address will be deferred.  (This mechanism can be used for
intentionally deferring mail while performing maintenance.)

=item F<./maildir/>

=item F</path/to/maildir/>

A line starting C<.> or C</> and ending with a C</> character is
treated as a mail directory.  Mail is delivered there using the qmail
maildir format.

=item F<./file>

=item F</path/to/file>

A line starting C<.> or C</> and NOT ending with a C</> character
specifies an ordinary Unix mbox file into which the message should be
delivered.

=item B<&>I<address>

C<&> indicates that a copy of the message should be forwarded to
I<address>.  You may not place a space between B<&> and address, nor
can I<address> contain angle brackets, comments, or anything other
than an email address with a fully-qualified domain name.

(Note that in qmail, the B<&> character is optional for certain email
addresses, while avenger.local always requires the B<&> character.)

Forwarding happens after all other lines in the file are processed.
If any other configuration line fails, for instance because a command
executed on behalf of a B<|> line exits non-zero, the mail is not
forwarded to any of the addresses.  (The exception is if a command
exits with status 99, in which case mail is forwarded to addresses in
all preceding B<&> lines, but subsequent lines are ignored.)

=item B<|> I<command>

Specifies that I<command> should be run as a shell command, with the
mail message as its standard input.  If I<command> exits with a status
other than 0, processing of the local rule file terminates
immediately, with avenger.local's exit status determined by
I<command>'s.

If I<command>'s status is 99, avenger.local exits with status 0,
effectively pretending the command just executed was the last line in
the F<.avenger/local*> file.  If I<command>'s exit status is between
64 and 78, inclusive, avenger.local exits with the same status as
I<command>.  If I<command> exits with status 100 or 112, avenger.local
exits with status 70.  For all other exit values, or if I<command>
terminates because of a signal, avenger.local exits with status 75.
Note that the B<--qmailexit> flag changes this behavior, as described
below.

See the file F</usr/include/sysexits.h> for more information on the
meaning of various exit statuses to sendmail.

=item B<<>I<address>

=item B<<!>I<command>

This sets the envelope sender (i.e., bounce address) for copies of the
message forwarded to users with B<&> lines.  Note that one sender
address applies to all recipients, regardless of where in the
F<.avenger/local*> file the bounce address is set.  It is not possible
to forward from different bounce addresses for different recipients.

The first form of this line simply sets the envelope sender to
I<address>.  No spaces are allowed between B<<> and the address.  No
angle brackets or comments are allowed either.

The second form of this line executes I<command> with the shell,
giving it the message body as standard input.  If I<command> exits
with status 0 and outputs exactly one line of text, this line will be
interpreted as the new envelope sender for forwarded copies the
message.  If I<command> exits with any of statuses 64-78, 99-100, or
111-112, processing of the F<avenger/.local*> halts exactly as for the
B<|> command.  For other exit statuses, or if I<command> outputs no
lines or more than one line, the command's result is ignored and
processing continues with the envelope sender unchanged.

=item B<!> I<command>

Runs I<command> with the shell, giving it the mail message on standard
input.  If the command exits 0 and outputs exactly one line of text
beginning C<.> or C</>, the output is interpreted as either a maildir
(if the line ends C</>) or a mailbox (if it doesn't) to which the
message should be delivered.  In other cases, either the B<!> line is
ignored, or processing halts, as described for the B<<!> command.

=back

A completely empty file (not even containing a comment or blank line),
or a missing F<.avenger/local> (with no extension file), is treated as
equivalent to a file with the line C<./Mailbox>.

=head2 OPTIONS

=over

=item B<-a> I<extra>

Specifies the extra portion of the local part of the email address
after the user name.  In other words, if avenger.local is invoked with
arguments B<-a> I<extra> B<-d> I<user>, it is equivalent to invoking
it with the arguments B<-d> I<user>B<+>I<extra>.  The B<-a> option
allows command-line compatibility with sendmail's procmail interface,
which separates out the user name from the extension portion of the
address.

=item B<-d> I<user>

Specifies the local user to deliver mail to.  Note that for
compatibility with other local mailers, the B<-d> is optional, you can
simply specify I<user> as the final command-line argument.

=item B<-f> I<sender>

=item B<-r> I<sender>

The B<-f> option specifies the envelope sender of the message.  For
historical reasons, B<-r> is synonymous with B<-f>.

=item B<-t>

This option is silently ignored, for command-line compatibility with
procmail.

=item B<-B>

Ordinarily, when forwarding a bounce message, avenger.local will
invoke sendmail with the argument B<-f> followed by an empty string
argument (i.e., specifying an empty from address).  This does not work
with some older versions of sendmail.  The B<-B> option says that
bounce messages should be forwarded with arguments B<-f @> instead,
which appears to produce the desired (MAILER-DAEMON) result with older
versions of sendmail.

=item B<-Y>

This option is silently ignored, for command-line compatibility with
procmail.

=item B<--fallback> I<program>

If the I<user> specified on the command line does not exist or have a
F<$HOME/.avenger/> directory, or else has UID 0 (root), or has an
invalid shell or an expired account, then avenger.local will not
attempt to deliver mail to the user.  Instead, it will attempt to run
the system's normal mail delivery agent as a fallback.  This program
is usually called F<mail.local>, but you can specify an alternative
with the B<--falback> option.  Note that this should be the full path
of the program, and should not contain any arguments.  avenger.local
will supply the arguments B<-f> I<from> B<-d> I<user>.

=item B<--fcntl>

This option enables fcntl (a.k.a. POSIX) file locking of mail spools,
in addition to flock and dotfile locking.  The advantage of fcntl
locking is that it may do the right thing over NFS.  However, if
either the NFS client or server does not properly support fcntl
locking, or the file system is not mounted with the appropriate
options, fcntl locking can fail in one of several ways.  It can allow
different processes to lock the same file concurrently--even on the
same machine.  It can simply hang when trying to acquire a lock, even
if no other process holds a lock on the file.  Also, on some OSes it
can interact badly with flock locking, because those OSes actually
implement flock in terms of fcntl.  For these reasons, avenger.local
performs dotfile and flock locking by default, but not fcntl locking.

=item B<--qmailexit>

When programs from B<|>, B<!>, and B<<!> exit with non-zero exit
status, the B<--qmailexit> flag causes avenger.local to translate the
exit codes to ones more suitable for qmail.  Any code that would cause
a hard error in sendmail causes avenger.local to exit with 100, any
soft error causes exit code 111, and exit code 99 is passed through.

=item B<--sendmail> I<program>

Specifies the program to run to send mail, when users have lines
beginning C<&> in their F<.avenger/local*> files.  If I<program>
contains spaces, it is broken into multiple arguments.  The default
value for I<program> is C<sendmail -oi -os -oee>.

=item B<--separator> I<char>

Specifies a separator character to place between portions of the
address extension.  The default value is C<+>.  Thus, the argument
B<-a a+b> would cause avenger.local to search for files
F<$HOME/.avenger/local+a+b>, F<$HOME/.avenger/local+a+default>, and
F<$HOME/.avenger/local+default>.  Specifying a different I<char>, say
C<->, would change the C<+> to C<-> in both the email address and file
names.

=item B<--smuser> I<user>

By default, sendmail is run as the user under which avenger.local is
invoked, which will ordinarily be root.  To drop privileges before
running sendmail, you can specify this argument and avenger.local will
run sendmail as I<user>.  Note that avenger doesn't run sendmail as
the recipient user, because this often results in undesirable
C<X-Authentication-Warning> fields in the header.  If you wish the
header to reflect a trail of how a message has been forwarded, see the
B<--to> option below.

=item B<--tmpfile> I<template>

avenger.local creates a copy of the message in a local file.
I<template> is a template for the name of the file, which must end
with a number of C<X> characters, which will be replaced by a unique
identifier.  (This is for use with the L<mkstemp(3)|mkstemp(3)>
library call.)  The default value is C</tmp/msg.XXXXXXXXXX>.

=item B<--to> I<address> (B<-D> I<address>)

Specifies the full envelope recipient address to which this message is
being delivered.  With this option, avenger.local adds a line
C<Delivered-To:  I<address>> to the header of the mail message.  It
also checks that the header did not previously contain the same
line--if the message has already been delivered to the same address,
this indicates a loop, and avenger.local exits with status 70.

=back

=head1 ENVIRONMENT

The following environment variables are set when running commands
specified in lines starting B<|>.

=over

=item B<EXT>

The local portion of the email address following the first separator
character (which is the C<+> character, unless set otherwise by
B<--separator>).  This variable is not set if there is no extension in
the email address.

=item B<EXT1>, B<EXT2>, ...

When B<EXT> itself contains a the separator character, B<EXT1>
contains the part of B<EXT> after the first separator, B<EXT2> the
part after the second separator, and so on for each separator
character in B<EXT>.

=item B<HOST>

If a recipient has been specified with the B<-D> I<recip> flag, this
variable will contain the host portion of I<recip>.

=item B<LOCAL>

If a recipient has been specified with the B<-D> I<recip> flag, this
variable will contain the local portion of I<recip>.

=item B<PREFIX>

=item B<SUFFIX>, B<SUFFIX1>, B<SUFFIX2>, ...

Assuming the separator is C<+>, when processing a file
F<local+base+default>, B<PREFIX> is set to F<base>, while B<SUFFIX> is
set to the portion of the name for which F<default> was substituted.
When the file does not end with F<default>, B<SUFFIX> is not set.
When the file is just F<local> with no extension, neither B<PREFIX>
nor B<SUFFIX> is set.  When B<SUFFIX> itself contains a C<+>
character, B<SUFFIX1> contains to the part of B<SUFFIX> after the
first C<+> character, B<SUFFIX2> contains the part after the second
C<+>, and so on for each C<+> character in suffix.

=item B<RECIPIENT>

If the B<--to> option was specified, the B<RECIPIENT> environment
variable is set to the address specified in that option.  Otherwise,
B<RECIPIENT> is not set.

=item B<RECIPIENT_HOST>

=item B<RECIPIENT_LOCAL>

These are the same as B<HOST> and B<LOCAL>, but with all characters
folded to lower-case.

=item B<RPLINE>

A C<Return-Path:> line suitable for prepending to the message header.

=item B<SENDER>

The envelope sender of the message.

=item B<SENDMAIL>

The value of the B<--sendmail> option, or C<sendmail -oi -os -oee> by
default.

=item B<SENDFROM>

This is the same as B<$SENDER>, unless envelope sender is empty (for a
bounce message) and the B<-B> option has been specified, in which case
B<SENDFROM> is C<@>.  You can forward a message on from the same
sender with a line like this:

     | $SENDMAIL -f "$SENDFROM" -- recpient1@host1.com ...

=item B<SEPARATOR>

The separator character specified by B<--separator>, or the default
C<+> if none has been explicitly specified.

=item B<UFLINE>

An mbox C<From > line suitable for prepending to the message before
appending it to a mailbox or passing it to a filter that expects such
a line.

=item B<USER>

The user to whom the message is being delivered.

=back

=head1 EXAMPLES

To use avenger.local with sendmail, you might put the following in
your sendmail m4 configuration file (this is the file ending F<.mc>
that produces your F<sendmail.cf> file):

	FEATURE(`local_procmail',
		`@libexecdir@/avenger.local',
		`avenger.local -a $h -d $u')

To deliver mail to a maildir directory called F<inbox> in your home
directory, you would place the following line in the file
F<$HOME/.avenger/local>:

	./inbox/

If you are subscribed to several mailing lists, you might wish to
spool them in separate files, so as to read them separately.  (For
example, the emacs editor has a newsreader, GNUS, that lets you read
multiple mailboxes more like newsgroups.)  To do this, you should
subscribe to each mailing list under a different address.  If your
address is I<user>B<@>I<host>, you might subscribe to the Mail Avenger
mailing list as I<user>B<+avenger@>I<host>.  To spool mail in file
F<$HOME/Mail/incoming/avenger-list.spool>, create a file
F<$HOME/Mail/.avenger/local+avenger> with the following line:

	./Mail/incoming/avenger-list.spool

To create a mailing list I<user>B<+friends@>I<host> for yourself and
your friends, create a file F<$HOME/Mail/.avenger/local+friends> with
your inbox and their addresses, for example:

      ./inbox/
      &friend1@host1.com
      &friend2@host2.com

=head1 FILES

F<@libexecdir@/avenger.local>,
F<$HOME/.avenger/local>,
F<$HOME/.avenger/local*>,
F</etc/mail/sendmail.cf>,
F<@sampledir@/avsendmail.m4>

=head1 SEE ALSO

L<avenger(1)|avenger(1)>,
L<deliver(1)|deliver(1)>,
L<dotlock(1)|dotlock(1)>,
L<mail.local(8)|mail.local(8)>

The Mail Avenger home page: L<http://www.mailavenger.org/>.

=head1 BUGS

avenger.local doesn't necessarily report problems in a the most useful
place when it encounters errors in a F<.avenger/local*> file.  It does
send some diagnostics to standard error, but these will typically end
up in the mail log or in bounce messages returned to the sender.

avenger.local should always provide the exact envelope recipient in
the B<RECIPIENT> environment variable.  Unfortunately, this
information is not available unless it has been supplied with the
B<-D> flag.  Often the envelope recipient is just
"B<${USER}${SEPARATOR}${EXT}@your.host.name>", but it might not be if
there are aliases or virtual domains.  On servers with virtual hosts,
the actual hostname used will be unavailable in the general case
(though you may be able to deduce it from B<$USER> and B<$EXT> if you
know your particular setup).  Note that it is possible to configure
sendmail to supply the full recipient address.  Mail avenger comes
with example sendmail configuration directives that can be included in
your F<sendmail.mc> m4 configuration file; see
F<@sampledir@/avsendmail.m4>.

To protect against concurrent accesses to mbox format files,
avenger.local uses both I<flock> and dotfiles to lock mailboxes.
However, it does not use I<fcntl>/I<lockf>-style locking by default.
Thus, if your mail reader exclusively uses I<fcntl> for locking, there
will be race conditions unless you specify the B<--fcntl> option.

=head1 AUTHOR

David MaziE<egrave>res


syntax highlighted by Code2HTML, v. 0.9.1