# # sample exim.conf for Exim4 to use with the vmail-sql database scheme # (http://www.ex-parrot.com/~chris/vmail-sql/) # # Note that the authenticators assume that passwords are stored # as "{plaintext}users_password" (needed for cram-md5) # # This is a working config but has surely room for improvement. # Send any remarks to vmail@plonk.de # # History: # 2005-02-08 made this public. parts of this are taken from the vmail-sql # mailing list # #################### # It is usually a good idea to test a new configuration for syntactic # # correctness before installing it (for example, by running the command # # "exim -C /config/file.new -bV"). # ################# #system_filter = /etc/exim/filter #system_filter_user = exim #local_interfaces = <; 127.0.0.1 ; ::1 #daemon_smtp_ports = 25 : 587 : 465 #tls_on_connect_ports = 465 smtp_accept_queue_per_connection = 30 # spamd address or socket #spamd_address = /var/run/spamd/socket #av_scanner = clamd:/var/run/clamav/clamd.sock hide mysql_servers = /vmail/exim/xxxxxxxx trusted_users = root:mail:www-data #untrusted_set_sender = tls_advertise_hosts = * # The next three settings create two lists of domains and one list of hosts. # These lists are referred to later in this configuration using the syntax # +local_domains, +relay_to_domains, and +relay_from_hosts, respectively. They # are all colon-separated lists: domainlist virtual_domains = \ mysql;SELECT domain_name FROM domain WHERE domain_name = '${quote_mysql:$domain}' : \ mysql;SELECT alias FROM domain_alias WHERE alias = '${quote_mysql:$domain}' domainlist local_domains = localhost : your.mail.server domainlist relay_to_domains = hostlist relay_from_hosts = 127.0.0.1 # Most straightforward access control requirements can be obtained by # appropriate settings of the above options. In more complicated situations, you # may need to modify the Access Control List (ACL) which appears later in this # file. # The first setting specifies your local domains, for example: # # domainlist local_domains = my.first.domain : my.second.domain # # You can use "@" to mean "the name of the local host", as in the default # setting above. This is the name that is specified by primary_hostname, # as specified above (or defaulted). If you do not want to do any local # deliveries, remove the "@" from the setting above. If you want to accept mail # addressed to your host's literal IP address, for example, mail addressed to # "user@[192.168.23.44]", you can add "@[]" as an item in the local domains # list. You also need to uncomment "allow_domain_literals" below. This is not # recommended for today's Internet. # The second setting specifies domains for which your host is an incoming relay. # If you are not doing any relaying, you should leave the list empty. However, # if your host is an MX backup or gateway of some kind for some domains, you # must set relay_to_domains to match those domains. For example: # # domainlist relay_to_domains = *.myco.com : my.friend.org # # This will allow any host to relay through your host to those domains. # See the section of the manual entitled "Control of relaying" for more # information. # The third setting specifies hosts that can use your host as an outgoing relay # to any other host on the Internet. Such a setting commonly refers to a # complete local network as well as the localhost. For example: # # hostlist relay_from_hosts = 127.0.0.1 : 192.168.0.0/16 # # The "/16" is a bit mask (CIDR notation), not a number of hosts. Note that you # have to include 127.0.0.1 if you want to allow processes on your host to send # SMTP mail by using the loopback address. A number of MUAs use this method of # sending mail. # All three of these lists may contain many different kinds of item, including # wildcarded names, regular expressions, and file lookups. See the reference # manual for details. The lists above are used in the access control list for # incoming messages. The name of this ACL is defined here: acl_smtp_mail = acl_check_mail acl_smtp_rcpt = acl_check_rcpt acl_smtp_data = acl_check_data # You should not change that setting until you understand how ACLs work. # Specify the domain you want to be added to all unqualified addresses # here. An unqualified address is one that does not contain an "@" character # followed by a domain. For example, "caesar@rome.example" is a fully qualified # address, but the string "caesar" (i.e. just a login name) is an unqualified # email address. Unqualified addresses are accepted only from local callers by # default. See the recipient_unqualified_hosts option if you want to permit # unqualified addresses from remote sources. If this option is not set, the # primary_hostname value is used for qualification. #qualify_domain = # If you want unqualified recipient addresses to be qualified with a different # domain to unqualified sender addresses, specify the recipient domain here. # If this option is not set, the qualify_domain value is used. # qualify_recipient = # The following line must be uncommented if you want Exim to recognize # addresses of the form "user@[10.11.12.13]" that is, with a "domain literal" # (an IP address) instead of a named domain. The RFCs still require this form, # but it makes little sense to permit mail to be sent to specific hosts by # their IP address in the modern Internet. This ancient format has been used # by those seeking to abuse hosts by using them for unwanted relaying. If you # really do want to support domain literals, uncomment the following line, and # see also the "domain_literal" router below. # allow_domain_literals # No deliveries will ever be run under the uids of these users (a colon- # separated list). An attempt to do so causes a panic error to be logged, and # the delivery to be deferred. This is a paranoic safety catch. There is an # even stronger safety catch in the form of the FIXED_NEVER_USERS setting # in the configuration for building Exim. The list of users that it specifies # is built into the binary, and cannot be changed. The option below just adds # additional users to the list. The default for FIXED_NEVER_USERS is "root", # but just to be absolutely sure, the default here is also "root". # Note that the default setting means you cannot deliver mail addressed to root # as if it were a normal user. This isn't usually a problem, as most sites have # an alias for root that redirects such mail to a human administrator. never_users = root # The setting below causes Exim to do a reverse DNS lookup on all incoming # IP calls, in order to get the true host name. If you feel this is too # expensive, you can specify the networks for which a lookup is done, or # remove the setting entirely. host_lookup = * # The settings below, which are actually the same as the defaults in the # code, cause Exim to make RFC 1413 (ident) callbacks for all incoming SMTP # calls. You can limit the hosts to which these calls are made, and/or change # the timeout that is used. If you set the timeout to zero, all RFC 1413 calls # are disabled. RFC 1413 calls are cheap and can provide useful information # for tracing problem messages, but some hosts and firewalls have problems # with them. This can result in a timeout instead of an immediate refused # connection, leading to delays on starting up an SMTP session. rfc1413_hosts = ${if eq{$interface_port}{25} {*}{}} rfc1413_query_timeout = 2s # By default, Exim expects all envelope addresses to be fully qualified, that # is, they must contain both a local part and a domain. If you want to accept # unqualified addresses (just a local part) from certain hosts, you can specify # these hosts by setting one or both of # # sender_unqualified_hosts = # recipient_unqualified_hosts = # # to control sender and recipient addresses, respectively. When this is done, # unqualified addresses are qualified using the settings of qualify_domain # and/or qualify_recipient (see above). # If you want Exim to support the "percent hack" for certain domains, # uncomment the following line and provide a list of domains. The "percent # hack" is the feature by which mail addressed to x%y@z (where z is one of # the domains listed) is locally rerouted to x@y and sent on. If z is not one # of the "percent hack" domains, x%y is treated as an ordinary local part. This # hack is rarely needed nowadays; you should not enable it unless you are sure # that you really need it. # # percent_hack_domains = # # As well as setting this option you will also need to remove the test # for local parts containing % in the ACL definition below. # When Exim can neither deliver a message nor return it to sender, it "freezes" # the delivery error message (aka "bounce message"). There are also other # circumstances in which messages get frozen. They will stay on the queue for # ever unless one of the following options is set. # This option unfreezes frozen bounce messages after two days, tries # once more to deliver them, and ignores any delivery failures. ignore_bounce_errors_after = 2d # This option cancels (removes) frozen messages that are older than a week. timeout_frozen_after = 3d freeze_tell = postmaster # #log_selector = +arguments -retry_defer log_selector = +all_parents -arguments +connection_reject +deliver_time \ +delivery_size -host_lookup_failed +incoming_interface +incoming_port \ +queue_time +received_recipients +sender_on_delivery +size_reject \ +smtp_confirmation +smtp_incomplete_transaction +smtp_protocol_error \ +smtp_protocol_error +smtp_syntax_error +tls_peerdn message_size_limit = 10M # #received_header_text = Received: \ # ${if def:sender_rcvhost {from ${if def:authenticated_id \ # {${sg{$sender_rcvhost}{ helo=[^)\\s]*}{}}} {$sender_rcvhost}}\n\t}\ # {${if def:sender_ident {from $sender_ident }}\ # ${if def:sender_helo_name {(helo=$sender_helo_name)\n\t}}}}\ # by $primary_hostname \ # ${if def:received_protocol {with $received_protocol}} \ # ${if def:tls_cipher {($tls_cipher)\n\t}}\ # (Exim $version_number)\n\t\ # id $message_id\ # ${if def:received_for {\n\tfor $received_for}} # #dns_check_names_pattern = \ # (?i)^(?>(?(1)\.|())[^\W](?>[a-z0-9-_]*[^\W_])?)+$ ###################################################################### # ACL CONFIGURATION # # Specifies access control lists for incoming SMTP mail # ###################################################################### begin acl acl_check_mail: # warn set $sender_helo_name = private accept # This access control list is used for every RCPT command in an incoming # SMTP message. The tests are run in order until the address is either # accepted or denied. acl_check_rcpt: # Accept if the source is local SMTP (i.e. not over TCP/IP). We do this by # testing for an empty sending host field. accept hosts = : # block leading dot and "@%!/" inside local_part of local_domains deny domains = +local_domains : +virtual_domains local_parts = ^[.] : ^.*[@%!/|] # block leading "./|", "@%!" and "/../" inside local_part of non-local_domains deny domains = !+local_domains : !+virtual_domains local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ # Accept mail to postmaster in any local domain, regardless of the source, accept local_parts = postmaster domains = +local_domains : +virtual_domains # Deny unless the sender address can be verified. require verify = sender # Accept if the message arrived over an authenticated connection, from accept authenticated = * verify = recipient # check blacklisted smtp hosts deny message = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text dnslists = ix.dnsbl.manitu.net : relays.ordb.org : sbl.spamhaus.org : list.dsbl.org #warn message = X-Warning: $sender_host_address is in a black list at $dnslist_domain # log_message = found in $dnslist_domain # Accept if the address is in a local domain, but only if the recipient can # be verified. Otherwise deny. The "endpass" line is the border between accept domains = +local_domains : +virtual_domains endpass verify = recipient # Accept if the address is in a domain for which we are relaying, but again, accept domains = +relay_to_domains endpass verify = recipient # If control reaches this point, the domain is neither in +local_domains # nor in +relay_to_domains. # Accept if the message comes from one of the hosts for which we are an # outgoing relay. accept hosts = +relay_from_hosts verify = recipient # an explicit message. deny message = relay not permitted # check SMTP DATA acl_check_data: # Do not scan messages submitted from our own hosts # and locally submitted messages. Since the DATA ACL accept hosts = 127.0.0.1:+relay_from_hosts # accept if authenticated accept authenticated = * # Reject spam messages # put headers in all messages (no matter if spam or not) #warn message = Classified as spam (score $spam_score) #warn condition = ${if <{$message_size}{200k}{1}{0}} # spam = nobody # log_message = Classified as spam (score $spam_score) # delay = 10s # control = fakereject # put spam header into message #warn message = X-Spam-Status: ${if >{$spam_score_int}{50} {Yes}{No}}, $spam_score\n\ # X-Spam-Report: $spam_report # Finally accept all other messages that have # made it to this point accept ###################################################################### # ROUTERS CONFIGURATION # # Specifies how addresses are handled # ###################################################################### # THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT! # # An address is passed to each router in turn until it is accepted. # ###################################################################### begin routers # This router routes to remote hosts over SMTP by explicit IP address, # when an email address is given in "domain literal" form, for example, # . The RFCs require this facility. However, it is # little-known these days, and has been exploited by evil people seeking # to abuse SMTP relays. Consequently it is commented out in the default # configuration. If you uncomment this router, you also need to uncomment # allow_domain_literals above, so that Exim can recognize the syntax of # domain literal addresses. # domain_literal: # driver = ipliteral # domains = ! +local_domains # transport = remote_smtp # This router routes addresses that are not in local domains by doing a DNS # lookup on the domain name. Any domain that resolves to 0.0.0.0 or to a # loopback interface address (127.0.0.0/8) is treated as if it had no DNS # entry. Note that 0.0.0.0 is the same as 0.0.0.0/32, which is commonly treated # as the local host inside the network stack. It is not 0.0.0.0/0, the default # route. If the DNS lookup fails, no further routers are tried because of # the no_more setting, and consequently the address is unrouteable. dnslookup: driver = dnslookup domains = ! +local_domains : ! +virtual_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 no_more # The remaining routers handle addresses in the local domain(s). virtual_forward: driver = redirect #srs = forward allow_fail allow_defer data = ${lookup mysql{SELECT remote_name FROM forwarder \ LEFT JOIN domain_alias ON domain_alias.domain_name = forwarder.domain_name \ WHERE local_part = '${quote_mysql:$local_part}' \ AND (forwarder.domain_name = '$domain' OR alias = '$domain')} \ {$value}fail} forbid_file forbid_pipe # MySQL local users configuration. virtual_localuser: driver = accept local_parts = ${lookup mysql{SELECT mbox_name FROM popbox \ LEFT JOIN domain_alias ON popbox.domain_name = domain_alias.domain_name \ WHERE (popbox.domain_name = '$domain' OR domain_alias.alias = '$domain') \ AND local_part = '${quote_mysql:$local_part}'} \ {$value}fail} transport = virtual_localdelivery virtual_defaultforward: driver = redirect allow_fail allow_defer data = ${lookup mysql{SELECT remote_name FROM forwarder \ LEFT JOIN domain_alias on domain_alias.domain_name = forwarder.domain_name \ WHERE (local_part = '*' OR local_part ='_default_') \ AND (forwarder.domain_name = '$domain' OR alias = '$domain')} \ {$value}fail} # If any of your aliases expand to pipes or files, you will need to set # up a user and a group for these deliveries to run under. You can do # this by uncommenting the "user" option below (changing the user name # as appropriate) and adding a "group" option if necessary. Alternatively, you # can specify "user" on the transports that are used. Note that the transports # listed below are the same as are used for .forward files; you might want # to set up different ones for pipe and file deliveries from aliases. system_aliases: driver = redirect allow_fail allow_defer data = ${lookup{$local_part}lsearch*{/etc/aliases}} # user = exim user = mail file_transport = address_file pipe_transport = address_pipe # This router handles forwarding using traditional .forward files in users' # home directories. If you want it also to allow mail filtering when a forward # file starts with the string "# Exim filter", uncomment the "allow_filter" # option. # The no_verify setting means that this router is skipped when Exim is # verifying addresses. Similarly, no_expn means that this router is skipped if # Exim is processing an EXPN command. # The check_ancestor option means that if the forward file generates an # address that is an ancestor of the current one, the current one gets # passed on instead. This covers the case where A is aliased to B and B # has a .forward file pointing to A. # The three transports specified at the end are those that are used when # forwarding generates a direct delivery to a file, or to a pipe, or sets # up an auto-reply, respectively. #userforward: # driver = redirect # check_local_user # file = $home/.forward # no_verify # no_expn # check_ancestor ## allow_filter # file_transport = address_file # pipe_transport = address_pipe # reply_transport = address_reply # This router matches local user mailboxes. If the router fails, the error # message is "Unknown user". #localuser: # #domains = local_domains # driver = accept # check_local_user # transport = local_delivery # cannot_route_message = Unknown user ###################################################################### # TRANSPORTS CONFIGURATION # ###################################################################### # ORDER DOES NOT MATTER # # Only one appropriate transport is called for each delivery. # ###################################################################### # A transport is used only when referenced from a router that successfully # handles an address. begin transports # This transport is used for delivering messages over SMTP connections. remote_smtp: driver = smtp #hosts_avoid_tls = * # This transport is used for local delivery to user mailboxes in traditional # BSD mailbox format. By default it will be run under the uid and gid of the # local user, and requires the sticky bit to be set on the /var/mail directory. # Some systems use the alternative approach of running mail deliveries under a # particular group instead of using the sticky bit. The commented options below # show how this can be done. local_delivery: driver = appendfile file = /var/mail/$local_part #directory = /var/spool/vmail/$local_part #maildir_format return_path_add envelope_to_add delivery_date_add user = mail group = mail mode = 0600 current_directory = / # This transport is used for handling pipe deliveries generated by alias or # .forward files. If the pipe generates any standard output, it is returned # to the sender of the message as a delivery error. Set return_fail_output # instead of return_output if you want this to happen only when the pipe fails # to complete normally. You can set different transports for aliases and # forwards if you want to - see the references to address_pipe in the routers # section above. address_pipe: driver = pipe return_output # This transport is used for handling deliveries directly to files that are # generated by aliasing or forwarding. address_file: driver = appendfile delivery_date_add envelope_to_add return_path_add # This transport is used for handling autoreplies generated by the filtering # option of the userforward router. address_reply: driver = autoreply virtual_localdelivery: driver = appendfile maildir_format directory = ${lookup mysql{SELECT path FROM domain \ LEFT JOIN domain_alias ON domain_alias.domain_name = domain.domain_name \ WHERE domain.domain_name = '$domain' OR domain_alias.alias = '$domain' \ LIMIT 1} \ {$value}fail}/${lookup mysql{SELECT mbox_name FROM popbox \ LEFT JOIN domain_alias ON popbox.domain_name = domain_alias.domain_name \ WHERE (popbox.domain_name = '$domain' OR domain_alias.alias = '$domain') \ AND local_part ='$local_part' \ LIMIT 1} \ {$value}fail} delivery_date_add envelope_to_add return_path_add user = mail mode = 0660 ###################################################################### # RETRY CONFIGURATION # ###################################################################### begin retry # This single retry rule applies to all domains and all errors. It specifies # retries every 15 minutes for 2 hours, then increasing retry intervals, # starting at 1 hour and increasing each time by a factor of 1.5, up to 16 # hours, then retries every 6 hours until 4 days have passed since the first # failed delivery. # 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 cram_md5: driver = cram_md5 public_name = CRAM-MD5 server_secret = ${lookup mysql{ \ select password_hash from popbox \ where local_part = '${quote_mysql:${extract {1}{@%!}{$1}}}' \ and domain_name = '${quote_mysql:${extract {2}{@%!}{$1}}}' \ }{${extract {2}{\}}{$value}}}{fail}} server_set_id = $1 # C: AUTH LOGIN [base64($user, \0, $pass)] # - if no authentication on AUTH LOGIN: # S: base64('Username:') # C: base64($user) # S: base64('Password:') # C: base64($pass) # # Used by: Outlook Express # login: driver = plaintext public_name = LOGIN server_prompts = "Username:: : Password::" server_condition = ${if and { \ {!eq {$1}{}} \ {!eq {$2}{}} \ {eq {\{plaintext\}$2} \ {${lookup mysql { \ select password_hash from popbox \ where local_part = '${quote_mysql:${extract {1}{@%!}{$1}}}' \ and domain_name = '${quote_mysql:${extract {2}{@%!}{$1}}}' \ }{$value}{*:*}}} \ }}{1}{0}} server_set_id = $1 # C: AUTH PLAIN base64(\0, $user, \0, $pass) # # used by: Netscape # plain: driver = plaintext public_name = PLAIN server_condition = ${if and { \ {!eq {$2}{}} \ {!eq {$3}{}} \ {eq {\{plaintext\}$3} \ {${lookup mysql { \ select password_hash from popbox \ where local_part = '${quote_mysql:${extract {1}{@%!}{$2}}}' \ and domain_name = '${quote_mysql:${extract {2}{@%!}{$2}}}' \ }{$value}{*:*}}} \ }}{1}{0}} server_set_id = $2 ###################################################################### # CONFIGURATION FOR local_scan() # ###################################################################### # If you have built Exim to include a local_scan() function that contains # tables for private options, you can define those options here. Remember to # uncomment the "begin" line. It is commented by default because it provokes # an error with Exim binaries that are not built with LOCAL_SCAN_HAS_OPTIONS # set in the Local/Makefile. # begin local_scan # End of Exim configuration file