includefile(../../release.yo)

gagmacrowarning(filtermail name)

htmlstyle(body)(color: #27408B; background: #FFFAF0)

whenhtml(mailto(Frank B. Brokken: f.b.brokken@rug.nl))

SUBST(USER)(frank)

DEFINEMACRO(lsoption)(3)(\
    bf(--ARG1)=tt(ARG3) (bf(-ARG2))\
)
DEFINEMACRO(laoption)(2)(\
    bf(--ARG1)=tt(ARG2)\
)
DEFINEMACRO(loption)(1)(\
    bf(--ARG1)\
)
DEFINEMACRO(soption)(1)(\
    bf(-ARG1)\
)

DEFINEMACRO(fm)(0)(bf(filtermail))
DEFINEMACRO(Fm)(0)(bf(Filtermail))

DELETEMACRO(tt)
DEFINEMACRO(tt)(1)(em(ARG1))

DEFINEMACRO(itt)(1)(it() tt(ARG1):)

COMMENT( man-request, section, date, distribution file, general name
)
manpage(filtermail)(1)(_CurYrs_)(filtermail__CurVers_)
        (fitermail - extensive mail filter)

COMMENT( man-request, larger title )
manpagename(filtermail)(Filter incoming e-mail to accepted, spam or ignored)

COMMENT( all other: add after () )
manpagesynopsis()

       fm() [OPTIONS] tt(base) nl()
        [OPTIONS] - cf. section bf(OPTIONS)nl()
        tt(base): the absolute path to the user's home directory

When specified paths with options or in the configuration file specifications
may start with tt(~/), in which case  tt(~) is replaced by tt(base).

manpagedescription()

Fm() filters incoming e-mail as either accepted, spam, or ignored e-mail. It
uses rule files, which are inspected in sequence until the incoming e-mail
matches a rule. Once that happens the rule's associated action (accept, spam,
or ignore) is executed. If the e-mail is not matched by any rule then the
e-mail is accepted.

Alternatively, when using option tt(--inspect) fm() can be used to find the
domain name of the sender, its IP address, its country of origin and the
cidr-range containing the received IP address (see sections bf(OPTIONS) and
bf(FILTERMAIL INSPECT) below).

Accepted e-mail normally is appended to the mail file which is used by the
incoming mail server when receiving mail for the current user. E.g., if the
user's username is tt(USER) then incoming mail is appended to the file
tt(/var/mail/USER). Users may also define directories to contain saved e-mails
(e.g., tt(~/Mail)), and fm() can be configured to append e-mail considered as
spam to, e.g., tt(~/Mail/spam). Likewise, e-mail matching the 'ignore'
criteria could be appended to tt(~/Mail/ignore). Instead of appending the
complete e-mail to its destination file the received e-mail's tt(From:) and
tt(Subject:) headers can be appended to its destination file. This is achieved
by prefixing tt(:HDRS:) to the name of the destination file. Alternatively,
such e-mail can also be ignored, losing it completely, by not specifying a
destination file. The option to merely log the received e-mail's tt(From:) and
tt(Subject:) headers may come in handy if the received e-mail is also kept
elsewhere (e.g., in another account, which forwards the received e-mail to the
computer running fm()) and the ignoring rules might result in occasional false
positive decisions.  (see also section bf(OPTIONS) below).

Fm() uses three types of files:
    itemization(
    it() The configuration file contains values of options with are generally
        used (see sections bf(CONFIGURATION) and bf(OPTIONS));
    it() Mail filtering rules are hierarchically ordered in the em(rules)
        file: incoming mail is sequentially matched against the patterns
        defined in files specified in the rules file until a match is
        found. Once a match has been found the rule's action (accept, ignore
        or spam) is executed, ending the filtering process (see section
        bf(RULES));
    it() Each file specified in the rules file defines matching patterns,
        which are tested sequentially. Testing those patterns ends once the
        incoming mail matches a pattern. The result of the matching is
        forwarded to the rules file which may result in executing the rule's
        action (see section bf(PATTERNS)).
    )

If fm() detects a syntax error in the rules file or in a rule specification
file the incoming mail is accepted. To avoid this situation the tt(--syntax)
option (see section bf(OPTIONS)) should be used when modifying, adding or
removing rule files to verify that the specified rules were correctly
formulated.

To use fm() the incoming mail server must recognize it as a valid mail
handling program (see section bf(EXAMPLES)).

manpagesection(CONFIGURATION)

Options (see section bf(OPTIONS)) not flagged with `NO_CONFIG' can also be
specified in a configutation file. By default the configuration file
tt(~/.filtermail/config) is used.

Command line options always take precedence over specifications in the
configuration file.

The configuration file em(must) exist, but may be empty. It must exist because
its directory defines the directory where the files defining the filtering
rules are located. Empty lines and the content of lines starting at the
tt(#)-character are ignored.

Option tt(--expire) is used to remove patterns whose date stamps (cf. section
bf(PATTERNS)) indicate dates before the date specified by tt(--expire). The
configuration file may contain tt(dont-expire:) lines. Each tt(dont-expire:)
line specifies the name of a pattern file whose entries don't expire. Files
specified in tt(dont-expire:) lines may not exist, but to avoid inspecting
pattern files for expired dates the name(s) of those file(s) must be identical
to the names of the file(s) used in the rules file (cf. section bf(RULES)
below).

Other files in the configuration file may use the tt([~]/path) format or must
be plain filenames (i.e., not starting with tt(/)-characters). Plain files are
relative to the directory containing the configuration file (cf. section
bf(EXAMPLES)).

manpagesection(RULES)

All mail filtering rules are defined in the tt(rules) file. Mail filtering
starts at the first rule until either the incoming e-mail matches a rule, or
until all rules have been processed and the e-mail does not match any rule. In
the latter case the e-mail is considered accepted.

Empty lines and lines whose first non-blank character is a tt(#)-character are
ignored. The rules themselves cannot contain tt(#)-characters.

Rules are written according to the following syntax (elements between square
brackets are optional, the content of bracketed sections followed by a tt(*)
character may be repeated (not using the square brackets). Lowercase words are
keywords and cannot be used otherwise. Capitalized words are described
below. Each rule is specified on its own line. Line continuation (using, e.g.,
tt(\) at the end of a line) is not supported). Here's the rule's syntax:
    verb(
    if Header File [and Header File]* Action
    )

tt(Header) is the name of a mail header (e.g., tt(From:, Received:)). Header
specifications must be identical to the first words of header lines of the
received e-mail. So to match the tt(From) header in the e-mail's first line
specify tt(From) (i.e., no colon). Some headers have variants. E.g.,
tt(Received:) and tt(Received-SPF:). To select all headers sharing their
initial characters append a tt(+)-character to the initial part (e.g., to
select all headers starting with tt(Received) use tt(Received+), and use
tt(From+) to select all tt(From:) headers including the e-mail's first line).

tt(File) is the name of the file containing patterns to inspect.  Filenames
must start with tt(./) and define the locations of files below the
configuration file's directory. E.g., tt(./spam/subject) specifies the file
tt(subject) in a subdirectory tt(spam) containing patterns considered by the
rule.

tt(Action) specifies the action to execute when e-mail matches a
rule. tt(Action) can be
    itemization(
    itt(accept)

       the e-mail is accepted (i.e., appended to the tt(accept) location
        spcified in the configuration file)

    itt(ignore)

       the e-mail is ignored (i.e., appended to the tt(ignore) location
        spcified in the configuration file)

    itt(spam)

       the e-mail is considered spam (i.e., appended to the tt(spam) location
        spcified in the configuration file)
    )

manpagesection(PATTERNS)

Files specified in tt(rules) files define patterns which may be found in the
headers defined by the rules. The header lines which are selected by the
tt(Header) specifications in the tt(rules) file are matched against those
patterns after removing the header labels from those lines. So tt(Subject:
hello world) is passed to the patterns as the (trimmed) line tt(hello
world). Once a header's content matches a pattern inspection ends with a
successful match (the rule itself may specify tt(not), in which case a
successful match results in a failing match of the rule).

Pattern files may start with file-specific comment (i.e., empty lines and
lines whose first non-blank character is tt(#)) up to a comment line equal to
tt(#=). The patterns themselves may also be preceded by comment lines. Once a
pattern is matched it is moved one position upward in the pattern file
(including its associated comment).

Pattern specifications use the following syntax (elements between square
brackets are optional (when used, the square brackets are not specified),
capitalized words are described below, each pattern is defined on a single
line, line continuation is not supported):
    verb(
    Nr Date Expression [and Expression]*
    )

    This pattern indicates a match when all tt(Expressions) match.

    This syntax uses the following elements:
    itemization(
    itt(Nr) specifies the number of times e-mail was successfully matched by
        the pattern. At each successful match the count is incremented (up to
        a maximum of 999), and the pattern rises one position in the pattern
        file. The field width of the number field must be at least 3 character
        positions wide. When adding a pattern use 1;
    itt(Date) shows the date of the most recent match. Its format is
        tt(yy-mm-dd), e.g. 23-03-31. When adding a pattern the current date
        could be used.
    itt(Expression) defines at least one matching mode and associated
        expression. 
    )

    The tt(Expressions) themselves use the following syntax:
   verb(MatchMode [not] Spec)
   The selected headers are matched against tt(Spec) using the specified
tt(MatchMode). The tt(not) keyword is optional. When specified (omit the
square brackets) the result of the match is negated. When multiple
tt(Expression) specifications are joined by tt(and) keywords, then the final
pattern results in a match if all tt(Expression) specifications indicate a
match. Once an tt(Expression) does not indicate a match, then subsequent
tt(Expressions) are not evaluated and headers do not match the pattern.

When using tt(not) the e-mail may not match the tt(Spec) specification.  E.g,
when e-mail should contain a tt(To:) header or a tt(Cc:) header the following
rule can be used (cf. section bf(EXAMPLES):)
        verb(
    if To: ./match/noto and Cc: ./match/noto  spam
        )
    with tt(match/noto):
        verb(
     1   23-05-10  p not  '.'
        )

    Note that tt(Spec) must be surrounded by single quotes. To use a single
quote inside a tt(Spec) escape it (as tt(\')). In general: the character
following a backslash is used as-is, removing the backslash from the tt(Spec)
(e.g., to construct a tt(Spec) containing tt('\n) specify tt(\'\\n)).

    There are five types of tt(MatchModes. MatchModes) using regular
expressions use extended regular expression patterns: prefix multipliers
and bounding-characters by backslashes when they should be interpreted as
ordinary characters (i.e., tt(*, +, ?, ^, $, |, (, ), [, ], {, }) should be
escaped when used as literal characters).
    itemization(
    itt(c) (cidr) matches tt([d{1.3}.d{1.3}.d{1.3}.d{1.3}]) IP address
        patterns found in selected headers against the tt(Spec) pattern,
        e.g., tt('1.22.333.0/24');
    itt(i) (ignore case) matches the selected headers case-insensitively
        against the tt(Spec) pattern, e.g., tt('yes');
    itt(n) (no-case pattern) matches the selected headers case-insensitively
        against the tt(Spec) regular expression pattern, e.g.,
        tt('news.*\.*@reply');
    itt(p) (pattern) matches the selected headers (case-sensitively)
        against the tt(Spec) regular expression pattern;
    itt(s) (string text) matches the selected headers as specified
        (case-sensitively) against the tt(Spec) pattern, e.g., tt('noreply@').
        This matchmode can also be used to match IP version 6 patterns if the
        cidr-range uses multiples of 16-bit values, e.g.,
        tt('[2a02:7a60:'); 
    itt($) (script or program): tt(Spec) calls a script or program. The
        selected headers are passed to the script or program, which must
        return 0 to indicate a match and any other value to indicate no
        match. The script or program may specify arguments, but in addition
        two additional arguments are passed to the script or program, the
        first one being the name of a file containing the selected e-mail
        headers, the second one being the name of the file containing the
        e-mail's content. The script or program does not use the tt(PATH)
        environment variable, so the path to the script or program (possibly
        starting with tt(~/)) must be specified. When tt(Spec) starts with the
        word tt(SHELL]) then the script or program is called as tt(/bin/sh -c
        'script/program [arguments]'). Examples:
       verb(
        # call program in the user's bin dir. with 4 arguments 
    '~/bin/program arg1, arg2'

        # call script in the user's bin dir. with 4 arguments
        # via /bin/sh
    'SHELL ~/bin/script arg1, arg2'      
        )
    )

manpageoptions()

Short options, when defined, are provided between parentheses immediately
following their long option equivalents. Several parameters specify locations
of files written or used by fm(). If a location specification starts with
tt(~/) then the tilde-character is replaced by the em(base) directory
specified as fm()'s argument. Otherwise, if the location does not start with a
slash (tt(/)) character then the location is prefixed by the path of the
directory containing the configuration file.

Some options can also be specified in the configuration file (cf. section
bf(CONFIGURATION)). Options that cannot be specified in the configuration file
are marked as tt(NO-CONFIG).


    itemization(
    it() loption(accept)([:HDRS:]path)nl()
       the path receiving accept-marked mail. Mail not matching any rules is
        also accepted. Prepend tt(:HDRS:) to tt(path) to log the mail's
        tt(From:) and tt(Subject:) headers to tt(path). To completely ignore
        accept-marked mail omit this option (although ignoring accept-marked
        mail is probably undesirable). Examples (commonly tt(USER) (used in
        the example) is replaced by the user's username):
       verb(    --accept /var/mail/USER
    --accept :HDRS:/var/mail/USER)

    it() loption(cls)nl()nl()
      By default fm() clears the terminal's screen (calling tt(tput
       clear)). If the screen should not be cleared option tt(--cls no) can be
       specified. A default value can also be specified in the configuration
       file, using 
            verb(
    cls: no
            )
      in which case option tt(--cls yes) can be specified to overrule the
       configuration file's specification. This option is only used when the
       tt(--inspect) option is specified.

     it() NO-CONFIG lsoption(config)(c)(path)nl() 
       the path to the configuration file (default: ~/etc/mailfilter/config).
        (see also section tt(CONFIGURATION) below).

    it() NO-CONFIG lsoption(expire)(e)(date)nl() 
       no mail is read, but patterns having date stamps older than tt(date)
        are removed from their files and are stored in files having extension
        tt(.exp) (cf. section bf(PATTERNS) below). Use format tt(yy-mm-dd)
        when specifying tt(date). This option and tt(--interactive) (see
        below) cannot both be specified. Example:
       verb(    --date 23-01-31)

    it() NO-CONFIG loption(help) (soption(h))nl()
       a summary of fm()'s usage is written to tt(cout) and fm() ends,
        returning 0 to the shell.

    it() loption(ignore)([:HDRS:]path)nl()
       the path receiving ignore-marked mail. Prepend tt(:HDRS:) to tt(path)
        to log the mail's tt(From:) and tt(Subject:) headers to tt(path). To
        completely ignore ignore-marked mail omit this option. Examples:
       verb(    --ignore ~/Mail/ignore
    --ignore :HDRS: ~/Mail/ignore)


    it() NO-CONFIG loption(inspect) (soption(I))nl()
       when specifying this option fm() expects a received e-mail file at
        its standard input showing the domain name of the sender, its IP
        address, its country of origin and the cidr-range containing the
        received IP address. E.g., 
       verb(
    from renxincj.com (unknown [104.223.188.228])
    IP = `104.223.188.228', Country: US,  CIDR = 104.223.128.0/17
        )
        See section bf(FILTERMAIL INSPECT) for additional info.

    it() NO-CONFIG loption(interactive) (soption(i))nl()
       the matching result of matching patterns is interactively simulated (no
        mail is read). This option and tt(--expire) cannot both be specified.

    it() lsoption(IP4-pattern)(p)(regex)nl() 
       by default IP4 patterns are recognized using the regular expression
        pattern tt(\[((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}))\]), matching
        addresses like tt([123.11.22.33]) in specified headers. This format is
        commonly encountered in tt(Received:) headers. When different
        IP4-patterns should be recognized then this option can be used to
        specify another regular expression for matching IP4-patterns in
        headers. 

        The required regex is an extended regular expression in which the
        characters tt(*, +, ?, ^, $, |, (, ), [, ], {,) and tt(}) must be
        escaped when used as literal characters. Perl-like escape
        sequences tt(\b) (word-boundary), tt(\d) (digit character), tt(\s)
        (white-space character), and tt(\w) (alpha-numeric character) are
        supported. Their capital variants represent their complementary sets.

        The regexes specified using this option must have at least
        five elements, addressable using indices 1..5:nl()
        * element 1 defines the complete IP4 pattern,nl()
        * element 2 defines the most significant (4th) octet (available
            in bits 24 thru 31 in the converted binary address),nl()
        * element 3 defines the 3th IP4 octet (available in bits
            16 thru 23 in the converted binary address),nl()
        * element 4 defines the 2nd IP4 octet (available in bits
            8 thru 15  in the converted binary address),nl()
        * element 5 defines the least significant (1st) IP4 octet (available
            in bits 0 thru 7 in the converted binary address).

    it() lsoption(log)(l)(spec)nl() 
       specify the log-facility. By default no logging is used.nl() 
       The tt(spec) argument can be the location of a file receiving the log
        messages.nl()
       If tt(spec) uses the format tt(facility:level) (tt(facility) and
        tt(level) being the names defined in the bf(syslog)(3) man-page
        omitting their tt(LOG_) prefixes) then the log messages are written by
        tt(syslog). Examples:
       verb(    --log log/log     # uses log/log in the configuration
                      # file's directory
    --log USER:NOTICE # uses syslog)

    it() loption(preamble)nl()
       merely verify that the basic options are correctly specified. No mail
        is read, but all options and configuration file specifications are
        processed. When the verification successfully ends the message 
       verb(    Preamble successfully completed)
       is written to tt(cout) and fm() returns 0.

    it() lsoption(received)(R)(content)nl() 
      before incoming mail reaches your computer your, e.g., organization's
       mail server may have processed the incoming mail, and it may be OK to
       inspect only the tt(Received:) headers following that mail server's
       tt(Received:) header. The content of the tt(Received:) header may
       (partially) be specified using this option, which can also be provided
       in the configuration file. E.g., if the tt(Received:) header
       originating from your organization's mail server contains
       tt(ourorganization.org) then the option tt(-r ourorganization.org)
       causes all tt(Received:) headers to be ignored until the tt(Received:)
       header containing tt(ourorganization.org) has been seen. If the
       incoming mail doesn't contain such a tt(Received:) header then all
       tt(Received:) headers are inspected.  This option is only used when the
       tt(--inspect) option is specified.

    it() lsoption(rules)(r)(path)nl() 
       the location of the rules specification file (cf. section bf(RULES)
        below).

    it() loption(spam) tt([:HDRS:]path)nl()
       the path receiving spam-marked mail. Prepend tt(:HDRS:) to tt(path) to
        log the mail's tt(From:) and tt(Subject:) headers to tt(path). To
        completely ignore spam-marked mail omit this option. Examples:
       verb(    --spam ~/Mail/spam
    --spam :HDRS: ~/Mail/spam)

    it() NO-CONFIG loption(syntax)nl()
       perform a syntax check of the specified rules. Encountered syntax
        errors are logged in the log-file. The begin and end of the syntax
        check is also logged in the log file. No mail is read from the
        standard input stream.

    it() NO-CONFIG loption(version) (soption(v))nl()
       writes fm()'s version to tt(cout) and ends, returning 0.
    )

manpagesection(FILTERMAIL INSPECT)

When specifying the tt(--inspect) (tt(-I)) option fm() expects a received
e-mail file at its standard input showing the domain name of the sender, its
IP address, its country of origin and the cidr-range containing the received
IP address. E.g.,
       verb(
    from renxincj.com (unknown [104.223.188.228])
    IP = `104.223.188.228', Country: US,  CIDR = 104.223.128.0/17
        ) 
    Mail handling programs (e.g., bf(mutt)(1)) allow its users to pipe
an e-mail file to a program, so the received e-mail can be inspected from
inside the mail handling program. E.g., with tt(mutt) typing tt(|) shows the
prompt
        verb(
    Pipe to command:
        )
and assuming that the fm() program is available in the user's tt(PATH)
environment variable enter `fm() -I' to pass the received e-mail to fm():
        verb(
    Pipe to command: filtermail -I
        )
    Depending on the content of the tt(Received:) headers fm()'s output shows
the domain name of the sender, its IP address, its country of origin and the
cidr-range containing the received IP address. E.g.,
        verb(
    from renxincj.com (unknown [104.223.188.228])
    IP = `104.223.188.228', Country: US,  CIDR = 104.223.128.0/17
        )

IP version 6 addresses are also inspected, producing output like
        verb(
    from mail.resoascijournal.info (s857e6ba3.fastvps-server.com \ 
                                                [2a03:f480:2:8::3f])
    IP = `2a03:f480:2:8::3f', Country: EE,  CIDR = 2a03:f480:2::/48
        )

If the received e-mail is considered conspicuous (e.g., spam or mail to
ignore) then the cidr range could be added to a file like
tt(suspect.cidr). Once more e-mails from the suspected cidr-range are
received, the range could be added to, e.g., tt(~/etc/filtermail/spam/cidr) or
to tt(~/etc/filtermail/ignore/cidr), using a pattern line like
        verb(
        1   23-05-10    s '2a03:f480:2:'
        )
       
    When the option tt(--cls) is specified as tt(yes) (either as command-line
option or in the configuration file) then the terminal screen will be cleared
before showing tt(--inspect's) output. 
    When the option tt(--received) is
specified tt(Received:) headers appearing before the tt(Received:) header
containing the content specified at the tt(--received) option are ignored.

manpagesection(EXAMPLES)

    itemization(
    it() tt(configure) fm() tt(as a valid mail handling program:)
    )

   Commonly incoming mail servers define a directory where valid mail handling
    programs (or links to those programs) are listed. E.g., bf(sendmail)(8)
    uses the `sendmail restricted shell' (tt(/etc/mail/smrsh)) directory. If
    fm() is installed in a standard user-accessible directory (e.g.,
    tt(/usr/bin)) then the tt(smrsh) directory should contain the link
   verb(    filtermail -> /usr/bin/filtermail)

   Once the fm() program is recognized by the incoming mail server users may
    filter incoming e-mail through fm() using, e.g., a tt(~/.forward)
    file. Such tt(.forward) files ignore empty lines and end-of-line comment
    (starting at tt(#)). Assuming a standard fm()-configuration (cf. section
    bf(CONFIGURATION)) and assuming that user tt(USER's) home-directory is
    tt(/home/USER), then tt(/home/USER/.forward) should contain the following
    line:
   verb(    "|/usr/bin/filtermail /home/USER") 
   Note the double quotes: they are required because fm() is called with
    an argument.

    itemization(
    itt(a configuration file)
    )

   The following configuration file specifies that the tt(rules)
    and log files are located in the configuration file's directory and
    defines paths for all three mail categories:
   verb(    rules:  rules
    log:    log/log
    accept: /var/spool/mail/USER
    spam:   ~/Mail/spam
    ignore: ~/Mail/ignore
 
    # as illustration of a 'dont-expire:' specification:
    #dont-expire: ./ignore/from)

    itemization(
    itt(rule specifications)
    )

    Filtering rules are defined in the file specified by the tt(--rules)
    option or in the tt(rules:) line of the configuration file. Note that the
    pattern files must start with tt(./).
   verb(
    if From:                    ./ignore/from           ignore
    if Subject:                 ./spam/nolowercase      spam

        # inspect all Received... headers:
    if Received+                ./spam/cidr             spam

        # a To: or Cc: header is required:
    if To:  ./match/noto  and  Cc: ./match/noto ignore
)
    The final rule uses the pattern in tt(./match/tocc) (shown below)
specifying the `any character' (tt('.')) regular expression: if the tt(To:)
header is empty (which is also true if there is no tt(To:) header, then the
tt(not To:) condition matches. The same holds true for the second
condition. So if neither condition matches there is neither a tt(To:) nor a
tt(Cc:) header, in which case the e-mail is sent to the tt(spam)
destination. Also note that, according to em(De Morgan's) rule, a tt(not X and
not Y) rule is identical to an tt(X or Y) rule.
 
    itemization(
    itt(pattern specifications)
    )

    verb(
    # the ./spam/nolowercase pattern:
    1   23-05-10    not p   '[a-z]'

    # e.g., the ./match/noto as used in the above example
    #       requiring either a To: or a Cc: header:
    1   23-05-10    p  not  '.'
    )
      
manpagefiles()

    By default the configuration file is expected in the subdirectory
tt(etc/filtermail) of the directory specified as fm()'s argument.

manpageseealso()

bf(mutt)(1), bf(pattern)(3bobcat), bf(regcomp)(3), bf(sendmail)(8),
bf(syslog)(3), bf(tput)(1), bf(whois)(1)

COMMENT(optional:
    manpagediagnostics()
)

manpagebugs()

None reported.

manpageauthor()
Frank B. Brokken (f.b.brokken@rug.nl).


