\input texinfo @c -*-texinfo-*- @smallbook @c %**start of header @setfilename mailfromd.info @settitle Mailfromd @c %**end of header @setchapternewpage odd @syncodeindex fn cp @syncodeindex vr cp @syncodeindex ky cp @syncodeindex pg cp @syncodeindex tp cp @include version.texi @include rendition.texi @ifinfo @dircategory Email @direntry * mailfromd: (mailfromd). Filter incoming mail by sender address. @end direntry @end ifinfo @copying Published by the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Copyright @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.'' @end copying @titlepage @title Mailfromd mail filter @subtitle version @value{VERSION}, @value{UPDATED} @author Sergey Poznyakoff. @page @vskip 0pt plus 1filll @insertcopying @end titlepage @page @summarycontents @page @contents @node Top, Intro, (dir), (dir) @ifinfo @chapter Mailfromd This edition of the @cite{Mailfromd Manual}, last updated @value{UPDATED}, documents @command{mailfromd} Version @value{VERSION}. @end ifinfo @menu * Intro:: Introduction to Mailfromd. * Overview:: How Address Verification Works. * Limitations:: Limitations of Address Verification. * Rate Limit:: Configuring Send Rate. * Building:: Building the Package. * Mailfromd Configuration:: Configuring @command{mailfromd}. * Sendmail Configuration:: Configuring Sendmail to use @command{mailfromd}. * Cache Database:: Managing Cache Database. * Reporting Bugs:: How to Report a Bug. Appendices * Copying This Manual:: The GNU Free Documentation License. * Concept Index:: Index of Concepts. @end menu @node Intro, Overview, Top, Top @chapter Introduction to @command{mailfromd} @command{Mailfromd} is a mail filter implementing @dfn{sender address verification} technique. The program is designed to work with @command{Sendmail}@footnote{See @uref{http://www.sendmail.org}} as a @command{Milter} filter. @dfn{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 @samp{MAILER-DAEMON} messages back. @node Overview, Limitations, Intro, Top @chapter 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: @cindex Standard address verification Suppose that the user @samp{} is trying to send mail to one of your local users. The remote machine connects to your MTA and issues @code{MAIL FROM: } command. However, your MTA does not have to take its word for it, so it uses @command{mailfromd} to verify the sender address validity. @command{Mailfromd} strips the domain name from the address (@samp{somedomain.net}) and queries DNS for MX records for that domain. Suppose, it receives the following list @itemize @bullet @item 10 relay1.somedomain.net @item 20 relay2.somedomain.net @end itemize It then connects to first MX server and asks it if it knows something about user @samp{jsmith}. This is called sending a @dfn{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, @command{mailfromd} selects next server from the list and continues the described process until it finds answer or the list of servers is exhausted. The @dfn{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 (@samp{S:} meaning messages sent by remote MTA, @samp{C:} meaning those sent by @command{mailfromd}): @smallexample C: HELO mydomain.net S: 220 OK, nice to meet you C: MAIL FROM: <> S: 220 <>: Sender OK C: RCPT TO: S: 220 : Recipient OK C: QUIT @end smallexample Probe messages are never delivered, deferred or bounced; they are always discarded. @cindex Strict address verification The described method of address verification is called @dfn{standard} method throughout this document. @command{Mailfromd} also implements a method we call @dfn{strict}. When using strict method, @command{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: @samp{} is a perfectly normal address, but it is being used by a spammer from some other domain, say @samp{otherdomain.com}. Standard method is not able to cope with such cases, whereas strict one is. An alert reader will ask: what happens if @command{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 @command{mailfromd} actions are configurable. For the detailed description of this, @xref{mailfromd.rc}. @cindex Caching After receiving a definitive answer, @command{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. @node Limitations, Rate Limit, Overview, Top @chapter 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: @itemize @bullet @item 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 @command{mailfromd} options to find an optimal configuration. @item 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. @item When verifying the remote address, no attempt to actually deliver the message is made. If MTA accepts the address, @command{mailfromd} assumes it is OK. However in reality, mail for a remote address can bounce @emph{after} the nearest MTA accepts the recipient address. @item If the remote server rejects the address, no attempt is being made to discern between various reasons for rejection (client rejected, @samp{HELO rejected}, @samp{MAIL FROM} rejected, etc.) @item Unfortunately, some major sites such as @indicateurl{yahoo.com} do not reject unknown addresses in reply to the @samp{RCPT TO} command, but report a delivery failure in response to end of @samp{DATA} after a message is transferred. Of course, sender address verification does not work with such sites. @item By default, @command{mailfromd} uses @samp{<>} as the sender email. However such an address is not accepted by some misconfigured hosts. You may wish to alter the default address using @option{--postmaster-email} option (@xref{pragma-mailfrom}, and @pxref{option-mailfrom}). @end itemize 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. @node Rate Limit, Building, Limitations, Top @chapter Configuring Send Rate. @cindex sending rate @cindex send rate Another feature offered by @command{mailfromd} is controlling user @dfn{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. @command{Mailfromd} configuration syntax offers a special condition @code{rate} (@pxref{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 @acronym{DBM} support (see next chapter). @node Building, Mailfromd Configuration, Rate Limit, Top @chapter Building the Package @enumerate 1 @item Make sure you have the necessary software installed. To build @command{mailfromd} you will need to have following packages on your machine: @enumerate A @item Sendmail 8.12.9 or newer @item @command{libmilter} library. @vindex BROKEN_PTHREAD_SLEEP @cindex libmilter, compiling It comes with Sendmail, but is not built by default. To build Sendmail with @command{libmilter} support, add following two lines to your @file{devtools/Site/site.config.m4}: @smallexample @group APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER') APPENDDEF(`confENVDEF', `-DBROKEN_PTHREAD_SLEEP') @end group @end smallexample @noindent After running @command{make install}, change to the directory @file{libmilter} and run @command{make} there. @emph{Important note:} make sure that @command{libmilter} is compiled with @code{BROKEN_PTHREAD_SLEEP} defined. If this symbol is not defined, @command{libmilter} will use @code{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. @cindex libmilter, forked version @cindex Patching libmilter The @command{mailfromd} package comes with a patch to @command{libmilter} that changes its multi-process model from @dfn{pthreads} to @dfn{forks}. It has been reported that @command{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 @file{libmilter-fork.a}, so that your original version of @file{libmilter.a} remains untouched. The patch was created for Sendmail version 8.13.1 and is located in the @file{etc} subdirectory of @command{mailfromd} distribution, in file @file{sendmail-8.13.1.diff} To apply the patch: @smallexample @group cd sendmail-8.13.1 patch -p0 < @var{path-to/}mailfromd-@value{VERSION}/etc/sendmail-8.13.1.diff @end group @end smallexample @noindent Then, proceed as described above in this section. @cindex @option{--with-forks} option, configure To build @command{mailfromd} with the modified version of @command{libmilter} use @option{--with-forks} option to @command{configure}: @smallexample ./configure --with-forks @end smallexample If you installed @command{libmilter-fork.a} to an unusual location, or renamed it, you can specify its full file name with this option, e.g.: @smallexample ./configure --with-forks=/usr/local/lib/libmilter-fork.a @end smallexample @item GNU mailutils version 0.6 or newer. It is available from @uref{http://www.gnu.org/software/mailutils}. @item A @acronym{DBM} library. @command{Mailfromd} is able to link with almost any existing library: old style @command{libdbm}, @command{libndbm}, Berkeley DB, @command{gdbm}. Notice that you can compile @command{mailfromd} without @acronym{DBM} too, but this is not recommended, since it will disable caching. Using @command{mailfromd} without caching can lead to increase in @acronym{CPU} usage, traffic outage and other disastrous effects. Besides, @acronym{DBM} is necessary for limiting user send rates. You have been warned. So, you want to select @acronym{DBM} implementation to use. The following table will help you do that. Column @samp{DB type} lists types of DBM databases supported by @command{mailfromd}. Column @samp{confMAPDEF} lists the value of @code{confMAPDEF} Sendmail configuration variable corresponding to that database type. It is here because it is usually wise to configure @command{mailfromd} to use the same database type as your Sendmail (If you don't know what @code{confMAPDEF} is, you probably are wasting your time reading this. Refer to Sendmail configuration guide first). @samp{N/A} in this column means there is no support for this database in Sendmail. Finally, column @samp{configure option} lists the option you should give to @command{configure} to enable using this database. @multitable @columnfractions 0.30 .20 .50 @item DB type @tab confMAPDEF @tab configure option @item DBM @tab N/A @tab @option{--with-dbm} @item NDBM @tab @option{-NNDBM} @tab @option{--with-ndbm} @item Berkeley DB @tab @option{-NNEWDB} @tab @option{--with-db2} @item GDBM @tab N/A @tab @option{--with-gdbm} @end multitable @end enumerate @item Decide what user privileges will be used to run @command{mailfromd} The program will refuse to run as root. By default it switches to the privileges of user @samp{mail}, group @samp{mail}. If there is no such user on your system, or you wish to use another user account for this purpose, override it using @var{DEFAULT_USER} environment variable. For example to use the privileges of user @samp{nobody}, run @smallexample ./configure DEFAULT_USER=nobody @end smallexample @item Decide where to install @command{mailfromd} and where its configuration and data files will be located. As usual, default value for installation prefix is @file{/usr/local}. If it does not suit you, specify another location using @option{--prefix} option, e.g.: @samp{--prefix=/usr}. During installation phase, the build system will install several files. These files are: @multitable @columnfractions 0.50 .5 @item File @tab Purpose @item @file{@var{prefix}/libexec/mailfromd} @tab Main daemon @item @file{@var{prefix}/etc/mailfromd.rc} @tab Configuration file@footnote{The configuration file will be installed only if it is not already there. Thus, if you are upgrading to a newer version of @command{mailfromd}, your old configuration file will be preserved with all your changes.} @item @file{@var{prefix}/info/mailfromd.info} @tab Documentation @end multitable At startup, @command{mailfromd} will look up its configuration defaults in file @file{@var{prefix}/etc/mailfromd.rc}. It is advisable to use the same settings for file name prefixes as those you used when configuring @command{mailutils}. In particular, try to use the same @option{--sysconfdir}, since it will facilitate configuring the whole system. Another important point is the location of @dfn{local state directory}, i.e. a directory where @command{mailfromd} will keep its data files (communication socket, pidfile and cache database). This directory is @file{@var{localstatedir}/mailfromd}. @item Select default communication socket. This is the socket used to communicate with @command{sendmail}. The default value is @file{unix:@var{localstatedir}/mailfromd/mailfrom}. To alter this, use @var{DEFAULT_SOCKET} environment variable, e.g.: @smallexample ./configure DEFAULT_SOCKET=inet:999@@localhost @end smallexample @item 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 @var{DEFAULT_EXPIRE_INTERVAL} environment variable. @item Run @command{configure} with all the desired options. For example, the following command: @smallexample ./configure DEFAULT_SOCKET=inet:999@@localhost --with-db2 @end smallexample @noindent will configure the package to use Berkeley DB2 database, and @samp{inet:999@@localhost} as the default communication socket. @item Run @command{make}. @item Run @command{make} install. @item Make sure @file{@var{localstatedir}/mailfromd} has right owner and mode. @item Examine configuration file (@file{@var{sysconfdir}/mailfromd.etc}) and edit it, if necessary. If you are upgrading from an oldest copy of @command{mailfromd}, your configuration file will remain untouched. @end enumerate @node Mailfromd Configuration, Sendmail Configuration, Building, Top @chapter Configuring @command{mailfromd} In the simplest case you will be able to start up @command{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. @cindex mailfromd configuration First of all, as any other utility, @command{mailfromd} accepts some @dfn{command line arguments}. Secondly, it is able to retrieve these arguments from a site-wide @dfn{mailutils configuration file}. And finally, it has its own @dfn{configuration file} that, among other things, defines the rules for probing email addresses. In this chapter we will discuss both @command{mailfromd} configuration file and its command line options. The use of mailutils configuration file is covered in @xref{configuration,,Mailutils Configuration File,mailutils, GNU Mailutils Manual}. Among the three methods, the use of @command{mailfromd} configuration file should be preferred. @menu * mailfromd.rc:: @command{Mailfromd} Configuration File. * options:: Command Line Options. * signals:: How to Stop @command{Mailfromd} @end menu @node mailfromd.rc @section @command{Mailfromd} Configuration File. @cindex mailfromd.rc @command{Mailfromd} configuration file is located in @file{@var{sysconfdir}/mailfromd.rc} (by default @file{/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. @menu * Comments:: Usual and pragmatic comments. * Literals:: Literals or atoms. * Actions:: Actions control the handling of the mail. * Conditionals:: Conditional Starements. * Configuration File Example:: A Working Configuration File Explained. * Reserved Words:: A Reference List of Reserved Words. @end menu @node Comments @subsection Comments @cindex Comments Two types of comments are allowed: C-style, enclosed between @samp{/*} and @samp{*/}, and shell-style, starting with @samp{#} character and extending up to the end of line: @smallexample /* This is a comment. */ # This too. @end smallexample @cindex Pragmatic comments @cindex #pragma If @samp{#} is immediately followed by word @samp{pragma} (with optional whitespace between them), such a construct introduces a @dfn{pragmatic comment}, i.e. an instruction changing some configuration setting. Two kinds of pragmatic comments are currently implemented: @samp{#pragma option} changes a value of a run-time option, and @samp{#pragma regex} controls the use of regular expressions in the configuration file. @cindex #pragma option The syntax of @samp{#pragma option} is: @smallexample #pragma option @var{name} @var{value} @end smallexample @noindent where @var{name} is the name of the option to set, and @var{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 @var{name} corresponds to a @dfn{long command line option} with the same semantics. Implemented options are: @anchor{expire-intervals} @table @option @item expire-interval @var{number} @cindex @option{expire-interval}, pragma Sets expiration interval for both positive and negative cache entries to the given @var{number} of seconds. @item positive-expire-interval @var{number} @cindex @option{positive-expire-interval}, pragma Sets expiration interval for positive cache entries to the given @var{number} of seconds. @item negative-expire-interval @var{number} @cindex @option{negative-expire-interval}, pragma Sets expiration interval for negative cache entries to the given @var{number} of seconds. @item rates-expire-interval @var{number} @cindex @option{rates-expire-interval}, pragma Sets expiration interval for entries in the rates database. @item relay @var{filename} @cindex @option{relay}, pragma @anchor{pragma relay} Specifies the file containing names of email domains relayed by this machine. Multiple pragmas accumulate. The constructed list of domains is analyzed by @code{relayed} directive (@pxref{relayed}). For example: @smallexample #pragma option relay "/etc/mail/sendmail.cw" #pragma option relay "/etc/mail/relay-domains" @end smallexample @item source @var{address} @cindex @option{source}, pragma Sets source address for TCP connections. @item timeout @var{number} @cindex @option{timeout}, pragma Sets I/O operation timeout in seconds. @command{Mailfromd} will wait @var{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, @command{mailfromd} will retry the operation until the number of retries (see below) is exhausted or the host finally responds. Default timeout is 3 seconds. @item retry @var{number} @cindex @option{retry}, pragma Sets number of retries for each I/O operation. Default is 3. @item milter-timeout @var{number} @cindex @option{milter-timeout}, pragma @anchor{pragma-mailfrom} Set the timeout value for connection between @command{libmilter} library and the MTA. Default value is whatever is set in @command{libmilter}. For Sendmail 8.12.9 it is 7210 seconds. You normally do not need to change this value. @item mailfrom @var{string} @cindex @option{mailfrom}, pragma @anchor{pragma mailfrom} Sets default email address used in @samp{MAIL FROM:} @acronym{SMTP} command when probing the remote host. This value can be overridden by @samp{AS} parameter to @command{poll} command (@pxref{poll}). Do not enclose the email in angle brackets, they will be added automatically where appropriate. For example: @smallexample #pragma option mailfrom "postmaster@@my.domain.com" @end smallexample Default value is @samp{""} (empty string), resulting in @samp{<>} email address. @item ehlo @var{string} @cindex @option{ehlo}, pragma @anchor{pragma ehlo} Sets default domain used in @samp{EHLO} (or @samp{HELO}) @acronym{SMTP} command when probing the remote host. This value can be overridden by @samp{FROM} parameter to @command{poll} command (@pxref{poll}). @anchor{pragma-debug} @item debug @var{string} @cindex @option{debug}, pragma Sets debugging level. @var{String} is a decimal number in the range 0 -- 100. Level 0 effectively disables debugging, while level 100 enables the most verbose debugging output. @end table @cindex #pragma regex @anchor{pragma regex} Another pragmatic comment, @samp{#pragma regex}, controls type of regular expressions used in the @dfn{probing program} (@pxref{probing-program}). You can use any number of these pragma directive in your @file{mailfromd.rc}, the scope of @samp{#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: @smallexample #pragma regex @var{list-of-flags} @end smallexample @noindent where @var{list-of-flags} is a whitespace-separated list of @dfn{regex flags}. Each regex-flag is a word specifying some regex feature. It can be preceded by @samp{+} to enable this feature (this is the default), by @samp{-} to disable it or by @samp{=} to reset regex flags to its value. Valid regex-flags are: @table @samp @item extended Use @acronym{POSIX} Extended Regular Expression syntax when interpreting regex. If not set, @acronym{POSIX} Basic Regular Expression syntax is used. @item icase Do not differentiate case. Subsequent regex searches will be case insensitive. @item newline @dfn{Match-any-character} operators don't match a newline. A non-matching list (@samp{[^...]}) not containing a newline does not match a newline. @dfn{Match-beginning-of-line} operator (@samp{^}) matches the empty string immediately after a newline. @dfn{Match-end-of-line} operator (@samp{$}) matches the empty string immediately before a newline. @end table For example, the following pragma enables @acronym{POSIX} extended, case insensitive matching (a good thing to start your @file{mailfromd.rc} with): @smallexample #pragma regex +extended +icase @end smallexample @node Literals @subsection Literals @anchor{probing-program} @cindex Probing program @cindex Probing actions, defining The rest of the configuration file represents a @dfn{probing program}, i.e. a program defining the behavior of @command{mailfromd} in various situations. The program consists of @dfn{conditionals} and @dfn{actions}. Both conditionals and actions operate on basic entities, or @dfn{atoms}, which are @dfn{literals}, Sendmail configuration file @dfn{variables}, and @dfn{expressions}. @cindex Literals A literal is any sequence of alpha-numeric characters that is not a reserved word (@pxref{Reserved Words}), or any sequence of characters enclosed in double quotation marks. Within the latter, the usual escape sequences are recognized, i.e. @multitable @columnfractions 0.30 .5 @item Sequence @tab Replaced with @item \a @tab Audible bell character (ASCII 7) @item \b @tab Backspace character (ASCII 8) @item \f @tab Form-feed character (ASCII 12) @item \n @tab Newline character (ASCII 10) @item \r @tab Carriage return character (ASCII 13) @item \t @tab Horizontal tabulation character (ASCII 9) @end multitable In addition, the sequence @samp{\@var{newline}} has the same effect as @samp{\n}. @cindex Sendmail variables Sendmail configuration variables are denoted exactly the same way they are in @file{sendmail.cf} configuration file, i.e. @samp{$X} (where @samp{X} represents any character), for variables whose name consists of a single character, and @samp{$@{@var{name}@}}, for the rest. For a full list of Sendmail variables, please refer to @cite{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 @command{mailfromd} (@pxref{Sendmail Configuration}). @cindex Expressions @anchor{Expressions} Expressions operate on atoms and return literal values. Think of them as of functions in programming languages. Currently the following expressions are implemented: @table @code @item hostname @var{atom} @cindex @code{hostname} @var{atom} should be a string representing an IP address in @samp{dotted-quad} notation. The result of this expression is the canonical name of host with this IP address obtained from DNS lookup. For example @smallexample hostname $@{client_addr@} @end smallexample @noindent returns the fully qualified domain name of the host represented by Sendmail variable @samp{client_addr}. Notice that the @code{hostname} expression caches its results, so no matter how many times @code{hostname $@{client_addr@}} will be used in @file{mailfromd.rc}, it will result in at most one DNS lookup. @item listens @var{atom} @cindex @code{listens} @var{atom} is a valid host name in symbolic or @samp{dotted-quad} notation. The @code{listens} expression returns @code{true} if the host listens on TCP port 25 and @code{false} otherwise. @item relayed @var{atom} @cindex @code{relayed} @anchor{relayed} Returns @code{true} if the string @var{atom} is found in one of relayed domain files (@xref{pragma relay}, and @pxref{option relay}). The usual construct is: @smallexample relayed hostname $@{client_addr@} @end smallexample @noindent which yields @code{true} if the IP address from Sendmail variable @samp{client_addr} is relayed by the local machine. @item validuser @var{email} @cindex @code{validuser} Returns @code{true} if the user part of @var{email} is a user supported by current authorization scheme. @FIXME{More info, please}. @end table @node Actions @subsection Actions @cindex Actions An @dfn{action} statement instructs @command{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 @samp{MAIL FROM} command. There are five such actions: @table @code @item accept @cindex accept Return an @code{accept} reply. The remote party will continue transmitting its message. @item reject @cindex reject Return a @code{reject} reply. The remote party will have to cancel transmitting its message. @item tempfail @cindex tempfail Return a @samp{temporary failure} reply. The remote party can retry to send its message later. @end table Each action can take up to three optional parameters. If only one parameter is given, it should be a valid three-digit @acronym{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 @acronym{SMTP} reply code as described above, and the second one can be either a valid extended @acronym{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 @acronym{SMTP} reply code, an extended reply code and a textual reply message, exactly in this order. For example: @smallexample accept accept 220 "Go on" accept 220 2.3.1 accept 220 2.3.1 "Go on" @end smallexample @cindex continue @cindex discard There are two continuation actions: @code{continue} instructs @command{mailfromd} to continue processing of the message, and @code{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: @table @command @item add @var{name} @var{string} @cindex add Add the header @var{name} with the value @var{string}. @item replace @var{name} @var{string} @cindex replace The same as @code{add}, but if the header @var{name} already exists, it will be removed first. @item delete @var{name} @cindex delete Delete the header named @var{name}. @end table @node Conditionals @subsection Conditional Statements @cindex Conditional statements @dfn{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: @dfn{if-else} branches and @dfn{on} switches. @cindex if @cindex elif @cindex else @cindex fi The syntax of an @dfn{if-else} branching construct is: @smallexample if @var{condition} @dots{} elif @var{condition} @dots{} else @dots{} fi @end smallexample @noindent where @samp{@dots{}} represent list of configuration file statements. There may be any number of @samp{elif} branches, but at most one @samp{else} branch. Both @samp{elif} and @samp{else} branches are optional. Conditional statements may be nested to any depth. @cindex Conditions A @dfn{condition}, represented in the above example as @var{condition}, is either a unary expression (@pxref{Expressions}) or a binary statement in the following form: @smallexample @var{atom} @var{operation} @var{atom} @end smallexample @noindent where @var{operation} is one of the following: @table @samp @item = @cindex @code{=} Returns @code{true} if both atoms are equal (exact string comparison). @smallexample "string" = "string" @result{} @code{true} "String" = "string" @result{} @code{false} @end smallexample @item != @cindex @code{!=} Returns @code{true} if the two atoms are not equal (exact string comparison). @item matches @cindex @code{matches} Right-hand atom should evaluate to a valid regular expression. The result of this test is @code{true} if the left-hand side atom matches the regular expression on the right side. Flags set by @code{#pragma regex} (@pxref{pragma regex}) control the type of regular expressions being used. For example: @smallexample $f @result{} "gray@@gnu.org.ua" $f matches ".*@@gnu\.org\.ua" @result{} @code{true} $f matches ".*@@GNU\.ORG\.UA" @result{} @code{false} #pragma regex +icase $f matches ".*@@GNU\.ORG\.UA" @result{} @code{true} @end smallexample @item fnmatches @cindex @code{fnmatches} Right-hand atom should evaluate to a valid shell globbing pattern. The test yields @code{true} if the result of evaluation of its left-hand atom matches the globbing pattern on the right. @smallexample $f @result{} "gray@@gnu.org.ua" $f fnmatches "*ua" @result{} @code{true} $f fnmatches "*org" @result{} @code{false} $f fnmatches "*org*" @result{} @code{true} @end smallexample @end table @cindex and @cindex or @cindex parentheses Such @dfn{basic conditions} may be combined using binary operators @code{or}, for logical OR, @code{and}, for logical AND, and unary operator @code{NOT}, for logical negation. The precedence and associativity of these are the same as in @acronym{C} language. To alter precedence, parentheses may be used. @cindex rate @anchor{rate}Apart from @dfn{binary} conditions, defined above, a special statement @code{rate} can be used in @code{if} contents. The syntax of this statement is as follows: @smallexample rate @var{email} @var{limit} @end smallexample The effect of this statement is to compute the sending rate for email address @var{email} and return @code{true} if it is greater than @var{limit}. The first argument, @var{email}, can be any valid configuration expression, in particular, most often you will wish to use @code{"$f"} in its place. The second argument, @var{limit}, is a constant specifying rate limit, in messages per second. You can specify another time precision using following syntax for @var{limit}: @smallexample @var{number1} / [ @var{number2} ] @var{time-unit} @end smallexample @noindent where brackets enclose an optional part. @var{time-unit} is any of following time units (or their plural forms): @itemize @bullet @item second @item minute @item hour @item week @item month @end itemize This syntax is interpreted as follows: @var{number2} (default 1) of @var{time-unit}s is converted into seconds and @var{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: @smallexample 20 / 1 hour 25 minutes @end smallexample It actually means a sending rate of @code{.00392156} messages per second. To summarize, here is a working example of @code{rate} statement: @smallexample if rate "#f" 20 / minute tempfail 410 "Mail sending rate exceeded. Try again later" fi @end smallexample @noindent (notice, however, that 20 messages per minute is way too rigit for the real life). @cindex on An @samp{on} switch is another kind of conditional statement. Actually, @samp{on} switch represents the core functionality of @command{mailfromd}: it performs MX probing and alters the control flow depending on the result. The syntax of @samp{on} switch is: @smallexample on poll for @var{email} host @var{host} from @var{domain} as @var{email} do @var{branches} done @end smallexample @cindex poll @anchor{poll} @code{poll} is the function that actually does the probing. In the description above it is given in its full form: with four arguments. Actually, @code{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 @code{poll} command are: @table @code @item poll @var{email} @itemx poll for @var{email} @cindex for @cindex @code{poll} command, standard verification @cindex standard verification with @code{poll} Perform a @samp{standard} verification of email address @var{email} (@pxref{Overview}). @item poll @var{email} host @var{host} @itemx poll for @var{email} host @var{host} @cindex host @cindex @code{poll} command, strict verification @cindex strict verification with @code{poll} Perform a @samp{strict} verification of email address @var{email} coming from host @var{host} @end table @cindex as @cindex from During verification, @code{poll} uses originator domain (argument to the @acronym{SMTP} @samp{HELO} command), and originator email (@acronym{SMTP} @samp{MAIL FROM} command) as set by options @option{ehlo} and @option{mailfrom} (@xref{pragma ehlo}, and @pxref{pragma mailfrom} options correspondingly. These defaults can be overridden by specifying two additional arguments to @code{poll}: @code{from @var{domain}} instructs @command{mailfromd} to use @var{domain} in @samp{HELO} command, and @code{as @var{email}} instruct it to use the given @var{email} with @samp{MAIL FROM} command. The command @code{poll} returns one of the following values: @table @samp @item success @cindex success Email existence is confirmed. @item not_found @cindex not_found Email existence is not confirmed. @item failure @cindex failure An unrecoverable error occurred during polling. This means that neither the remote host, nor any of its MXs accepted @acronym{SMTP} connection. @item temp_failure @cindex temp_failure A temporary failure occurred during polling. @end table @cindex when @cindex branching, @code{on} statement The @var{branches} in @code{on} statement have the following syntax: @smallexample where @var{list-of-codes}: @dots{} @end smallexample @noindent where @var{list-of-codes} is a list of the above return codes separated by whitespace or the word @code{or}, and @samp{@dots{}} is a list of actions to be performed when @code{poll} return value falls in this list. Thus, consider the following statement: @smallexample on poll $f do when success: accept when not_found or failure: reject 510 "Sender validity not confirmed" when temp_failure: tempfail done @end smallexample @noindent It will use standard verification of the sender email address (@code{$f} variable). If the sender validity is confirmed, Sendmail will accept the sender. If @code{poll} returned @code{not_found} or @code{failure}, the sender will be rejected with code 510 and diagnostics @samp{Sender validity not confirmed}, otherwise, Sendmail will return to the sender a temporary error, suggesting him to try to send his message later. @node Configuration File Example @subsection Example of Configuration File Following is a working sample of @file{mailfromd.rc} file. Line numbers on the left were added for the ease of referencing. The file is described in detail below. @smallexample @group 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 @end group @end smallexample 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 @acronym{POSIX} extended regexs. Lines 11--12 accept all mail coming from a null address (@samp{<>}). These will probably be the first lines of any @command{mailfromd} configuration file. Lines 13--15 reject all mail coming from (supposedly) dynamic IP addresses in supposition that the users should use the @acronym{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 @samp{yahoo.com} subdomains. As described above (@pxref{Limitations}), @samp{yahoo.com} always replies positive to @samp{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. @node Reserved Words @subsection Reserved Words @cindex Reserved Words @cindex Keywords For your reference, here is an alphabetical list of all reserved words: @itemize @bullet @item accept @item add @item and @item as @item continue @item delete @item discard @item do @item done @item elif @item else @item fi @item fnmatche @item for @item from @item host @item hostname @item if @item matches @item not @item on @item or @item poll @item rate @item reject @item relayed @item replace @item tempfail @item when @end itemize @node options @section Command Line Options. @menu * Operation Modifiers:: * General Settings:: * Timeout Control:: * Logging and Debugging:: * Informational Options:: @end menu @node Operation Modifiers @subsection Operation Modifiers @table @option @item --daemon Run in daemon mode (default). @item --delete[=@var{db}] Delete given entries from the database. Optional argument @var{db} selects the database to expire entries from. If it is @samp{cache}, the usual cache database is used. This is the default. Otherwise, if @var{db} is @samp{rates}, the rates database is used instead. @item --expire[=@var{db}] Delete all expired entries from the database. See @option{--delete} for the description of optional @var{db} argument. @item --list[=@var{db}] List cache or rates database. @item --show-defaults Show compilation defaults. @item -t @itemx --test Run in test mode. @end table @node General Settings @subsection General Settings @table @option @item -D @var{string} @itemx --domain=@var{string} @itemx --ehlo=@var{string} Set default SMTP domain. Overrides @samp{#pragma option ehlo} (@pxref{pragma ehlo}). @item -e @var{number} @itemx --expire-interval=@var{number} Set cache expiration interval to @var{number} seconds. This option sets expiration intervals for both positive and negative cache entries. It overrides @samp{#pragma option expire-interval}. If you wish to set different expiration intervals for positive and negative entries, use @samp{positive-expire-interval} and @samp{negative-expire-interval} pragmas (@pxref{expire-intervals}). @item --foreground Stay in foreground. @item --postmaster-email=@var{email} @itemx --mailfrom=@var{email} @anchor{option-mailfrom} Set postmaster email address. Overrides @samp{#pragma option ehlo}. @item -p @var{string} @itemx --port=@var{string} Set communication socket. Overrides @samp{#pragma option port}. @item --pidfile=@var{file} Set pidfile name. Overrides @samp{#pragma option pidfile}. @item -r @itemx --remove Force removing local socket file, if it already exists. @item -S @itemx --source Set source address for TCP connections. Overrides @samp{#pragma option source}. @item -u @var{name} @itemx --user @var{name} Switch to this user privileges after startup. Overrides @samp{#pragma option user}. @end table @node Timeout Control @subsection Timeout Control @table @option @item --milter-timeout=@var{number} Set MTA connection timeout. Overrides @samp{#pragma option milter-timeout}. @item --relayed-domain-file=@var{file} @anchor{option relay} Read relayed domains from @var{file}. Overrides @samp{#pragma option relay}. @item --retry=@var{NUMBER} Retry failed I/O operations @var{number} times. Overrides @samp{#pragma option retry}. @item --timeout=@var{number} Set I/O operation timeout (seconds). Overrides @samp{#pragma option timeout}. @end table @node Logging and Debugging @subsection Logging and Debugging @table @option @item -d @var{level} @itemx --debug=@var{level} Set debugging level. Overrides @samp{#pragma option debug}. Argument @var{level} is a decimal integer (@pxref{pragma-debug}). For backward compatibility with the versions prior to 1.14.91, @var{level} can contain following characters: @table @samp @item y Equivalent to @option{--dump-grammar-trace}. @item l Equivalent to @option{--dump-lex-trace}. @item d Equivalent to @option{--dump-tree}. @end table Of course, you will not need these, unless you are hacking on @command{mailfromd}. @item --dump-grammar-trace Enable debugging of configuration file parser. @item --dump-lex-trace Enable debugging of configuration file lexical analyzer @item --dump-tree Dump the compiled configuration file tree to stdout. @item -s @itemx --stderr Log to stderr. @item -X @itemx --transcript Enable transcript. @item --log-facility=@var{facility} Output logs to syslog @var{facility}. @end table @node Informational Options @subsection Informational Options @table @option @item -? @itemx --help Give a short help summary. @item --license Print license and exit. @item --usage Give a short usage message. @item -V @itemx --version Print program version. @end table @node signals @section How to Stop @command{Mailfromd} @cindex Signals @cindex SIGHUP @cindex SIGTERM @cindex SIGINT Use one of the following signals to stop a running instance of @command{mailfromd}: @code{SIGHUP}, @code{SIGTERM}, @code{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. @node Sendmail Configuration, Cache Database, Mailfromd Configuration, Top @chapter Configuring Sendmail to use @command{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 @command{mailfromd}. @cindex f, Sendmail variable @cindex i, Sendmail variable @cindex client_addr, Sendmail variable @cindex confMILTER_MACROS_ENVFROM @command{Mailfromd} in default configuration uses the following sendmail macros: @code{i}, @code{f}, @code{client_addr}. So, you should make sure your sendmail configuration passes these macros to Milter. This is done by defining @code{confMILTER_MACROS_ENVFROM} in your @code{mc} file. By default, @code{i} is always passed, so for most sites it is sufficient to add @code{@{client_addr@}, f} to this variable. Of course, if you modify @file{mailfromd.rc}, make sure Sendmail exports all variables used by your modifications. @cindex INPUT_MAIL_FILTER Beside this, you should specify the socket to communicate with @command{mailfromd}. @smallexample define(`confMILTER_MACROS_ENVFROM',dnl confMILTER_MACROS_ENVFROM `, @{client_addr@}, f') INPUT_MAIL_FILTER(`mailfrom', `S=unix:/usr/local/var/mailfromd') @end smallexample @cindex sendmail.cf If you prefer to fiddle with @file{sendmail.cf} directly, here is the sample configuration (long lines being split for readability): @smallexample 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 @end smallexample @node Cache Database, Reporting Bugs, Sendmail Configuration, Top @chapter Managing Cache Database Several options are provided for managing @command{mailfromd} cache database. Running @command{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 @var{email}:@var{IP} combination for strict mode), status (either @samp{success} if the email was confirmed, or @samp{not_found} otherwise), and timestamp. For example: @smallexample 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 @end smallexample The option @option{--delete} instructs @command{mailfromd} to delete from the database all users enumerated in the command line. For example: @smallexample mailfromd --delete gray@@farlep.net gray@@gnu.org.ua:127.0.0.1 @end smallexample The option @option{--expire} removes from the database all expired entries. It is a good idea to add to the crontab something like @smallexample 0 1 1 * * /usr/libexec/mailfromd --expire @end smallexample @node Reporting Bugs, Copying This Manual, Cache Database, Top @chapter How to Report a Bug Email bug reports to @email{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: @itemize @item Version of the package you are using. @item Compilation options used when configuring the package. @item Conditions under which the bug appears. @end itemize @node Copying This Manual, Concept Index, Reporting Bugs, Top @include fdl.texi @node Concept Index, , Copying This Manual, Top @comment node-name, next, previous, up @unnumbered Concept Index This is a general index of all issues discussed in this manual @printindex cp @bye