1MILTER-REGEX(8) BSD System Manager's Manual MILTER-REGEX(8)
2
4 milter-regex — sendmail milter plugin for regular expression filtering
5
7 milter-regex [-d] [-c config] [-f facility] [-j dirname] [-l loglevel]
8 [-m number] [-p pipe] [-r pid-file] [-t] [-u user]
9 [-G group] [-P mode] [-U user]
10
12 The milter-regex plugin can be used with the milter API of sendmail(8) to
13 filter mails using regular expressions matching SMTP envelope parameters
14 and mail headers and body.
15
16 The options are as follows:
17
18 -d Don't detach from controlling terminal and produce verbose
19 debug output on stdout.
20
21 -c config Use the specified configuration file instead of the default,
22 /etc/mail/milter-regex.conf.
23
24 -f facility
25 Use the specified syslog facility instead of the default, dae‐
26 mon.
27
28 -j dirname
29 Change root to the specified directory.
30
31 -l loglevel
32 Only log messages up to and including the specified level.
33 See syslog(3) for the numerical values, e.g. the default
34 LOG_INFO=6.
35
36 -m number Ignore mail body after the specified number of lines.
37
38 -p pipe Use the specified pipe to interface sendmail(8). Default is
39 unix:/var/spool/milter-regex/sock.
40
41 -r pid-file
42 Write the pid to the specified file. Default is not to write a
43 file.
44
45 -t Test the configuration file and immediately exit with a status
46 indicating whether the file is valid.
47
48 -u user Run as the specified user instead of the default, mregex.
49 When milter-regex is started as root, it calls setuid(2) to
50 drop privileges. The non-privileged user should have read
51 access to the configuration file and read-write access to the
52 pipe.
53
54 -G group Set the group ID of the pipe.
55
56 -P mode Set the permissions of the pipe to the specified mode instead
57 of the default, 0600.
58
59 -U user Set the user ID of the pipe.
60
62 The plugin needs to be registered in the sendmail(8) configuration, by
63 adding the following lines to the .mc file
64
65 INPUT_MAIL_FILTER(`milter-regex',
66 `S=unix:/var/spool/milter-regex/sock, T=S:30s;R:2m')
67
68 rebuilding /etc/mail/sendmail.cf from the .mc file using m4(1), and
69 restarting sendmail(8).
70
72 The configuration file consists of rules that, when matched, cause
73 sendmail(8) to reject mails. Emtpy lines and lines starting with # are
74 ignored, as well as leading whitespace (blanks, tabs). Trailing back‐
75 slashes can be used to wrap long rules into multiple lines. Each rule
76 starts with one of the following commands:
77
78 reject <message>
79 Subsequent rules cause the mail to be rejected with a permanent
80 error consisting of the specified text part. The SMTP reply con‐
81 sists of the three-digit code 554 (RFC 2821 "command rejected for
82 policy reasons"), the extended reply code 5.7.1 (RFC 1893 "Perma‐
83 nent Failure", "Security or Policy Status", "Delivery not autho‐
84 rized, message refused") and the text part (which defaults to "Com‐
85 mand rejected", if not specified). This is a permanent failure,
86 which causes the sender to remove the message from its queue with‐
87 out trying to retransmit, commonly generating a bounce message to
88 the sender.
89
90 tempfail <message>
91 Subsequent matching rules cause the mail to be rejected with a tem‐
92 porary error consisting of the specified text part. The SMTP reply
93 consists of the three-digit code 451 (RFC 2821 "Requested action
94 aborted: local error in processing"), the extended reply code 4.7.1
95 (RFC 1893 "Persistent Transient Failure", "Security or Policy Sta‐
96 tus", "Delivery not authorized, message refused") and the text part
97 (which defaults to "Please try again later", if not specified).
98 This is a temporary failure, which causes the sender to keep the
99 message in its queue and try to retransmit it, commonly for several
100 days.
101
102 discard
103 Subsequent matching rules cause the mail to be accepted but then
104 discarded silently. Note that connect and helo rules should not
105 use discard.
106
107 quarantine <message>
108 Subsequent matching rules cause the mail to be quarantined in
109 sendmail(8).
110
111 accept
112 Subsequent matching rules cause the mail to be accepted without
113 further rule evaluation. Can be used for whitelist criteria.
114
115 A command is followed by one or more expressions, each causing the previ‐
116 ous command to be executed when matched. The following expressions can
117 be used:
118
119 connect <hostname> <address>
120 Reject the connection if both the sender's hostname and address
121 match the specified regular expressions. The numerical address is
122 either dotted-quad (IPv4) or coloned-hex (IPv6). The hostname is
123 the result of a DNS reverse resolution of the numerical address
124 (which sendmail(8) performs independantly of the milter plugin).
125 When resolution fails, the hostname contains the numerical address
126 in square brackets.
127
128 helo <name>
129 Reject the connection if the sender supplied HELO name matches the
130 specified regular expression. Commonly, the sender supplies his
131 fully-qualified hostname as HELO name.
132
133 envfrom <address>
134 Reject the mail if the sender supplied envelope MAIL FROM address
135 matches the specified regular expression. Addresses commonly have
136 the form <user@host.doma.in>.
137
138 envrcpt <address>
139 Reject the mail if the sender supplied envelope RCPT TO address
140 matches the specified regular expression.
141
142 header <name> <value>
143 Reject the mail if a header matches the specified name and value.
144 For instance, the header "Subject: Test" matches name Subject and
145 value Test.
146
147 body <line>
148 Reject the mail if a body line matches the specified regular
149 expression.
150
151 macro <name> <value>
152 Reject the mail if a sendmail macro value matches.
153
154 The plugin regularly checks the configuration file for modification and
155 reloads it automatically. Signals like SIGHUP will terminate the plugin,
156 according to the milter signal handler. The plugin reacts to any kind of
157 error, like syntax errors in the configuration file, by failing open,
158 accepting all messages. When the plugin is not running, sendmail(8) will
159 accept all messages.
160
162 The regular expressions used in the configuration rules are enclosed in
163 arbitrary delimiters, no further escaping is needed.
164
165 The first character of an argument is taken as the delimiter, and all
166 subsequent characters up to the next occurance of the same delimiter are
167 taken literally as the regular expression. Since the delimiter itself
168 cannot be part of the regular expression (no escaping is supported), a
169 delimiter must be chosen that doesn't occur in the regular expression
170 itself. Each argument can use a different delimiter, all characters
171 except spaces and tabs are valid.
172
173 Two immediately adjacent delimiters form an empty regular expression,
174 which always matches and requires no regexec(3) call. This can be used
175 in rules requiring multiple arguments, to match only some arguments.
176
177 See re_format(7) for a detailed description of basic and extended regular
178 expressions.
179
180 Optionally, the following flags can be used after the closing delimiter:
181 e Extended regular expression. This sets REG_EXTENDED for regcomp(3).
182 i Ignore upper/lower case. This sets REG_ICASE.
183 n Not matching. Reverses the matching result, i.e. the mail is
184 rejected if the regular expression does not match.
185
187 A rule can consist of either a simple term or more complex expressions.
188 A term has the form
189
190 header /From/ /domain/i
191
192 and expressions can be built combining terms with operators "and", "or",
193 "not" and parentheses, as in
194
195 header /From/ /domain/i and body /money/
196 ( not header /From/ /domain/ ) and ( body /sex/ or body /fast/ )
197
198 Operator precedence should not be relied on, instead parentheses should
199 be used to resolve any ambiguities (they usually produce syntax errors
200 from the parser).
201
203 Macros allow to store terms or expressions as a name, and $name can be
204 used as term within other rules, expressions or macro definitions. Exam‐
205 ple:
206
207 friends = header /^Received$/ /^from [^ ]*(ork.net|home.com)/e
208 attachments = header ,^Content-Type$, ,multipart/mixed, and \
209 body ,^Content-Type: application/,
210 executables = $attachments and body ,name=".*.(pif|exe|scr)"$,e
211
212 reject "executable attachment from non-friends"
213 $executables and not $friends
214
215 Macro names must begin with a letter and may contain alphanumeric charac‐
216 ters and punctuation characters. Reserved keywords (like "reject" or
217 "header") cannot be used as macro names. Macros must be defined before
218 use, the definition must precede the use in the configuration file, read
219 from top to bottom.
220
222 Rules are evaluated in the order specified in the configuration file,
223 from top to bottom. When a rule matches, the corresponding action is
224 taken, that is the last action specified before the matching rule.
225
226 The plugin evaluates the rules every time a line of mail (or envelope) is
227 received. As soon as a rule matches, the action is taken immediately,
228 possibly before the entire mail is received, even if further lines might
229 possibly make other rules match, too. This means the first rule matching
230 chronologically has precedence.
231
232 If evaluation for a line of mail makes two (or more) rules match, the
233 rule that comes first in the configuration file has precedence.
234
235 Boolean expressions are short-circuit evaluated, that means "a or b"
236 becomes true as soon as one of the terms is true and "a and b" becomes
237 false as soon as one of the terms is false, even if the other term is not
238 known, possibly because the relevant mail line has not been received yet.
239
241 # /etc/mail/milter-regex.conf example
242
243 # Accept anything encrypted, just to demonstrate sendmail macros
244 accept
245 macro /tls_version/ /TLSv/
246
247 tempfail "Sender IP address not resolving"
248 connect /\[.*\]/ //
249
250 reject "Malformed HELO (not a domain, no dot)"
251 helo /\./n
252
253 reject "Malformed RCPT TO (not an email address, not <.*@.*>)"
254 envrcpt /<(.*@.*|Postmaster)>/ein
255
256 reject "HTML mail not accepted"
257 # use comma as delimiter here, as / occurs within RE
258 header /^Content-type$/i ,^text/html,i
259 body ,^Content-type: text/html,i
260
261 # Swen worm
262 discard
263 header /^(TO|FROM|SUBJECT)$/e //
264 header /^Content-type$/i /boundary="Boundary_(ID_/i
265 header /^Content-type$/i /boundary="[a-z]*"/
266 body ,^Content-type: audio/x-wav; name="[a-z]*\.[a-z]*",i
267
268 # Some nasty spammer
269 reject "Business Corp spam, get lost"
270 body /^Business Corp. for W.& L. AG/i and \
271 ( body /043.*317.*0285/ or body /0041.43.317.02.85/ )
272
273
275 milter-regex sends log messages to syslogd(8) using facility daemon and,
276 with increasing verbosity, level err, notice, info and debug. The fol‐
277 lowing syslog.conf(5) section can be used to log messages to a dedicated
278 file:
279
280 !milter-regex
281 daemon.err;daemon.notice /var/log/milter-regex
282
284 Syntax for milter-regex in BNF:
285
286 file = ( rule | macro ) file
287 rule = action expr-list
288 action = "reject" msg | "tempfail" msg | "discard" |
289 "quarantine" msg | "accept"
290 msg = ( '"' | "'" ) string ( '"' | "'" )
291 expr-list = expr [ expr-list ]
292 expr = term | term "and" expr | term "or" expr | "not" term
293 term = '(' expr ')' | "connect" arg arg | "helo" arg |
294 "envfrom" arg | "envrcpt" arg | "header" arg arg |
295 "body" arg | "macro" arg arg | '$' name
296 arg = del regex del flags
297 del = '/' | ',' | '-' | ...
298 flags = [ 'e' ] [ 'i' ] [ 'n' ]
299 macro = name '=' expr
300
302 /etc/mail/milter-regex.conf
303
305 mailstats(1), regex(3), syslog(3), syslog.conf(5), re_format(7),
306 sendmail(8), syslogd(8)
307
308 Simple Mail Transfer Protocol, RFC 2821.
309
310 Enhanced Mail System Status Codes, RFC 1893.
311
313 The first version of milter-regex was written in 2003. Boolean expres‐
314 sion evaluation was added in 2004.
315
317 Daniel Hartmeier ⟨daniel@benzedrine.cx⟩
318
319BSD September 24, 2003 BSD