###################################################################### # Runtime configuration file for Exim # ###################################################################### # This file is divided into several parts, all but the first of which are # headed by a line starting with the word "begin". Only those parts that # are required need to be present. Blank lines, and lines starting with # # are ignored. exim_group = {{ exim_user_name }} exim_user = {{ exim_group_name }} keep_environment = HOME : LANG : USER add_environment = PATH=/sbin::/usr/sbin::/bin::/usr/bin ###################################################################### # MAIN CONFIGURATION SETTINGS # ###################################################################### # Specify your host's canonical name here. This should normally be the fully # qualified "official" name of your host. If this option is not set, the # uname() function is called to obtain the name. In many cases this does # the right thing and you need not set anything explicitly. primary_hostname = {{ exim_server_name }} smtp_banner = {{ exim_server_name }} ESMTP Exim $version_number $tod_full # 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: {% if exim_mailman_transport %} domainlist mailman_domains = mail.ivimey.org {% endif %} domainlist local_domains = {{ exim_local_domains | join(" : ") }} hostlist relay_from_hosts = {{ exim_relay_from_nets | join(" : ") }} hostlist relay_to_domains = {{ exim_relay_to_domains | join(" : ") }} hostlist no_lookup_hosts = {{ exim_no_lookup_hosts | join(" : ") }} hostlist whitelist_hosts = {{ exim_whitelist_hosts | join(" : ") }} hostlist blacklist_hosts = {{ exim_blacklist_hosts | join(" : ") }} hostlist no_greylisting = {{ exim_no_greylist_hosts | join(" : ") }} {% for vtag, vdomain in exim_virtual_domains.iteritems() %} domainlist {{ vtag }}_domains = {{ vdomain.domains | join(" : ") }} {% endfor %} # DKIM setup DKIM_CANON = {{ exim_dkim_canon }} DKIM_SELECTOR = {{ exim_dkim_selector }} # Get the domain from the outgoing mail. DKIM_DOMAIN = ${lc:${domain:$h_from:}} # The file is based on the outgoing domain-name in the from-header. DKIM_FILE = /etc/exim4/dkim/${lc:${domain:$h_from:}}.pem # If key exists then use it, if not don't. DKIM_PRIVATE_KEY = ${if exists {DKIM_FILE} {DKIM_FILE} {0} } # 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 lists for # checking incoming messages. The names of these ACLs are defined here: acl_smtp_connect = acl_check_connect acl_smtp_mail = acl_check_mail acl_smtp_rcpt = acl_check_rcpt acl_smtp_data = acl_check_data acl_smtp_mime = acl_check_mime acl_smtp_dkim = acl_check_dkim # You should not change those settings until you understand how ACLs work. # Verify sites known to sign mail with DKIM KNOWN_DKIM_SIGNERS = = {{ exim_dkim_known_signers | join(" : ") }} dkim_verify_signers = $dkim_signers : KNOWN_DKIM_SIGNERS # If you are running a version of Exim that was compiled with the content- # scanning extension, you can cause incoming messages to be automatically # scanned for viruses. You have to modify the configuration in two places to # set this up. The first of them is here, where you define the interface to # your scanner. This example is typical for ClamAV; see the manual for details # of what to set for other virus scanners. The second modification is in the # acl_check_data access control list (see below). #av_scanner = clamd:/var/run/clamd.exim/clamd.sock #av_scanner = cmdline:/usr/local/f-prot/f-prot %s:Infection:Infection. (.+)$ # For spam scanning, there is a similar option that defines the interface to # SpamAssassin. You do not need to set this if you are using the default, which # is shown in this commented example. As for virus scanning, you must also # modify the acl_check_data access control list to enable spam scanning. # spamd_address = 127.0.0.1 783 # If Exim is compiled with support for TLS, you may want to enable the # following options so that Exim allows clients to make encrypted # connections. In the authenticators section below, there are template # configurations for plaintext username/password authentication. This kind # of authentication is only safe when used within a TLS connection, so the # authenticators will only work if the following TLS settings are turned on # as well. # Allow any client to use TLS. tls_advertise_hosts = * # Specify the location of the Exim server's TLS certificate and private key. # The private key must not be encrypted (password protected). You can put # the certificate and private key in the same file, in which case you only # need the first setting, or in separate files, in which case you need both # options. tls_certificate = {{ exim_tls_certificate }} tls_privatekey = {{ exim_tls_privatekey }} # The mysql_servers, pgsql_servers, oracle_servers, or ibase_servers option # (as appropriate) must be set to a colon-separated list of server information. # Each item in the list is a slash-separated list of four items: host name, # database name, user name, and password. hide mysql_servers = {{ exim_mysql_hostname }}/{{ exim_mysql_database }}/{{ exim_mysql_user }}/N7wa24WpewdTLH7v # In order to support roaming users who wish to send email from anywhere, # you may want to make Exim listen on other ports as well as port 25, in # case these users need to send email from a network that blocks port 25. # The standard port for this purpose is port 587, the "message submission" # port. See RFC 4409 for details. Microsoft MUAs cannot be configured to # talk the message submission protocol correctly, so if you need to support # them you should also allow TLS-on-connect on the traditional but # non-standard port 465. local_interfaces = <; 192.168.32.1 ; 82.68.47.198 ; 127.0.0.1 daemon_smtp_ports = 25 : 465 : 587 tls_on_connect_ports = 465 # 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). # 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 = {{ exim_server_name }} # 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 users specified by # never_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:bin:daemon:lp:sync:games:man:lp:uucp:proxy:nobody trusted_users = {{ exim_trusted_user }} # 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 = !+no_lookup_hosts:* # This setting, if uncommented, allows users to authenticate using # their system passwords against saslauthd if they connect over a # secure connection. If you have network logins such as NIS or # Kerberos rather than only local users, then you possibly also want # to configure /etc/sysconfig/saslauthd to use the 'pam' mechanism # too. Once a user is authenticated, the acl_check_rcpt ACL then # allows them to relay through the system. # #auth_advertise_hosts = ${if eq {$tls_cipher}{}{}{*}} # # By default, we set this option to allow SMTP AUTH from nowhere # (Exim's default would be to allow it from anywhere, even on an # unencrypted connection). # # Comment this one out if you uncomment the above. Did you make sure # saslauthd is actually running first? # auth_advertise_hosts = * # 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 SMTP sessions. (The default was # reduced from 30s to 5s for release 4.61.) #rfc1413_hosts = * rfc1413_query_timeout = 0s # 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 = 7d # By default, messages that are waiting on Exim's queue are all held in a # single directory called "input" which it itself within Exim's spool # directory. (The default spool directory is specified when Exim is built, and # is often /var/spool/exim/.) Exim works best when its queue is kept short, but # there are circumstances where this is not always possible. If you uncomment # the setting below, messages on the queue are held in 62 subdirectories of # "input" instead of all in the same directory. The subdirectories are called # 0, 1, ... A, B, ... a, b, ... z. This has two benefits: (1) If your file # system degrades with many files in one directory, this is less likely to # happen; (2) Exim can process the queue one subdirectory at a time instead of # all at once, which can give better performance with large queues. # split_spool_directory = true smtp_accept_max_nonmail = 25 # Expand on "Administrative Prohibition" error messages. # http://www.exim.org/pipermail/exim-users/Week-of-Mon-20030428/053322.html # http://www.exim.org/pipermail/exim-users/Week-of-Mon-20030428/053243.html smtp_return_error_details = true # Don't insist on delivering only a certain number of messages per connection smtp_accept_queue_per_connection = 0 # Don't insist on 7-bit ASCII mail; 8-bit is ok too. accept_8bitmime = true # callout address verification callout_negative_expire = 18h callout_positive_expire = 9d callout_domain_negative_expire = 18h callout_domain_positive_expire = 9d # reject huge messages message_size_limit = {{ exim_message_size_limit }} ###################################################################### # ACL CONFIGURATION # # Specifies access control lists for incoming SMTP mail # ###################################################################### begin acl acl_check_connect: deny hosts = +blacklist_hosts message = Mail not permitted from your IP accept ###################################################################### acl_check_helo: # If the remote host greets with an IP address, then reject the mail. # deny message = $sender_helo_name is not valid as a HELO greeting. log_message = Remote host used IP address in HELO/EHLO greeting condition = ${if isip {$sender_helo_name}{true}{false}} # Accept messages from inside the network accept hosts = : +relay_from_hosts # Likewise if the peer greets with one of our own names # deny message = $sender_helo_name is my name, not your name. log_message = Remote host used my name in HELO/EHLO greeting. condition = ${if match_domain{$sender_helo_name}\ {$primary_hostname:+local_domains:+relay_to_domains}\ {true}{false}} # ok for now accept delay = {{ exim_intercommand_delay }} #-----------------------------------MAIL ACL------------------------------------------ # This access control list is used for the MAIL command in an incoming # SMTP message. acl_check_mail: # Hosts are required to say HELO (or EHLO) before sending mail. # So don't allow them to use the MAIL command if they haven't # done so. deny condition = ${if eq{$sender_helo_name}{} {1}} message = Nice boys say HELO first accept message = Accepted: sender is whitelisted log_message = Mail Accepted from $sender_host_address through sender whitelist entry senders = @@lsearch;{{ exim_whitelist_sender_file }} # white- and black-lists for hosts (connecting IPs) and senders (MAIL FROM) # that we definitely do or don't want. accept message = Accepted through host whitelist entry log_message = Mail Accepted from $sender_host_address through host whitelist entry hosts = +whitelist_hosts # Use the lack of reverse DNS to trigger greylisting. Some people # even reject for it but that would be a little excessive. warn condition = ${if eq{$sender_host_name}{} {1}} set acl_m_greylistreasons = Host $sender_host_address lacks reverse DNS\n$acl_m_greylistreasons # Deny if the sender is in one of a number of domains I don't want mail from. deny sender_domains = partial-lsearch;{{ exim_bad_mailfrom_hosts }} message = Sorry, I do not accept mail from $sender_address. accept delay = {{ exim_intercommand_delay }} #-----------------------------------RCPT ACL------------------------------------------ # This access control list is used for every RCPT command in an incoming # SMTP message. 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. # Deny if the sender is <> and there are more than 1 recipients deny senders = : message = Invalid use of null sender condition = ${if > {$rcpt_count} {1} {1} } ###### # The following section of the ACL is concerned with local parts that contain # @ or % or ! or / or | or dots in unusual places. # # The characters other than dots are rarely found in genuine local parts, but # are often tried by people looking to circumvent relaying restrictions. # Therefore, although they are valid in local parts, these rules lock them # out, as a precaution. # # Empty components (two dots in a row) are not valid in RFC 2822, but Exim # allows them because they have been encountered. (Consider local parts # constructed as "firstinitial.secondinitial.familyname" when applied to # someone like me, who has no second initial.) However, a local part starting # with a dot or containing /../ can cause trouble if it is used as part of a # file name (e.g. for a mailing list). This is also true for local parts that # contain slashes. A pipe symbol can also be troublesome if the local part is # incorporated unthinkingly into a shell command line. # # Two different rules are used. The first one is stricter, and is applied to # messages that are addressed to one of the local domains handled by this # host. The line "domains = +local_domains" restricts it to domains that are # defined by the "domainlist local_domains" setting above. The rule blocks # local parts that begin with a dot or contain @ % ! / or |. If you have # local accounts that include these characters, you will have to modify this # rule. deny message = Restricted characters in address domains = +local_domains local_parts = ^[.] : ^.*[@%!/|] delay = {{ exim_error_delay }} # The second rule applies to all other domains, and is less strict. The line # "domains = !+local_domains" restricts it to domains that are NOT defined by # the "domainlist local_domains" setting above. The exclamation mark is a # negating operator. This rule allows your own users to send outgoing # messages to sites that use slashes and vertical bars in their local parts. # It blocks local parts that begin with a dot, slash, or vertical bar, but # allows these characters within the local part. However, the sequence /../ # is barred. The use of @ % and ! is blocked, as before. The motivation here # is to prevent your users (or your users' viruses) from mounting certain # kinds of attack on remote sites. deny message = Restricted characters in address domains = !+local_domains local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ delay = {{ exim_error_delay }} # ##### # Accept mail coming from localhost (non-TCPIP) accept hosts = : # Accept mail to postmaster in any local domain, regardless of the source, # and without verifying the sender. accept local_parts = postmaster domains = +local_domains # white- and black-lists for hosts (connecting IPs) and senders (MAIL FROM) # that we definitely do or don't want. accept message = Accepted through host whitelist entry log_message = Mail Accepted from $sender_host_address through host whitelist entry hosts = +whitelist_hosts accept message = Accepted through sender whitelist entry log_message = Mail Accepted from $sender_host_address through sender whitelist entry senders = @@lsearch;{{ exim_whitelist_sender_file }} deny message = Mail not permitted from sender senders = @@lsearch;{{ exim_blacklist_sender_file }} deny message = Mail not permitted from host $sender_host_address. log_message = Mail not permitted from host $sender_host_address. hosts = +blacklist_hosts # Deny unless the sender address can be routed. For proper verification of the # address, read the documentation on callouts and add the /callout modifier. #require verify = sender # Accept if the message comes from one of the hosts for which we are an # outgoing relay. It is assumed that such hosts are most likely to be MUAs, # so we set control=submission to make Exim treat the message as a # submission. It will fix up various errors in the message, for example, the # lack of a Date: header line. If you are actually relaying out out from # MTAs, you may want to disable this. If you are handling both relaying from # MTAs and submissions from MUAs you should probably split them into two # lists, and handle them differently. # Recipient verification is omitted here, because in many cases the clients # are dumb MUAs that don't cope well with SMTP error responses. If you are # actually relaying out from MTAs, you should probably add recipient # verification here. # Note that, by putting this test before any DNS black list checks, you will # always accept from these hosts, even if they end up on a black list. The # assumption is that they are your friends, and if they get onto a black # list, it is a mistake. accept hosts = +relay_from_hosts control = submission # Accept if the message arrived over an authenticated connection, from # any host. Again, these messages are usually from MUAs, so recipient # verification is omitted, and submission mode is set. And again, we do this # check before any black list tests. accept authenticated = * control = submission # If reverse DNS lookup of the sender's host fails (i.e. there is # no rDNS entry, or a forward lookup of the resulting name does not # match the original IP address), then reject the message. # #deny message = reverse DNS lookup failed for host $sender_host_address. #!verify = reverse_host_lookup # Deny unless the sender address can be verified. warn message = <$sender_address> does not appear to be a valid sender. !verify = sender/callout=20s,defer_ok set acl_m_greylistreasons = Sender <$sender_address> failed callout check\n$acl_m_greylistreasons # Insist that any other recipient address that we accept is either in one of # our local domains, or is in a domain for which we explicitly allow # relaying. Any other domain is rejected as being unacceptable for relaying. require message = relay not permitted domains = +local_domains : +relay_to_domains # We also require all accepted addresses to be verifiable. This check will # do local part verification for local domains, but only check the domain # for remote domains. The only way to check local parts for the remote # relay domains is to use a callout (add /callout), but please read the # documentation about callouts before doing this. require verify = recipient ############################################################################# # There are no default checks on DNS black lists because the domains that # contain these lists are changing all the time. However, here are two # examples of how you can get Exim to perform a DNS black list lookup at this # point. The first one denies, whereas the second just warns. The third # triggers greylisting for any host in the blacklist. # # deny message = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text # dnslists = black.list.example # # warn dnslists = black.list.example # add_header = X-Warning: $sender_host_address is in a black list at $dnslist_domain # log_message = found in $dnslist_domain # # warn dnslists = black.list.example # set acl_m_greylistreasons = Host found in $dnslist_domain\n$acl_m_greylistreasons # ############################################################################# ############################################################################# # This check is commented out because it is recognized that not every # sysadmin will want to do it. If you enable it, the check performs # Client SMTP Authorization (csa) checks on the sending host. These checks # do DNS lookups for SRV records. The CSA proposal is currently (May 2005) # an Internet draft. You can, of course, add additional conditions to this # ACL statement to restrict the CSA checks to certain hosts only. # # require verify = csa ############################################################################# # Alternatively, greylist for it: warn !verify = csa set acl_m_greylistreasons = Host failed CSA check\n$acl_m_greylistreasons # At this point, the address has passed all the checks that have been # configured, so we accept it unconditionally. accept #-----------------------------------DKIM ACL------------------------------------------ acl_check_dkim: accept hosts = +relay_from_hosts accept authenticated = * accept dkim_status = none condition = ${if eq {$acl_c_dkim_hdr}{1} {no}{yes}} set acl_c_dkim_hdr = 1 add_header = :at_start:X-DKIM: Exim 4 on $primary_hostname (no dkim signature) warn condition = ${if eq {$acl_c_dkim_hdr}{1} {no}{yes}} set acl_c_dkim_hdr = 1 add_header = :at_start:X-DKIM: Exim 4 on $primary_hostname warn dkim_status = fail message = Rejected: $dkim_verify_reason add_header = :at_start:X-DKIM: Exim 4 on $primary_hostname (fail dkim signature) set acl_m_greylistreasons = Host failed DKIM check\n$acl_m_greylistreasons accept dkim_status = invalid add_header = :at_start:Authentication-Results: $primary_hostname $dkim_cur_signer ($dkim_verify_status); $dkim_verify_reason accept dkim_status = pass add_header = :at_start:Authentication-Results: $primary_hostname; dkim=$dkim_domain, header.i=@$dkim_cur_signer ($dkim_verify_status) accept #-----------------------------------DATA ACL------------------------------------------ # This ACL is used after the contents of a message have been received. This # is the ACL in which you can test a message's headers or body, and in # particular, this is where you can invoke external virus or spam scanners. # Some suggested ways of configuring these tests are shown below, commented # out. Without any tests, this ACL accepts all messages. If you want to use # such tests, you must ensure that Exim is compiled with the content-scanning # extension (WITH_CONTENT_SCAN=yes in Local/Makefile). acl_check_data: # Accept mail coming from localhost (non-TCPIP) accept message = Accepted as local delivery hosts = : accept message = Accepted through host whitelist entry hosts = +whitelist_hosts accept message = Accepted through whitelist entry senders = @@lsearch;/etc/exim4/whitelist_senders # white- and black-lists for hosts (connecting IPs) and senders (MAIL FROM) # that we definitely do or don't want. # Note that, by putting this test before any DNS black list checks, you will # always accept from these hosts, even if they end up on a black list. The # assumption is that they are your friends, and if they get onto a black # list, it is a mistake. deny message = Mail not permitted from sender senders = @@lsearch;/etc/exim4/blacklist_senders accept message = Accepted as from relayable host hosts = +relay_from_hosts # Accept if the message arrived over an authenticated connection, from # any host. Again, these messages are usually from MUAs, so recipient # verification is omitted, and submission mode is set. And again, we do this # check before any black list tests. accept authenticated = * message = Accepted as authenticated # Deny partial (MIME message/partial) messages, which can easily be # used to circumvent content scanning. deny message = Message fragments administratively prohibited condition = ${if match \ {$h_content-type:}{\N\bmessage/partial\b\N}{1}} # Insist that the messages are in English - well, not Russian deny message = Message administratively prohibited condition = ${if match \ {$h_content-type:}{koi18r}{1}} # Insist no viagra! deny message = Message administratively prohibited condition = ${if match {$h_from:}{VIAGRA}{1}} # Insist that the message address headers make sense deny message = Your message headers contain invalid syntax: $acl_verify_message !verify = header_syntax # Put simple tests first. A good one is to check for the presence of a # Message-Id: header, which RFC2822 says SHOULD be present. Some broken # or misconfigured mailer software occasionally omits this from genuine # messages too, though -- although it's not hard for the offender to fix # after they receive a bounce because of it. # warn condition = ${if !def:h_Message-ID: {1}} log_message = Message is missing the Message-ID header. set acl_m_greylistreasons = Message is missing the Message-ID header. RFC2822 says that all mail SHOULD have one. # Bypass SpamAssassin checks if the message is too large (4 million). # accept condition = ${if >={$message_size}{4000000} {1}} add_header = X-Spam-Note: SpamAssassin run bypassed due to message size add_header = Subject: [L] $h_Subject: # Run SpamAssassin, but allow for it to fail or time out. Add a warning message # and accept the mail if that happens. Add an X-Spam-Flag: header if the SA # score exceeds the SA system threshold. # warn spam = nobody/defer_ok add_header = X-Spam-Flag: YES warn condition = ${if !def:spam_score_int {1}} add_header = X-Spam-Note: SpamAssassin invocation failed # Unconditionally add score and report headers # warn add_header = X-Spam-Score: $primary_hostname: $spam_score ($spam_bar)\n\ X-Spam-Report: $spam_report # And reject if the SpamAssassin score is greater than 5.9 # deny condition = ${if >{$spam_score_int}{59} {1}} message = Your message scored $spam_score SpamAssassin points. Report follows:\n\ $spam_report # Trigger greylisting (if enabled) if the SpamAssassin score is greater than 2 # warn condition = ${if >{$spam_score_int}{20} {1}} set acl_m_greylistreasons = Message has $spam_score SpamAssassin points\n$acl_m_greylistreasons # Tag the subject if the SpamAssassin score is greater than 4.9 # warn condition = ${if >{$spam_score_int}{49} {1}} add_header = Subject: *SPAM* $h_Subject: # Deny non-local messages with no Message-ID, or no Date # # Note that some specialized MTAs, such as certain mailing list # servers, do not automatically generate a Message-ID for bounces. # Thus, we add the check for a non-empty sender. # deny message = Message is missing one or more required headers and so is not valid. log_message = Missing header lines !senders = : postmaster@* condition = ${if or { {!def:h_From:} {!def:h_Date:} } {true}{false} } # Warn unless there is a verifiable sender address in at least # one of the "Sender:", "Reply-To:", or "From:" header lines. # warn message = X-Sender-Verify-Failed: No valid sender in message header log_message = No valid sender in message header !verify = header_sender # Deny if the message contains a virus. Before enabling this check, you # must install a virus scanner and set the av_scanner option above. # # deny malware = * # message = This message contains a virus ($malware_name). # If you want to greylist _all_ mail rather than only mail which looks like there # might be something wrong with it, then you can do this... # # warn set acl_m_greylistreasons = We greylist all mail\n$acl_m_greylistreasons # Now, invoke the greylisting. For this you need to have installed the exim-greylist # package which contains this subroutine, and you need to uncomment the bit below # which includes it too. Whenever the $acl_m_greylistreasons variable is non-empty, # greylisting will kick in and will defer the mail to check if the sender is a # proper mail which which retries, or whether it's a zombie. For more details, see # the exim-greylist.conf.inc file itself. # accept message = Accepted as from non-greylistable host $sender_host_address:\n$acl_m_greylistreasons hosts = +no_greylisting require acl = greylist_mail accept # To enable the greylisting, also uncomment this line: .include /etc/exim4/exim-greylist.conf.inc acl_check_mime: # File extension filtering. deny message = Blacklisted file extension $mime_filename detected condition = ${if match \ {${lc:$mime_filename}} \ {\N(\.cmd|\.dll|\.url|\.vbs|\.btm|\.prf|\.pif|\.scr|\.lnk|\.msi)$\N} \ {1}{0}} # File extension filtering. deny message = Mailserver does not accept Windows executables: resend as zip or tar file. condition = ${if match \ {${lc:$mime_filename}} \ {\N(\.exe|\.com|\.bat)$\N} \ {1}{0}} accept #-----------------------------------END ACL------------------------------------------ ###################################################################### # 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 addresses that are not in local domains by doing a DNS # lookup on the domain name. The exclamation mark that appears in "domains = ! # +local_domains" is a negating operator, that is, it can be read as "not". The # recipient's domain must not be one of those defined by "domainlist # local_domains" above for this router to be used. # # If the router is used, 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 transport = remote_smtp ignore_target_hosts = 0.0.0.0 : \ 127.0.0.0/8 :\ 10.0.0.0/8 :\ 172.16.0.0/16 :\ 192.168.32.0/16 :\ 169.254.0.0/16 no_more # Alternatively, comment out the above router and uncomment this one to # route all mail to a smarthost instead of sending it directly to the # intended recipients. If your smarthost requires authentication, change # 'remote_smtp' to 'remote_msa' and set up the 'client_auth' authenticator # later in this file. You might need to change the port number in the # remote_msa transport. # #smarthost: # driver = manualroute # domains = ! +local_domains # transport = remote_smtp # route_data = smarthost.myisp.net # no_more # The remaining routers handle addresses in the local domain(s), that is those # domains that are defined by "domainlist local_domains" above. {% if exim_mailman_transport %} # We want this router first in case we have a list named something like # mailman-owner mm21_main_route: driver = accept domains = +mailman_domains local_parts = * require_files = /var/lib/mailman/lists/${lc::$local_part}/config.pck transport = mm21_transport mm21_special_route: driver = accept domains = +mailman_domains local_parts = * local_part_suffix = "-bounces:-bounces+*:-confirm+*:-join:-leave:-owner:-request:-admin" require_files = /var/lib/mailman/lists/${lc::$local_part}/config.pck transport = mm21_transport mailman_ivimeyorg_users: driver = redirect allow_defer allow_fail data = ${lookup{$local_part}lsearch {/etc/exim4/mailman-ivimey-aliases} {$value} fail} domains = mail.ivimey.org retry_use_local_part file_transport = address_file pipe_transport = address_pipe no_rewrite {% endif %} # # The remaining routers handle addresses in the local domain(s). {% for vtag, vdomain in exim_virtual_domains.iteritems() %} {{ vtag }}_users: driver = redirect allow_defer allow_fail data = ${lookup{$local_part}lsearch{/etc/exim/{{ vtag }}-aliases}} domains = +{{ vtag }}_domains qualify_domain = {{ vdomain.domains[0] }} forbid_file forbid_pipe retry_use_local_part no_rewrite {% endfor %} # 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" or "# Sieve filter", uncomment # the "allow_filter" option. # If you want this router to treat local parts with suffixes introduced by "-" # or "+" characters as if the suffixes did not exist, uncomment the two local_ # part_suffix options. Then, for example, xxxx-foo@your.domain will be treated # in the same way as xxxx@your.domain by this router. You probably want to make # the same change to the localuser router. # 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 # local_part_suffix = +* : -* # local_part_suffix_optional file = $home/.forward allow_filter no_verify no_expn check_ancestor file_transport = address_file pipe_transport = address_pipe reply_transport = address_reply {% if exim_procmail_transport %} procmail: driver = accept check_local_user require_files = ${local_part}:+${home}/.procmailrc:/usr/bin/procmail transport = procmail no_verify {% endif %} # This router matches local user mailboxes. {% for vtag, vdomain in exim_virtual_domains.iteritems() %} localuser_{{ vtag }}: driver = accept domains = {{ vdomain.domains | join(" : ") }} local_parts = lsearch;/etc/exim4/{{ vtag }}-imap-users transport = imap_delivery {% endfor %} #localuser: # driver = accept # check_local_user ## local_part_suffix = +* : -* ## local_part_suffix_optional # 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 helo_data = {{ exim_server_name }} dkim_domain = DKIM_DOMAIN dkim_selector = DKIM_SELECTOR dkim_private_key = DKIM_PRIVATE_KEY dkim_canon = DKIM_CANON # This transport is used for delivering messages over LMTP to an IMAP server imap_delivery: driver = lmtp socket = {{ exim_imap_deliver }} batch_max = 50 # This transport is used for delivering messages over SMTP using the # "message submission" port (RFC4409). remote_msa: driver = smtp port = 587 hosts_require_auth = * {% if exim_procmail_transport %} # This transport invokes procmail to deliver mail procmail: driver = pipe command = "/usr/bin/procmail -d $local_part" return_path_add delivery_date_add envelope_to_add user = $local_part initgroups return_output {% endif %} {% if exim_mailman_transport %} ## Mailman 2.1 transport mm21_transport: driver = pipe command = /usr/lib/mailman/mail/mailman "${if def:local_part_suffix{${substr_2:{${sg{${lc:$local_part_suffix}}{\\\\\+.*}{}}}}{post}}" ${lc:$local_part} return_output initgroups current_directory = /usr/lib/mailman home_directory = /usr/lib/mailman user = list group = list {% endif %} # This transport is used for handling pipe deliveries generated by alias or # .forward files. 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 ###################################################################### # RETRY CONFIGURATION # ###################################################################### begin retry # WARNING: If you do not have any retry rules at all (this section of the # configuration is non-existent or empty), Exim will not do any retries of # messages that fail to get delivered at the first attempt. # Address or Domain Error Retries # ----------------- ----- ------- * * F,2h,15m; G,16h,1h,1.5; F,4d,6h ###################################################################### # REWRITE CONFIGURATION # ###################################################################### begin rewrite {% for vtag, vdomain in exim_virtual_domains.iteritems() %} # {{ vtag }} {% for vrewrite in vdomain.rewrites %} "{{ vrewrite.from }}" "{{ vrewrite.to }}" {{ vrewrite.opts }} {% endfor %} {% endfor %} ###################################################################### # AUTHENTICATION CONFIGURATION # ###################################################################### begin authenticators # This authenticator supports CRAM-MD5 username/password authentication # with Exim acting as a _client_, as it might when sending its outgoing # mail to a smarthost rather than directly to the final recipient. # Replace SMTPAUTH_USERNAME and SMTPAUTH_PASSWORD as appropriate. #client_auth: # driver = cram_md5 # public_name = CRAM-MD5 # client_name = SMTPAUTH_USERNAME # client_secret = SMTPAUTH_PASSWORD # # The following authenticators support plaintext username/password # authentication using the standard PLAIN mechanism and the traditional # but non-standard LOGIN mechanism, with Exim acting as the server. # PLAIN and LOGIN are enough to support most MUA software. # # These authenticators are not complete: you need to change the # server_condition settings to specify how passwords are verified. # They are set up to offer authentication to the client only if the # connection is encrypted with TLS, so you also need to add support # for TLS. See the global configuration options section at the start # of this file for more about TLS. # # The default RCPT ACL checks for successful authentication, and will accept # messages from authenticated users from anywhere on the Internet. #lookup_cram: # driver = cram_md5 # public_name = CRAM-MD5 # server_secret = ${lookup{$1}lsearch{/etc/exim4/authpwd}{$value}fail} # server_set_id = $1 # # PLAIN authentication has no server prompts. The client sends its # credentials in one lump, containing an authorization ID (which we do not # use), an authentication ID, and a password. The latter two appear as # $auth2 and $auth3 in the configuration and should be checked against a # valid username and password. In a real configuration you would typically # use $auth2 as a lookup key, and compare $auth3 against the result of the # lookup, perhaps using the crypteq{}{} condition. #auth_plain: # driver = plaintext # public_name = PLAIN # server_set_id = $auth2 # server_prompts = : # server_condition = ${if saslauthd{ {$2}{$3}{smtp} } {1}} # server_advertise_condition = ${if def:tls_cipher } SQL_AUTH_PLAIN_LOOKUP=SELECT MD5(u.password) \ FROM users u \ WHERE u.userid='${quote_mysql:${local_part:$auth2}}' AND \ u.domain='${quote_mysql:${domain:$auth2}}' AND \ u.enabled='Y'; auth_plain: driver = plaintext public_name = PLAIN server_prompts = : server_advertise_condition = ${if def:tls_cipher } server_condition = ${if and { \ {!eq{$auth2}{}} \ {!eq{$auth3}{}} \ { crypteq{$auth3}{\{md5\}${lookup mysql{SQL_AUTH_PLAIN_LOOKUP}{$value}fail}} } \ } {1}{0}} # server_set_id = $auth2 # LOGIN authentication has traditional prompts and responses. There is no # authorization ID in this mechanism, so unlike PLAIN the username and # password are $auth1 and $auth2. Apart from that you can use the same # server_condition setting for both authenticators. #LOGIN: # driver = plaintext # server_set_id = $auth1 # server_prompts = <| Username: | Password: # server_condition = ${if saslauthd{ {$1}{$2}{smtp} } {1}} # server_advertise_condition = ${if def:tls_cipher } SQL_AUTH_LOGIN_LOOKUP=SELECT MD5(u.password) \ FROM users u \ WHERE u.userid='${quote_mysql:${local_part:$auth1}}' AND \ u.domain='${quote_mysql:${domain:$auth1}}' AND \ u.enabled='Y'; LOGIN: driver = plaintext server_prompts = <| Username: | Password: server_advertise_condition = ${if def:tls_cipher } server_condition = ${if and { \ {!eq{$auth1}{}} \ {!eq{$auth2}{}} \ { crypteq{$auth2}{\{md5\}${lookup mysql{SQL_AUTH_LOGIN_LOOKUP}{$value}fail}} } \ } {1}{0}} ###################################################################### # 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