Commit | Line | Data |
---|---|---|
185b5456 MW |
1 | ### -*-m4-*- |
2 | ### | |
3 | ### Basic settings for distorted.org.uk Exim configuration | |
4 | ### | |
5 | ### (c) 2012 Mark Wooding | |
6 | ### | |
7 | ||
8 | ###----- Licensing notice --------------------------------------------------- | |
9 | ### | |
10 | ### This program is free software; you can redistribute it and/or modify | |
11 | ### it under the terms of the GNU General Public License as published by | |
12 | ### the Free Software Foundation; either version 2 of the License, or | |
13 | ### (at your option) any later version. | |
14 | ### | |
15 | ### This program is distributed in the hope that it will be useful, | |
16 | ### but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | ### GNU General Public License for more details. | |
19 | ### | |
20 | ### You should have received a copy of the GNU General Public License | |
21 | ### along with this program; if not, write to the Free Software Foundation, | |
22 | ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
23 | ||
24 | ###-------------------------------------------------------------------------- | |
25 | ### Global settings. | |
26 | ||
27 | SECTION(global, priv)m4_dnl | |
b1d083dd | 28 | admin_groups = CONF_admin_groups |
185b5456 MW |
29 | prod_requires_admin = false |
30 | ||
31 | SECTION(global, logging)m4_dnl | |
32 | log_file_path = : syslog | |
33 | log_selector = \ | |
34 | +smtp_confirmation \ | |
35 | +tls_peerdn | |
36 | log_timezone = true | |
37 | syslog_duplication = false | |
38 | syslog_timestamp = false | |
39 | ||
40 | SECTION(global, daemon)m4_dnl | |
41 | local_interfaces = <; CONF_interfaces | |
42 | extra_local_interfaces = <; 0.0.0.0 ; :: | |
43 | ||
44 | SECTION(global, resource)m4_dnl | |
45 | deliver_queue_load_max = 8 | |
46 | queue_only_load = 12 | |
47 | smtp_accept_max = 16 | |
48 | smtp_accept_queue = 32 | |
49 | smtp_accept_reserve = 4 | |
50 | smtp_load_reserve = 10 | |
51 | smtp_reserve_hosts = +trusted | |
52 | ||
53 | SECTION(global, policy)m4_dnl | |
54 | host_lookup = * | |
55 | ||
56 | SECTION(global, users)m4_dnl | |
57 | gecos_name = $1 | |
58 | gecos_pattern = ([^,:]*) | |
59 | ||
60 | SECTION(global, incoming)m4_dnl | |
61 | received_header_text = Received: \ | |
2cf9db84 | 62 | ${if def:sender_rcvhost \ |
9384ef4f | 63 | {from $sender_rcvhost\n\t} \ |
2cf9db84 MW |
64 | {${if def:sender_ident \ |
65 | {from ${quote_local_part:$sender_ident} }}}}\ | |
185b5456 | 66 | by $primary_hostname \ |
b92689d6 MW |
67 | (Exim $version_number)\ |
68 | ${if def:tls_cipher {\n\t} { }}\ | |
185b5456 MW |
69 | ${if def:received_protocol \ |
70 | {with $received_protocol \ | |
b92689d6 | 71 | ${if def:tls_cipher {(cipher=$tls_cipher)}}}}\n\t\ |
185b5456 | 72 | ${if def:sender_address \ |
43e6fc69 | 73 | {(envelope-from $sender_address\ |
185b5456 MW |
74 | ${if def:authenticated_id \ |
75 | {; auth=$authenticated_id}})\n\t}}\ | |
76 | id $message_exim_id\ | |
77 | ${if def:received_for {\n\tfor $received_for}} | |
78 | ||
79 | SECTION(global, smtp)m4_dnl | |
80 | smtp_return_error_details = true | |
81 | accept_8bitmime = true | |
82 | ||
83 | SECTION(global, process)m4_dnl | |
84 | extract_addresses_remove_arguments = false | |
85 | headers_charset = utf-8 | |
86 | qualify_domain = CONF_master_domain | |
87 | ||
88 | SECTION(global, bounce)m4_dnl | |
89 | delay_warning = 1h : 24h : 2d | |
90 | ||
91 | DIVERT(null) | |
92 | ###-------------------------------------------------------------------------- | |
93 | ### Access control lists. | |
94 | ||
95 | SECTION(global, acl-after) | |
96 | SECTION(global, acl)m4_dnl | |
97 | acl_smtp_helo = helo | |
98 | SECTION(acl, misc)m4_dnl | |
99 | helo: | |
fe8f2338 MW |
100 | ## Check that the caller's claimed identity is actually plausible. |
101 | ## This seems like it's a fairly effective filter on spamminess, but | |
102 | ## it's too blunt a tool. Rather than reject, add a warning header. | |
103 | ## Only we can't do this the easy way, so save it up for use in MAIL. | |
104 | ## Also, we're liable to get a subsequent HELO (e.g., after STARTTLS) | |
105 | ## and we should only care about the most recent one. | |
106 | warn set acl_c_helo_warning = false | |
107 | !condition = \ | |
108 | ${if exists {CONF_sysconf_dir/helo.conf} \ | |
109 | {${lookup {$sender_helo_name} \ | |
110 | partial0-lsearch \ | |
111 | {CONF_sysconf_dir/helo.conf} \ | |
112 | {${if match_ip \ | |
113 | {$sender_host_address} \ | |
114 | {$value}}}}}} | |
115 | !verify = helo | |
116 | set acl_c_helo_warning = true | |
185b5456 MW |
117 | |
118 | accept | |
119 | ||
120 | SECTION(global, acl)m4_dnl | |
284c9d7e MW |
121 | acl_not_smtp_start = not_smtp_start |
122 | SECTION(acl, misc)m4_dnl | |
123 | not_smtp_start: | |
124 | ## Record the user's name. | |
125 | warn set acl_c_user = $sender_ident | |
126 | ||
127 | ## Done. | |
128 | accept | |
129 | ||
130 | SECTION(global, acl)m4_dnl | |
185b5456 MW |
131 | acl_smtp_mail = mail |
132 | SECTION(acl, mail)m4_dnl | |
133 | mail: | |
134 | ||
fe8f2338 MW |
135 | ## If we stashed a warning header about HELO from earlier, we should |
136 | ## add it now. | |
137 | warn condition = $acl_c_helo_warning | |
138 | add_header = :after_received:X-Distorted-Warning: \ | |
139 | BADHELO \ | |
140 | Client's HELO doesn't match its IP address.\n\t\ | |
d70f6d53 MW |
141 | HELO name=$sender_helo_name, \ |
142 | address=$sender_host_address | |
fe8f2338 | 143 | |
185b5456 MW |
144 | ## Always allow the empty sender, so that we can receive bounces. |
145 | accept senders = : | |
146 | ||
147 | ## Ensure that the sender is routable. This is important to prevent | |
148 | ## undeliverable bounces. | |
149 | require message = Invalid sender; \ | |
150 | ($sender_verify_failure; $acl_verify_message) | |
151 | verify = sender | |
152 | ||
153 | ## If this is directly from a client then hack on it for a while. | |
154 | warn condition = ${if eq{$acl_c_mode}{submission}} | |
155 | control = submission | |
156 | ||
284c9d7e MW |
157 | ## Insist that a local client connect through TLS. |
158 | deny message = Hosts within CONF_master_domain must use TLS | |
159 | !condition = ${if eq{$acl_c_mode}{submission}} | |
160 | hosts = +allnets | |
161 | !encrypted = * | |
162 | ||
163 | ## Check that a submitted message's sender address is allowable. | |
164 | require acl = mail_check_auth | |
165 | ||
185b5456 MW |
166 | SECTION(acl, mail-tail)m4_dnl |
167 | ## And we're done. | |
168 | accept | |
169 | ||
170 | SECTION(global, acl)m4_dnl | |
171 | acl_smtp_connect = connect | |
172 | SECTION(acl, connect)m4_dnl | |
173 | connect: | |
174 | SECTION(acl, connect-tail)m4_dnl | |
e12c9586 | 175 | ## Configure variables according to the submission mode. |
185b5456 | 176 | warn acl = check_submission |
e12c9586 MW |
177 | |
178 | ## Done. | |
185b5456 MW |
179 | accept |
180 | ||
181 | check_submission: | |
182 | ## See whether this message needs hacking on. | |
183 | accept !hosts = +localnet | |
184 | !condition = ${if ={$received_port}{CONF_submission_port}} | |
185 | set acl_c_mode = relay | |
186 | ||
187 | ## Remember to apply submission controls. | |
188 | warn set acl_c_mode = submission | |
189 | ||
190 | ## Done. | |
191 | accept | |
192 | ||
193 | SECTION(global, acl)m4_dnl | |
194 | acl_smtp_rcpt = rcpt | |
195 | SECTION(acl, rcpt)m4_dnl | |
196 | rcpt: | |
197 | ||
198 | ## Reject if the client isn't allowed to relay and the recipient | |
199 | ## isn't in one of our known domains. | |
200 | deny message = Relaying not permitted | |
201 | !hosts = CONF_relay_clients | |
202 | !authenticated = * | |
203 | !domains = +known | |
204 | ||
205 | ## Ensure that the recipient is routable. | |
206 | require message = Invalid recipient \ | |
207 | ($recipient_verify_failure; $acl_verify_message) | |
208 | verify = recipient | |
209 | ||
210 | SECTION(acl, rcpt-tail)m4_dnl | |
211 | ## Everything checks out OK: let this one go through. | |
212 | accept | |
213 | ||
214 | SECTION(global, acl)m4_dnl | |
215 | acl_smtp_data = data | |
216 | SECTION(acl, data)m4_dnl | |
217 | data: | |
218 | ||
219 | SECTION(acl, data-tail)m4_dnl | |
220 | accept | |
221 | ||
222 | SECTION(global, acl)m4_dnl | |
223 | acl_smtp_expn = expn_vrfy | |
224 | acl_smtp_vrfy = expn_vrfy | |
225 | SECTION(acl)m4_dnl | |
226 | expn_vrfy: | |
227 | accept hosts = +trusted | |
228 | deny message = Suck it and see | |
229 | ||
230 | DIVERT(null) | |
231 | ###-------------------------------------------------------------------------- | |
284c9d7e MW |
232 | ### Verification of sender address. |
233 | ||
234 | SECTION(acl, misc)m4_dnl | |
235 | mail_check_auth: | |
236 | ||
237 | ## If this isn't a submission then it doesn't need checking. | |
238 | accept condition = ${if !eq{$acl_c_mode}{submission}} | |
239 | ||
240 | ## If the caller hasn't formally authenticated, but this is a | |
241 | ## loopback connection, then we can trust identd to tell us the right | |
242 | ## answer. So we should stash the right name somewhere consistent. | |
243 | warn set acl_c_user = $authenticated_id | |
244 | hosts = +localnet | |
245 | !authenticated = * | |
246 | set acl_c_user = $sender_ident | |
247 | ||
248 | ## User must be authenticated. | |
249 | deny message = Sender not authenticated | |
250 | !hosts = +localnet | |
251 | !authenticated = * | |
252 | ||
253 | ## Make sure that the local part is one that the authenticated sender | |
254 | ## is allowed to claim. | |
255 | deny message = Sender address forbidden to calling user | |
256 | !condition = ${LOOKUP_DOMAIN($sender_address_domain, | |
257 | {${if and {{match_local_part \ | |
258 | {$acl_c_user} \ | |
259 | {+dom_users}} \ | |
260 | {match_local_part \ | |
261 | {$sender_address_local_part} \ | |
262 | {+dom_locals}}}}}, | |
263 | {${if and {{match_local_part \ | |
264 | {$sender_address_local_part} \ | |
265 | {+user_extaddr}} \ | |
266 | {or {{eq {$sender_address_domain} \ | |
267 | {}} \ | |
268 | {match_domain \ | |
269 | {$sender_address_domain} \ | |
270 | {+public}}}}}}})} | |
271 | ||
272 | ## All done. | |
273 | accept | |
274 | ||
275 | DIVERT(null) | |
276 | ###-------------------------------------------------------------------------- | |
185b5456 MW |
277 | ### Common options for forwarding routers. |
278 | ||
279 | ## We're pretty permissive here. | |
280 | m4_define(<:FILTER_BASE:>, | |
281 | <:driver = redirect | |
282 | modemask = 002 | |
283 | check_owner = false | |
284 | check_group = false | |
285 | allow_filter = true | |
286 | allow_defer = true | |
287 | allow_fail = true | |
288 | forbid_blackhole = false | |
289 | check_ancestor = true:>) | |
290 | ||
291 | ## Common options for forwarding routers at verification time. | |
292 | m4_define(<:FILTER_VERIFY:>, | |
293 | <:verify_only = true | |
294 | user = CONF_filter_user | |
295 | forbid_filter_dlfunc = true | |
296 | forbid_filter_logwrite = true | |
297 | forbid_filter_perl = true | |
298 | forbid_filter_readsocket = true | |
299 | forbid_filter_run = true | |
300 | file_transport = dummy | |
301 | directory_transport = dummy | |
302 | pipe_transport = dummy | |
303 | reply_transport = dummy:>) | |
304 | ||
305 | ## Transports for redirection filters. | |
306 | m4_define(<:FILTER_TRANSPORTS:>, | |
7ab75d6f | 307 | <:file_transport = mailbox |
185b5456 MW |
308 | directory_transport = maildir |
309 | pipe_transport = pipe | |
310 | reply_transport = reply:>) | |
311 | ||
7ab75d6f MW |
312 | m4_define(<:FILTER_ROUTER:>, |
313 | <:$1_vrf: | |
314 | $2 | |
315 | FILTER_VERIFY<::>$3 | |
316 | $1: | |
317 | $2 | |
318 | verify = no | |
319 | FILTER_TRANSPORTS<::>$4:>) | |
320 | ||
185b5456 MW |
321 | DIVERT(null) |
322 | ###-------------------------------------------------------------------------- | |
323 | ### Some standard transports. | |
324 | ||
325 | m4_define(<:USER_DELIVERY:>, | |
326 | <:delivery_date_add = true | |
327 | envelope_to_add = true | |
328 | return_path_add = true:>) | |
329 | ||
330 | SECTION(transports)m4_dnl | |
331 | ## A standard transport for remote delivery. Try to do TLS, and don't worry | |
332 | ## too much if it's not very secure: the alternative is sending in plaintext | |
333 | ## anyway. | |
334 | smtp: | |
335 | driver = smtp | |
336 | tls_require_ciphers = CONF_acceptable_ciphers | |
337 | tls_dh_min_bits = 1020 | |
338 | tls_tempfail_tryclear = true | |
339 | ||
340 | ## Transport to a local SMTP server; use TLS and perform client | |
341 | ## authentication. | |
342 | smtp_local: | |
343 | driver = smtp | |
344 | hosts_require_tls = * | |
345 | tls_certificate = CONF_sysconf_dir/client.cert | |
346 | tls_privatekey = CONF_sysconf_dir/client.key | |
347 | tls_verify_certificates = CONF_ca_dir/ca.cert | |
348 | tls_require_ciphers = CONF_good_ciphers | |
b6d74252 | 349 | tls_dh_min_bits = 2046 |
185b5456 MW |
350 | tls_tempfail_tryclear = false |
351 | authenticated_sender = ${if def:authenticated_id \ | |
0bed9b7f | 352 | {$authenticated_id@CONF_master_domain} \ |
185b5456 MW |
353 | fail} |
354 | ||
355 | ## A standard transport for local delivery. | |
356 | deliver: | |
357 | driver = appendfile | |
358 | file = /var/mail/$local_part | |
8f6af4ae MW |
359 | group = mail |
360 | mode = 0600 | |
361 | mode_fail_narrower = false | |
185b5456 MW |
362 | USER_DELIVERY |
363 | ||
364 | ## Transports for user filters. | |
365 | mailbox: | |
366 | driver = appendfile | |
8f6af4ae | 367 | initgroups = true |
185b5456 MW |
368 | USER_DELIVERY |
369 | ||
370 | maildir: | |
371 | driver = appendfile | |
372 | maildir_format = true | |
8f6af4ae | 373 | initgroups = true |
185b5456 MW |
374 | USER_DELIVERY |
375 | ||
376 | pipe: | |
377 | driver = pipe | |
8f6af4ae MW |
378 | path = ${if and {{def:home} {exists{$home/bin}}} {$home/bin:} {}}\ |
379 | /usr/local/bin:/usr/local/sbin:\ | |
380 | /usr/bin:/usr/sbin:/bin:/sbin | |
381 | initgroups = true | |
382 | umask = 002 | |
383 | return_fail_output = true | |
384 | log_output = true | |
185b5456 MW |
385 | |
386 | ## A special dummy transport for use during address verification. | |
387 | dummy: | |
388 | driver = appendfile | |
389 | file = /dev/null | |
390 | ||
391 | DIVERT(null) | |
392 | ###-------------------------------------------------------------------------- | |
393 | ### Retry configuration. | |
394 | ||
395 | SECTION(retry, default)m4_dnl | |
396 | ## Default. | |
397 | * * \ | |
398 | F,2h,15m; G,16h,2h,1.5; F,4d,6h | |
399 | ||
400 | DIVERT(null) | |
401 | ###----- That's all, folks -------------------------------------------------- |