From: Nathan Ollerenshaw ## I've been working quite hard to come up with a config that reasonably ## matches the qmail-ldap setup, without the warts. I want to submit it ## for inclusion in your config.samples archive, in case anyone else needs ## to do the same as I. I hope its useful. ## ## A few notes; it supports catchalls but not dash extension addressing, ## as I couldn't be bothered, and I'm unsure as to how many people ## actually use the feature. Certainly nobody on my system. It supports ## autoreplies, but not an autoreply on a catchall, because this just ## kills your mailserver when someone does a dictionary spam attack ## against a domain set up this way. ###################################################################### # Runtime configuration file for Exim # ###################################################################### #domainlist local_domains = @ : lsearch:/apps/conf/mail/locals domainlist local_domains = lsearch;/apps/conf/mail/locals domainlist relay_to_domains = # the pop-before-smtp package at http://popbsmtp.sourceforge.net/ # creates the /etc/mail/popauth.db file for us. We have to use dbmnz # lookup type here. hostlist relay_from_hosts = 127.0.0.1 : net-dbmnz;/etc/mail/popauth.db primary_hostname = [[[SET THIS TO LOCAL HOST NAME]]] # LDAP settings # Set the following to your ldap server(s) ldap_default_servers = ldap::389 BASEDN = [[[SET THIS TO YOUR BASE DN IN LDAP]]] acl_smtp_rcpt = acl_check_rcpt acl_smtp_data = acl_check_data exim_user = vmail exim_group = vmail trusted_users = vmail never_users = root host_lookup = * rfc1413_hosts = * rfc1413_query_timeout = 0s ignore_bounce_errors_after = 2d timeout_frozen_after = 7d bounce_return_body = false accept_8bitmime = true allow_mx_to_ip = true auto_thaw = 60m smtp_accept_max = 0 smtp_load_reserve = 20 delay_warning = 4h:8h:24h dns_again_means_nonexist = !+local_domains : !+relay_to_domains spamd_address = 127.0.0.1 783 av_scanner = clamd:127.0.0.1 3310 # Spool settings split_spool_directory = true check_spool_space = 100M check_spool_inodes = 1000 # Logging - enable a bunch of extra useful stuff. Never know, could help # one day, and at least its better than qmail! Har har! log_selector = +delivery_size +received_sender +received_recipients \ +subject +sender_on_delivery # NOTE TO SELF: Lets use syslog and have all six mail servers log to a # central location so its easier to do statistics gathering and fault # analysis. # MACROS # Secret for all machines in the cluster. Change it to whatever you feel # is best. SECRET = Ni2opNyw2pNM3cmWn21nOSbwdq GET_ADDRESS_DATA = ${lookup ldap {\ ldap:///BASEDN??sub?(&(uid=${quote_ldap:$local_part}@${quote_ldap:$domain}))\ }\ } GET_CATCHALL_DATA = ${lookup ldap {\ ldap:///BASEDN??sub?(&(uid=catchall@${quote_ldap:$domain}))\ }\ } MSGCOOKIE = ${hmac{md5}{SECRET}{$body_linecount}} ###################################################################### # ROUTERS CONFIGURATION # # Specifies how addresses are handled # ###################################################################### begin routers dnslookup: driver = dnslookup domains = ! +local_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 no_more system_aliases: driver = redirect condition = ${if eq {{$primary_hostname}{$domain} {1}{0}} } allow_fail allow_defer data = ${lookup{$local_part}lsearch{/etc/aliases}} file_transport = address_file pipe_transport = address_pipe # the forward router does the initial LDAP lookup. It then caches this in # $address_data for use by any of the other routers. Each router will fall # through if they then don't meet their condition. lookup: driver = redirect address_data = GET_ADDRESS_DATA # data is intentionally left blank so that the router will decline # we just want this router to do a lookup so the results are available # for the other routers. data = # OK, this is where we start supporting crazy qmail-ldap stuff. First, we # check if the address has a deliveryMode of 'forwardonly'. forwardonly is # a misnomer, because its possible for and address to be a forward, a mailbox # and an autoreply. So, we make it do the forward, and check to see if it is # also a reply or localdelivery, if so we set unseen to yes to make Exim # copy the message and send it to the next router. forward: driver = redirect condition = ${if match {${extract{deliveryMode}{$address_data}}}{forwardonly} {1}{0}} data = ${extract{mailForwardingAddress}{$address_data}} unseen = ${if or {{match {${extract{deliveryMode}{$address_data}}}{reply}} \ {match {${extract{deliveryMode}{$address_data}}}{localdelivery}}} \ {yes}{no}} # Same deal, check if its a reply, if so we send it to the correct transport. # After, we see if it needs to go to localdelivery as well. reply: driver = accept condition = ${if match {${extract{deliveryMode}{$address_data}}}{reply} {1}{0}} transport = auto_reply unseen = ${if match {${extract{deliveryMode}{$address_data}}}{localdelivery} {yes}{no}} localdelivery: driver = accept condition = ${if match {${extract{deliveryMode}{$address_data}}}{localdelivery} {1}{0}} transport = local_delivery # If we've reached this point, the account doesn't exist, so we need to # check to see if there is a catchall account, and if so do the usual for # it too. NOTE: we do not support auto-reply in a catch-all. # # This could, of course, be abused by someone assigning an auto-reply to # a forward_catchall. # NOTE TO SELF: See if reply router can be failed if an address comes from # a catchall. lookup_catchall: driver = redirect address_data = GET_CATCHALL_DATA # data is intentionally left blank so that the router will decline # just want this router to do a lookup. data = # could probably do a no_more = true based on the result of that LDAP # lookup to skip the next few routers, but there is no point as they are # not doing anything heavy so I'll just let them fall through and fail. # The catchall routers are exactly the same as the above routers, except # they make use of the GET_CATCHALL_DATA address_data to decide what to do # with the mail. forward_catchall: driver = redirect condition = ${if match {${extract{deliveryMode}{$address_data}}}{forwardonly} {1}{0}} data = ${extract{mailForwardingAddress}{$address_data}} unseen = ${if match {${extract{deliveryMode}{$address_data}}}{localdelivery} {yes}{no}} localdelivery_catchall: driver = accept condition = ${if match {${extract{deliveryMode}{$address_data}}}{localdelivery} {1}{0}} transport = local_delivery ###################################################################### # TRANSPORTS CONFIGURATION # ###################################################################### begin transports remote_smtp: driver = smtp # Deliver to the mailbox specified in the LDAP directory. We make sure # that quota is obeyed, and we try to send a message to the user if it # gets to over 85%. local_delivery: driver = appendfile maildir_format directory = ${extract{mailMessageStore}{$address_data}}/Maildir create_directory directory_mode = 0700 delivery_date_add envelope_to_add return_path_add group = vmail user = vmail mode = 0600 quota = ${eval:${sg{${extract{1}{,}{${extract{mailQuota}{$address_data}}}}}{S}{}}/1024}K maildir_use_size_file = true quota_warn_threshold = 85% # We set this to iso-2022-jp because we're in japan. Set it to whatever. auto_reply: driver = autoreply subject = "[Auto-Reply] $header_subject" headers = "Content-Type: text/plain; charset=iso-2022-jp" to = "$sender_address" text = ${extract{mailReplyText}{$address_data}} from = $local_part@$domain ###################################################################### # ACL CONFIGURATION # # Specifies access control lists for incoming SMTP mail # ###################################################################### begin acl # You should probably set up exiscan-acl's mime check here to scan for viruses # and spam and reject at SMTP time. As I won't be doing that for a while, I've # left it as an exercise for the reader. acl_check_rcpt: accept hosts = : deny message = Restricted characters in address domains = +local_domains local_parts = ^[.] : ^.*[@%!/|] deny message = Restricted characters in address domains = !+local_domains local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ accept local_parts = postmaster domains = +local_domains require verify = sender accept domains = +local_domains endpass verify = recipient accept domains = +relay_to_domains endpass verify = recipient accept hosts = +relay_from_hosts accept authenticated = * deny message = relay not permitted acl_check_data: require verify = header_syntax message = This message has malformed headers. deny message = This message contains malformed MIME ($demime_reason). demime = * condition = ${if >{$demime_errorlevel}{2}{1}{0}} deny message = We do not accept ".$found_extension" attachments here as \ they are common file extensions for viruses. If you wish \ to send such an attachment, please zip it first. demime = bat:btm:cmd:com:cpl:dll:exe:lnk:msi:pif:prf:reg:scr:vbs:url accept begin retry # Address or Domain Error Retries # ----------------- ----- ------- * * F,2h,15m; G,16h,1h,1.5; F,4d,6h ###################################################################### # REWRITE CONFIGURATION # ###################################################################### # There are no rewriting specifications in this default configuration file. begin rewrite ###################################################################### # AUTHENTICATION CONFIGURATION # ###################################################################### # There are no authenticator specifications in this default configuration file. begin authenticators plain: driver = plaintext public_name = PLAIN server_condition = ${if ldapauth {user="uid=${quote_ldap_dn:$2},BASEDN" \ pass=${quote:$3} ldap:///}{yes}{no}} server_set_id = $2 login: driver = plaintext public_name = LOGIN server_prompts = Username:: : Password:: server_condition = ${if ldapauth {user="uid=${quote_ldap_dn:$1},BASEDN" \ pass=${quote:$2} ldap:///}{yes}{no}} server_set_id = $1 ###################################################################### # CONFIGURATION FOR local_scan() # ###################################################################### # begin local_scan # End of Exim configuration file