<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <HTML ><HEAD ><link rel='stylesheet' type='text/css' href='manpage.css'> <!-- $Id: maildropfilter.sgml,v 1.7 2004/07/27 01:36:41 mrsam Exp $ --> <!-- Copyright 1998 - 2003 Double Precision, Inc. See COPYING for --> <!-- distribution information. --> <meta name="MSSmartTagsPreventParsing" content="TRUE"> <link rel="icon" href="icon.gif" type="image/gif" /> <TITLE >maildropfilter</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.7"></HEAD ><BODY CLASS="REFENTRY" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><H1 ><A NAME="MAILDROPFILTER" ></A >maildropfilter</H1 ><DIV CLASS="REFNAMEDIV" ><A NAME="AEN6" ></A ><H2 >Name</H2 >maildropfilter -- maildrop's filtering language</DIV ><DIV CLASS="REFSYNOPSISDIV" ><A NAME="AEN9" ></A ><H2 >Synopsis</H2 ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN10" ></A ><P ><TT CLASS="FILENAME" >/etc/maildrop/maildroprc</TT >, <TT CLASS="FILENAME" >$HOME/.mailfilter</TT >, <TT CLASS="FILENAME" >$HOME/.mailfilters/*</TT >, and friends...</P ><P ></P ></DIV ></DIV ><DIV CLASS="REFSECT1" ><A NAME="AEN15" ></A ><H2 >DESCRIPTION</H2 ><P >This manual page describes the language used by <B CLASS="COMMAND" >maildrop</B > to filter E-mail messages. The mail filtering instructions are read from a file. The language is loosely structured, it is based on pattern matching. The language has a distinct lexical and syntactical structure, very similar to Perl's, but it is important to note that it is not Perl, and is very different from Perl, in certain cases.</P ><P >If the filtering instructions do not exist, <B CLASS="COMMAND" >maildrop</B > delivers the message to the default mailbox without doing any additional processing, making it indistinguishable from the usual mail delivery agent.</P ><P >It is important to note that <B CLASS="COMMAND" >maildrop</B > reads and parses the <SPAN CLASS="SYSTEMITEM" >filter file</SPAN > before doing anything. If there are any errors <B CLASS="COMMAND" >maildrop</B > prints an error message, and terminates with the exit code set to <SPAN CLASS="ERRORCODE" >EX_TEMPFAIL</SPAN >. A compliant mail transport agent should re-queue the message for a later delivery attempt. Hopefully, most simple syntax errors will not cause mail to be bounced back if the error is caught and fixed quickly.</P ><DIV CLASS="REFSECT2" ><A NAME="AEN26" ></A ><H3 >Environment</H3 ><P ><A NAME="ENVIRONMENT" ></A > <B CLASS="COMMAND" >maildrop</B > uses variables to access and manipulate messages. Variables are arbitrary text accessed by referring to the name of the variable, such as <VAR CLASS="VARNAME" >HOME</VAR >, or <VAR CLASS="VARNAME" >DEFAULT</VAR >. Text is placed into a variable by using an assignment statement, such as:</P ><A NAME="AEN33" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN34" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >FILE="IN.junk"</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >This statement puts the text "IN.junk" (without the quotes) into a variable whose name is <VAR CLASS="VARNAME" >FILE</VAR >. Later, the contents of a variable are accessed by using the $ symbol and the name for the variable. For example: <A NAME="AEN38" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN39" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >to $FILE</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></P ><P >This will deliver the current message to the mailbox file (or a maildir directory) named "IN.junk".</P ><P ><B CLASS="COMMAND" >maildrop</B > initially creates variables from the environment variables of the operating system, UNLESS <B CLASS="COMMAND" >maildrop</B > runs in delivery mode. Each operating system environment variable becomes a <B CLASS="COMMAND" >maildrop</B > variable. When running in delivery mode, <B CLASS="COMMAND" >maildrop</B > does not import the environment for security reasons. In all cases <B CLASS="COMMAND" >maildrop</B > resets the following variables to their default values: <VAR CLASS="VARNAME" >HOME</VAR >, <VAR CLASS="VARNAME" >DEFAULT</VAR >, <VAR CLASS="VARNAME" >SHELL</VAR >, <VAR CLASS="VARNAME" >PATH</VAR >, <VAR CLASS="VARNAME" >LOCKEXT</VAR >, <VAR CLASS="VARNAME" >LOCKREFRESH</VAR >, <VAR CLASS="VARNAME" >LOCKSLEEP</VAR >, <VAR CLASS="VARNAME" >LOCKTIMEOUT</VAR >, <VAR CLASS="VARNAME" >MAILDIRQUOTA</VAR >, <VAR CLASS="VARNAME" >SENDMAIL</VAR > and <VAR CLASS="VARNAME" >LOGNAME</VAR >.</P ><P >There's one exception to this rule which applies to the version of <B CLASS="COMMAND" >maildrop</B > that comes with the <A HREF="http://www.courier-mta.org/" TARGET="_top" ><TT CLASS="APPLICATION" >Courier Mail Server</TT ></A >. The following does not apply to the standalone version of <B CLASS="COMMAND" >maildrop</B >: when running in delivery mode, if the <VAR CLASS="OPTION" >-d</VAR > flag was not used, or if it specifies the same userid as the one that's running <B CLASS="COMMAND" >maildrop</B >, the following variables are automatically imported from the environment: <VAR CLASS="VARNAME" >HOME</VAR >, <VAR CLASS="VARNAME" >SHELL</VAR >, <VAR CLASS="VARNAME" >LOGNAME</VAR > and <VAR CLASS="VARNAME" >MAILDIRQUOTA</VAR >. These environment variables are initialized by Courier prior to running <B CLASS="COMMAND" >maildrop</B >. Additionally, the initial value for the <VAR CLASS="VARNAME" >DEFAULT</VAR > maildrop variable is imported from the <VAR CLASS="VARNAME" >MAILDROPDEFAULT</VAR > environment variable. This is because Courier overloads the DEFAULT environment variable to store the defaulted portion of the local mailbox address. See the <A HREF="dot-courier.html" TARGET="_top" ><SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >dot-courier</SPAN >(5)</SPAN ></A > man page in the Courier distribution. You can grab Courier's <VAR CLASS="VARNAME" >DEFAULT</VAR > value by using the <B CLASS="COMMAND" >import</B > command. Note, however, that this will clobber the old contents of <VAR CLASS="VARNAME" >DEFAULT</VAR >, which is probably not what you want. The right way to do this would be something like this:</P ><A NAME="AEN80" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN81" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >SAVEDEFAULT=$DEFAULT import DEFAULT LOCALDEFAULT=$DEFAULT DEFAULT=$SAVEDEFAULT</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >All internal variables are exported back as environment variables when <B CLASS="COMMAND" >maildrop</B > runs an external command. Changes to internal variables, made by the <SPAN CLASS="SYSTEMITEM" >filter file</SPAN >, are reflected in the exported environment.</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN86" ></A ><H3 >Lexical structure</H3 ><P >Most whitespace is generally ignored. The <SPAN CLASS="TOKEN" >#</SPAN > character introduces a comment running to the end of the line, which is also ignored. Unlike other mail filters, <B CLASS="COMMAND" >maildrop</B > parses the <SPAN CLASS="SYSTEMITEM" >filter file</SPAN > before taking any action with the message. If there are syntax errors in the file, <B CLASS="COMMAND" >maildrop</B > displays an error message, and returns <SPAN CLASS="ERRORCODE" >EX_TEMPFAIL</SPAN >. That should cause the mail message to remain in the queue, and, hopefully allow the problem to be corrected, without bouncing any mail.</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >In <B CLASS="COMMAND" >maildrop</B >, the end of line is a lexical token. In order to continue a long statement on the next line, terminate the line with a backslash character.</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN97" ></A ><H3 >Literal text</H3 ><P >Literal text in the <B CLASS="COMMAND" >maildrop</B > filtering language is surrounded by either single or double quotes. In order to enter a single quote into a text literal surrounded by single quotes, or a double quote into a literal surrounded by double quotes, prefix it with a backslash character. Use two backslash characters characters to enter one backslash character in the text literal.</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >A backslash followed by either a backslash, or a matching quote, is the only situation where the backslash character is actually removed, leaving only the following character in the actual text literal. If a backslash character is followed by any other character, the backslash is NOT removed.</P ></TD ></TR ></TABLE ></DIV ><P >Multiple text literals in a row are automatically concatenated, even if they use different quotes. For example:</P ><A NAME="AEN104" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN105" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >FOOBAR="Foo"'bar' SAVEDEFAULT=$DEFAULT import DEFAULT LOCALDEFAULT=$DEFAULT DEFAULT=$SAVEDEFAULT</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >This sets the variable <VAR CLASS="VARNAME" >FOOBAR</VAR > to the text "Foobar".</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN109" ></A ><H3 >Variable substitution</H3 ><P ><A NAME="VARSUBST" ></A > Variable substitution is performed on text literals that's surrounded by double quotation marks. The "<SPAN CLASS="TOKEN" >$</SPAN >" character, followed by a variable name, is replaced by that variable's contents.</P ><A NAME="AEN114" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN115" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >MAILBOX="$HOME/Mailbox"</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >This sets the variable <VAR CLASS="VARNAME" >MAILBOX</VAR > to the contents of the variable <VAR CLASS="VARNAME" >HOME</VAR > followed by <TT CLASS="LITERAL" >"/Mailbox"</TT >. Variable names must begin with an uppercase letter, a lowercase letter, or an underscore. Following that, all letters, digits, and underscores are taken as a variable name, and its contents replace the <SPAN CLASS="TOKEN" >$</SPAN > sign, and the variable name. It is possible to access variables whose name includes other characters, by using braces as follows:</P ><A NAME="AEN122" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN123" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >MAILBOX="${HOME-WORD}/Mailbox"</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >Inserts the contents of the <VAR CLASS="VARNAME" >HOME-WORD</VAR > variable. If the variable does not exist, the empty text literal is used to replace the variable name. It is not possible to access variables whose names include the <SPAN CLASS="TOKEN" >}</SPAN > character.</P ><P >If the <SPAN CLASS="TOKEN" >$</SPAN > character is not followed by a left brace, letter, or an underscore, the <SPAN CLASS="TOKEN" >$</SPAN > character remains unmolested in the text literal. A backslash followed by the <SPAN CLASS="TOKEN" >$</SPAN > character results in a <SPAN CLASS="TOKEN" >$</SPAN > character in the text literal, without doing any variable substitution.</P ><P >Variable substitution is not done in text literals which are surrounded by single quotes (apostrophes).</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN134" ></A ><H3 >Command line arguments</H3 ><P ><B CLASS="COMMAND" >maildrop</B > initializes special variables: <VAR CLASS="VARNAME" >$1</VAR >, <VAR CLASS="VARNAME" >$2</VAR >, and so on, with additional parameters specified on the <B CLASS="COMMAND" >maildrop</B > command line. A <SPAN CLASS="SYSTEMITEM" >filter file</SPAN > may use those variables just like any other variables.</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN142" ></A ><H3 >Predefined variables</H3 ><A NAME="PREDEFINED" ></A ><P >The following variables are automatically defined by <B CLASS="COMMAND" >maildrop</B >. The default values for the following variables may be changed by the system administrator. For security reasons, the values of the following variables are always reset to their default values, and are never imported from the environment:</P ><P ></P ><DIV CLASS="VARIABLELIST" ><DL ><DT ><VAR CLASS="VARNAME" >DEFAULT</VAR ></DT ><DD ><P >The default mailbox to deliver the message to. If the <SPAN CLASS="SYSTEMITEM" >filter file</SPAN > does not indicate a mailbox to deliver this message to, the message is delivered to this mailbox. The default mailbox is defined by the system administrator. </P ></DD ><DT ><VAR CLASS="VARNAME" >FROM</VAR ></DT ><DD ><P >Message envelope sender. This is usually the same address as what appears in the <TT CLASS="LITERAL" >From:</TT > header, but may not be. This information may or may not be available to <B CLASS="COMMAND" >maildrop</B > on your system. The message envelope sender is usually specified with the <VAR CLASS="OPTION" >-f</VAR > option to <B CLASS="COMMAND" >maildrop</B >. If the <VAR CLASS="OPTION" >-f</VAR > option is not given, <B CLASS="COMMAND" >maildrop</B > looks for the <TT CLASS="LITERAL" >From_</TT > line in the message. As the last resort, <TT CLASS="LITERAL" >FROM</TT > defaults to the userid which invoked <B CLASS="COMMAND" >maildrop</B >. Note that <VAR CLASS="VARNAME" >FROM</VAR > may be empty - the message envelope sender is empty for bounce messages. </P ></DD ><DT ><VAR CLASS="VARNAME" >HOME</VAR ></DT ><DD ><P >Home directory of the user running <B CLASS="COMMAND" >maildrop</B >. </P ></DD ><DT ><VAR CLASS="VARNAME" >HOSTNAME</VAR ></DT ><DD ><P >Network name of the machine running maildrop. Obtained from <SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >gethostname</SPAN >(3)</SPAN >. </P ></DD ><DT ><VAR CLASS="VARNAME" >LOCKEXT</VAR ></DT ><DD ><P >Extension for dot-lock files (default: <TT CLASS="LITERAL" >.lock</TT >). </P ></DD ><DT ><VAR CLASS="VARNAME" >LOCKREFRESH</VAR ></DT ><DD ><P >Refresh interval, in seconds, for dot-locks (default: <TT CLASS="LITERAL" >15</TT >). When <B CLASS="COMMAND" >maildrop</B > dot-locks a mailbox, <B CLASS="COMMAND" >maildrop</B > tries to refresh the lock periodically in order to keep other programs from removing a stale dot-lock. This is only required if a dot-lock exists for a prolonged period of time, which should be discouraged anyway. </P ></DD ><DT ><VAR CLASS="VARNAME" >LOCKSLEEP</VAR ></DT ><DD ><P >Number of seconds to wait to try again to create a dot-lock file, if one already exists (default: 5). </P ></DD ><DT ><VAR CLASS="VARNAME" >LOCKTIMEOUT</VAR ></DT ><DD ><P >Number of seconds to wait before removing a stale dot-lock file (default: <TT CLASS="LITERAL" >60</TT >). If a dot-lock file still exists after <VAR CLASS="VARNAME" >LOCKTIMEOUT</VAR > seconds, <B CLASS="COMMAND" >maildrop</B > assumes that the process holding the lock no longer exists, and the dot-lock file can be safely removed. After removing the dot-lock file, <B CLASS="COMMAND" >maildrop</B > waits <VAR CLASS="VARNAME" >LOCKSLEEP</VAR > seconds before trying to create its own dot-lock file, in order to avoid a race condition with another process which is also trying to remove the same stale dot-lock, at the same time. </P ></DD ><DT ><VAR CLASS="VARNAME" >LOGNAME</VAR ></DT ><DD ><P >Name of the user to who the message is being delivered. </P ></DD ><DT ><VAR CLASS="VARNAME" >MAILFILTER</VAR ></DT ><DD ><P >This is the name of the original <SPAN CLASS="SYSTEMITEM" >filter file</SPAN > that was given to <B CLASS="COMMAND" >maildrop</B > on the command line. This is mostly usefull to <TT CLASS="LITERAL" >-default</TT > <SPAN CLASS="SYSTEMITEM" >filter file</SPAN >s, it allows them to obtain the <A HREF="maildrop.html#moption" TARGET="_top" >value of the -M option</A > specified on the command line. </P ></DD ><DT ><VAR CLASS="VARNAME" >PATH</VAR ></DT ><DD ><P >Command execution path. <B CLASS="COMMAND" >maildrop</B > resets PATH to the system default (usually <TT CLASS="LITERAL" >/bin:/usr/bin:/usr/local/bin</TT >). </P ></DD ><DT ><VAR CLASS="VARNAME" >SENDMAIL</VAR ></DT ><DD ><P >The mail delivery agent. When <B CLASS="COMMAND" >maildrop</B > is instructed to deliver the message to a mailbox whose name begins with the ! character, this is interpreted as a request to forward the message. The <VAR CLASS="VARNAME" >SENDMAIL</VAR > command is executed to forward the message. </P ></DD ><DT ><VAR CLASS="VARNAME" >SHELL</VAR ></DT ><DD ><P >The login shell. The shell is used to execute all commands invoked by <B CLASS="COMMAND" >maildrop</B >. </P ></DD ><DT ><VAR CLASS="VARNAME" >VERBOSE</VAR ></DT ><DD ><P >Current Debug level (default: <TT CLASS="LITERAL" >0</TT >). Setting <VAR CLASS="VARNAME" >VERBOSE</VAR > to progressive higher values, between 1 and 9, produces debugging output on standard error. <B CLASS="COMMAND" >maildrop</B > ignores the <VAR CLASS="VARNAME" >VERBOSE</VAR > variable in delivery mode (in order not to confuse the mail transport agent). </P ></DD ><DT ><VAR CLASS="VARNAME" >UMASK</VAR ></DT ><DD ><P >The file creation mode mask, in octal. The default setting of <TT CLASS="LITERAL" >077</TT > creates mailboxes that are readable and writable by the owner only. Use <TT CLASS="LITERAL" >007</TT > to create mailboxes that are readable/writable by both owner and the group. Use <TT CLASS="LITERAL" >037</TT > to create mailboxes that are readable by both owner and group, but writable by owner only. Permissions on existing mailboxes are not changed, this setting affects only new mailboxes. When delivering to maildirs this setting sets the permissions on new messages only. Access permissions on messages in maildirs are also affected by the permissions on the maildir directories.</P ></DD ></DL ></DIV ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN264" ></A ><H3 >Other special variables</H3 ><P >The following variables are automatically used by <B CLASS="COMMAND" >maildrop</B > when the <SPAN CLASS="SYSTEMITEM" >filter file</SPAN > is being processed:</P ><P ></P ><DIV CLASS="VARIABLELIST" ><DL ><DT ><VAR CLASS="VARNAME" >EXITCODE</VAR ></DT ><DD ><P >Return code for <B CLASS="COMMAND" >maildrop</B >. When <B CLASS="COMMAND" >maildrop</B > successfully delivers a message, it terminates with this exit code, which defaults to 0. When the <B CLASS="COMMAND" >to</B > or the <B CLASS="COMMAND" >cc</B > command is used to deliver the message to an external process, via a pipe, <B CLASS="COMMAND" >maildrop</B > will set this variable to the exit code of the external process. Since <B CLASS="COMMAND" >maildrop</B > immediately terminates after completing the <B CLASS="COMMAND" >to</B > command this means that <B CLASS="COMMAND" >maildrop</B >'s exit code will be the exit code of the external process. If the <B CLASS="COMMAND" >to</B > command does not deliver the message to a process you must set <VAR CLASS="VARNAME" >EXITCODE</VAR > before the <B CLASS="COMMAND" >to</B > command, since <B CLASS="COMMAND" >maildrop</B > terminates immediately after finishing the delivery. </P ></DD ><DT ><VAR CLASS="VARNAME" >KEYWORDS</VAR ></DT ><DD ><P >The <VAR CLASS="VARNAME" >KEYWORDS</VAR > variable is used only when delivering a message to a maildir, and implements the optional IMAP keyword extension as implemented in the <A HREF="http://www.courier-mta.org/" TARGET="_top" >Courier-IMAP</A >. It may be optionally initialized to contain a comma-separate list of keywords. The <A HREF="r1.html#TO" ><B CLASS="COMMAND" >to</B ></A >, or the <A HREF="r1.html#CC" ><B CLASS="COMMAND" >cc</B ></A > command, delivers the message to the maildir normally, but also associated the list of keywords in <VAR CLASS="VARNAME" >KEYWORDS</VAR > with the newly delivered message.</P ><P ><VAR CLASS="VARNAME" >KEYWORDS</VAR > must be set before the message is delivered to a maildir. The contents of <VAR CLASS="VARNAME" >KEYWORDS</VAR > are ignored, when delivering on an mbox folder. </P ></DD ><DT ><VAR CLASS="VARNAME" >LINES</VAR ></DT ><DD ><P >Number of lines in the current message. Note that this may be an approximation. It may or may not take into account the -A option, or any mbox "From_" lines. Use this as criteria for filtering, nothing more. </P ></DD ><DT ><VAR CLASS="VARNAME" >MAILDIRQUOTA</VAR ></DT ><DD ><P >Set this variable in order to manually enforce a maximum size on ANY maildir where the message is delivered. This is an optional feature that must be enabled by the system administrator, see <A HREF="maildirquota.html" TARGET="_top" ><SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >maildirquota</SPAN >(8)</SPAN ></A > for more information. </P ></DD ><DT ><VAR CLASS="VARNAME" >RETURNCODE</VAR ></DT ><DD ><P >This variable is set when <B CLASS="COMMAND" >maildrop</B > runs the <A HREF="#xfilter" TARGET="_top" >xfilter</A > command, or a command that's specified within a pair of backtick characters ( command substitution ). The <VAR CLASS="VARNAME" >RETURNCODE</VAR > variable will be set to the exit code of the command, after it completes. </P ></DD ><DT ><VAR CLASS="VARNAME" >SIZE</VAR ></DT ><DD ><P >Number of bytes in the message. This may or may not include the -A option, and the mbox From_ line. Use this as a criteria for filtering, nothing more.</P ></DD ></DL ></DIV ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN329" ></A ><H3 >Unquoted text</H3 ><P >All text strings in <SPAN CLASS="SYSTEMITEM" >filter file</SPAN >s should be in single, or double quotes. However, for convenience sake, quotes can be omitted under certain circumstances.</P ><P >Text that includes ONLY letters, digits, and the following characters: <TT CLASS="LITERAL" >_-.:/${}@</TT > may appear without quotes. Note that this does not allow spaces, or backslashes to be entered, however the text is still variable-substituted, and the substituted text may contain other characters.</P ><P >Also, note that patterns (see below) begin with the slash character. Normally, anything that begins with the slash is interpreted as a pattern. However, text immediately after <SPAN CLASS="QUOTE" >"VARIABLE="</SPAN > is interpreted as a string even if it begins with a slash. This is why something like: <A NAME="AEN337" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN338" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >MAILDIR=/var/spool/mail</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE > works as expected. Using quotes, though, is highly recommended. You must use quotes to set a variable to a lone slash, because an unquoted slash is interpreted as a division sign.</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN340" ></A ><H3 >Command substitution</H3 ><P >Text enclosed in back-tick characters is interpreted as a shell command. The shell command is executed as a child process by <B CLASS="COMMAND" >maildrop</B >. Its output is used in place of the command. For example: <A NAME="AEN344" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN345" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >DIR=`ls`</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE > places the names of the files in the current directory into the DIR variable.</P ><P >The output of the command will have all newline characters replaced by spaces, and leading and trailing spaces will be stripped (multiple spaces are not removed, though). Also, the contents of the message being delivered is made available to the command on standard input.</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN348" ></A ><H3 >Patterns</H3 ><A NAME="PATTERNS" ></A ><P >The pattern syntax in <B CLASS="COMMAND" >maildrop</B > is similar to the <B CLASS="COMMAND" >grep</B > command's syntax, with some minor differences. A pattern takes the following form in the <SPAN CLASS="SYSTEMITEM" >filter file</SPAN >: <A NAME="AEN355" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN356" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >/<VAR CLASS="REPLACEABLE" >pattern</VAR >/:<VAR CLASS="REPLACEABLE" >options</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></P ><P ><VAR CLASS="REPLACEABLE" >pattern</VAR > specifies the text to look for in the message. <VAR CLASS="REPLACEABLE" >pattern</VAR >, because the leading slash will then be interpreted as a division sign. If you must search for text that starts with a space, use something like <TT CLASS="LITERAL" >"/[ ] ... /"</TT >.</P ><P >With the exception of the following characters, an exact match is looked for. The following special characters are used to specify complex patterns. If it is necessary to look for one of the following characters, verbatim, in the message, put a backslash in front of it. "x" and "abc" designates an arbitrary character, or a pattern, which may include other special characters as well.</P ><P ></P ><DIV CLASS="VARIABLELIST" ><DL ><DT ><TT CLASS="LITERAL" >x*</TT ></DT ><DD ><P >Look for zero, or more, occurrences of the single character <VAR CLASS="REPLACEABLE" >x</VAR >. </P ></DD ><DT ><TT CLASS="LITERAL" >(abc)*</TT ></DT ><DD ><P >Look for zero or more occurrences of <VAR CLASS="REPLACEABLE" >abc</VAR >. </P ></DD ><DT ><TT CLASS="LITERAL" >x+</TT ></DT ><DD ><P >Look for at least one, may be more, occurrences of the single character <VAR CLASS="REPLACEABLE" >x</VAR >. </P ></DD ><DT ><TT CLASS="LITERAL" >(abc)+</TT ></DT ><DD ><P >Look for at least one, or more, occurrences of <VAR CLASS="REPLACEABLE" >abc</VAR >.</P ></DD ><DT ><TT CLASS="LITERAL" >x?</TT ></DT ><DD ><P >Look for zero, or one occurrence of the single character <VAR CLASS="REPLACEABLE" >x</VAR >. </P ></DD ><DT ><TT CLASS="LITERAL" >.</TT ></DT ><DD ><P >The period matches any character except the newline character. (This is also applicable within sets - see below). </P ></DD ><DT ><TT CLASS="LITERAL" >(abc)?</TT ></DT ><DD ><P >look for zero, or one occurrence, of "abc". </P ></DD ><DT ><TT CLASS="LITERAL" >abc!def</TT ></DT ><DD ><P >The exclamation mark is used to separate sections of matched pattern. See "<A HREF="#patmatch" TARGET="_top" >Pattern Match Results</A >" below. </P ></DD ><DT ><TT CLASS="LITERAL" >[abc]</TT ></DT ><DD ><P >Specifies a set of characters - this matches one character, either <VAR CLASS="REPLACEABLE" >a</VAR >, <VAR CLASS="REPLACEABLE" >b</VAR >, or <VAR CLASS="REPLACEABLE" >c</VAR >. List all characters that can be matched between the brackets. One or more characters can be listed. For example, <TT CLASS="LITERAL" >[~=+]</TT > matches either a tilde, an equals sign, or a +. This is EXACTLY equivalent to <TT CLASS="LITERAL" >(~|=|+)</TT >, however with large list of characters this notation is much shorter. In addition, <TT CLASS="LITERAL" >[<VAR CLASS="REPLACEABLE" >a</VAR >-<VAR CLASS="REPLACEABLE" >b</VAR >]</TT > matches any character between <VAR CLASS="REPLACEABLE" >a</VAR > and <VAR CLASS="REPLACEABLE" >b</VAR >, inclusive. For example: <TT CLASS="LITERAL" >[0-9]</TT > matches a digit. <TT CLASS="LITERAL" >[0-9A-Za-z_]</TT > matches either a digit, a letter, or an underscore. To include the dash, the left or the right bracket character in the set itself, prefix them with a backslash. Use two backslashes to include the backslash character itself. (Other, historical ways of including these special characters are permitted, but discouraged). </P ></DD ><DT ><TT CLASS="LITERAL" >[^abc]</TT ></DT ><DD ><P >specifies a set of characters that is NOT the given characters indicated. If the set begins with the ^ symbol, it matches a single character that is NOT any of the characters listed. </P ></DD ><DT ><TT CLASS="LITERAL" >\x</TT ></DT ><DD ><P >where "<VAR CLASS="REPLACEABLE" >x</VAR >" is a character. Specifies that <VAR CLASS="REPLACEABLE" >x</VAR > must be matched exactly. In order to match any special character verbatim (for example - you want to match the asterisk, *) you must prefix it with a backslash character. Use two backslashes in order to match a backslash character verbatim. Also, there are several characters reserved for matching control characters, without having to enter them verbatim into the pattern. <A HREF="#control" TARGET="_top" >See below</A > for more information. </P ></DD ><DT ><TT CLASS="LITERAL" >\nnn</TT ></DT ><DD ><P >specifies a character in octal. "nnn" is an octal number.</P ></DD ></DL ></DIV ><P >The following shorthand notation can be used to specify some common sets. Note that <B CLASS="COMMAND" >maildrop</B > always uses the "C" locale:</P ><P ></P ><DIV CLASS="VARIABLELIST" ><DL ><DT ><TT CLASS="LITERAL" >[:alnum:]</TT ></DT ><DD ><P >An alphanumeric character, same as <TT CLASS="LITERAL" >[0-9A-Za-z]</TT >. </P ></DD ><DT ><TT CLASS="LITERAL" >[:alpha:]</TT ></DT ><DD ><P >An uppercase or a lowercase letter, same as <TT CLASS="LITERAL" >[A-Za-z]</TT >. </P ></DD ><DT ><TT CLASS="LITERAL" >[:cntrl:]</TT ></DT ><DD ><P >A control character. </P ></DD ><DT ><TT CLASS="LITERAL" >[:digit:]</TT ></DT ><DD ><P >A digit, same as <TT CLASS="LITERAL" >[0-9]</TT >. </P ></DD ><DT ><TT CLASS="LITERAL" >[:graph:]</TT ></DT ><DD ><P >A "graphable" character (a non-control character that's not a space). </P ></DD ><DT ><TT CLASS="LITERAL" >[:lower:]</TT ></DT ><DD ><P >A lowercase letter, same as<TT CLASS="LITERAL" >[a-z]</TT >. </P ></DD ><DT ><TT CLASS="LITERAL" >[:print:]</TT ></DT ><DD ><P >A printable character (not a control character). </P ></DD ><DT ><TT CLASS="LITERAL" >[:punct:]</TT ></DT ><DD ><P >A punctuation character. </P ></DD ><DT ><TT CLASS="LITERAL" >[:space:]</TT ></DT ><DD ><P >Any whitespace character. </P ></DD ><DT ><TT CLASS="LITERAL" >[:upper:]</TT ></DT ><DD ><P >An uppercase letter, same as <TT CLASS="LITERAL" >[A-Z]</TT >. </P ></DD ><DT ><TT CLASS="LITERAL" >[:wbreak:]</TT ></DT ><DD ><P >Any character other than a letter, digit, or an underscore, same as <TT CLASS="LITERAL" >[^a-zA-Z0-9_]</TT >. </P ></DD ><DT ><TT CLASS="LITERAL" >[:xdigit:]</TT ></DT ><DD ><P >A hexadecimal digit, same as <TT CLASS="LITERAL" >[0-9A-Fa-f]</TT >.</P ></DD ></DL ></DIV ><P >To match any special character, put a backslash in front of it. For example, <TT CLASS="LITERAL" >\?</TT > matches the question mark. To match a backslash, use <TT CLASS="LITERAL" >\\</TT >.</P ><P >Normally, the pattern can be found anywhere within the message header or body (see below). However, putting the character <SPAN CLASS="TOKEN" >^</SPAN > at the beginning of the pattern forces the pattern to be matched against the beginning of the line only. Putting the character <SPAN CLASS="TOKEN" >$</SPAN > at the end of the pattern forces the pattern to be matched against the end of the line only.</P ><P >Elsewhere in the pattern, the <SPAN CLASS="TOKEN" >$</SPAN > sign is used for variable substitution (see above). To include the <SPAN CLASS="TOKEN" >$</SPAN > character in the pattern, prefix it with a backslash.</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN526" ></A ><H3 >Other backslash substitutions</H3 ><A NAME="CONTROL" ></A ><P >The following backslashed characters are interpreted as follows, when used in a pattern specification:</P ><P ></P ><DIV CLASS="VARIABLELIST" ><DL ><DT ><TT CLASS="LITERAL" >\n</TT ></DT ><DD ><P >Matches a newline character. Note - this is only effective if the <A HREF="#options" TARGET="_top" >w option</A > is specified, because without this option <B CLASS="COMMAND" >maildrop</B > does not recognize multi-line patterns. </P ></DD ><DT ><TT CLASS="LITERAL" >\r</TT ></DT ><DD ><P >Matches a carriage return. Note - <B CLASS="COMMAND" >maildrop</B > automatically ignores carriage returns at the end of each line. I don't know why you'd want to use \r, but it's there if you need it. </P ></DD ><DT ><TT CLASS="LITERAL" >\t</TT ></DT ><DD ><P >Matches a tab. </P ></DD ><DT ><TT CLASS="LITERAL" >\f</TT ></DT ><DD ><P >Matches a form feed. </P ></DD ><DT ><TT CLASS="LITERAL" >\v</TT ></DT ><DD ><P >Matches a vertical tab.</P ></DD ></DL ></DIV ><P >Long double or singly-quoted text can be broken across multiple lines by ending the line with a lone backslash character, like this: <A NAME="AEN560" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN561" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >TEXT="This is a long \ text string"</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE > The backslash, the newline, and all leading whitespace on the next line is removed, resulting in "This is a long text string".</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN563" ></A ><H3 >Pattern options</H3 ><A NAME="OPTIONS" ></A ><P >Following <TT CLASS="LITERAL" >/<VAR CLASS="REPLACEABLE" >pattern</VAR >/,</TT > there may be an optional colon, followed by one. or more options. The following options may be specified in any order:</P ><P ></P ><DIV CLASS="VARIABLELIST" ><DL ><DT ><TT CLASS="LITERAL" >h</TT ></DT ><DD ><P >Match this pattern against the message header.</P ></DD ><DT ><TT CLASS="LITERAL" >b</TT ></DT ><DD ><P >Match this pattern against the message body.</P ></DD ><DT ><TT CLASS="LITERAL" >w</TT ></DT ><DD ><P >Match this pattern against the entire message and/or body.</P ></DD ><DT ><TT CLASS="LITERAL" >D</TT ></DT ><DD ><P >This is a case sensitive match. Normally the patterns match either uppercase or lowercase text. <TT CLASS="LITERAL" >/john/</TT > will match "John", "john", or "JOHN". Specify the D option for a case-sensitive search: lowercase letters in the pattern must match lowercase letters in the message; ditto for uppercase.</P ></DD ></DL ></DIV ><P >Please note that the 'b' and the 'w' options consume an excessive amount of CPU time, and should be avoided, if possible. HINT: If possible, use the <VAR CLASS="VARNAME" >SIZE</VAR > variable to avoid using patterns with these flags on large messages.</P ><P >If neither 'h' or 'b' is specified, the pattern is matched against the header only. Specifying the 'b' option causes the pattern to be matched against the message body. Specifying both causes the pattern to be matched against the entire message.</P ><P >Normally, each line in the message gets matched against the pattern individually. When applying patterns to a header, multi-line headers (headers split on several lines by beginning each continuation line with whitespace) are silently combined into a single line, before the pattern is applied. Specifying the 'w' flag causes the pattern to be applied to the whole part of the message that's being searched (which is specified via the presence, or the absence, of the h and b flags). Also, if the 'w' flag is used, but neither 'h' nor 'b' flags are used, the 'b' flag is the default, instead of the 'h' flag.</P ><P >This flag also changes the way that <SPAN CLASS="TOKEN" >^</SPAN > and <SPAN CLASS="TOKEN" >$</SPAN > is interpreted in patterns. Normally, those characters anchor the pattern at the beginning, or the end, of each line. When the 'w' flag is specified, <SPAN CLASS="TOKEN" >^</SPAN > and <SPAN CLASS="TOKEN" >$</SPAN > anchors the pattern against the beginning, or the end, of either the header, body, or both.</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN600" ></A ><H3 >Weighted scoring</H3 ><P >Patterns are evaluated by <B CLASS="COMMAND" >maildrop</B > as any other numerical expression. If a pattern is found, <B CLASS="COMMAND" >maildrop</B >'s filter interprets the results of the pattern match as number 1, or true, for filtering purposes. If a pattern is not found the results of the pattern search is zero. Once a pattern is found, the search stops. Second, and subsequent occurrences of the same pattern are NOT searched for.</P ><P ><B CLASS="COMMAND" >maildrop</B > can also do weighted scoring. In weighted scoring, multiple occurrences of the same pattern are used to calculate a numerical score.</P ><P >To use a weighted search, specify the pattern as follows: <A NAME="AEN608" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN609" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >/<VAR CLASS="REPLACEABLE" >pattern</VAR >/:<VAR CLASS="REPLACEABLE" >options</VAR >,<VAR CLASS="REPLACEABLE" >xxx</VAR >,<VAR CLASS="REPLACEABLE" >yyy</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE > where <VAR CLASS="REPLACEABLE" >xxx</VAR > and <VAR CLASS="REPLACEABLE" >yyy</VAR > are two numbers. <VAR CLASS="REPLACEABLE" >yyy</VAR > is optional -- it will default to 1, if missing.</P ><P >The first occurrence of the pattern is evaluated as xxx. The second occurrence of the pattern is evaluated as xxx*yyy, the third as xxx*yyy*yyy, etc... All occurrences of the pattern are added up to calculate the final score.</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >When the <TT CLASS="LITERAL" >w</TT > option is not specified, <B CLASS="COMMAND" >maildrop</B > does not recognize multiple occurrences of the same pattern in the same line. This is required in order to have the <SPAN CLASS="TOKEN" >^</SPAN > and <SPAN CLASS="TOKEN" >$</SPAN > operators working correctly. For example: <A NAME="AEN625" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN626" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >/^Received:/:1</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE > This pattern counts how many Received: headers the message has, and does not recognize any occurrences of the text "Received:" anywhere else in the headers.</P ></TD ></TR ></TABLE ></DIV ><P >You must specify the <TT CLASS="LITERAL" >w</TT > option in order to take into account multiple occurrences of the same pattern in the message. This also activates all the usual semantics of the 'w' option. For example: <A NAME="AEN630" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN631" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >/[:upper:]/:wbD,1</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE > counts the number of uppercase letters in the body of the message.</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN633" ></A ><H3 >Pattern Match Results</H3 ><A NAME="PATMATCH" ></A ><P >After a pattern is successfully matched, the actual text that is matched is placed in the <VAR CLASS="VARNAME" >MATCH</VAR > variable. For example: <A NAME="AEN638" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN639" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >/^From:.*/</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE > matches a line of the form: <A NAME="AEN641" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN642" ></A ><P >From: postmaster@localhost</P ><P ></P ></DIV ></BLOCKQUOTE ></P ><P >Here the variable <VAR CLASS="VARNAME" >MATCH</VAR > will be set to "From: postmaster@localhost", which can be used in subsequent statements. It is possible to use selective parts of the matched string by using the <SPAN CLASS="TOKEN" >!</SPAN > character in patterns. For example: <A NAME="AEN647" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN648" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >/^From: *!.*/</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE > matched against the same line will set <VAR CLASS="VARNAME" >MATCH</VAR > to "From: " and <VAR CLASS="VARNAME" >MATCH2</VAR > to "postmaster@localhost". More than one <SPAN CLASS="TOKEN" >!</SPAN > character may be used. Subsequent matched text is assigned to <VAR CLASS="VARNAME" >MATCH3</VAR >, <VAR CLASS="VARNAME" >MATCH4</VAR >, and so on.</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >Please note that the abuse of this feature will eat plenty of CPU time -- the <SPAN CLASS="TOKEN" >!</SPAN > character introduces a lot of complexity for <B CLASS="COMMAND" >maildrop</B > to deal with.</P ></TD ></TR ></TABLE ></DIV ><P >When there is more than one way to match a string, <B CLASS="COMMAND" >maildrop</B > favors matching as much as possible initially. For example: <A NAME="AEN661" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN662" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >/^To:.*,!.*/</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE > when matched against <A NAME="AEN664" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN665" ></A ><P >To: joe@somewhere,bob@somewhere.else,gary@whoknowswhere</P ><P ></P ></DIV ></BLOCKQUOTE > will set <VAR CLASS="VARNAME" >MATCH</VAR > to "To: joe@somewhere,bob@somewhere.else," and <VAR CLASS="VARNAME" >MATCH2</VAR > to "gary@whoknowswhere".</P ><P >The <VAR CLASS="VARNAME" >MATCH</VAR > variables are NOT set when weighted scoring is used, since the same pattern is matched multiple times.</P ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN671" ></A ><H3 >Expressions</H3 ><P >Although <B CLASS="COMMAND" >maildrop</B > evaluates expressions numerically, results of expressions are stored as text literals. When necessary, text literals are converted to numbers, then the results of a mathematical operation is converted back into a text literal.</P ><DIV CLASS="REFSECT3" ><A NAME="AEN675" ></A ><H4 >Operators</H4 ><P >The following operators carry their usual meaning, and are listed in order from lowest precedence, to the highest:</P ><A NAME="AEN678" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN679" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" > || && < <= > >= == != lt le gt ge eq ne | & + - * / =~ /<VAR CLASS="REPLACEABLE" >pattern</VAR >/ /<VAR CLASS="REPLACEABLE" >pattern</VAR >/ ! ~ <VAR CLASS="REPLACEABLE" >function()</VAR > </PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN684" ></A ><H4 >Variable assignment</H4 ><A NAME="ASSIGN" ></A ><A NAME="AEN687" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN688" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >VARIABLE=<VAR CLASS="REPLACEABLE" >expression</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >Assigns the result of the expression to <VAR CLASS="REPLACEABLE" >VARIABLE</VAR > (note no leading $ in front of variable).</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >If <VAR CLASS="REPLACEABLE" >VARIABLE</VAR > is NOT surrounded by quotes, then it may contain only letters, numbers, underscores, dashes, and a selected few other characters. In order to initialize a variable whose name contains non-standard punctuation marks, surround the name of the variable with quotes.</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN696" ></A ><H4 >cc - deliver a copy of the message</H4 ><A NAME="CC" ></A ><A NAME="AEN699" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN700" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >cc <VAR CLASS="REPLACEABLE" >expression</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The <B CLASS="COMMAND" >cc</B > statement is very similar to the <B CLASS="COMMAND" >to</B > statement, except that after delivering the message <B CLASS="COMMAND" >maildrop</B > continues to process the <SPAN CLASS="SYSTEMITEM" >filter file</SPAN >, unlike the <B CLASS="COMMAND" >to</B > statement which immediately terminates <B CLASS="COMMAND" >maildrop</B > after the delivery is complete. Essentially, the message is carbon copied to the given mailbox, and may be delivered again to another mailbox by another <B CLASS="COMMAND" >cc</B > or <B CLASS="COMMAND" >to</B > statement.</P ><P ><A HREF="#to" TARGET="_top" >See the <B CLASS="COMMAND" >to</B > statement</A > for more details. When <B CLASS="COMMAND" >cc</B > is used to deliver a message to a process <B CLASS="COMMAND" >maildrop</B > will set the <VAR CLASS="VARNAME" >EXITCODE</VAR > variable to the process's exit code.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN718" ></A ><H4 >dotlock - create a manual dot-lock</H4 ><A NAME="DOTLOCK" ></A ><A NAME="AEN721" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN722" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >dotlock <VAR CLASS="REPLACEABLE" >expression</VAR > { ... }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P ><B CLASS="COMMAND" >maildrop</B > automatically creates a lock when a message is delivered to a mailbox. Depending upon your system configuration, <B CLASS="COMMAND" >maildrop</B > will use either dot-locks, or the flock() system call.</P ><P >The <B CLASS="COMMAND" >dotlock</B > statement creates an explicit dot-lock file. Use the <A HREF="#flock" TARGET="_top" ><B CLASS="COMMAND" >flock</B > statement</A > to create an explicit flock() lock.</P ><P >The <VAR CLASS="REPLACEABLE" >expression</VAR > is a filename that should be used as a lock file. <B CLASS="COMMAND" >maildrop</B > creates the indicated dot-lock, executes the filtering instructions contained within the { ... } block, and removes the lock. The expression <I CLASS="EMPHASIS" >must</I > be the name of the dot-lock file itself, <I CLASS="EMPHASIS" >NOT</I > the name of the mailbox file you want to lock.</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >With manual locking, it is possible to deadlock multiple <B CLASS="COMMAND" >maildrop</B > processes (or any other processes that try to claim the same locks).</P ><P >No deadlock detection is possible with dot-locks, and since <B CLASS="COMMAND" >maildrop</B > automatically refreshes all of its dot-locks regularly, they will never go stale. You'll have <B CLASS="COMMAND" >maildrop</B > processes hanging in limbo, until their watchdog timers go off, aborting the mail delivery.</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN743" ></A ><H4 >echo - output diagnostic information</H4 ><A NAME="ECHO" ></A ><A NAME="AEN746" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN747" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >echo <VAR CLASS="REPLACEABLE" >expression</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P ><B CLASS="COMMAND" >maildrop</B > will print the given text. This is usually used when <B CLASS="COMMAND" >maildrop</B > runs in embedded mode, but can be used for debugging purposes. Normally, a newline is printed after the text. If text is terminated with a \c, no newline will be printed.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN753" ></A ><H4 >exception - trap fatal errors</H4 ><A NAME="EXCEPTION" ></A ><A NAME="AEN756" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN757" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >exception { ... }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The <B CLASS="COMMAND" >exception</B > statement traps errors that would normally cause <B CLASS="COMMAND" >maildrop</B > to terminate. If a fatal error is encountered anywhere within the block of statements enclosed by the <B CLASS="COMMAND" >exception</B > clause, execution will resume immediately following the <B CLASS="COMMAND" >exception</B > clause.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN764" ></A ><H4 >exit - terminate filtering unconditionally</H4 ><A NAME="EXIT" ></A ><A NAME="AEN767" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN768" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >exit</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The <B CLASS="COMMAND" >exit</B > statement immediately terminates filtering. <B CLASS="COMMAND" >maildrop</B >'s return code is set to the value of the <VAR CLASS="VARNAME" >EXITCODE</VAR > variable. Normally, <B CLASS="COMMAND" >maildrop</B > terminates immediately after <A HREF="#to" TARGET="_top" >successfully delivering the message</A > to a mailbox. The <B CLASS="COMMAND" >exit</B > statement causes <B CLASS="COMMAND" >maildrop</B > to terminate without delivering the message anywhere.</P ><P >The <B CLASS="COMMAND" >exit</B > statement is usually used when <B CLASS="COMMAND" >maildrop</B > runs in <A HREF="maildrop.html#embedded" TARGET="_top" >embedded mode</A >, when message delivery instructions are not allowed.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN782" ></A ><H4 >flock - create an manual flock() lock</H4 ><A NAME="FLOCK" ></A ><A NAME="AEN785" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN786" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >flock <VAR CLASS="REPLACEABLE" >expression</VAR > { ... }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P ><B CLASS="COMMAND" >maildrop</B > automatically creates a lock when a message is delivered to a mailbox. Depending upon your system configuration, <B CLASS="COMMAND" >maildrop</B > will use either dot-locks, or the flock() system call.</P ><P >The <B CLASS="COMMAND" >flock</B > statement creates a manual flock() lock. Use the <A HREF="#dotlock" TARGET="_top" ><B CLASS="COMMAND" >dotlock</B > statement</A > to create a manual dot-lock file.</P ><P >The <VAR CLASS="REPLACEABLE" >expression</VAR > is the name of the file that should be locked. <B CLASS="COMMAND" >maildrop</B > creates the lock on the indicated file, executes the filtering instructions contained within the { ... } block, and removes the lock.</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >With manual locking, it is possible to deadlock multiple <B CLASS="COMMAND" >maildrop</B > processes (or any other processes that try to claim the same locks). The operating system will automatically break flock() deadlocks. When that happens, one of the <B CLASS="COMMAND" >maildrop</B > processes will terminate immediately. Use the <B CLASS="COMMAND" >exception</B > statement in order to trap this exception condition, and execute an alternative set of filtering instructions.</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN804" ></A ><H4 >foreach - iterate over text sections matched by a pattern</H4 ><A NAME="AEN806" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN807" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >foreach /pattern/:options { ... } foreach (expression) =~ /pattern/:options { ... }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The <B CLASS="COMMAND" >foreach</B > statement executes a block of statements for each occurrence of the given pattern in the given message, or expression. On every iteration <VAR CLASS="VARNAME" >MATCH</VAR > variable will be set to the matched string. All the usual options may be applied to the pattern match, EXCEPT the following: <P ></P ><DIV CLASS="VARIABLELIST" ><DL ><DT >,xxx,yyy</DT ><DD ><P >Weighted scoring is meaningless, in this context.</P ></DD ><DT >!</DT ><DD ><P >The ! operator in the pattern does not work as expected. For each iteration, only the <VAR CLASS="VARNAME" >MATCH</VAR > variable will be set. If the pattern includes the ! operator, the statements will be executed once for each section in the matched string, with the <VAR CLASS="VARNAME" >MATCH</VAR > variable set to the contents of each section.</P ></DD ></DL ></DIV ></P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN823" ></A ><H4 >if - conditional execution</H4 ><A NAME="IF" ></A ><A NAME="AEN826" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN827" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >if (<VAR CLASS="REPLACEABLE" >expression</VAR >) { ... } else { ... }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >Conditional execution. If <VAR CLASS="REPLACEABLE" >expression</VAR > evaluates to a logical true (note - parenthesis are required) then the first set of statements is executed. The <B CLASS="COMMAND" >else</B > keyword, and the subsequent statements, are optional. If present, and the expression evaluates to a logical false, the <B CLASS="COMMAND" >else</B > part is executed.</P ><P ><B CLASS="COMMAND" >maildrop</B > evaluates all expression as text strings. In the context of a logical expression, an empty string, or the number 0 constitutes a logical false value, anything else is a logical true value.</P ><P >If the <B CLASS="COMMAND" >if</B > part, or the <B CLASS="COMMAND" >else</B > part consists of only one statement, the braces may be omitted.</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >The grammar of this <B CLASS="COMMAND" >if</B > statement is stricter than usual. If you get baffling syntax errors from <B CLASS="COMMAND" >maildrop</B >, make sure that the braces, and the if statement, appear on separate lines. Specifically: the closing parenthesis, the closing braces, and the else statement, must be at the end of the line (comments are allowed), and there may not be any blank lines in between (not even ones containing comments only).</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN843" ></A ><H4 >import - access original environment variable</H4 ><A NAME="IMPORT" ></A ><A NAME="AEN846" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN847" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >import <VAR CLASS="REPLACEABLE" >variable</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >When <B CLASS="COMMAND" >maildrop</B > starts, it normally imports the contents of the environment variables, and assigns them to internal <B CLASS="COMMAND" >maildrop</B > variables. For example, if there was an environment variable <VAR CLASS="VARNAME" >FOO</VAR >, the internal <B CLASS="COMMAND" >maildrop</B > variable <VAR CLASS="VARNAME" >FOO</VAR > will have the contents of the environment variable. From then on, <VAR CLASS="VARNAME" >FOO</VAR > will be no different than any other variable, and when <B CLASS="COMMAND" >maildrop</B > runs an external command, the contents of <B CLASS="COMMAND" >maildrop</B >'s variables will be exported as the environment for the command.</P ><P >Certain variables, like <VAR CLASS="VARNAME" >HOME</VAR > and <VAR CLASS="VARNAME" >PATH</VAR >, are always reset to fixed defaults, for security reasons. Also, in delivery and embedded modes, the environment is not imported at all, and <B CLASS="COMMAND" >maildrop</B > starts with only the fixed default variables.</P ><P >The <B CLASS="COMMAND" >import</B > statement initializes the specified variable with the contents of the original environment variable when <B CLASS="COMMAND" >maildrop</B > started. For example: <A NAME="AEN866" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN867" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >echo "PATH is $PATH" PATH="/bin" echo "PATH is $PATH" import PATH echo "PATH is $PATH" exit</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></P ><P >This results in the following output: <A NAME="AEN870" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN871" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >PATH is /bin:/usr/bin:/usr/local/bin PATH is /bin PATH is /home/root/bin:/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></P ><P >This shows that when <B CLASS="COMMAND" >maildrop</B > starts <VAR CLASS="VARNAME" >PATH</VAR > is set to the fixed default of <TT CLASS="LITERAL" >/bin:/usr/bin:/usr/local/bin</TT >. However, the original contents of the <VAR CLASS="VARNAME" >PATH</VAR > environment variable we different, and the <B CLASS="COMMAND" >import</B > statement shows what it was.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN879" ></A ><H4 >include - execute filtering instructions from another file</H4 ><A NAME="INCLUDE" ></A ><A NAME="AEN882" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN883" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >include <VAR CLASS="REPLACEABLE" >expression</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The include statement reads a file, and executes filtering instructions contained in that file. Note that the include statement is processed when the current <SPAN CLASS="SYSTEMITEM" >filter file</SPAN > is being executed. When <B CLASS="COMMAND" >maildrop</B > reads the initial <SPAN CLASS="SYSTEMITEM" >filter file</SPAN >, any syntax errors in the filtering instructions are immediately reported, and <B CLASS="COMMAND" >maildrop</B > will terminate with a return code of <SPAN CLASS="ERRORCODE" >EX_TEMPFAIL</SPAN >. Any errors in files specified by <B CLASS="COMMAND" >include</B > statements are NOT reported, because those files will not be read until the <B CLASS="COMMAND" >include</B > statement is itself executed.</P ><P >If the specified file does not exist, or if there are any syntax errors in the file, <B CLASS="COMMAND" >maildrop</B > reports the error, and terminates with a return code of <SPAN CLASS="ERRORCODE" >EX_TEMPFAIL</SPAN >.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN897" ></A ><H4 >log, logfile - log message deliveries</H4 ><A NAME="LOG" ></A ><A NAME="AEN900" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN901" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >logfile <VAR CLASS="REPLACEABLE" >expression</VAR > log <VAR CLASS="REPLACEABLE" >expression</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >Logging in <B CLASS="COMMAND" >maildrop</B > is normally turned off. The <B CLASS="COMMAND" >logfile</B > statement specifies the file where <B CLASS="COMMAND" >maildrop</B > will log how the message has been disposed of. The parameter is then name of the file. If the file exists <B CLASS="COMMAND" >maildrop</B > appends to the file.</P ><P >For each delivery (the <A HREF="#to" TARGET="_top" ><B CLASS="COMMAND" >to</B ></A > and <A HREF="#cc" TARGET="_top" ><B CLASS="COMMAND" >cc</B ></A > statements, and default deliveries) <B CLASS="COMMAND" >maildrop</B > records the <TT CLASS="LITERAL" >From:</TT > and the <TT CLASS="LITERAL" >Subject:</TT > fields, together with the current time, in the log file.</P ><P >The <B CLASS="COMMAND" >log</B > statement adds additional logging text to the log file. The <B CLASS="COMMAND" >log</B > statement works exactly like the <B CLASS="COMMAND" >echo</B > statement, except that the text is written to the logfile, instead of standard output.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN922" ></A ><H4 >to - deliver message to a mailbox</H4 ><A NAME="TO" ></A ><A NAME="AEN925" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN926" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >to <VAR CLASS="REPLACEABLE" >expression</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The <B CLASS="COMMAND" >to</B > statement delivers the message to a mailbox. <VAR CLASS="REPLACEABLE" >expression</VAR > must evaluate to a valid mailbox. A valid mailbox is either a mailbox file, a maildir, or an external program (which includes forwarding to another address).</P ><P >The <B CLASS="COMMAND" >to</B > statement is the final delivery statement. <B CLASS="COMMAND" >maildrop</B > delivers message, then immediately terminates, with its return code set to the <VAR CLASS="VARNAME" >EXITCODE</VAR > variable. If there was an error while delivering the message, <B CLASS="COMMAND" >maildrop</B > terminates with the <SPAN CLASS="ERRORCODE" >EX_TEMPFAIL</SPAN > exit code. A properly-written mail transport agent should re-queue the message, and re-attempt delivery at some later time.</P ><P >An <VAR CLASS="REPLACEABLE" >expression</VAR > that begins with the "<SPAN CLASS="TOKEN" >|</SPAN >" character specifies an external program to run to handle the actual delivery. The <VAR CLASS="VARNAME" >SHELL</VAR > variable specifies the shell to execute the given command. The message is provided to the command on standard input. <B CLASS="COMMAND" >maildrop</B >'s exit code will be the process's exit code.</P ><P >An <VAR CLASS="REPLACEABLE" >expression</VAR > that begins with an exclamation mark, "<SPAN CLASS="TOKEN" >!</SPAN >" specifies a whitespace-delimited list of E-mail addresses to forward the message to. The program specified by the <VAR CLASS="VARNAME" >SENDMAIL</VAR > variable is run as an external program, with the list of E-mail addresses provided as parameters to the program.</P ><P >Otherwise, <VAR CLASS="REPLACEABLE" >expression</VAR > names the mailbox where <B CLASS="COMMAND" >maildrop</B > delivers the message. If <VAR CLASS="REPLACEABLE" >expression</VAR > is a directory, <B CLASS="COMMAND" >maildrop</B > assumes that the directory is a maildir directory. Otherwise, <B CLASS="COMMAND" >maildrop</B > will deliver the message to a file, formatted in traditional mailbox format. <B CLASS="COMMAND" >maildrop</B > will use either dot-locking, or flock()-locking when delivering the message to the file.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN954" ></A ><H4 >while - repeatedly execute a block of statements</H4 ><A NAME="WHILE" ></A ><A NAME="AEN957" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN958" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >while (<VAR CLASS="REPLACEABLE" >expression</VAR >) { ... }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The <VAR CLASS="REPLACEABLE" >expression</VAR > is repeatedly evaluated. Each time it <A HREF="#if" TARGET="_top" >evaluates to a logical true</A >, the statements inside the braces are executed. When <VAR CLASS="REPLACEABLE" >expression</VAR > evaluates to a logical false, the while loop is over. Take care to avoid infinite loops.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN965" ></A ><H4 >xfilter - filter message through another program</H4 ><A NAME="XFILTER" ></A ><A NAME="AEN968" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN969" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >xfilter <VAR CLASS="REPLACEABLE" >expression</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P ><VAR CLASS="REPLACEABLE" >expression</VAR > specifies an external program that <B CLASS="COMMAND" >maildrop</B > runs to filter the current message. The current message will be piped to the filter program as standard input. The output of the filter program replaces the current message being delivered. The external program must terminate with an exit code of 0. If the external program does not terminate with an exit code of 0, or if it does not read the message from the standard input, <B CLASS="COMMAND" >maildrop</B > terminates with an exit code of <SPAN CLASS="ERRORCODE" >EX_TEMPFAIL</SPAN >.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN977" ></A ><H4 >|| - logical or</H4 ><A NAME="AEN979" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN980" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >||</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > </PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >If <VAR CLASS="REPLACEABLE" >expression1</VAR > evaluates to a logical true, the result of the <SPAN CLASS="TOKEN" >||</SPAN > is <VAR CLASS="REPLACEABLE" >expression1</VAR >, otherwise it's <VAR CLASS="REPLACEABLE" >expression2</VAR >, which is evaluated.</P ><P ><B CLASS="COMMAND" >maildrop</B > uses the following concept of true/false: an empty text literal, or a text literal that consists of the single character "0" is a logical false value. Anything else is a logical true value.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN992" ></A ><H4 >&& - logical and</H4 ><A NAME="AEN994" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN995" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >&&</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > </PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >If <VAR CLASS="REPLACEABLE" >expression1</VAR > evaluates to a logical false, the result of the <SPAN CLASS="TOKEN" >&&</SPAN > is <VAR CLASS="REPLACEABLE" >expression1</VAR >, otherwise it's <VAR CLASS="REPLACEABLE" >expression2</VAR >, which is evaluated.</P ><P ><B CLASS="COMMAND" >maildrop</B > uses the following concept of true/false: an empty text literal, or a text literal that consists of the single character "0" is a logical false value. Anything else is a logical true value.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1007" ></A ><H4 ><, <=, >, >=, ==, != - numerical comparison</H4 ><A NAME="AEN1009" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1010" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" ><</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" ><=</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >></SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >>=</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >==</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >!=</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > </PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >These operators compare their left hand side expression against their right hand side. These operators compare the numerical values of each side, as floating point numbers. If the numbers compare as indicated, the result of the comparison is the text string "1", otherwise it is the text string 0.</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >Ccomparisons are not associative: "<TT CLASS="LITERAL" >a < b < c</TT >" is an error. If it is absolutely necessary, use "<TT CLASS="LITERAL" >(a < b) < c</TT >".</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1035" ></A ><H4 >lt, le, gt, ge, eq, ne - text comparison</H4 ><A NAME="AEN1037" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1038" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >lt</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >le</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >gt</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >ge</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >eq</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >ne</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > </PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >These operators compare their left hand side expression against their right hand side. These operators compare each side as text strings (alphabetically, although the text may include anything). If the text strings compare as indicated, the result of the comparison is the text string "1", otherwise it is the text string 0.</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >Comparisons are not associative: "<TT CLASS="LITERAL" >a lt b lt c</TT >" is an error. If it is absolutely necessary, use "<TT CLASS="LITERAL" >(a lt b) lt c</TT >". (But why would you?).</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1063" ></A ><H4 >| - bitwise or</H4 ><A NAME="AEN1065" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1066" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >|</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >This is the bitwise or operator. Its result is a 32 bit integer, which is a bitwise-or combination of the left hand side and the right hand side.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1072" ></A ><H4 >& - bitwise and</H4 ><A NAME="AEN1074" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1075" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >&</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >This is the bitwise and operator. Its result is a 32 bit integer, which is a bitwise-and combination of the left hand side and the right hand side.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1081" ></A ><H4 >+, -, *, / - numerical operations</H4 ><A NAME="AEN1083" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1084" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >+</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >-</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >*</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > <VAR CLASS="REPLACEABLE" >expression1</VAR > <SPAN CLASS="TOKEN" >/</SPAN > <VAR CLASS="REPLACEABLE" >expression2</VAR > </PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >These are numerical, floating point, operators.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1099" ></A ><H4 >=~ /pattern/:options - pattern match against string</H4 ><A NAME="AEN1101" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1102" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><VAR CLASS="REPLACEABLE" >expression</VAR > <SPAN CLASS="TOKEN" >=~</SPAN > /<VAR CLASS="REPLACEABLE" >pattern</VAR >:<VAR CLASS="REPLACEABLE" >option</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The left hand side of the <SPAN CLASS="TOKEN" >=~</SPAN > operator can be any expression. The right hand side is always a pattern specification. The result of the operator is the weighted match of the pattern against <VAR CLASS="REPLACEABLE" >expression</VAR > (if the options do not specify weighted scoring, the result is simply 1 if the pattern was found, 0 if not).</P ><P >See "<A HREF="#patterns" TARGET="_top" >Patterns</A >" for more information.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1113" ></A ><H4 >/pattern/:options - pattern match against message</H4 ><A NAME="AEN1115" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1116" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><VAR CLASS="REPLACEABLE" >expression</VAR > <SPAN CLASS="TOKEN" >=~</SPAN > /<VAR CLASS="REPLACEABLE" >pattern</VAR >:<VAR CLASS="REPLACEABLE" >option</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The result of this operator is the weighted match of the pattern against the current message (if the options do not specify weighted scoring, the result is simply 1 if the pattern was found, 0 if not).</P ><P >See "<A HREF="#patterns" TARGET="_top" >Patterns</A >" for more information.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1125" ></A ><H4 >!, ~ - logical/bitwise not operator.</H4 ><A NAME="AEN1127" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1128" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><SPAN CLASS="TOKEN" >!</SPAN > <VAR CLASS="REPLACEABLE" >expression</VAR > <SPAN CLASS="TOKEN" >~</SPAN > <VAR CLASS="REPLACEABLE" >expression</VAR ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The result of the <SPAN CLASS="TOKEN" >!</SPAN > operator is a logical opposite of its right hand side expression. If the right hand side expression evaluated to a logical true, the result is a logical false. If it evaluated to a logical false, the result is a logical true.</P ><P ><B CLASS="COMMAND" >maildrop</B > uses the following concept of true/false: an empty text literal, or a text literal that consists of the single character "0" is a logical false value. Anything else is a logical true value.</P ><P >The result of the <SPAN CLASS="TOKEN" >~</SPAN > operator is a bitwise complement of its right hand side expression. The right hand side expression is evaluated as a 32 bit integer, and the result of this operator is a bitwise complement of the result.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1140" ></A ><H4 >escape(string) - escape special characters in a string.</H4 ><A NAME="AEN1142" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1143" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" ><TT CLASS="FUNCTION" >escape</TT >(<VAR CLASS="REPLACEABLE" >expression</VAR >)</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The <TT CLASS="FUNCTION" >escape</TT > function returns its sole argument with every occurrence of a special character prefixed by a backslash. A special character is any of the following characters: <A NAME="AEN1149" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1150" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >|!$()[]\+*?.&;`'-~<>^{}"</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></P ><P >This can used when <A HREF="#patmatch" TARGET="_top" >matching pattern sections</A >, and then taking one section and matching it again. For example: <A NAME="AEN1154" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1155" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >if ( /^From: *!.*/ ) { MATCH2=escape($MATCH2) if ( /^Subject:.*$MATCH2/ ) { ... } }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></P ><P >This example checks if the contents of the <TT CLASS="LITERAL" >From:</TT > header can also be found in the <TT CLASS="LITERAL" >Subject:</TT > header. If the <TT CLASS="FUNCTION" >escape</TT > function were not used, then any special characters in the <TT CLASS="LITERAL" >From:</TT > header that are also used in regular expressions, such as <SPAN CLASS="TOKEN" >*</SPAN > or <SPAN CLASS="TOKEN" >+</SPAN >, would introduce unpredictable behavior, most likely a syntax error.</P ><P >The reason why this list of special characters also includes characters not used in <B CLASS="COMMAND" >maildrop</B >'s regular expressions is to allow <B CLASS="COMMAND" >maildrop</B >'s variables to be used on the command line of a shell command executed by the <B CLASS="COMMAND" >xfilter</B > command, backtick characters, or <B CLASS="COMMAND" >to</B > or <B CLASS="COMMAND" >cc</B > commands.</P ><P >Although using data from an external data source is dangerous, and it may result in inadvertent exploits, using the escape function should hopefully result in fewer surprises.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1171" ></A ><H4 >gdbmopen, gdbmclose, gdbmfetch, gdbmstore - GDBM support in <B CLASS="COMMAND" >maildrop</B ></H4 ><P >These functions provide support for GDBM database files. See <A HREF="maildropgdbm.html" TARGET="_top" ><SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >maildropgdbm</SPAN >(5)</SPAN ></A > for more information.</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >The system administrator can disable GDBM support in <B CLASS="COMMAND" >maildrop</B >, so these commands may not be available to you.</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1182" ></A ><H4 >getaddr(string) - extract RFC 2822 addresses from a header.</H4 ><A NAME="GETADDR" ></A ><A NAME="AEN1185" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1186" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >if ( /^From: *!.*/ ) { ADDR=getaddr($MATCH2) }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >This function is usually applied to a header that contains <A HREF="http://www.rfc-editor.org/rfc/rfc2822.txt" TARGET="_top" >RFC 2822</A > addresses. It extracts the actual addresses from the header, without any comments or extraneous punctuation. Each address is followed by a newline character. For example, if <VAR CLASS="REPLACEABLE" >string</VAR > contains: <A NAME="AEN1191" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1192" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >joe@domain.com (Joe Brown), "Alex Smith" <alex@domain.com>, tom@domain.com</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE > The result of the <TT CLASS="FUNCTION" >getaddr</TT > function is the following string: <A NAME="AEN1195" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1196" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >joe@domain.com<SPAN CLASS="TOKEN" ><NL></SPAN >alex@domain.com<SPAN CLASS="TOKEN" ><NL></SPAN >tom@domain.com<SPAN CLASS="TOKEN" ><NL></SPAN ></PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >Because <TT CLASS="FUNCTION" >getaddr</TT >() interprets <A HREF="http://www.rfc-editor.org/rfc/rfc822.txt" TARGET="_top" >RFC 2822</A > loosely, it is not necessary to strip off the "<TT CLASS="LITERAL" >To:</TT >" or the "<TT CLASS="LITERAL" >Cc:</TT >" header from the string, before feeding it to <TT CLASS="FUNCTION" >getaddr()</TT >. For example, the following snippet of code takes all addresses in the message, and concatenates them into a single string, separated by spaces: <A NAME="AEN1208" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1209" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >ADDRLIST="" foreach /^(To|Cc): .*/ { foreach (getaddr $MATCH) =~ /.+/ { ADDRLIST="$ADDRLIST $MATCH" } }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></P ></TD ></TR ></TABLE ></DIV ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >In certain rare situations, <A HREF="http://www.rfc-editor.org/rfc/rfc822.txt" TARGET="_top" >RFC 2822</A > allows spaces to be included in E-mail addresses, so this example is just educational.</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1214" ></A ><H4 >hasaddr(string) - Search for an address.</H4 ><A NAME="AEN1216" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1217" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >if ( hasaddr(<VAR CLASS="REPLACEABLE" >string</VAR >) ) { ... }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >"<VAR CLASS="REPLACEABLE" >string</VAR >" is of the form <TT CLASS="LITERAL" >user@domain</TT >. The hasaddr function returns 1 if this address is included in any <TT CLASS="LITERAL" >To:</TT >, <TT CLASS="LITERAL" >Cc:</TT >,<TT CLASS="LITERAL" > Resent-To:</TT >, or <TT CLASS="LITERAL" >Resent-Cc:</TT >, header in the message, otherwise this function returns 0.</P ><P >This is more than just a simple text search. Each header is parsed according to <TT CLASS="LITERAL" >RFC822</TT >. Addresses found in the header are extracted, ignoring all comments and names. The remaining addresses are checked, and if "<VAR CLASS="REPLACEABLE" >string</VAR >" is one of them, <TT CLASS="FUNCTION" >hasaddr</TT > returns 1, otherwise it returns 0.</P ><P >The comparison is case-insensitive. This actually violates <TT CLASS="LITERAL" >RFC822</TT > (and several others) a little bit, because the user part of the address may be (but is not required to be) case sensitive.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1233" ></A ><H4 >length (string) - length of a string</H4 ><A NAME="AEN1235" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1236" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >if (length(<VAR CLASS="REPLACEABLE" >string</VAR >) > 80) { ... }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The <TT CLASS="FUNCTION" >length</TT > function returns the number of characters in <VAR CLASS="REPLACEABLE" >string</VAR >.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1242" ></A ><H4 >lookup (expr, 'filename', 'options') - read file for patterns</H4 ><A NAME="AEN1244" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1245" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >if (lookup(<VAR CLASS="REPLACEABLE" >expr</VAR >, <TT CLASS="FILENAME" >file</TT >, "<VAR CLASS="REPLACEABLE" >option</VAR >")) { ... }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P ><VAR CLASS="REPLACEABLE" >expr</VAR > is any expression. <TT CLASS="FILENAME" >filename</TT > is a name of a file containing a list of patterns. Note that <TT CLASS="FILENAME" >filename</TT > is relative to the current directory, which is the home directory of the user when <B CLASS="COMMAND" >maildrop</B > runs in delivery mode, or embedded mode. <B CLASS="COMMAND" >maildrop</B > then reads the file. Blank lines will be ignored, as well as any lines that begin with the # character (comments).</P ><P >Leading whitespace (but not trailing whitespace, take care) is removed, and the remaining contents of each line are interpreted as a pattern which is matched against <VAR CLASS="REPLACEABLE" >expr</VAR >. As soon as the match is found, <TT CLASS="FUNCTION" >lookup</TT > returns "1". If no match is found after reading the entire file, <TT CLASS="FUNCTION" >lookup</TT > returns "0". For example: <A NAME="AEN1260" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1261" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >if ( /^To: *!.*/ && lookup( $MATCH2, "badto.dat" )) { exit }</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></P ><P >The file badto.dat contains the following two lines: <A NAME="AEN1264" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1265" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >friend@public ^[^@]*$</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ></P ><P >If a message has a <TT CLASS="LITERAL" >To:</TT > header that contains the text "<TT CLASS="LITERAL" >friend@public</TT >", or does not contain at least one <SPAN CLASS="TOKEN" >@</SPAN > character, then the message will be silently dropped on the floor ( <B CLASS="COMMAND" >maildrop</B > will terminate without delivering the message anywhere).</P ><P ><VAR CLASS="REPLACEABLE" >options</VAR > are the pattern matching options to use. The only supported option is "D" (the rest are meaningless, in this case).</P ><DIV CLASS="NOTE" ><P ></P ><TABLE CLASS="NOTE" WIDTH="100%" BORDER="0" ><TR ><TD WIDTH="25" ALIGN="CENTER" VALIGN="TOP" >NOTE:</TD ><TD ALIGN="LEFT" VALIGN="TOP" ><P >Be careful with discarding messages like that. Pattern matching can be tricky, and a slight miscalculation can cause mail to be unintentionally discarded. It is much desirable to first deliver message to a separate folder or mailbox, and once the filter is verified to work correctly, change it so the messages are discarded completely.</P ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1276" ></A ><H4 >substr(string,start [,count]) - return substring</H4 ><A NAME="AEN1278" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1279" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >foo=substr($foo, 1, 10)</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The <TT CLASS="FUNCTION" >substr</TT > function takes <VAR CLASS="REPLACEABLE" >start</VAR > number of characters from <VAR CLASS="REPLACEABLE" >string</VAR >. If <VAR CLASS="REPLACEABLE" >count</VAR > is specified, at most <VAR CLASS="REPLACEABLE" >count</VAR > characters starting at position <VAR CLASS="REPLACEABLE" >start</VAR > are kept, any excess is trimmed.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1288" ></A ><H4 >time - return current time</H4 ><A NAME="AEN1290" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1291" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >foo=time</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >The <TT CLASS="FUNCTION" >time</TT > function returns the current time, in seconds, since January 1, 1970. This function is useful when using GDBM files. See <A HREF="maildropex.html" TARGET="_top" ><SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >maildropex</SPAN >(7)</SPAN ></A > for an example of using the <TT CLASS="FUNCTION" >time</TT > function.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1300" ></A ><H4 >tolower(string) - Convert string to lowercase.</H4 ><A NAME="AEN1302" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1303" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >foo=tolower(<VAR CLASS="REPLACEABLE" >string</VAR >)</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >This function returns the <VAR CLASS="REPLACEABLE" >string</VAR > with all uppercase characters replaced by lowercase characters.</P ></DIV ><DIV CLASS="REFSECT3" ><A NAME="AEN1308" ></A ><H4 >toupper(string) - Convert string to uppercase.</H4 ><A NAME="AEN1310" ></A ><BLOCKQUOTE CLASS="BLOCKQUOTE" ><DIV CLASS="INFORMALEXAMPLE" ><P ></P ><A NAME="AEN1311" ></A ><TABLE BORDER="0" BGCOLOR="#E0E0E0" WIDTH="100%" ><TR ><TD ><PRE CLASS="PROGRAMLISTING" >foo=toupper(<VAR CLASS="REPLACEABLE" >string</VAR >)</PRE ></TD ></TR ></TABLE ><P ></P ></DIV ></BLOCKQUOTE ><P >This function returns the <VAR CLASS="REPLACEABLE" >string</VAR > with all lowercase characters replaced by uppercase characters.</P ></DIV ></DIV ><DIV CLASS="REFSECT2" ><A NAME="AEN1316" ></A ><H3 >Statements</H3 ><P >The <SPAN CLASS="SYSTEMITEM" >filter file</SPAN > is read by <B CLASS="COMMAND" >maildrop</B > (<TT CLASS="FILENAME" >$HOME/.mailfilter</TT > or another file), and it contains filtering statements, one per line. The filtering language used by <B CLASS="COMMAND" >maildrop</B > has a loosely - defined grammatical structure.</P ><P >Statements are listed one per line. Multiple statements may be listed on the same line by separating them with semicolons. To continue a long statement on the next line, terminate the line with a backslash character.</P ></DIV ></DIV ><DIV CLASS="REFSECT1" ><A NAME="AEN1324" ></A ><H2 >BUGS</H2 ><P >If <TT CLASS="FUNCTION" >getaddr</TT >() or <TT CLASS="FUNCTION" >hasaddr</TT >() functions are used on broken headers, the results are unpredictable.</P ><P ><TT CLASS="FUNCTION" >hasaddr</TT >() is completely case insensitive. This actually violates a few RFCs, because the userid portion of the address could be case-sensitive, but it's not in too many cases, so there.</P ></DIV ><DIV CLASS="REFSECT1" ><A NAME="AEN1331" ></A ><H2 >SEE ALSO</H2 ><P ><A HREF="lockmail.html" TARGET="_top" ><SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >lockmail</SPAN >(1)</SPAN ></A >, <A HREF="maildrop.html" TARGET="_top" ><SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >maildrop</SPAN >(1)</SPAN ></A >, <A HREF="maildropgdbm.html" TARGET="_top" ><SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >maildropgdbm</SPAN >(5)</SPAN ></A >, <A HREF="maildirquota.html" TARGET="_top" ><SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >maildirquota</SPAN >(8)</SPAN ></A >, <A HREF="reformail.html" TARGET="_top" ><SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >reformail</SPAN >(1)</SPAN ></A >, <SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >egrep</SPAN >(1)</SPAN >, <SPAN CLASS="CITEREFENTRY" ><SPAN CLASS="REFENTRYTITLE" >sendmail</SPAN >(8)</SPAN >.</P ></DIV ></BODY ></HTML >