=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] [-D I] [-a I] [-d] I =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) 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 IB<+>IB<@>I by executing B B<-D> IB<+>IB<@>I B<-d> IB<+>I. Alternatively, you can execute B B<-a> I B<-d> I, 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, if I's home directory does not contain a subdirectory F<.avenger>, avenger.local simply executes the default mail delivery agent (usually called F). For users who do have F<.avenger> directories, mail is delivered according to rule files called F<.avenger/local*>. Mail to IB<@>I is delivered according to rules in F<.avenger/local>. Mail to IB<+>IB<@>I 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 IB<+>IB<+>IB<@>I 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 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 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 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
C<&> indicates that a copy of the message should be forwarded to I
. You may not place a space between B<&> and address, nor can I
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 Specifies that I should be run as a shell command, with the mail message as its standard input. If I exits with a status other than 0, processing of the local rule file terminates immediately, with avenger.local's exit status determined by I's. If I'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's exit status is between 64 and 78, inclusive, avenger.local exits with the same status as I. If I exits with status 100 or 112, avenger.local exits with status 70. For all other exit values, or if I 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 for more information on the meaning of various exit statuses to sendmail. =item B<<>I
=item B<I 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
. 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 with the shell, giving it the message body as standard input. If I 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 exits with any of statuses 64-78, 99-100, or 111-112, processing of the F halts exactly as for the B<|> command. For other exit statuses, or if I 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 Runs I 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 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 B<-d> I, it is equivalent to invoking it with the arguments B<-d> IB<+>I. 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 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 as the final command-line argument. =item B<-f> I =item B<-r> I 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 If the I 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, 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 B<-d> I. =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 Specifies the program to run to send mail, when users have lines beginning C<&> in their F<.avenger/local*> files. If I contains spaces, it is broken into multiple arguments. The default value for I is C. =item B<--separator> I 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, say C<->, would change the C<+> to C<-> in both the email address and file names. =item B<--smuser> I 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. Note that avenger doesn't run sendmail as the recipient user, because this often results in undesirable C 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