######### # WARNING WARNING WARNING # WARNING WARNING WARNING # WARNING WARNING WARNING # WARNING WARNING WARNING # WARNING WARNING WARNING # this file is generated dynamically from the files in # CONFDIR/conf.d/ and /etc/exim4/update-exim4.conf.conf # Any changes you make here will be lost. # See /usr/share/doc/exim4-base/README.Debian and update-exim4.conf(8) # for instructions of customization. # WARNING WARNING WARNING # WARNING WARNING WARNING # WARNING WARNING WARNING # WARNING WARNING WARNING # WARNING WARNING WARNING ######### # begin processing main ##### # vim:set syntax=conf: ###################################################################### # Runtime configuration file for Exim # ###################################################################### # This is a sample exim4.conf file by Marc MERLIN # It should be fully working for most systems, although you can edit some # values and remove unneeded rewrites and/or checks for mailman if they're # not needed on your system # 2002/09/21 - mm2: you should be able to change all the relevant settings # without modifying this configuration file # 2002/09/30 - mm3: Added code to refuse multiple receipients for null envelope # without modifying this configuration file # 2002/10/13 - mm4: Parse additional directors from include file # Load file with local addresses # Add header to tell SA not to run for mail from local users # and not reject Email for whitelisted users # Fixed SMTP auth client expressions # 2002/10/28 - mm5: Fixed missing plus in front of nodnsdomains (Nico Erfurth) # smtp_reserve_hosts is now +relay_from_host # Added Lines: header for maildir delivery # Added host_find_failed = defer for smarthos # Removed all SA-Exim headers in remote_smtp transport # 2002/12/14 - mm6: When comparing addresses against file lists, use $lc # added smtp_accept_max_nonmail # added all the new callback options and a new callback # ACL for yahoo-like hosts (to deactivate random probing) # (/etc/exim/acls/norandomcallbackdomains) # Added smtp_return_error_details (exim 4.11) # 2003/04/11 - mm7: Rewrite for the debian exim4 package in split files # authentication rules heavily borrowed from the deb pkg # 2003/05/01 - mm8: Added smtp_max_unknown_commands # Added 4 new acls entry points from exim 4.11 # Set header_maxsize / header_line_maxsize # Reformatted whitespace in ACLs in a consistent way # Added optional TEERGRUBE delay for each failed ACL # Added anti dictionnary attack rules # Added dictionnary attack prevention # Temporarily disabled random ACLs since they may not work # Added '+' header addressing for most local routers # Moved localuser_maildir right before localuser # Made rewrite tests conditional # mailman rules are now dependant on MALIMAN_HOME with ifdef # 2003/08/03 - mm9: Working virtual routers (courtesy of Uriah Welcome) ###################################################################### # MAIN CONFIGURATION SETTINGS # ###################################################################### MMVER=mm9 # Just for reference and scripts, on debian, the main binary is # installed as exim4 exim_path = /usr/sbin/exim4 # Macro defining the main configuration directory, we use no abolute # paths. CONFDIR = /etc/exim4 # Dynamically loadable local_scan rules! :-) # local_scan_path = /usr/lib/exim4/local_scan/accept.so # You don't *really* need to turn SA off here, it's off by default in # CONFDIR/spamassassin.conf # That said, it will fail if you don't have the dlopen_localscan patch # or the sa-exim module in the specified location # See htp://marc.merlins.org/linux/exim/sa.html for more details. local_scan_path = /usr/lib/exim4/local_scan/sa-exim.so # MAILNAME is the hostname you want for this mail server (like foo.company.tld) # It defaults to the machine fqdn #MAILNAME= \ # .include /etc/mailname MAILNAME=linuxmafia.com # Enable TLS by setting the path to your combined cert # incoming TLS will be automatically disabled if the cert can't be found CERTNAME=/etc/ssl/certs/MAILNAME_cert.pem # Set this to your mailman home dir MAILMAN_HOME=/var/lib/mailman # # If the above is set and you use a different domain for your lists, you # should also set LISTDOMAIN to have auto-rewrites to that domain if the # local part is a list name # lists. If you don't use mailman, you can ignore this (set it to MAILNAME) #LISTDOMAIN= \ # .include CONFDIR/domains/listdomain LISTDOMAIN=linuxmafia.com # MAINDOMAIN would be something like company.tld, you can use this if you want # to rewrite hostnames to your mail domain. Set it to MAILNAME otherwise #MAINDOMAIN= \ # .include CONFDIR/domains/maindomain MAINDOMAIN=linuxmafia.com # Uncomment this if you want all domains in domains/localdomains to be rewritten # to MAINDOMAIN (note that you also have domains/localdomains.norewrite) MAIN_CANONIZE=yes # if you want to send autoreponses from a different domain, you can chose it # here #AUTORESPONDDOMAIN=MAINDOMAIN # You can use a smarthost if needed SMARTHOST_ROUTELIST= \ .include CONFDIR/domains/smarthostroutelist #SMARTHOST_ROUTELIST= * smtp.relayhost.tld TRUSTED_USERS=mail TRUSTED_GROUPS=mail RFC1918=10.0.0.0/8 : 172.16.0.0/12 : 192.168.0.0/16 # To or from IPs we don't want to handle mail for (localhost/APIPA/test block) # Add RFC1918 for an internet only connected system #BOGUSIPS=127.0.0.1/8 : 169.254.0.0/16 : 192.0.2.0/24 : RFC1918 BOGUSIPS=127.0.0.1/8 : 169.254.0.0/16 : 192.0.2.0/24 # Enable teergrubing on acl errors and say how long we delay (unset to disable) TEERGRUBE=60s # How many bad receipients must fail before we drop the connection # (if you are teergrubing, i.e. the above is set, then this value isn't used) ALLOWEDRCPTFAIL=3 # This is out of place, but we need to do this now because MAILNAME may be # empty up to now, but in that case, we have to set it to primary_hostname # since we're going to use its value .ifdef MAILNAME # The hostname the system displays when you connect to it. primary_hostname = MAILNAME # Specify the domain you want to be added to all unqualified addresses # here. Unqualified addresses are accepted only from local callers by # default. See the receiver_unqualified_{hosts,nets} options 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 = MAILNAME .else # we let primary_hostname and qualify_domain default to the local hostname # and we set MAILNAME to that value (@ is primary_hostname) MAILNAME = @ .endif .ifndef AUTORESPONDDOMAIN AUTORESPONDDOMAIN = MAILNAME .endif # "@[]" it matches any local IP interface address # @mx_any matches any domain that has an MX record pointing to the local host # "@mx_primary" and "@mx_secondary" are similar domainlist local_domains = @ : @[] : localhost : MAILNAME : LISTDOMAIN : CONFDIR/domains/localdomains : CONFDIR/domains/localdomains_norewrite domainlist relay_to_domains = partial-lsearch;CONFDIR/domains/relaytodomains:\ partial-lsearch;CONFDIR/domains/relaytodomains.local domainlist envdomain_disable_callback = CONFDIR/acls/noenvcallbackdomains HDR_DOMAIN_DISABLE_CALLBACK=CONFDIR/acls/nohdrcallbackdomains domainlist domains_callback_norandom = CONFDIR/acls/norandomcallbackdomains NO_RANDOM_CALLBACK=CONFDIR/acls/norandomcallbackdomains domainlist nodnsdomains = CONFDIR/acls/nodnsdomains localpartlist noenvfromcheck = CONFDIR/acls/destwhitelist localpartlist noenvfromcallback = CONFDIR/acls/destwhitelist localpartlist nosarej = CONFDIR/acls/destwhitelist localpartlist nohdrsyncheck = CONFDIR/acls/destwhitelist localpartlist nohdrfromcallback = CONFDIR/acls/destwhitelist hostlist rfc1918 = RFC1918 # To or from IPs we don't want to handle mail for (localhost/APIPA/test block) hostlist bogusips = BOGUSIPS hostlist localadds = +rfc1918 : @ : @[] : CONFDIR/acls/localadds: localhost hostlist host_reject = CONFDIR/acls/hostreject HOSTREJECTRCPT1=CONFDIR/acls/hostrejectrcpt hostlist host_reject_rcpt = net-lsearch;HOSTREJECTRCPT1 hostlist hosts_disable_callback = CONFDIR/acls/nocallbackhosts hostlist relay_from_hosts = +localadds : CONFDIR/acls/relayfromhosts hostlist auth_relay_hosts = * hostlist auth_over_tls_hosts = * hostlist expn_hosts = *.MAINDOMAIN:localhost hostlist vrfy_hosts = * hostlist hosts_avoid_tls = CONFDIR/acls/hostsavoidtls hostlist hosts_try_auth = CONFDIR/hoststryauth BLOCKENVSEND1=CONFDIR/acls/denyenvsenders addresslist denyenvsenders = lsearch;BLOCKENVSEND1 # Exim options # These options specify the Access Control Lists (ACLs) that # are used for incoming SMTP messages - after the RCPT and DATA # commands, respectively. acl_smtp_connect = check_connect acl_smtp_starttls = check_tls acl_smtp_mail = check_mail acl_smtp_rcpt = check_rcpt acl_smtp_data = check_data acl_smtp_auth = check_auth acl_smtp_expn = check_expn acl_smtp_vrfy = check_vrfy acl_not_smtp = check_nonsmtp log_selector = \ +address_rewrite \ +all_parents \ +arguments \ +connection_reject \ +delay_delivery \ +delivery_size \ +dnslist_defer \ +incoming_interface \ +incoming_port \ +lost_incoming_connection \ +queue_run \ +received_sender \ +received_recipients \ +retry_defer \ +sender_on_delivery \ +size_reject \ +skip_delivery \ +smtp_confirmation \ +smtp_connection \ +smtp_protocol_error \ +smtp_syntax_error \ +subject \ +tls_cipher \ +tls_peerdn \ # Mailman variables MAILMAN_WRAP=MAILMAN_HOME/mail/mailman MAILMAN_UID=list MAILMAN_GID=daemon # Filter all the virus crap (if you ask me, it's tempting to let it through # and let darwinism do its work :-p) system_filter = CONFDIR/system_filter.exim system_filter_file_transport = address_file system_filter_pipe_transport = address_pipe system_filter_directory_transport = address_directory message_body_visible = 5000 # listen on all all interfaces? # if local_interfaces is unset, we listen on all interfaces smtp_banner = "${primary_hostname} ESMTP Exim ${version_number} #${compile_number} ${tod_full} - MMVER" tls_certificate = CERTNAME tls_privatekey = CERTNAME tls_advertise_hosts = ${if exists {CERTNAME}{*}{127.0.0.1/8}} # 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 = # If this is uncommented, we accept and relay mail for all domains we are # in the DNS as an MX for. #relay_domains_include_local_mx = true # No local deliveries will ever be run under the uids of these users (a colon- # separated list). An attempt to do so gets changed so that it runs under the # uid of "nobody" instead. This is a paranoiac safety catch. Note 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 # If you want Exim to support the "percent hack" for all your local domains, # uncomment the following line. This is the feature by which mail addressed # to x%y@z (where z is one of your local domains) is locally rerouted to # x@y and sent on. Otherwise x%y is treated as an ordinary local part # percent_hack_domains=* # If this option is set, then any process that is running as one of the # listed users may pass a message to Exim and specify the sender's # address using the "-f" command line option, without Exim's adding a # "Sender" header. trusted_users = TRUSTED_USERS trusted_groups = TRUSTED_GROUPS # Some operating systems use the "gecos" field in the system password file # to hold other information in addition to users' real names. Exim looks up # this field when it is creating "sender" and "from" headers. If these options # are set, exim uses "gecos_pattern" to parse the gecos field, and then # expands "gecos_name" as the user's name. $1 etc refer to sub-fields matched # by the pattern. gecos_pattern = ^([^,:]*) gecos_name = $1 # This sets the maximum number of messages that will be accepted in one # connection. The default is 10, which is probably enough for most purposes, # but is too low on dialup SMTP systems, which often have many more mails # queued for them when they connect. It also doesn't work well if you use # mailman since it wants to shove as many rcpt to for one mail as it can smtp_accept_queue_per_connection = 100 # Send a mail to the postmaster when a message is frozen. There are many # reasons this could happen; one is if exim cannot deliver a mail with no # return address (normally a bounce) another that may be common on dialup # systems is if a DNS lookup of a smarthost fails. Read the documentation # for more details: you might like to look at the auto_thaw option freeze_tell = postmaster # This string defines the contents of the \`Received' message header that # is added to each message, except for the timestamp, which is automatically # added on at the end, preceded by a semicolon. The string is expanded each # time it is used. received_header_text = "Received: \ ${if def:sender_rcvhost {from ${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 {\n\t(Cipher ${tls_cipher}) }}\ ${if def:tls_peerdn {(PeerDN ${tls_peerdn}) }}\ (Exim ${version_number} #${compile_number})\n\t\ id ${message_id}\ ${if def:authenticated_id { by authid <$authenticated_id>}}\ ${if def:sender_host_authenticated { with $sender_host_authenticated}}\ ${if def:received_for {\n\tfor <$received_for>}}" # # Non default options are added here # # This creates 62 subdirs in /var/spool/exim/input to allow for better disk # performance split_spool_directory # This will thaw (i.e. unfreeze) frozen messages every 4 days auto_thaw = 4d # This will throw away bounces of bounces every 3 days ignore_bounce_errors_after = 3d # This throws away any frozen message that's been in the queue for more than 10d timeout_frozen_after = 10d # See smtp_load_reserve smtp_reserve_hosts = +relay_from_hosts # How much load we're willing to accept # At this LA only hosts in smtp_reserve_hosts can connect smtp_load_reserve = 40 # When to abandon queue runs deliver_queue_load_max = 20 # After a this load we only queue incoming messages queue_only_load = 20 # max queue running processes to run simultaneously queue_run_max = 30 # Lets you set how many SMTP calls are handled # This allows many more TCP connections in wait state smtp_connect_backlog = 50 # When we start just queueing smtp_accept_queue = 150 # We will not accpet more than 200 incoming SMTP calls at once smtp_accept_max = 200 # Handle when warning Emails are sent delay_warning = 2h:8h:24h:48h # Decide when to refuse incoming mail check_log_inodes = 2048 check_log_space = 3M check_spool_inodes = 100 check_spool_space = 20M # Make 3 NIS queries on an unknown users before deciding that the user # doesn't exist (just in case NIS didn't work) finduser_retries = 3 # size limitations message_size_limit = 30M # This would devide the above value by the number of receipients # message_size_limit_count_receipients = true # We don't need to bounce more than 10K back to a user return_size_limit = 10K # Let's not wait more than 5s if an ident query isn't getting an answer rfc1413_query_timeout = 5s # This accomodates broken MUAs that add a dot after a domain strip_trailing_dot # To allow variable expansion and logging on chars with 8th bit on. print_topbitchars # Allow domain literals (for ipliteral router to work) allow_domain_literals # How many bad commands trigger a connection clause (exim 4.11 or better) # (you need at least 4 for a STARTTLS session) smtp_accept_max_nonmail = 7 # Number of unknown SMTP commands we accept before dropping the connection smtp_max_unknown_commands = 1 # Extended callouts appeared in exim 4.11 # If a host is broken, for instance by refusing NULL mail froms, we bounce # all their mail until they fix it. Let's only remember this for 5m # (default is 3h) callout_domain_negative_expire = 5m # The usefulness of this option is unknown to me, default is 7d callout_domain_positive_expire = 7d # How long you cache a failed callout (default is 2h, but I prefer to not # penalize someone who just fixed his mail) callout_negative_expire = 5m # How long we cache an address that was successfully checked. Let's not overload # remote servers for nothing, 1 week should be enough (default is 1 day) callout_positive_expire = 24h # What random local part we use for testing (that way, you can find out hosts # that accept any local part because they don't do SMTP time address # verification callout_random_local_part = callout-check-$primary_host_name-$tod_epoch # This returns informative error messages when we reject Email based on # syntax or other header checks (like exim 3 used to do by default) smtp_return_error_details = true # The maximum size of headers for a mail header_maxsize = 128k # The maximum size of a single header line header_line_maxsize = 7k ############################################### # ACL directives that aren't in the acl section ############################################### # 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 = * # We probably don't really care about ident anymore nowadays... rfc1413_hosts = !* # Do not advertize auth clients that can relay (otherwise netscape will try to # auth, even if it is not required) auth_advertise_hosts = !+relay_from_hosts : +auth_relay_hosts # Do not even provide an SMTP banner host_reject_connection = +host_reject # This seems to be the only way to qualify unqualified Sender: headers -- Marc sender_unqualified_hosts = +localadds # Also accept recipient_unqualified_hosts = +localadds # You don't want to enable this, trust me (it will refuse many legitimate mail) # See the RCPT TO ACL below instead helo_verify_hosts = !* # But you can get a warning with this (in theory, I couldn't find it) helo_try_verify_hosts = !* # If you had to accept bad HELO data from some broken hosts, you'd do this here helo_accept_junk_hosts = !* # Who is subject to smtp_accept_max_nonmail smtp_accept_max_nonmail_hosts = * # end of main ##### # begin processing acl ##### ###################################################################### # ACL CONFIGURATION # # Specifies access control lists for incoming SMTP mail # ###################################################################### begin acl spf_rcpt_acl: # Check envelope sender warn set acl_m8 = $sender_address deny !acl = spf_check warn message = Received-SPF: $acl_m8 ($acl_m7) accept spf_from_acl: # Check header From: warn set acl_m8 = ${address:$h_from:} deny !acl = spf_check warn message = Received-SPF: $acl_m8 ($acl_m7) accept spf_check: warn set acl_m9 = ${readsocket{/tmp/spfd}\ {ip=$sender_host_address\n\ helo=${if def:sender_helo_name\ {$sender_helo_name}{NOHELO}}\ \nsender=$acl_m8\n\n}{20s}{\n}{socket failure}} # Defer on socket error defer condition = ${if eq{$acl_m9}{socket failure}{yes}{no}} message = Cannot connect to spfd # Prepare answer and get results warn set acl_m9 = ${sg{$acl_m9}{\N=(.*)\n\N}{=\"\$1\" }} set acl_m8 = ${extract{result}{$acl_m9}{$value}{unknown}} set acl_m7 = ${extract{header_comment}{$acl_m9}{$value}{}} # Check for fail deny condition = ${if eq{$acl_m8}{fail}{yes}{no}} message = ${extract{smtp_comment}{$acl_m9}{$value}{}} log_message = Not authorized by SPF accept ## End of SPF ACLs check_connect: accept check_tls: accept check_mail: 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. # check_rcpt: # Accept if source is local SMTP (i.e. not over TCP/IP). We do this by # testing for an empty sending host field. accept hosts = : # This is to accept anything from localhost, and especially mailman which # chokes badly if you refuse its mail accept hosts = 127.0.0.1/8 # Deny if the local part contains @ or % or / or | or !. These are rarely # found in genuine local parts, but are often tried by people looking to # circumvent relaying restrictions. # # Also deny if the local part starts with a dot. Empty components aren't # strictly legal in RFC 2822, but Exim allows them because this is common. # However, actually starting with a dot may cause trouble if the local part # is used as a file name (e.g. for a mailing list). # deny local_parts = ^.*[@%!/|] : ^\\. warn message = X-WhitelistedRCPT-nohdrsyncheck: Yes local_parts = +nohdrsyncheck:postmaster:abuse warn message = X-WhitelistedRCPT-nohdrfromcallback: Yes local_parts = +nohdrfromcallback:postmaster:abuse warn message = X-SA-Do-Not-Rej: Yes local_parts = +nosarej:postmaster:abuse warn message = X-SA-Do-Not-Run: Yes hosts = +relay_from_hosts warn message = X-SA-Do-Not-Run: Yes authenticated = * # Accept mail to postmaster in any local domain, regardless of the source, # and without verifying the sender. accept domains = +local_domains local_parts = postmaster ####################################################################### # Ok, now that we have all the overrides, we can start the deny rules # ####################################################################### deny message = "HELO/EHLO required by SMTP RFC" condition = ${if eq{$sender_helo_name}{}{yes}{no}} .ifdef TEERGRUBE delay = TEERGRUBE .endif deny message = "Invalid domain or IP given in HELO/EHLO" !condition = ${if match{$sender_helo_name}{\\\.}{yes}{no}} .ifdef TEERGRUBE delay = TEERGRUBE .endif deny message = Only one receipient accepted for NULL sender senders = : condition = ${if >{$rcpt_count}{1} {1}} .ifdef TEERGRUBE delay = TEERGRUBE .endif # Normal unknown user handling is lower, we just do this one first to cut # down on our processing .ifdef TEERGRUBE deny log_message = Teergrube: dictionnary attack (ALLOWEDRCPTFAIL failed probes) message = unknown user condition = ${if >{$rcpt_fail_count}{1} {1}{0}} .else drop log_message = Dictionnary attack ($rcpt_fail_count failed probes). Dropping connection message = unknown user ($rcpt_fail_count failed queries) condition = ${if >{$rcpt_fail_count}{${eval:ALLOWEDRCPTFAIL-2}} {1}{0}} .endif # In teargrube mode, we listen for ever and delay more and more and more # Otherwise, we close the connection after a few failures, but we still # delay the sender because people who do dictionnary attacks can # reconnect and try again, so let's slow them down delay = ${eval:30*$rcpt_fail_count}s domains = +local_domains !verify = recipient # Explicit blacklists go before our whitelists, people ended up there for # a reason # Blacklist of hosts deny hosts = +host_reject_rcpt message = Host $sender_host_address is blocked: ${lookup{$sender_host_address}lsearch{HOSTREJECTRCPT1}{$value}{"unspecified reason"}} .ifdef TEERGRUBE delay = TEERGRUBE .endif # Blacklist of envelope senders deny senders = +denyenvsenders message = Sender $sender_address is blocked: ${lookup{$sender_address}lsearch{BLOCKENVSEND1}{$value}{"unspecified reason"}} # Deny unless the sender address can be verified. deny local_parts = !+noenvfromcheck !verify = sender .ifdef TEERGRUBE delay = TEERGRUBE .endif ################# # Warning Rules # ################# warn message = X-Broken-Reverse-DNS: no host name for for IP address $sender_host_address !verify = reverse_host_lookup .ifdef TEERGRUBE delay = TEERGRUBE .endif .ifdef MAILMAN_HOME # Accept bounces to lists even if callbacks or other checks would fail warn message = X-WhitelistedRCPT-nohdrfromcallback: Yes condition = ${if and {{match{$local_part}{.*-bounces\+.*}} {exists {MAILMAN_HOME/lists/${sg{$local_part}{(.*)-bounces\+.*}{\$1}}}}}{yes}{no}} accept condition = ${if and {{match{$local_part}{.*-bounces\+.*}} {exists {MAILMAN_HOME/lists/${sg{$local_part}{(.*)-bounces\+.*}{\$1}}}}}{yes}{no}} .endif # Now, do basic address checking, that we forgo if the receipient is in a # whilelist deny hosts = !+localadds:!+hosts_disable_callback:* sender_domains = !+envdomain_disable_callback:!+domains_callback_norandom:* local_parts = !+noenvfromcallback # random might be buggy in 4.14 from what I read on the exim list #!verify = sender/callout=90s,random,postmaster !verify = sender/callout=90s,postmaster # We check a random address so that we know not to bother doing further # callbacks against sites that accept all addresses .ifdef TEERGRUBE delay = TEERGRUBE .endif # We do a separate callback for special hosts that we want to do callback # on but that prevent random from working (yahoo for instance will refuse # an RCPT on a known spammer, but will otherwise accept RCPT TOs non # existing addresses (in an attempt to prevent dictionnary attacks against # their user DB) deny hosts = !+localadds:!+hosts_disable_callback:* sender_domains = +domains_callback_norandom local_parts = !+noenvfromcallback !verify = sender/callout=90s,postmaster .ifdef TEERGRUBE delay = TEERGRUBE .endif # Blocking just on RBLs is so yesterday, see SpamAssassin at SMTP time instead # http://marc.merlins.org/linux/exim/sa.html :) # deny message = X-RBL-Warning: $sender_host_address is in the MAPS relay list. http://mail-abuse.org/cgi-bin/nph-rss?query=$sender_host_address # log_message = found in $dnslist_domain # dnslists = relays.mail-abuse.org #.ifdef TEERGRUBE # delay = TEERGRUBE #.endif # deny message = X-RBL-Warning: $sender_host_address is in the MAPS blacklist. http://mail-abuse.org/cgi-bin/nph-rss?query=$sender_host_address # log_message = found in $dnslist_domain # dnslists = blackholes.mail-abuse.org #.ifdef TEERGRUBE # delay = TEERGRUBE #.endif # warn message = X-DUL-Warning: $sender_host_address is in the MAPS dialup list. http://mail-abuse.org/cgi-bin/nph-rss?query=$sender_host_address # log_message = found in $dnslist_domain # !authenticated = * # dnslists = dialups.mail-abuse.org #.ifdef TEERGRUBE # delay = TEERGRUBE #.endif # 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 # passing on to the next ACL statement (if tests above it fail) or denying # access (if tests below it fail). accept domains = +local_domains endpass message = unknown user verify = recipient # Accept if the address is in a domain for which we are relaying, but again, # only if the recipient can be verified (this saves your secondary # MXes from accepting mail that they then can't send to your primary # MX) accept domains = +relay_to_domains endpass message = unrouteable address verify = recipient/callout=30s/callout_defer_ok # 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. 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. accept hosts = +localadds:+relay_from_hosts verify = recipient accept hosts = +auth_relay_hosts endpass message = authentication required authenticated = * warn message = X-Broken-Reverse-DNS: no host name found for IP address $sender_host_address !verify = reverse_host_lookup # Reaching the end of the ACL causes a "deny", but we might as well give # an explicit message. deny message = relay not permitted .ifdef TEERGRUBE delay = TEERGRUBE .endif check_data: deny !verify = header_syntax !condition = $header_X-WhitelistedRCPT-nohdrsyncheck: # Exims with my exim4.gooderror.diff patch, or exim 4.14+ will return # informative error messages. You can override that with a generic # message though (or you can use this for older exims) #message = Syntax error in the headers of your message. .ifdef TEERGRUBE delay = TEERGRUBE .endif # Accept if source is local SMTP (i.e. not over TCP/IP). We do this by # testing for an empty sending host field. accept hosts = : # This is to accept anything from localhost, and especially mailman which # chokes badly if you refuse its mail accept hosts = 127.0.0.1/8 deny hosts = !+localadds:!+hosts_disable_callback:* #sender_domains = !+envdomain_disable_callback:* !condition = $header_X-WhitelistedRCPT-nohdrfromcallback: !condition = ${lookup{${domain:$header_from:}}lsearch{HDR_DOMAIN_DISABLE_CALLBACK} {yes}{no}} # See the rcpt to ACL, we don't check some domains in random mode # (like yahoo.com) !condition = ${lookup{${domain:$header_from:}}lsearch{NO_RANDOM_CALLBACK} {yes}{no}} # random might be buggy in 4.14 from what I read on the exim list #!verify = header_sender/callout=90s,postmaster,random !verify = header_sender/callout=90s,postmaster # Thanks to the exim4.gooderror.diff patch, exim will return # informative error messages. You can override that with a generic # message though #message = Header sender couldn't be verified .ifdef TEERGRUBE delay = TEERGRUBE .endif deny hosts = !+localadds:!+hosts_disable_callback:* #sender_domains = !+envdomain_disable_callback:* !condition = $header_X-WhitelistedRCPT-nohdrfromcallback: !condition = ${lookup{${domain:$header_from:}}lsearch{HDR_DOMAIN_DISABLE_CALLBACK} {yes}{no}} # See the rcpt to ACL, we only check some domains in norandom mode # (like yahoo.com) condition = ${lookup{${domain:$header_from:}}lsearch{NO_RANDOM_CALLBACK} {yes}{no}} !verify = header_sender/callout=90s,postmaster # Thanks to the exim4.gooderror.diff patch, exim will return # informative error messages. You can override that with a generic # message though #message = Header sender couldn't be verified .ifdef TEERGRUBE delay = TEERGRUBE .endif accept check_auth: accept hosts = +auth_over_tls_hosts endpass message = STARTTLS required before AUTH encrypted = * accept check_expn: accept hosts = +expn_hosts deny message = expn not allowed from this host, sorry .ifdef TEERGRUBE delay = TEERGRUBE .endif check_vrfy: accept hosts = +vrfy_hosts deny message = vrfy not allowed from this host, sorry .ifdef TEERGRUBE delay = TEERGRUBE .endif check_nonsmtp: accept # end of acl ##### # begin processing router ##### ###################################################################### # 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 # Magic router to force successful verification of header from headers # for domains that don't resolve always_verify: driver = manualroute domains = +nodnsdomains verify_sender verify_only route_list = * smarthost: driver = manualroute domains = ! +local_domains route_list = SMARTHOST_ROUTELIST # Let's not deal with "impossible" target IP addresses ignore_target_hosts = +bogusips # You don't want SMTP callouts through a smarthost, it probably won't work no_verify # If you're on a laptop, let's not freeze messages because the network is # down host_find_failed = defer # Optimization since the smarthost router is independent of the local part same_domain_copy_routing = yes transport = remote_smtp # This router routes to remote hosts over SMTP using a DNS lookup with # default options. dnslookup: driver = dnslookup domains = ! +local_domains # Let's not deal with "impossible" target IP addresses ignore_target_hosts = +bogusips # Optimization since the dnslookup router is independent of the local part same_domain_copy_routing = yes transport = remote_smtp # This router routes to remote hosts over SMTP by explicit IP address, # given as a "domain literal" in the form [nnn.nnn.nnn.nnn]. The RFCs # require this facility, which is why it is enabled by default in Exim. # If you want to lock it out, set forbid_domain_literals in the main # configuration section above. literal: driver = ipliteral domains = ! +local_domains # Let's not deal with "impossible" target IP addresses ignore_target_hosts = +bogusips transport = remote_smtp # This has to come first so that we can override the aliases in # CONFDIR/aliases # We try both CDB and the source text file so that you can use either (although # CDB does override source text) # These virtual domains need to list _all_ the Emails for those domains. virtualcdb: debug_print = "R: virtualcdb for $local_part@$domain" driver = redirect domains = dsearch;CONFDIR/virtualdomains/virtualcdb allow_defer allow_fail # One can argue removing the no_more here, as it prevents the non cdb version from # being used, should it be more up to date (i.e. you added an entry, but forgot to # make the cdb version) no_more data=${lookup{$local_part}cdb*{CONFDIR/virtualdomains/virtualcdb/$domain}} virtual: debug_print = "R: virtual for $local_part@$domain" driver = redirect domains = dsearch;CONFDIR/virtualdomains/virtualsrc allow_defer allow_fail no_more data=${lookup{$local_part}lsearch*{CONFDIR/virtualdomains/virtualsrc/$domain}} # An overlay virtual domain only needs to list Emails that get rewritten virtual_overlaycdb: debug_print = "R: virtual_overlaycdb for $local_part@$domain" driver = redirect domains = dsearch;CONFDIR/virtualdomains/virtualoverlaycdb allow_defer allow_fail data=${lookup{$local_part}cdb*{CONFDIR/virtualdomains/virtualcdb/$domain}} virtual_overlay: debug_print = "R: virtual_overlay for $local_part@$domain" driver = redirect domains = dsearch;CONFDIR/virtualdomains/virtualoverlaysrc allow_defer allow_fail data=${lookup{$local_part}lsearch*{CONFDIR/virtualdomains/virtualsrc/$domain}} real_localuser_maildir: debug_print = "R: real_localuser_maildir for $local_part@$domain" driver = accept check_local_user require_files = ${local_part}:+${home}:+${home}/Maildir local_part_prefix = real- transport = local_delivery_maildir # This allows local delivery to be forced, avoiding alias files and # forwarding. real_localuser: debug_print = "R: real_localuser for $local_part@$domain" driver = accept check_local_user local_part_prefix = real- transport = local_delivery # This director handles aliasing using a traditional aliases file. # 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. system_aliases: debug_print = "R: system_aliases for $local_part@$domain" driver = redirect allow_defer allow_fail data = ${lookup{$local_part}lsearch{CONFDIR/aliases}} file_transport = address_file pipe_transport = address_pipe directory_transport = address_directory # Note that user and group are set/overriden in the transports user = mail group = mail retry_use_local_part .ifdef MAILMAN_HOME # We want this router first in case we have a list named something like # mailman-owner mm21_main_director: debug_print = "R: mm21_main_director for $local_part@$domain" driver = accept # We'll allow listname+foo addressing, but not for other admin addresses local_part_suffix = +* local_part_suffix_optional require_files = MAILMAN_HOME/lists/${lc::$local_part}/config.pck transport = mm21_transport mm21_director: debug_print = "R: mm21_director for $local_part@$domain" driver = accept require_files = MAILMAN_HOME/lists/${lc::$local_part}/config.pck local_part_suffix = "-bounces:-bounces+*:-confirm+*:-join:-leave:-owner:-request:-admin" transport = mm21_transport .endif ## Spam Assassin # Old router from dman, not needed anymore since we do it in local_scan #spamcheck: # # do not use this director when verifying a local-part at SMTP-time # no_verify # # When to scan a message : # # - it isn't already flagged as spam # # - it isn't already scanned # # - it didn't originate locally # #condition = "${if and { {!def:h_X-Spam-Flag:} {!eq {$received_protocol}{spam-scanned}} {!eq {$received_protocol}{local}} } {1}{0}}" # condition = "${if and { {!def:h_X-Spam-Flag:} {!eq {$received_protocol}{spam-scanned}} } {1}{0}}" # driver = smartuser # transport = spamcheckbatch uservacation: debug_print = "R: user_vacation for $local_part@$domain" driver = accept # See spec file chapter 41.7 local_part_suffix = +* local_part_suffix_optional check_local_user # do not reply to errors or lists condition = "${if or {{match {$h_precedence:} {(?i)junk|bulk|list}} \ {eq {$sender_address} {}}} {no} {yes}}" no_expn require_files = ${local_part}:${home}/.vacation.msg # do not reply to errors and bounces or lists senders = " ! ^.*-request@.*:\ ! ^owner-.*@.*:\ ! ^postmaster@.*:\ ! ^listmaster@.*:\ ! ^mailer-daemon@.*\ ! ^root@.*" transport = vacation_reply unseen user = ${local_part} no_verify # Run procmail for users who have a .procmailrc file procmail: debug_print = "R: procmail for $local_part@$domain" driver = accept # See spec file chapter 41.7 local_part_suffix = +* local_part_suffix_optional check_local_user require_files = ${local_part}:+${home}:+${home}/.procmailrc:+/usr/bin/procmail transport = procmail_pipe no_verify no_expn # This router handles forwarding using traditional .forward files. # It also allows mail filtering when a forward file starts with the # string "# Exim filter": to disable filtering, uncomment the "filter" # option. 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. # For standard debian setup of one group per user, it is acceptable---normal # even---for .forward to be group writable. If you have everyone in one # group, you should comment out the "modemask" line. Without it, the exim # default of 022 will apply, which is probably what you want. userforward: debug_print = "R: userforward for $local_part@$domain" driver = redirect allow_filter check_ancestor check_local_user # Not specifying the directory forces exim to do a stat on $home first, and # defer if NFS is hosed file = $home/.forward # See spec file chapter 41.7 local_part_suffix = +* local_part_suffix_optional modemask = 002 file_transport = address_file pipe_transport = address_pipe directory_transport = address_directory reply_transport = address_reply no_verify # On my site expn is used to map user aliases to the main login name. I do # not want for expn to show me what's in .forward, be it another Email or # a call to a script. Comment no_expn if you want that behavior -- Marc no_expn localuser_maildir: debug_print = "R: localuser_maildir for $local_part@$domain" driver = accept # See spec file chapter 41.7 local_part_suffix = +* local_part_suffix_optional check_local_user require_files = ${local_part}:+${home}:+${home}/Maildir transport = local_delivery_maildir # This router matches local user mailboxes. localuser: debug_print = "R: localuser for $local_part@$domain" driver = accept # See spec file chapter 41.7 local_part_suffix = +* local_part_suffix_optional check_local_user transport = local_delivery # end of router ##### # begin processing transport ##### ###################################################################### # TRANSPORTS CONFIGURATION # ###################################################################### # ORDER DOES NOT MATTER # # Only one appropriate transport is called for each delivery. # ###################################################################### begin transports .ifdef MAILMAN_HOME ## For Mailman 2.1, you only need one transport, albeit with a rather ## elaborate command... mm21_transport: debug_print = "T: mm21_transport for $local_part@$domain" driver = pipe # In case you wonder, substr_2 removes the leading '-' # and the regex removes optional +foo=hostname that can be after -bounce # (if you use VERP) -- Marc command = MAILMAN_WRAP "${if def:local_part_suffix{${substr_2:{${sg{${lc:$local_part_suffix}}{\\\\\+.*}{}}}}{post}}" ${lc:$local_part} current_directory = MAILMAN_HOME home_directory = MAILMAN_HOME user = MAILMAN_UID group = MAILMAN_GID .endif # This transport is used for procmail procmail_pipe: debug_print = "T: procmail_pipe for $local_part@$domain" driver = pipe path = "/bin:/usr/bin:/usr/local/bin" command = "/usr/bin/procmail -d ${local_part}" return_path_add delivery_date_add envelope_to_add user = $local_part group = mail # The lines header is used by mutt and similar MUAs headers_remove = "Lines" headers_add = "Lines: $body_linecount\n" # This is not really needed anymore #check_string = "From " #escape_string = ">From " # This transport is used for local delivery to user mailboxes. On debian # systems group mail is used so we can write to the /var/spool/mail # directory. (The alternative, which most other unixes use, is to deliver # as the user's own group, into a sticky-bitted directory) local_delivery: debug_print = "T: local_delivery for $local_part@$domain" driver = appendfile return_path_add delivery_date_add envelope_to_add file = /var/spool/mail/${local_part} group = mail mode = 0660 no_mode_fail_narrower use_fcntl_lock use_lockfile # This is not really needed anymore #check_string = "From " #escape_string = ">From " # Those options are for Maildir+ (Courier Imap), but compatible with regular # Maildir local_delivery_maildir: debug_print = "T: local_delivery_maildir for $local_part@$domain" driver = appendfile maildir_format create_directory maildir_tag = ,S=$message_size directory = /home/${local_part}/Maildir/ return_path_add delivery_date_add envelope_to_add group = mail mode = 0660 no_mode_fail_narrower # The lines header is used by mutt and similar MUAs headers_remove = "Lines" headers_add = "Lines: $body_linecount\n" # This transport is used for handling pipe addresses 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 or return_output if you want this to happen # only when the pipe fails to complete normally. address_pipe: debug_print = "T: address_pipe for $local_part@$domain" driver = pipe allow_commands = " \ /usr/bin/procmail:\ MAILMAN_HOME/mail/mailman:\ " log_defer_output log_fail_output path = "/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin" #return_fail_output return_output user = mail group = mail # The lines header is used by mutt and similar MUAs headers_remove = "Lines" headers_add = "Lines: $body_linecount\n" # This is the example of a transport that doesn't drop the perms to uid/gid # mail and trusts the calling router to do that # This transport is used for handling pipe addresses 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 or return_output if you want this to happen # only when the pipe fails to complete normally. address_pipe_root: debug_print = "T: address_pipe_root for $local_part@$domain" driver = pipe allow_commands = " \ /usr/bin/procmail:\ " log_defer_output log_fail_output path = "/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin" #return_fail_output return_output # The lines header is used by mutt and similar MUAs headers_remove = "Lines" headers_add = "Lines: $body_linecount\n" # This transport is used for handling file addresses generated by alias # or .forward files. address_file: debug_print = "T: address_file for $local_part@$domain" driver = appendfile delivery_date_add envelope_to_add return_path_add user = mail group = mail # This transport is used for handling deliveries to directories that are # generated by aliasing or forwarding. # This is not in the maildir format. If you want that, set your transport # to local_delivery_maildir instead address_directory: debug_print = "T: address_directory for $local_part@$domain" driver = appendfile delivery_date_add envelope_to_add return_path_add create_directory directory_file = "q${base62:$tod_epoch}-$inode" # The lines header is used by mutt and similar MUAs headers_remove = "Lines" headers_add = "Lines: $body_linecount\n" # This transport is used for handling autoreplies generated by the filtering # option of the forwardfile director. address_reply: debug_print = "T: autoreply for $local_part@$domain" driver = autoreply # This transport is used for delivering messages over SMTP connections. remote_smtp: debug_print = "T: remote_smtp for $local_part@$domain" driver = smtp # This deals with misocnfigurations like this one that redirect mail to us # (i.e. 'mail' is unqualified and resolves back to us) # worldclasssportfishing.net MX 30 mail dns_qualify_single = false # This fixes a problem if TLS is enabled where a misunderstanding on the RFC # can cause comunication failure between two hosts hosts_nopass_tls = * hosts_avoid_tls = +hosts_avoid_tls hosts_try_auth = +hosts_try_auth # This is an example, we're doing this in the system filter instead # Removing X-Mailer would remove X-Mailer: MygoodMUA :-( #headers_remove = "X-MSMail-Priority:X-MimeOLE" # This is generally set on messages originating from local users and it tells # SA-Exim not to scan the message or that the message was scanned. # Let's remove these headers if the message is sent remotely headers_remove = "X-SA-Do-Not-Run:X-SA-Exim-Scanned:X-SA-Exim-Rcpt-To:X-SA-Exim-Version" #helo_data = "You shouldn't rely on HELO data" vacation_reply: debug_print = "T: vacation_reply for $local_part@$domain" driver = autoreply file = ${home}/.vacation.msg file_expand from = Autoreply System log = ${home}/.vacation.log once = ${home}/.vacation.db once_repeat = 7d subject = ${if def:h_Subject: {Re: ${quote:${escape:${length_50:$h_Subject:}}} (autoreply)} {I am on vacation} } text = "\ Dear $h_from\n\n\ This is an automatic reply. Feel free to send additional\n\ mail, as only this one notice will be generated. The following\n\ is a prerecorded message, sent for ${local_part}@AUTORESPONDDOMAIN:\n\ ====================================================\n\n\ " to = "$sender_address" # Spam Assassin sample entries from dman. Not needed anymore since we run # SA from local_scan. You'd need one or the other, not both # Again, unless you know why, don't enable this, it's only for reference. #spamcheckbatch: # driver = pipe # command = /usr/sbin/exim -oMr spam-scanned -bS # transport_filter = /usr/bin/spamc -p 784 # bsmtp = all # home_directory = "CONFDIR/spamassassin" # current_directory = "CONFDIR/spamassassin" # # must use a privileged user to set $received_protocol on the way back in! # user = mail # group = mail # return_path_add = false # log_output = true # return_fail_output = true # prefix = # suffix = ## Spam Assassin #spamcheck: # driver = pipe # command = /usr/sbin/exim -i -oMr spam-scanned -f "${if eq {${sender_address}}{} {mailer-daemon} {${sender_address}} }" -- ${local_part} # transport_filter = /usr/bin/spamc -p 784 # home_directory = "CONFDIR/spamassassin" # current_directory = "CONFDIR/spamassassin" # # must use a privileged user to set $received_protocol on the way back in! # user = mail # group = mail # log_output = true # return_fail_output = true # end of transport ##### # begin processing retry ##### ###################################################################### # 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 24 # hours, then retries every 6 hours until 4 days have passed since the first # failed delivery. # Domain Error Retries # ------ ----- ------- * * F,2h,15m; G,24h,1h,1.5; F,4d,6h # end of retry ##### # begin processing rewrite ##### ###################################################################### # REWRITE CONFIGURATION # ###################################################################### begin rewrite # E rewrite all envelope fields # F rewrite the envelope From field # T rewrite the envelope To field # b rewrite the `Bcc:' header # c rewrite the `Cc:' header # f rewrite the `From:' header # h rewrite all headers # r rewrite the `Reply-to:' header # s rewrite the `Sender:' header # t rewrite the `To:' header # # S rewrite at SMTP time, before the mail is handled internally # # Pattern Replacement Flags .ifdef MAINDOMAIN # We want some receipients to stay local (to use the local CONFDIR/aliases) # Everything else gets rewritten to the MAINDOMAIN mail hub # Of course, if MAILNAME == MAINDOMAIN, the rewrite does nothing *@@ ${lookup{${lc:$1}}lsearch*{CONFDIR/localemails}{$0}{$1@MAINDOMAIN}} T # Outside of the envelope To, we make the local hostname disappear in case it is # internal and not resolvable from the internet (your mail could be rejected # otherwise) *@@ $1@MAINDOMAIN Fbcfrst .endif .ifdef MAINDOMAIN .ifdef MAIN_CANONIZE # This canonizes all incoming Emails to your master domain *@partial-lsearch;CONFDIR/domains/localdomains $1@MAINDOMAIN hE .endif .endif .ifdef LISTDOMAIN *@MAINDOMAIN "${if exists {MAILMAN_HOME/lists/${lc:$1}} {$1@LISTDOMAIN}fail}" hE .endif # end of rewrite ##### # begin processing auth ##### ###################################################################### # AUTHENTICATION CONFIGURATION # ###################################################################### begin authenticators # The examples below are for server side authentication; they allow two # styles of plain-text authentication against an CONFDIR/smtpauthdb.server file # which should have user IDs in the first column and crypted passwords # in the second. The columns need to be separated by ':'. # exim needs access to the UNENCRYPTED passwd so that it can also work with # cram-md5 (which requires it) srv_auth_plain: driver = plaintext public_name = PLAIN # The trick here is that we modify the password so that it can't match :fail: server_condition = "${if or {{eq{${sg{$3}{:fail:}{}}}{${extract{1}{::}{${lookup{$2}lsearch{CONFDIR/smtpauthdb.server}{$value}{:fail:}}}}}}{pam{${lc:$2}:$3}}}{1}{0}}" server_set_id = $2 svr_auth_login: driver = plaintext public_name = LOGIN server_prompts = "Username:: : Password::" # The trick here is that we modify the password so that it can't match :fail: server_condition = "${if or {{eq{${sg{$2}{:fail:}{}}}{${extract{1}{::}{${lookup{$1}lsearch{CONFDIR/smtpauthdb.server}{$value}{:fail:}}}}}}{pam{${lc:$1}:$2}}}{1}{0}}" server_set_id = $1 srv_auth_cram_md5: driver = cram_md5 public_name = CRAM-MD5 server_secret = ${extract{2}{::}{${lookup{$1}lsearch{CONFDIR/smtpauthdb.server}{$value}fail}}} server_set_id = $1 # Here is an example of CRAM-MD5 authentication against PostgreSQL: # # srv_psqldb_auth: # driver = cram_md5 # public_name = CRAM-MD5 # server_secret = ${lookup pgsql{SELECT pw FROM users WHERE username = '${quote_pgsql:$1}'}{$value}fail} # server_set_id = $1 # These examples below are the equivalent for client side authentication. # They get the passwords from CONFDIR/smtpauthdb.server.server. This file should have # three columns separated by colons, the first contains the name of the # mailserver to authenticate against, the second the username and the third # contains the password. ### # example for CONFDIR/smtpauthdb.server.server ### mail.server:clientname:secret ### # default entry: ### *:clientname:secret client_auth_plain: driver = plaintext public_name = PLAIN client_send = "^${extract{1}{::}{${lookup{$host}lsearch*{CONFDIR/smtpauthdb.client}{$value}fail}}}^${extract{2}{::}{${lookup{$host}lsearch*{CONFDIR/smtpauthdb.client}{$value}fail}}}" client_auth_login: driver = plaintext public_name = LOGIN client_send = ": ${extract{1}{::}{${lookup{$host}lsearch*{CONFDIR/smtpauthdb.client}{$value}fail}}} : ${extract{2}{::}{${lookup{$host}lsearch*{CONFDIR/smtpauthdb.client}{$value}fail}}}" client_cram_md5: driver = cram_md5 public_name = CRAM-MD5 client_name = ${extract{1}{::}{${lookup{$host}lsearch*{CONFDIR/smtpauthdb.client}{$value}fail}}} client_secret = ${extract{2}{::}{${lookup{$host}lsearch*{CONFDIR/smtpauthdb.client}{$value}fail}}} # end of auth #####