General-Purpose Mail Filter
Apart from the milter handlers described in the previous section, MFL defines two special handlers, called ‘begin’ and ‘end’, which supply startup and cleanup instructions for the filter program.
The ‘begin’ special handler is executed once for each SMTP session, after the connection has been established but before the first milter handler has been called. Similarly, the ‘end’ handler is executed exactly once, after the connection has been closed. Neither of them takes any arguments.
The two handlers are defined using the following syntax:
# Begin handler begin do … done # End handler end do … done
where ‘…’ represent any MFL statements.
An MFL program may have multiple ‘begin’ and ‘end’ definitions. They can be intermixed with other definitions. The compiler combines all ‘begin’ statements into a single one, in the order they appear in the sources. Similarly, all ‘end’ blocks are concatenated together. The resulting ‘begin’ is called once, at the beginning of each SMTP session, and ‘end’ is called once at its termination.
Multiple ‘begin’ and ‘end’ handlers are a useful feature
for writing modules (see Modules), because each module can thus
have its own initialization and cleanup blocks. Notice, however, that
in this case the order in which subsequent ‘begin’ and ‘end’
blocks are executed is not defined. It is only warranted that all
‘begin’ blocks are executed at startup and all ‘end’ blocks
are executed at shutdown. It is also warranted that all ‘begin’
and ‘end’ blocks defined within a compilation unit (i.e. a single
abstract source file, with all
#include_once statements expanded in place) are executed in
order of their appearance in the unit.
Due to their special nature, the startup and cleanup blocks impose certain restrictions on the statements that can be used within them:
returncannot be used in ‘begin’ and ‘end’ handlers.
tempfail. They can, however, be used in
catchstatements, declared in ‘begin’ blocks (see example below).
The ‘begin’ handlers are the usual place to put global initialization code to. For example, if you do not want to use DNS caching, you can do it this way:
begin do db_set_active("dns", 0) done
Additionally, you can set up global exception handling routines there. For example, the following ‘begin’ statement disables DNS cache and, for all exceptions not handled otherwise, installs a handler that logs the exception along with the stack trace and continues processing the message:
begin do db_set_active("dns", 0) catch * do echo "Caught exception $1: $2" stack_trace() continue done done
This document was generated on January 3, 2019 using makeinfo.Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved.