Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
MILTER-REGEX(8)		  BSD System Manager's Manual	       MILTER-REGEX(8)

     milter-regex -- sendmail milter plugin for	regular	expression filtering

     milter-regex [-d] [-c config] [-f facility] [-j dirname] [-l loglevel]
		  [-m number] [-p pipe]	[-r pid-file] [-t] [-u user]
		  [-G group] [-P mode] [-U user]

     The milter-regex plugin can be used with the milter API of	sendmail(8) to
     filter mails using	regular	expressions matching SMTP envelope parameters
     and mail headers and body.

     The options are as	follows:

     -d		Don't detach from controlling terminal and produce verbose de-
		bug output on stdout.

     -c	config	Use the	specified configuration	file instead of	the default,

     -f	facility
		Use the	specified syslog facility instead of the default, dae-

     -j	dirname
		Change root to the specified directory.

     -l	loglevel
		Only log messages up to	and including the specified level.
		See syslog(3) for the numerical	values,	e.g. the default

     -m	number	Ignore mail body after the specified number of lines.

     -p	pipe	Use the	specified pipe to interface sendmail(8).  Default is

     -r	pid-file
		Write the pid to the specified file. Default is	not to write a

     -t		Test the configuration file and	immediately exit with a	status
		indicating whether the file is valid.

     -u	user	Run as the specified user instead of the default, _milter-
		regex.	When milter-regex is started as	root, it calls
		setuid(2) to drop privileges.  The non-privileged user should
		have read access to the	configuration file and read-write ac-
		cess to	the pipe.

     -G	group	Set the	group ID of the	pipe.

     -P	mode	Set the	permissions of the pipe	to the specified mode instead
		of the default,	0600.

     -U	user	Set the	user ID	of the pipe.

     The plugin	needs to be registered in the sendmail(8) configuration, by
     adding the	following lines	to the .mc file

		   `S=unix:/var/run/milter-regex/sock, T=S:30s;R:2m')

     rebuilding	/etc/mail/ from the .mc file	using m4(1), and
     restarting	sendmail(8).

     The configuration file consists of	rules that, when matched, cause
     sendmail(8) to reject mails.  Emtpy lines and lines starting with # are
     ignored, as well as leading whitespace (blanks, tabs).  Trailing back-
     slashes can be used to wrap long rules into multiple lines.  Each rule
     starts with one of	the following commands:

     reject <message>
	   Subsequent rules cause the mail to be rejected with a permanent er-
	   ror consisting of the specified text	part.  The SMTP	reply consists
	   of the three-digit code 554 (RFC 2821 "command rejected for policy
	   reasons"), the extended reply code 5.7.1 (RFC 1893 "Permanent Fail-
	   ure", "Security or Policy Status", "Delivery	not authorized,	mes-
	   sage	refused") and the text part (which defaults to "Command	re-
	   jected", if not specified).	This is	a permanent failure, which
	   causes the sender to	remove the message from	its queue without try-
	   ing to retransmit, commonly generating a bounce message to the

     tempfail <message>
	   Subsequent matching rules cause the mail to be rejected with	a tem-
	   porary error	consisting of the specified text part.	The SMTP reply
	   consists of the three-digit code 451	(RFC 2821 "Requested action
	   aborted: local error	in processing"), the extended reply code 4.7.1
	   (RFC	1893 "Persistent Transient Failure", "Security or Policy Sta-
	   tus", "Delivery not authorized, message refused") and the text part
	   (which defaults to "Please try again	later",	if not specified).
	   This	is a temporary failure,	which causes the sender	to keep	the
	   message in its queue	and try	to retransmit it, commonly for several

	   Subsequent matching rules cause the mail to be accepted but then
	   discarded silently.	Note that connect and helo rules should	not
	   use discard.

     quarantine	<message>
	   Subsequent matching rules cause the mail to be quarantined in

	   Subsequent matching rules cause the mail to be accepted without
	   further rule	evaluation.  Can be used for whitelist criteria.

     A command is followed by one or more expressions, each causing the	previ-
     ous command to be executed	when matched.  The following expressions can
     be	used:

     connect <hostname>	<address>
	   Reject the connection if both the sender's hostname and address
	   match the specified regular expressions.  The numerical address is
	   either dotted-quad (IPv4) or	coloned-hex (IPv6).  The hostname is
	   the result of a DNS reverse resolution of the numerical address
	   (which sendmail(8) performs independantly of	the milter plugin).
	   When	resolution fails, the hostname contains	the numerical address
	   in square brackets.

     helo <name>
	   Reject the connection if the	sender supplied	HELO name matches the
	   specified regular expression.  Commonly, the	sender supplies	his
	   fully-qualified hostname as HELO name.

     envfrom <address>
	   Reject the mail if the sender supplied envelope MAIL	FROM address
	   matches the specified regular expression.  Addresses	commonly have
	   the form <>.

     envrcpt <address>
	   Reject the mail if the sender supplied envelope RCPT	TO address
	   matches the specified regular expression.

     header <name> <value>
	   Reject the mail if a	header matches the specified name and value.
	   For instance, the header "Subject: Test" matches name Subject and
	   value Test.

     body <line>
	   Reject the mail if a	body line matches the specified	regular	ex-

     macro <name> <value>
	   Reject the mail if a	sendmail macro value matches.

     The plugin	regularly checks the configuration file	for modification and
     reloads it	automatically.	Signals	like SIGHUP will terminate the plugin,
     according to the milter signal handler.  The plugin reacts	to any kind of
     error, like syntax	errors in the configuration file, by failing open, ac-
     cepting all messages.  When the plugin is not running, sendmail(8)	will
     accept all	messages.

     The regular expressions used in the configuration rules are enclosed in
     arbitrary delimiters, no further escaping is needed.

     The first character of an argument	is taken as the	delimiter, and all
     subsequent	characters up to the next occurance of the same	delimiter are
     taken literally as	the regular expression.	 Since the delimiter itself
     cannot be part of the regular expression (no escaping is supported), a
     delimiter must be chosen that doesn't occur in the	regular	expression it-
     self.  Each argument can use a different delimiter, all characters	except
     spaces and	tabs are valid.

     Two immediately adjacent delimiters form an empty regular expression,
     which always matches and requires no regexec(3) call.  This can be	used
     in	rules requiring	multiple arguments, to match only some arguments.

     See re_format(7) for a detailed description of basic and extended regular

     Optionally, the following flags can be used after the closing delimiter:
     e	  Extended regular expression.	This sets REG_EXTENDED for regcomp(3).
     i	  Ignore upper/lower case.  This sets REG_ICASE.
     n	  Not matching.	 Reverses the matching result, i.e. the	mail is	re-
	  jected if the	regular	expression does	not match.

     A rule can	consist	of either a simple term	or more	complex	expressions.
     A term has	the form

     header /From/ /domain/i

     and expressions can be built combining terms with operators "and",	"or",
     "not" and parentheses, as in

     header /From/ /domain/i and body /money/
     ( not header /From/ /domain/ ) and	( body /sex/ or	body /fast/ )

     Operator precedence should	not be relied on, instead parentheses should
     be	used to	resolve	any ambiguities	(they usually produce syntax errors
     from the parser).

     Macros allow to store terms or expressions	as a name, and $name can be
     used as term within other rules, expressions or macro definitions.	 Exam-

     friends	     = header /^Received$/ /^from [^ ]*(|
     attachments     = header ,^Content-Type$, ,multipart/mixed, and \
			 body ,^Content-Type: application/,
     executables     = $attachments and	body ,name=".*.(pif|exe|scr)"$,e

     reject "executable	attachment from	non-friends"
     $executables and not $friends

     Macro names must begin with a letter and may contain alphanumeric charac-
     ters and punctuation characters.  Reserved	keywords (like "reject"	or
     "header") cannot be used as macro names.  Macros must be defined before
     use, the definition must precede the use in the configuration file, read
     from top to bottom.

     Rules are evaluated in the	order specified	in the configuration file,
     from top to bottom.  When a rule matches, the corresponding action	is
     taken, that is the	last action specified before the matching rule.

     The plugin	evaluates the rules every time a line of mail (or envelope) is
     received.	As soon	as a rule matches, the action is taken immediately,
     possibly before the entire	mail is	received, even if further lines	might
     possibly make other rules match, too.  This means the first rule matching
     chronologically has precedence.

     If	evaluation for a line of mail makes two	(or more) rules	match, the
     rule that comes first in the configuration	file has precedence.

     Boolean expressions are short-circuit evaluated, that means "a or b" be-
     comes true	as soon	as one of the terms is true and	"a and b" becomes
     false as soon as one of the terms is false, even if the other term	is not
     known, possibly because the relevant mail line has	not been received yet.

     # /usr/local/etc/milter-regex.conf	example

     # Accept anything encrypted, just to demonstrate sendmail macros
     macro /tls_version/ /TLSv/

     tempfail "Sender IP address not resolving"
     connect /\[.*\]/ //

     reject "Malformed HELO (not a domain, no dot)"
     helo /\./n

     reject "Malformed RCPT TO (not an email address, not <.*@.*>)"
     envrcpt /<(.*@.*|Postmaster)>/ein

     reject "HTML mail not accepted"
     # use comma as delimiter here, as / occurs	within RE
     header /^Content-type$/i ,^text/html,i
     body ,^Content-type: text/html,i

     # Swen worm
     header /^(TO|FROM|SUBJECT)$/e //
     header /^Content-type$/i /boundary="Boundary_(ID_/i
     header /^Content-type$/i /boundary="[a-z]*"/
     body ,^Content-type: audio/x-wav; name="[a-z]*\.[a-z]*",i

     # Some nasty spammer
     reject "Business Corp spam, get lost"
     body /^Business Corp. for W.& L. AG/i and \
	     ( body /043.*317.*0285/ or	body /0041.43.317.02.85/ )

     milter-regex sends	log messages to	syslogd(8) using facility daemon and,
     with increasing verbosity,	level err, notice, info	and debug.  The	fol-
     lowing syslog.conf(5) section can be used to log messages to a dedicated

     daemon.err;daemon.notice	     /var/log/milter-regex

     Syntax for	milter-regex in	BNF:

     file	     = ( rule |	macro )	file
     rule	     = action expr-list
     action	     = "reject"	msg | "tempfail" msg | "discard" |
		       "quarantine" msg	| "accept"
     msg	     = ( '"' | "'" ) string ( '"' | "'"	)
     expr-list	     = expr [ expr-list	]
     expr	     = term | term "and" expr |	term "or" expr | "not" term
     term	     = '(' expr	')' | "connect"	arg arg	| "helo" arg |
		       "envfrom" arg | "envrcpt" arg | "header"	arg arg	|
		       "body" arg | "macro" arg	arg | '$' name
     arg	     = del regex del flags
     del	     = '/' | ',' | '-' | ...
     flags	     = [ 'e' ] [ 'i' ] [ 'n' ]
     macro	     = name '='	expr


     mailstats(8), regex(3), syslog(3),	syslog.conf(5),	re_format(7),
     sendmail(8), syslogd(8)

     Simple Mail Transfer Protocol, RFC	2821.

     Enhanced Mail System Status Codes,	RFC 1893.

     The first version of milter-regex was written in 2003.  Boolean expres-
     sion evaluation was added in 2004.

     Daniel Hartmeier <>

BSD			      September	24, 2003			   BSD


Want to link to this manual page? Use this URL:

home | help