     [file version.texi not included]
     [file rendition.texi not included]

Published by the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

Copyright © 2005, 2006 Sergey Poznyakoff

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover texts being ``Mailfromd Manual'', and with the Back-Cover Texts as in (a) below.  A copy of the license is included in the section entitled ``GNU Free Documentation License''.

(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify this GNU Manual, like GNU software.  Copies published by the Free Software Foundation raise funds for GNU development.''

Mailfromd
*********

This edition of the Mailfromd Manual, last updated UPDATED, documents mailfromd Version VERSION.

Introduction to mailfromd
*************************

Mailfromd is a mail filter implementing sender address verification technique. The program is designed to work with Sendmail (See http://www.sendmail.org) as a Milter filter.

Sender address verification allows you to block a sender address if it is not deliverable, thereby cutting off a large amount of spam. It is also useful to block mail for undeliverable recipients, for example on a mail relay host that does not have a list of all the valid recipient addresses. This prevents undeliverable junk mail from entering the queue, so that your MTA doesn't have to waste resources trying to send MAILER-DAEMON messages back.

How Address Verification Works
******************************

A sender address is verified by probing its MX servers for that address, until one of them gives a definite (positive or negative) reply. Let's illustrate how it works on an example:

Suppose that the user <jsmith@somedomain.net> is trying to send mail to one of your local users. The remote machine connects to your MTA and issues MAIL FROM: <jsmith@somedomain.net> command. However, your MTA does not have to take its word for it, so it uses mailfromd to verify the sender address validity. Mailfromd strips the domain name from the address (somedomain.net) and queries DNS for MX records for that domain. Suppose, it receives the following list

  * 10 relay1.somedomain.net

  * 20 relay2.somedomain.net

It then connects to first MX server and asks it if it knows something about user jsmith. This is called sending a probe message. If the server replies positive, the incoming mail is accepted. Otherwise, if it replies negative the mail is rejected. If the MX server cannot be connected, mailfromd selects next server from the list and continues the described process until it finds answer or the list of servers is exhausted.

The probe message is like a normal mail except that no data are ever being sent. The probe message in our example might look as follows (S: meaning messages sent by remote MTA, C: meaning those sent by mailfromd):

     C: HELO mydomain.net
     S: 220 OK, nice to meet you
     C: MAIL FROM: <>
     S: 220 <>: Sender OK
     C: RCPT TO: <jsmith@somedomain.net>
     S: 220 <jsmith@remote.net>: Recipient OK
     C: QUIT

Probe messages are never delivered, deferred or bounced; they are always discarded.

The described method of address verification is called standard method throughout this document. Mailfromd also implements a method we call strict. When using strict method, mailfromd first resolves IP address of sender machine to a fully qualified domain name. Then it obtains MX records for this machine, and then proceeds with probing as described above.

So, the difference between the two methods is in the set of MX records that are being probed: standard method queries MXs based on the sender email domain, strict method works with MXs for the sender IP address.

Strict method allows to cut off much larger amount of spam, although it does have its drawbacks. Returning to our example above, consider the following situation: <jsmith@somedomain.net> is a perfectly normal address, but it is being used by a spammer from some other domain, say otherdomain.com. Standard method is not able to cope with such cases, whereas strict one is.

An alert reader will ask: what happens if mailfromd is not able to get a definitive answer from any of MX servers? The answer is: it returns temporary failure, which will urge the remote party to retry sending his/her message later. However, you may redefine this behavior. Actually all mailfromd actions are configurable. For the detailed description of this, see mailfromd.rc.

After receiving a definitive answer, mailfromd will cache it in its database, so that next time your MTA receives a message from that address (or from the sender IP/email address pair, for strict method), it will not waste its time trying to reach MX servers again. The records remain in the cache database for a certain time, after which they are discarded.

Limitations of Address Verification
***********************************

Before deciding whether and how to use sender address verification, you should be aware of its limitations.

Both standard and strict methods suffer from the following limitations:

  * The sender verification methods will perform poorly on highly loaded sites. The traffic and/or resource usage overhead may not be feasible for you. However, you may experiment with various mailfromd options to find an optimal configuration.

  * Some sites may blacklist your MTA if it probes them too often. This drawback can to a certain extent be eliminated by raising the expiration timeout in your cache database.

  * When verifying the remote address, no attempt to actually deliver the message is made. If MTA accepts the address, mailfromd assumes it is OK. However in reality, mail for a remote address can bounce after the nearest MTA accepts the recipient address.

  * If the remote server rejects the address, no attempt is being made to discern between various reasons for rejection (client rejected, HELO rejected, MAIL FROM rejected, etc.)

  * Unfortunately, some major sites such as yahoo.com do not reject unknown addresses in reply to the RCPT TO command, but report a delivery failure in response to end of DATA after a message is transferred. Of course, sender address verification does not work with such sites.

  * By default, mailfromd uses <> as the sender email. However such an address is not accepted by some misconfigured hosts. You may wish to alter the default address using --postmaster-email option (see pragma-mailfrom, and see option-mailfrom).

In addition, strict verification breaks forward mail delivery. This is obvious, since mail forwarding is based on delivering unmodified message to another location, so the sender address domain will most probably not be the same as that of the MTA doing the forwarding.

Configuring Send Rate.
**********************

Another feature offered by mailfromd is controlling user send rate. Send rate for a given user is defined as a number of messages he is allowed to send within the predefined interval of time.

Mailfromd configuration syntax offers a special condition rate (see rate) that checks whether the send rate for a given user is greater than a certain value. Depending on its return, a decision can be made whether to accept or to refuse the message.

For this feature to work, the package must be configured with DBM support (see next chapter).

Building the Package
********************

 1. Make sure you have the necessary software installed.

     To build mailfromd you will need to have following packages on your machine:

      A. Sendmail 8.12.9 or newer

      B. libmilter library.

          It comes with Sendmail, but is not built by default. To build Sendmail with libmilter support, add following two lines to your devtools/Site/site.config.m4:

               APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER')
               APPENDDEF(`confENVDEF', `-DBROKEN_PTHREAD_SLEEP')

          After running make install, change to the directory libmilter and run make there.

          Important note: make sure that libmilter is compiled with BROKEN_PTHREAD_SLEEP defined. If this symbol is not defined, libmilter will use sleep in signal-handler thread, which may cause various program misbehaviors, including coredumps. This problem has been asserted on (at least) GNU/Linux and FreeBSD systems.

          The mailfromd package comes with a patch to libmilter that changes its multi-process model from pthreads to forks. It has been reported that mailfromd shows better performance when linked with this modified version. If you decide to try it, notice that it will be installed under the name libmilter-fork.a, so that your original version of libmilter.a remains untouched. The patch was created for Sendmail version 8.13.1 and is located in the etc subdirectory of mailfromd distribution, in file sendmail-8.13.1.diff

          To apply the patch:

               cd sendmail-8.13.1
               patch -p0 < PATH-TO/mailfromd-VERSION/etc/sendmail-8.13.1.diff

          Then, proceed as described above in this section.

          To build mailfromd with the modified version of libmilter use --with-forks option to configure:

               ./configure --with-forks

          If you installed libmilter-fork.a to an unusual location, or renamed it, you can specify its full file name with this option, e.g.:

               ./configure --with-forks=/usr/local/lib/libmilter-fork.a

      C. GNU mailutils version 0.6 or newer.

          It is available from http://www.gnu.org/software/mailutils.

      D. A DBM library.

          Mailfromd is able to link with almost any existing library: old style libdbm, libndbm, Berkeley DB, gdbm. Notice that you can compile mailfromd without DBM too, but this is not recommended, since it will disable caching. Using mailfromd without caching can lead to increase in CPU usage, traffic outage and other disastrous effects. Besides, DBM is necessary for limiting user send rates. You have been warned.

          So, you want to select DBM implementation to use. The following table will help you do that. Column DB type lists types of DBM databases supported by mailfromd. Column confMAPDEF lists the value of confMAPDEF Sendmail configuration variable corresponding to that database type. It is here because it is usually wise to configure mailfromd to use the same database type as your Sendmail (If you don't know what confMAPDEF is, you probably are wasting your time reading this. Refer to Sendmail configuration guide first). N/A in this column means there is no support for this database in Sendmail. Finally, column configure option lists the option you should give to configure to enable using this database.

          DB type       confMAPDEF   configure option
          DBM           N/A          --with-dbm
          NDBM          -NNDBM       --with-ndbm
          Berkeley DB   -NNEWDB      --with-db2
          GDBM          N/A          --with-gdbm

 2. Decide what user privileges will be used to run mailfromd

     The program will refuse to run as root. By default it switches to the privileges of user mail, group mail. If there is no such user on your system, or you wish to use another user account for this purpose, override it using DEFAULT_USER environment variable. For example to use the privileges of user nobody, run

          ./configure DEFAULT_USER=nobody

 3. Decide where to install mailfromd and where its configuration and data files will be located.

     As usual, default value for installation prefix is /usr/local. If it does not suit you, specify another location using --prefix option, e.g.: --prefix=/usr.

     During installation phase, the build system will install several files. These files are:

     File   Purpose
     PREFIX/libexec/mailfromd   Main daemon
     PREFIX/etc/mailfromd.rc   Configuration
     file (The configuration file will be installed only if it is
     not already there. Thus, if you are upgrading to a newer version of
     mailfromd, your old configuration file will be preserved
     with all your changes.)
     PREFIX/info/mailfromd.info   Documentation

     At startup, mailfromd will look up its configuration defaults in file PREFIX/etc/mailfromd.rc.

     It is advisable to use the same settings for file name prefixes as those you used when configuring mailutils. In particular, try to use the same --sysconfdir, since it will facilitate configuring the whole system.

     Another important point is the location of local state directory, i.e. a directory where mailfromd will keep its data files (communication socket, pidfile and cache database). This directory is LOCALSTATEDIR/mailfromd.

 4. Select default communication socket.

     This is the socket used to communicate with sendmail. The default value is unix:LOCALSTATEDIR/mailfromd/mailfrom. To alter this, use DEFAULT_SOCKET environment variable, e.g.:

          ./configure DEFAULT_SOCKET=inet:999@localhost

 5. Select default expiration interval.

     The default value is 86400 seconds, i.e. 24 hours. It is OK for most sites. If, however, you wish to change it, use DEFAULT_EXPIRE_INTERVAL environment variable.

 6. Run configure with all the desired options.

     For example, the following command:

          ./configure DEFAULT_SOCKET=inet:999@localhost --with-db2

     will configure the package to use Berkeley DB2 database, and inet:999@localhost as the default communication socket.

 7. Run make.

 8. Run make install.

 9. Make sure LOCALSTATEDIR/mailfromd has right owner and mode.

 10. Examine configuration file (SYSCONFDIR/mailfromd.etc) and edit it, if necessary. If you are upgrading from an oldest copy of mailfromd, your configuration file will remain untouched.

Configuring mailfromd
*********************

In the simplest case you will be able to start up mailfromd without any additional command line options: the default values provided when compiling the package and the default configuration file are enough. Nonetheless, several methods are provided for controlling and altering the behavior of the program.

First of all, as any other utility, mailfromd accepts some command line arguments. Secondly, it is able to retrieve these arguments from a site-wide mailutils configuration file. And finally, it has its own configuration file that, among other things, defines the rules for probing email addresses.

In this chapter we will discuss both mailfromd configuration file and its command line options. The use of mailutils configuration file is covered in see Mailutils Configuration File (GNU Mailutils Manual).

Among the three methods, the use of mailfromd configuration file should be preferred.

Mailfromd Configuration File.
=============================

Mailfromd configuration file is located in SYSCONFDIR/mailfromd.rc (by default /usr/local/etc/mailfromd.rc). It allows to control all aspects of program behavior.

The file has a simple syntax, similar to that of Bourne shell. All syntactical entities are separated by any amount of white-space characterd (i.e. spaces, tabulations or newlines). The following sections describe the syntax in detail.

Comments
--------

Two types of comments are allowed: C-style, enclosed between /* and */, and shell-style, starting with # character and extending up to the end of line:

     /* This is
        a comment. */
     # This too.

If # is immediately followed by word pragma (with optional whitespace between them), such a construct introduces a pragmatic comment, i.e. an instruction changing some configuration setting. Two kinds of pragmatic comments are currently implemented: #pragma option changes a value of a run-time option, and #pragma regex controls the use of regular expressions in the configuration file.

The syntax of #pragma option is:

     #pragma option NAME VALUE

where NAME is the name of the option to set, and VALUE is its new value. String values may be enclosed in a pair of double or single quotes, although this is not mandatory. The quoting must be used only if the string contains whitespace characters.

Each NAME corresponds to a long command line option with the same semantics.

Implemented options are:

expire-interval NUMBER
     Sets expiration interval for both positive and negative cache entries to the given NUMBER of seconds.

positive-expire-interval NUMBER
     Sets expiration interval for positive cache entries to the given NUMBER of seconds.

negative-expire-interval NUMBER
     Sets expiration interval for negative cache entries to the given NUMBER of seconds.

rates-expire-interval NUMBER
     Sets expiration interval for entries in the rates database.

relay FILENAME
     Specifies the file containing names of email domains relayed by this machine. Multiple pragmas accumulate. The constructed list of domains is analyzed by relayed directive (see relayed). For example:

          #pragma option relay "/etc/mail/sendmail.cw"
          #pragma option relay "/etc/mail/relay-domains"

source ADDRESS
     Sets source address for TCP connections.

timeout NUMBER
     Sets I/O operation timeout in seconds. Mailfromd will wait NUMBER of seconds for the success of each I/O operation with the remote MX. If the remote party does not respond within this amount of time, mailfromd will retry the operation until the number of retries (see below) is exhausted or the host finally responds. Default timeout is 3 seconds.

retry NUMBER
     Sets number of retries for each I/O operation. Default is 3.

milter-timeout NUMBER
     Set the timeout value for connection between libmilter library and the MTA. Default value is whatever is set in libmilter. For Sendmail 8.12.9 it is 7210 seconds. You normally do not need to change this value.

mailfrom STRING
     Sets default email address used in MAIL FROM: SMTP command when probing the remote host. This value can be overridden by AS parameter to poll command (see poll).

     Do not enclose the email in angle brackets, they will be added automatically where appropriate. For example:

          #pragma option mailfrom "postmaster@my.domain.com"

     Default value is "" (empty string), resulting in <> email address.

ehlo STRING
     Sets default domain used in EHLO (or HELO) SMTP command when probing the remote host. This value can be overridden by FROM parameter to poll command (see poll).

debug STRING
     Sets debugging level. STRING is a decimal number in the range 0 -- 100. Level 0 effectively disables debugging, while level 100 enables the most verbose debugging output.

Another pragmatic comment, #pragma regex, controls type of regular expressions used in the probing program (see probing-program). You can use any number of these pragma directive in your mailfromd.rc, the scope of #pragma regex extends to the next occurrence of this directive or to the end of configuration file, whichever occurs first.

The syntax of this pragma is:

     #pragma regex LIST-OF-FLAGS

where LIST-OF-FLAGS is a whitespace-separated list of regex flags. Each regex-flag is a word specifying some regex feature. It can be preceded by + to enable this feature (this is the default), by - to disable it or by = to reset regex flags to its value. Valid regex-flags are:

extended
     Use POSIX Extended Regular Expression syntax when interpreting regex. If not set, POSIX Basic Regular Expression syntax is used.

icase
     Do not differentiate case. Subsequent regex searches will be case insensitive.

newline
     Match-any-character operators don't match a newline.

     A non-matching list ([^...]) not containing a newline does not match a newline.

     Match-beginning-of-line operator (^) matches the empty string immediately after a newline.

     Match-end-of-line operator ($) matches the empty string immediately before a newline.

For example, the following pragma enables POSIX extended, case insensitive matching (a good thing to start your mailfromd.rc with):

     #pragma regex +extended +icase

Literals
--------

The rest of the configuration file represents a probing program, i.e. a program defining the behavior of mailfromd in various situations. The program consists of conditionals and actions. Both conditionals and actions operate on basic entities, or atoms, which are literals, Sendmail configuration file variables, and expressions.

A literal is any sequence of alpha-numeric characters that is not a reserved word (see Reserved Words), or any sequence of characters enclosed in double quotation marks. Within the latter, the usual escape sequences are recognized, i.e.

Sequence   Replaced with
\a   Audible bell character (ASCII 7)
\b   Backspace character (ASCII 8)
\f   Form-feed character (ASCII 12)
\n   Newline character (ASCII 10)
\r   Carriage return character (ASCII 13)
\t   Horizontal tabulation character (ASCII 9)

In addition, the sequence \NEWLINE has the same effect as \n.

Sendmail configuration variables are denoted exactly the same way they are in sendmail.cf configuration file, i.e. $X (where X represents any character), for variables whose name consists of a single character, and ${NAME}, for the rest.

For a full list of Sendmail variables, please refer to Sendmail (tm) Installation and Operation Guide.

Notice that wherever you are using a Sendmail variable in your configuration file, you should make sure that Sendmail exports this variable to mailfromd (see Sendmail Configuration).

Expressions operate on atoms and return literal values. Think of them as of functions in programming languages. Currently the following expressions are implemented:

dbmap FILE ATOM
     FILE should be a literal string, ATOM an arbitrary atom which evaluates to a valid string.  This conditional returns true if the key ATOM is present in the DBM file FILE.  If ATOM contains a @ character, only the part before this character will be used, thus allowing to check emails against the aliases database:

          if not dbmap "/etc/mail/aliases" $f
             ...
          fi

     Notice that FILE must not end in .db suffix.

hostname ATOM
     ATOM should be a string representing an IP address in dotted-quad notation. The result of this expression is the canonical name of host with this IP address obtained from DNS lookup. For example

          hostname ${client_addr}

     returns the fully qualified domain name of the host represented by Sendmail variable client_addr.

     Notice that the hostname expression caches its results, so no matter how many times hostname ${client_addr} will be used in mailfromd.rc, it will result in at most one DNS lookup.

listens ATOM
     ATOM is a valid host name in symbolic or dotted-quad notation. The listens expression returns true if the host listens on TCP port 25 and false otherwise.

relayed ATOM
     Returns true if the string ATOM is found in one of relayed domain files (see pragma relay, and see option relay). The usual construct is:

          relayed hostname ${client_addr}

     which yields true if the IP address from Sendmail variable client_addr is relayed by the local machine.

validuser EMAIL
     Returns true if the user part of EMAIL is a user supported by current authorization scheme. More info, please.

Actions
-------

An action statement instructs mailfromd to communicate to Sendmail a certain command. There are three kinds of actions: return actions, continue actions and header manipulation actions.

Return actions tell Sendmail to return given status code to the remote party as a reply to MAIL FROM command. There are five such actions:

accept
     Return an accept reply. The remote party will continue transmitting its message.

reject
     Return a reject reply. The remote party will have to cancel transmitting its message.

tempfail
     Return a temporary failure reply. The remote party can retry to send its message later.

Each action can take up to three optional parameters. If only one parameter is given, it should be a valid three-digit SMTP reply code. Notice, that no check on validity is being performed. If you supply an invalid code for the given action, it will be ignored.

If two parameters are given, first of them must be a valid SMTP reply code as described above, and the second one can be either a valid extended SMTP reply code (three decimal numbers, separated by dots), or a string representing textual reply message.

Finally, if three parameters are given, they must be: an SMTP reply code, an extended reply code and a textual reply message, exactly in this order.

For example:

     accept
     accept 220 "Go on"
     accept 220 2.3.1
     accept 220 2.3.1 "Go on"

There are two continuation actions: continue instructs mailfromd to continue processing of the message, and discard instructs it to accept the message and silently discard it without delivering it to any recipient.

Header manipulation actions allow you to alter values of the message headers:

add NAME STRING
     Add the header NAME with the value STRING.

replace NAME STRING
     The same as add, but if the header NAME already exists, it will be removed first.

delete NAME
     Delete the header named NAME.

Conditional Statements
----------------------

Conditional expressions, or conditionals for short, test some conditions and alter the control flow depending on the result. There are two kinds of conditional statements: if-else branches and on switches.

The syntax of an if-else branching construct is:

     if CONDITION
        ...
     elif CONDITION
        ...
     else
        ...
     fi

where ... represent list of configuration file statements. There may be any number of elif branches, but at most one else branch. Both elif and else branches are optional. Conditional statements may be nested to any depth.

A condition, represented in the above example as CONDITION, is either a unary expression (see Expressions) or a binary statement in the following form:

     ATOM OPERATION ATOM

where OPERATION is one of the following:

=
     Returns true if both atoms are equal (exact string comparison).

          "string" = "string" => true
          "String" = "string" => false

!=
     Returns true if the two atoms are not equal (exact string comparison).

matches
     Right-hand atom should evaluate to a valid regular expression. The result of this test is true if the left-hand side atom matches the regular expression on the right side. Flags set by #pragma regex (see pragma regex) control the type of regular expressions being used. For example:

          $f => "gray@gnu.org.ua"
          $f matches ".*@gnu\.org\.ua" => true
          $f matches ".*@GNU\.ORG\.UA" => false
          #pragma regex +icase
          $f matches ".*@GNU\.ORG\.UA" => true

fnmatches
     Right-hand atom should evaluate to a valid shell globbing pattern. The test yields true if the result of evaluation of its left-hand atom matches the globbing pattern on the right.

          $f => "gray@gnu.org.ua"
          $f fnmatches "*ua" => true
          $f fnmatches "*org" => false
          $f fnmatches "*org*" => true

Such basic conditions may be combined using binary operators or, for logical OR, and, for logical AND, and unary operator NOT, for logical negation. The precedence and associativity of these are the same as in C language. To alter precedence, parentheses may be used.

Apart from binary conditions, defined above, a special statement rate can be used in if contents. The syntax of this statement is as follows:

     rate EMAIL LIMIT

The effect of this statement is to compute the sending rate for email address EMAIL and return true if it is greater than LIMIT.

The first argument, EMAIL, can be any valid configuration expression, in particular, most often you will wish to use "$f" in its place. The second argument, LIMIT, is a constant specifying rate limit, in messages per second. You can specify another time precision using following syntax for LIMIT:

     NUMBER1 / [ NUMBER2 ] TIME-UNIT

where brackets enclose an optional part. TIME-UNIT is any of following time units (or their plural forms):

  * second

  * minute

  * hour

  * week

  * month

This syntax is interpreted as follows: NUMBER2 (default 1) of TIME-UNITs is converted into seconds and NUMBER1 is divided by it. Obtained number is used as the rate limit. (Notice, that all calculations are done over double-precision floating point numbers). Moreover, the time specification can actually consist of several time unit parts. For example, the following is a valid rate specification:

     20 / 1 hour 25 minutes

It actually means a sending rate of .00392156 messages per second.

To summarize, here is a working example of rate statement:

     if rate "#f" 20 / minute
         tempfail 410 "Mail sending rate exceeded. Try again later"
     fi

(notice, however, that 20 messages per minute is way too rigit for the real life).

An on switch is another kind of conditional statement. Actually, on switch represents the core functionality of mailfromd: it performs MX probing and alters the control flow depending on the result. The syntax of on switch is:

     on poll for EMAIL host HOST from DOMAIN as EMAIL
     do
     BRANCHES
     done

poll is the function that actually does the probing. In the description above it is given in its full form: with four arguments. Actually, poll takes from one to four arguments, altering its behavior. The arguments may appear in any order, their semantics is determined by the keyword preceding them.

So, the basic forms of poll command are:

poll EMAIL
poll for EMAIL
     Perform a standard verification of email address EMAIL (see Overview).

poll EMAIL host HOST
poll for EMAIL host HOST
     Perform a strict verification of email address EMAIL coming from host HOST

During verification, poll uses originator domain (argument to the SMTP HELO command), and originator email (SMTP MAIL FROM command) as set by options ehlo and mailfrom (see pragma ehlo, and see pragma mailfrom options correspondingly. These defaults can be overridden by specifying two additional arguments to poll: from DOMAIN instructs mailfromd to use DOMAIN in HELO command, and as EMAIL instruct it to use the given EMAIL with MAIL FROM command.

The command poll returns one of the following values:

success
     Email existence is confirmed.

not_found
     Email existence is not confirmed.

failure
     An unrecoverable error occurred during polling. This means that neither the remote host, nor any of its MXs accepted SMTP connection.

temp_failure
     A temporary failure occurred during polling.

The BRANCHES in on statement have the following syntax:

          where LIST-OF-CODES:
            ...

where LIST-OF-CODES is a list of the above return codes separated by whitespace or the word or, and ... is a list of actions to be performed when poll return value falls in this list.

Thus, consider the following statement:

     on poll $f do
     when success:
             accept
     when not_found or failure:
             reject 510 "Sender validity not confirmed"
     when temp_failure:
             tempfail
     done

It will use standard verification of the sender email address ($f variable). If the sender validity is confirmed, Sendmail will accept the sender. If poll returned not_found or failure, the sender will be rejected with code 510 and diagnostics Sender validity not confirmed, otherwise, Sendmail will return to the sender a temporary error, suggesting him to try to send his message later.

Example of Configuration File
-----------------------------

Following is a working sample of mailfromd.rc file. Line numbers on the left were added for the ease of referencing. The file is described in detail below.

      1 #pragma option relay "/etc/mail/sendmail.cw"
      2 #pragma option relay "/etc/mail/relay-domains"
      3 #pragma option timeout 7500
      4 #pragma option retry 3
      5 #pragma option milter-timeout 7
      6 #pragma option mailfrom ""
      7 #pragma option ehlo "gnu.org"
      8 #pragma regex +extended +icase
      9 #pragma option debug 10
     10
     11 if $f = ""
     12      accept
     13 elif hostname ${client_addr} matches
     14             ".*(adsl|sdsl|hdsl|ldsl|dialin|dialup|ppp|dhcp|dynamic).*"
     15      reject 550 "Use your SMTP relay"
     16 elif hostname ${client_addr} matches
     17             ".*-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}.*"
     18      on poll host ${client_addr} for $f do
     19      when success:
     20              accept
     21      when not_found or failure:
     22              reject 510 "Sender validity not confirmed"
     23      when temp_failure:
     24              tempfail
     25      done
     26 elif relayed hostname ${client_addr}
     27      accept
     28 elif $f fnmatches "*yahoo.com"
     29      accept
     30 else
     31      on poll $f do
     32      when success:
     33              accept
     34      when not_found or failure:
     35              reject 510 "Sender validity not confirmed"
     36      when temp_failure:
     37              tempfail
     38      done
     39 fi
     40
     41 if rate "#f" 20 / minute
     42    tempfail 410 "Mail sending rate exceeded. Try again later"
     43 fi

Lines 1--9 declare various program options. In particular, lines 1--2 read names of the relayed domains from two usual sendmail files. Line 8 declares that all regular expressions below will be case insensitive POSIX extended regexs.

Lines 11--12 accept all mail coming from a null address (<>). These will probably be the first lines of any mailfromd configuration file.

Lines 13--15 reject all mail coming from (supposedly) dynamic IP addresses in supposition that the users should use the SMTP relays of their providers.

The conditional on lines 16--17 tests if the remote machine resolves to a name, containing four numbers, separated with dashes. Such hosts are often dynamic IP addresses, therefore lines 18--25 impose strict verification on such hosts.

Lines 26--27 accept any mail coming from the domains we relay.

Lines 28--29 accept any mail coming from yahoo.com subdomains. As described above (see Limitations), yahoo.com always replies positive to MAIL FROM command, so it is no use querying it (unfortunately).

All hosts not matching any of the above conditions, go through the standard verification procedure on lines 31--39.

Finally, if all the message passes all of the above checks, the sending rate of its sender is checked (lines 41--43), and if it is exceeded the sender is returned error code 410.

Reserved Words
--------------

For your reference, here is an alphabetical list of all reserved words:

  * accept

  * add

  * and

  * as

  * continue

  * delete

  * discard

  * do

  * done

  * elif

  * else

  * fi

  * fnmatche

  * for

  * from

  * host

  * hostname

  * if

  * matches

  * not

  * on

  * or

  * poll

  * rate

  * reject

  * relayed

  * replace

  * tempfail

  * when

Command Line Options.
=====================

Operation Modifiers
-------------------

--daemon
     Run in daemon mode (default).

--delete[=DB]
     Delete given entries from the database. Optional argument DB selects the database to expire entries from. If it is cache, the usual cache database is used. This is the default. Otherwise, if DB is rates, the rates database is used instead.

--expire[=DB]
     Delete all expired entries from the database. See --delete for the description of optional DB argument.

--list[=DB]
     List cache or rates database.

--show-defaults
     Show compilation defaults.

-t
--test
     Run in test mode.

General Settings
----------------

-D STRING
--domain=STRING
--ehlo=STRING
     Set default SMTP domain. Overrides #pragma option ehlo (see pragma ehlo).

-e NUMBER
--expire-interval=NUMBER
     Set cache expiration interval to NUMBER seconds. This option sets expiration intervals for both positive and negative cache entries. It overrides #pragma option expire-interval. If you wish to set different expiration intervals for positive and negative entries, use positive-expire-interval and negative-expire-interval pragmas (see expire-intervals).

--foreground
     Stay in foreground.

--postmaster-email=EMAIL
--mailfrom=EMAIL
     Set postmaster email address. Overrides #pragma option ehlo.

-p STRING
--port=STRING
     Set communication socket. Overrides #pragma option port.

--pidfile=FILE
     Set pidfile name. Overrides #pragma option pidfile.

-r
--remove
     Force removing local socket file, if it already exists.

-S
--source
     Set source address for TCP connections. Overrides #pragma option source.

-u NAME
--user NAME
     Switch to this user privileges after startup. Overrides #pragma option user.

Timeout Control
---------------

--milter-timeout=NUMBER
     Set MTA connection timeout. Overrides #pragma option milter-timeout.

--relayed-domain-file=FILE
     Read relayed domains from FILE. Overrides #pragma option relay.

--retry=NUMBER
     Retry failed I/O operations NUMBER times. Overrides #pragma option retry.

--timeout=NUMBER
     Set I/O operation timeout (seconds). Overrides #pragma option timeout.

Logging and Debugging
---------------------

-d LEVEL
--debug=LEVEL
     Set debugging level.  Overrides #pragma option debug. Argument LEVEL is a decimal integer (see pragma-debug).  For backward compatibility with the versions prior to 1.14.91, LEVEL can contain following characters:

     y
          Equivalent to --dump-grammar-trace.

     l
          Equivalent to --dump-lex-trace.

     d
          Equivalent to --dump-tree.

     Of course, you will not need these, unless you are hacking on mailfromd.

--dump-grammar-trace
     Enable debugging of configuration file parser.

--dump-lex-trace
     Enable debugging of configuration file lexical analyzer

--dump-tree
     Dump the compiled configuration file tree to stdout.

-s
--stderr
     Log to stderr.

-X
--transcript
     Enable transcript.

--log-facility=FACILITY
     Output logs to syslog FACILITY.

Informational Options
---------------------

-?
--help
     Give a short help summary.

--license
     Print license and exit.

--usage
     Give a short usage message.

-V
--version
     Print program version.

How to Stop Mailfromd
=====================

Use one of the following signals to stop a running instance of mailfromd: SIGHUP, SIGTERM, SIGINT. All three signals have the same effect: the program cancels handling any pending requests, uninitializes the communitation socket (if it is a UNIX socket, the program unlinks it) and exits.

Configuring Sendmail to use mailfromd
*************************************

This chapter assumes you are familiar with Sendmail configuration in general and with Milter configuration directives in particular. It concentrates only on issues, specific for mailfromd.

Mailfromd in default configuration uses the following sendmail macros: i, f, client_addr. So, you should make sure your sendmail configuration passes these macros to Milter. This is done by defining confMILTER_MACROS_ENVFROM in your mc file. By default, i is always passed, so for most sites it is sufficient to add {client_addr}, f to this variable. Of course, if you modify mailfromd.rc, make sure Sendmail exports all variables used by your modifications.

Beside this, you should specify the socket to communicate with mailfromd.

     define(`confMILTER_MACROS_ENVFROM',dnl
     confMILTER_MACROS_ENVFROM `, {client_addr}, f')
     INPUT_MAIL_FILTER(`mailfrom', `S=unix:/usr/local/var/mailfromd')

If you prefer to fiddle with sendmail.cf directly, here is the sample configuration (long lines being split for readability):

     O Milter.macros.envfrom=i, {auth_type}, {auth_authen}, \
        {auth_ssf}, {auth_author}, {mail_mailer}, {mail_host}, \
        {mail_addr} ,{mail_addr}, {client_addr}, f
     Xmailfrom, S=unix:/usr/local/var/mailfromd

Managing Cache Database
***********************

Several options are provided for managing mailfromd cache database.

Running mailfromd --list outputs the contents of the cache database. If no arguments are given, the entire database is dumped to standard output, otherwise only matching entries are looked up. Each line of output consists of three fields: email address (or EMAIL:IP combination for strict mode), status (either success if the email was confirmed, or not_found otherwise), and timestamp. For example:

     485nena@141.com           not_found Sat Jun  4 22:50:24 2005
     fotinija@optician.com     not_found Sat Jun  4 22:56:02 2005
     ceqbbf@proxad.net           success Sat Jun  4 23:00:10 2005
     6frederik@access-one.com  not_found Sat Jun  4 23:27:30 2005

The option --delete instructs mailfromd to delete from the database all users enumerated in the command line. For example:

     mailfromd --delete gray@farlep.net gray@gnu.org.ua:127.0.0.1

The option --expire removes from the database all expired entries. It is a good idea to add to the crontab something like

     0 1 1 * * /usr/libexec/mailfromd --expire

How to Report a Bug
*******************

Email bug reports to bug-mailfromd@gnu.org.ua. Be sure to include word ``mailfromd'' somewhere in the ``Subject:'' field.

As the purpose of bug reporting is to improve software, please be sure to include maximum information when reporting a bug. The information needed is:

  * Version of the package you are using.

  * Compilation options used when configuring the package.

  * Conditions under which the bug appears.

     [file fdl.texi not included]

Concept Index
*************

This is a general index of all issues discussed in this manual