--- /dev/null
+$Cambridge: exim/configs/ABOUT,v 1.1 2004/10/08 10:50:49 ph10 Exp $
+
+CVS directory exim/exim-conf
+----------------------------
+
+This directory contains sample configurations and similar files that have been
+submitted by Exim users. The files are not locally modified, and so do not have
+CVS version Ids.
+
+End
--- /dev/null
+Date: Wed, 14 Jan 1998 15:07:22 +0200
+From: Vladimir Litovka <doka@grunt.vl.net.ua>
+
+[Syntax converted for Exim 4 by PH, 06-Dec-2001. Unchecked.]
+
+Although exim not intended for use in UUCP environment (it doesn't know
+anything about bang!path addresses), I'm successfully using it for delivering
+mail to UUCP clients. For this purposes I'm using two rewrite rules:
+
+#--------------------- REWRITE CONFIGURATION ------------------------#
+
+# system!system.domain.net!user
+\N^([^!]+)!((\w+)(\.\w+)+)!(.*)@your\.domain\N \
+ "${if eq {$1}{$3}{$5@$2}{$2!$5@$1}}" Tbcrtq
+
+# system*!user
+\N^([^!]+)!(.*)@your\.domain\N $2@$1 Tbcrtq
+
+#--------------------------------------------------------------------#
+
+The first rule check
+ if destination address in form:
+ uuname!system.some.domain!user
+ and
+ uuname == system
+ it rewrites address to user@system.some.domain
+ else it rewrites it to system.some.domain!user@uuname
+ and QUIT.
+
+The second rule check
+ if destination address in form:
+ uuname1!uuname2!FQDN!...!uunameN!user
+ it rewrites it to
+ uuname2!FQDN!...!uunameN!user@uuname1
+ and QUIT.
+
+For successfully delivering mail to uucp domain you must create such
+transport:
+
+#-------------------------------------------------------------------#
+uux:
+ driver = pipe;
+ command = /usr/bin/uux - -r $host!rmail ($local_part@$domain)
+ path = /usr/local/bin:/usr/bin:/bin
+ return_fail_output
+ user = uucp
+#-------------------------------------------------------------------#
+
+and such router:
+
+#-------------------------------------------------------------------#
+force_uucp:
+ driver = manualroute
+ route_data = partial-lsearch;/etc/exim/maps/force.uucp
+#-------------------------------------------------------------------#
+
+and use something similar to this force.uucp:
+
+# Domain Relay Options
+# ------ ----- -------
+system1 system1 uux
+system1.domain system1 uux
+#
+system2 system2 uux
+system2.domain system2 uux
+
+(!) Note, that you need unqualified names (system1, system2) because
+second rewrite rule don't do qualification (it known nothing about this).
--- /dev/null
+From: Kind@edb.uib.no
+Date: Sun, 2 Aug 1998 15:24:05 +0200
+
+[Syntax converted for Exim 4 by PH, 06-Dec-2001. Unchecked.]
+
+This is how I have configured a PP-inspired vacationnote, there is (was?)
+such a feature in PP. The user makes a file "tripnote" in his/her
+homedirectory, the message is passed to the sender once with a short
+leading text.
+
+############
+# TRANSPORT
+vacation_reply:
+ driver = autoreply
+ file = $home/tripnote
+ file_expand
+ log = $home/tripnote.log
+ once = $home/tripnote.db
+ from = vacation@yourdomain.org
+ to = $sender_address
+ subject = "Re: $h_subject"
+ 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@yourdomain.org:\n\
+ ====================================================\n\n\
+ "
+
+# ROUTER
+user_vacation:
+ driver = accept
+ check_local_user
+ require_files = $local_part:$home/tripnote
+ no_verify
+ senders = !^.*-request@.* : !^owner-.*@.* : !^postmaster@.* : \
+ ! ^listmaster@.* : !^mailer-daemon@.*
+ transport = vacation_reply
+ unseen
--- /dev/null
+Date: Tue, 14 Sep 1999 00:58:56 +0200
+Updated: Fri, 11 Jan 2002 05:13:57 +0200
+From: Vadim Vygonets <vadik@cs.huji.ac.il>
+
+This is the Exim configuration file of a machine which delivers mail to several
+local domains, where the mail is delivered locally, several hairy domains,
+handled as described below, and a half-virtual domain, which is first processed
+by its special alias file, then processed as other local domains (including the
+processing by the global alias file).
+
+This contribution consists of a number of files that are in the tar archive
+C022.tar, which unpacks into a directory called "virtual". See the README file
+therein for an explanation of the configuration.
+
+This is the updated virtual domain handling for Exim 4. The
+main changes are:
+
+1. Now there's the alias file admin.raw for privileged aliases
+ (such as Postmaster). It is processed earlier than
+ domain-specific files. The domain is not preserved on
+ redirection.
+
+2. <DOMAIN>.rewrite.raw is gone, and <DOMAIN>.aliases.raw is
+ renamed to <DOMAIN>.raw. The functionality was put into
+ entries with keys ending with a '+', and the data are allowed
+ to have no domain (which made the rewrite rule slightly more
+ complicated).
+
--- /dev/null
+Date: Wed, 22 Nov 2000 17:51:42 -0500 (EST)
+From: Dave C. <djc@microwave.com>
+
+[Syntax converted for Exim 4 by PH, 06-Dec-2001. Unchecked.]
+
+Ok.. Ive come up with something which might be worth including in the
+cookbook. Credit where it is due, the idea for this came from Nigel's
+C014.
+
+I have a setup to support ETRN for a few small (ok, two) domains.
+Currently it just leaves all the mail in the exim spool, and uses the
+default exim etrn response to flush it out.
+
+I don't like that - I agree with the opinion expressed on the list that
+mail should be delivered somewhere else, and then shoved down an SMTP
+session by some other program. Ive searched far and wide for something
+suitable to do that shoving, and finally hit upon the only program I
+trust to do that, handling errors and rejections correctly - exim
+itself.
+
+Nigel's solution for 'situation where a site I MX for has a known
+outage', combined with a bit of bash scriptery, seems to form a neat
+solution. (An intermittently connected host sort of falls under the
+'known outage' category ;)
+
+Without any further fluff, here are the details. Additional comments
+appear below..
+
+Either the real (intermittently connected) destination host needs to be
+listed as the lowest MX (with the exim server as a less preferred) , or
+the exim server needs to be the lowest MX, but have a router before the
+lookuphost router which uses route_list or something appropriate to
+normally deliver mail to the dialup host. The former is probably better
+for a host which is usually connected and is only occasionally
+disconnected (since other hosts would be able to delivery directly most
+of the time, skipping an extra relay), while the latter would probably
+work better for the converse ;) This paragraph actually applies anytime
+you are using ETRN..
+
+In either case, the routers below must precede whatever router handles
+the normal direct-to-dialup-destination..
+
+--
+
+smtp_etrn_command = /etc/exim/etrn_script $domain
+
+[- Content of /etc/exim/etrn_script: -]
+#!/bin/sh
+
+# Where exim lives
+EXIM=/usr/sbin/exim
+
+# Something appropriate to generate a temporary unique string
+UNIQ=`head -c100 /dev/urandom | md5sum | cut -f 1 -d" "`
+
+arg=$1
+domain=`echo $arg | sed 's/^\#//g'`
+
+if ( test -f /var/spool/etrn/${domain} ); then
+ exim_lock -q /var/spool/etrn/${domain} "mv /var/spool/etrn/${domain} /tmp/etrn-bsmtp-${UNIQ}"
+ ( cat /tmp/etrn-bsmtp-${UNIQ}
+ echo "QUIT" ) | $EXIM -bS -oMr etrn_requeue
+ rm -f /tmp/etrn-bsmtp-${UNIQ}
+fi
+
+$EXIM -R $domain
+
+[- end of etrn_script -]
+
+[- exim transport -]
+
+bsmtp_for_etrn:
+ driver=appendfile
+ file=/var/spool/etrn/$domain
+ user=exim
+ batch_max = 1000
+ use_bsmtp
+
+[- routers -]
+[- You probably would want to put the domains in a file or a dbm and
+[- adjused the 'domains' setting appropriately for both of these..
+
+# If any message has already been delivered to the bsmtp file,
+# this will detect the existence of the file and all messages will
+# go there, regardless of age.
+etrn_already:
+ driver = accept
+ transport = bsmtp_for_etrn
+ require_files = /var/spool/etrn/$domain
+ domains = etrntest.somedomain.com
+
+# If a message has been on the queue for over the specified amount of
+# time, this will catch it and drop it into the bsmtp file
+etrn_delay:
+ driver = accept
+ transport = bsmtp_for_etrn
+ condition = ${if >{$message_age}{1800} {yes}{no}}
+ domains = etrntest.somedomain.com
+
+[- -]
+
+Basically, this setup lets exim try to deliver to the real host for up
+to whatever time is specified in the \%etrn_delay%\ router. (1800 seconds =
+30 minutes), and then delivers all waiting messages, and any further
+messages, directly to a BSMTP file. This setup uses one big BSMTP
+file per domain, it probably wouldnt be too complex to have it use separate
+files.
+
+When the \^etrn_script^\ runs, it locks and renames the BSMTP file, and
+reinjects the messages to Exim, which (presumably) will now be able to
+deliver them. If it can't, then once they are too old they will again
+be sent off to the BSMTP file.. (If for som reason this occurs over and
+over without Exim being able to deliver them, eventually the messages
+will be returned with \*too many Received headers*\; this is a good
+thing, since their age will never get high enough for them to be
+returned by any retry rules).
--- /dev/null
+From: Kirill Miazine <lists@km.krot.org>
+Date: Tue, 2 Apr 2002 19:41:24 +0200
+
+Hello,
+
+Since Exim 4 configuration needed to get Mailman work differs a little
+bit from Exim 3 and since I still haven't seen a "recipe" for Mailman
+with Exim 4, I'm providing my configuration (based heavily on
+http://www.exim.org/howto/mailman.html).
+
+Following goes into main config settings:
+
+domainlist lists_domains = lists.krot.org
+MAILMAN_HOME=/local/lists
+MAILMAN_WRAP=MAILMAN_HOME/mail/wrapper
+MAILMAN_UID=mailman
+MAILMAN_GID=exim
+
+
+Following routers are defined:
+
+list_owner:
+ driver = redirect
+ domains = +lists_domains
+ require_files = MAILMAN_HOME/lists/$local_part/config.db
+ local_part_suffix = -owner
+ data = ${lc:$local_part}-admin@$domain
+
+owner_list:
+ driver = redirect
+ domains = +lists_domains
+ require_files = MAILMAN_HOME/lists/$local_part/config.db
+ local_part_prefix = owner-
+ data = ${lc:$local_part}-admin@$domain
+
+list_admin:
+ driver = accept
+ domains = +lists_domains
+ require_files = MAILMAN_HOME/lists/$local_part/config.db
+ local_part_suffix = -admin
+ transport = list_admin
+
+list_request:
+ driver = accept
+ domains = +lists_domains
+ require_files = MAILMAN_HOME/lists/$local_part/config.db
+ local_part_suffix = -request
+ transport = list_request
+
+list:
+ driver = accept
+ domains = +lists_domains
+ require_files = MAILMAN_HOME/lists/$local_part/config.db
+ transport = list
+
+
+And these transports are needed:
+
+list_admin:
+ driver = pipe
+ command = MAILMAN_WRAP mailowner ${lc:$local_part}
+ current_directory = MAILMAN_HOME
+ home_directory = MAILMAN_HOME
+ user = MAILMAN_UID
+ group = MAILMAN_GID
+
+list_request:
+ driver = pipe
+ command = MAILMAN_WRAP mailcmd ${lc:$local_part}
+ current_directory = MAILMAN_HOME
+ home_directory = MAILMAN_HOME
+ user = MAILMAN_UID
+ group = MAILMAN_GID
+
+list:
+ driver = pipe
+ command = MAILMAN_WRAP post ${lc:$local_part}
+ current_directory = MAILMAN_HOME
+ home_directory = MAILMAN_HOME
+ user = MAILMAN_UID
+ group = MAILMAN_GID
+
+Mailman was configured --with-mail-gid=exim.
--- /dev/null
+# Below is an Exim 4 config file which is designed for an Exim server that
+# is put in front of an Exchange 5.5 system but which verifies the valid
+# addresses that are stored in Exchange via LDAP lookups against the Exchange
+# server. The advantage being that I can do much more aggressive spam
+# fighting, make my own set of policy decisions etc, using the flexibility of
+# Exim while still supporting the Exchange system for final delivery (not my
+# ideal situation but the company relies on it). In any case, I thought this
+# was sufficiently useful and answers some semi-regular questions on the list,
+# that it might be included in either the FAQ or the sample configs.
+
+# From: Tabor J. Wells <twells@fsckit.net>
+# Date: Wed, 21 Aug 2002 11:16:36 -0400
+
+
+
+
+######################################################################
+# Runtime configuration file for Exim #
+######################################################################
+
+
+# This is a default configuration file which will operate correctly in
+# uncomplicated installations. Please see the manual for a complete list
+# of all the runtime configuration options that can be included in a
+# configuration file. There are many more than are mentioned here. The
+# manual is in the file doc/spec.txt in the Exim distribution as a plain
+# ASCII file. Other formats (PostScript, Texinfo, HTML, PDF) are available
+# from the Exim ftp sites. The manual is also online at the Exim web sites.
+
+
+# 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.
+
+
+########### IMPORTANT ########## IMPORTANT ########### IMPORTANT ###########
+# #
+# Whenever you change Exim's configuration file, you *must* remember to #
+# HUP the Exim daemon, because it will not pick up the new configuration #
+# until you do. However, any other Exim processes that are started, for #
+# example, a process started by an MUA in order to send a message, will #
+# see the new configuration as soon as it is in place. #
+# #
+# You do not need to HUP the daemon for changes in auxiliary files that #
+# are referenced from this file. They are read every time they are used. #
+# #
+# It is usually a good idea to test a new configuration for syntactic #
+# correctness before installing it (for example, by running the command #
+# "exim -C /config/file.new -bV"). #
+# #
+########### IMPORTANT ########## IMPORTANT ########### IMPORTANT ###########
+
+
+
+######################################################################
+# 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 =
+
+
+# The next three settings create two lists of domains and one list of hosts.
+# These lists are referred to later in this configuration using the syntax
+# +local_domains, +relay_to_domains, and +relay_from_hosts, respectively. They
+# are all colon-separated lists:
+
+domainlist local_domains = @ : dbm;/etc/exim/db/localdomains.db
+domainlist relay_to_domains =
+hostlist relay_from_hosts = 127.0.0.1 : 192.168.1.0/24
+
+# Most straightforward access control requirements can be obtained by
+# appropriate settings of the above options. In more complicated situations, you
+# may need to modify the Access Control List (ACL) which appears later in this
+# file.
+
+# The first setting specifies your local domains, for example:
+#
+# domainlist local_domains = my.first.domain : my.second.domain
+#
+# You can use "@" to mean "the name of the local host", as in the default
+# setting above. This is the name that is specified by primary_hostname,
+# as specified above (or defaulted). If you do not want to do any local
+# deliveries, remove the "@" from the setting above. If you want to accept mail
+# addressed to your host's literal IP address, for example, mail addressed to
+# "user@[192.168.23.44]", you can add "@[]" as an item in the local domains
+# list. You also need to uncomment "allow_domain_literals" below. This is not
+# recommended for today's Internet.
+
+# The second setting specifies domains for which your host is an incoming relay.
+# If you are not doing any relaying, you should leave the list empty. However,
+# if your host is an MX backup or gateway of some kind for some domains, you
+# must set relay_to_domains to match those domains. For example:
+#
+# domainlist relay_to_domains = *.myco.com : my.friend.org
+#
+# This will allow any host to relay through your host to those domains.
+# See the section of the manual entitled "Control of relaying" for more
+# information.
+
+# The third setting specifies hosts that can use your host as an outgoing relay
+# to any other host on the Internet. Such a setting commonly refers to a
+# complete local network as well as the localhost. For example:
+#
+# hostlist relay_from_hosts = 127.0.0.1 : 192.168.0.0/16
+#
+# The "/16" is a bit mask (CIDR notation), not a number of hosts. Note that you
+# have to include 127.0.0.1 if you want to allow processes on your host to send
+# SMTP mail by using the loopback address. A number of MUAs use this method of
+# sending mail.
+
+
+# All three of these lists may contain many different kinds of item, including
+# wildcarded names, regular expressions, and file lookups. See the reference
+# manual for details. The lists above are used in the access control list for
+# incoming messages. The name of this ACL is defined here:
+
+acl_smtp_rcpt = acl_check_rcpt
+
+# You should not change that setting until you understand how ACLs work.
+
+
+# Specify the domain you want to be added to all unqualified addresses
+# here. An unqualified address is one that does not contain an "@" character
+# followed by a domain. For example, "caesar@rome.example" is a fully qualified
+# address, but the string "caesar" (i.e. just a login name) is an unqualified
+# email address. Unqualified addresses are accepted only from local callers by
+# default. See the recipient_unqualified_hosts option if you want to permit
+# unqualified addresses from remote sources. If this option is not set, the
+# primary_hostname value is used for qualification.
+
+# qualify_domain =
+
+
+# If you want unqualified recipient addresses to be qualified with a different
+# domain to unqualified sender addresses, specify the recipient domain here.
+# If this option is not set, the qualify_domain value is used.
+
+# qualify_recipient =
+
+
+# The following line must be uncommented if you want Exim to recognize
+# addresses of the form "user@[10.11.12.13]" that is, with a "domain literal"
+# (an IP address) instead of a named domain. The RFCs still require this form,
+# but it makes little sense to permit mail to be sent to specific hosts by
+# their IP address in the modern Internet. This ancient format has been used
+# by those seeking to abuse hosts by using them for unwanted relaying. If you
+# really do want to support domain literals, uncomment the following line, and
+# see also the "domain_literal" router below.
+
+# allow_domain_literals
+
+
+# No deliveries will ever be run under the uids of these users (a colon-
+# separated list). An attempt to do so causes a panic error to be logged, and
+# the delivery to be deferred. This is a paranoic safety catch. Note that the
+# default setting means you cannot deliver mail addressed to root as if it
+# were a normal user. This isn't usually a problem, as most sites have an alias
+# for root that redirects such mail to a human administrator.
+
+never_users = root
+
+
+# The setting below causes Exim to do a reverse DNS lookup on all incoming
+# IP calls, in order to get the true host name. If you feel this is too
+# expensive, you can specify the networks for which a lookup is done, or
+# remove the setting entirely.
+
+host_lookup = *
+
+
+# The settings below, which are actually the same as the defaults in the
+# code, cause Exim to make RFC 1413 (ident) callbacks for all incoming SMTP
+# calls. You can limit the hosts to which these calls are made, and/or change
+# the timeout that is used. If you set the timeout to zero, all RFC 1413 calls
+# are disabled. RFC 1413 calls are cheap and can provide useful information
+# for tracing problem messages, but some hosts and firewalls have problems
+# with them. This can result in a timeout instead of an immediate refused
+# connection, leading to delays on starting up an SMTP session.
+
+rfc1413_hosts = *
+rfc1413_query_timeout = 30s
+
+
+# By default, Exim expects all envelope addresses to be fully qualified, that
+# is, they must contain both a local part and a domain. If you want to accept
+# unqualified addresses (just a local part) from certain hosts, you can specify
+# these hosts by setting one or both of
+#
+# sender_unqualified_hosts =
+# recipient_unqualified_hosts =
+#
+# to control sender and recipient addresses, respectively. When this is done,
+# unqualified addresses are qualified using the settings of qualify_domain
+# and/or qualify_recipient (see above).
+
+
+# If you want Exim to support the "percent hack" for certain domains,
+# uncomment the following line and provide a list of domains. The "percent
+# hack" is the feature by which mail addressed to x%y@z (where z is one of
+# the domains listed) is locally rerouted to x@y and sent on. If z is not one
+# of the "percent hack" domains, x%y is treated as an ordinary local part. This
+# hack is rarely needed nowadays; you should not enable it unless you are sure
+# that you really need it.
+#
+# percent_hack_domains =
+#
+# As well as setting this option you will also need to remove the test
+# for local parts containing % in the ACL definition below.
+
+
+# When Exim can neither deliver a message nor return it to sender, it "freezes"
+# the delivery error message (aka "bounce message"). There are also other
+# circumstances in which messages get frozen. They will stay on the queue for
+# ever unless one of the following options is set.
+
+# This option unfreezes frozen bounce messages after two days, tries
+# once more to deliver them, and ignores any delivery failures.
+
+ignore_bounce_errors_after = 2d
+
+# This option cancels (removes) frozen messages that are older than a week.
+
+timeout_frozen_after = 7d
+
+# Defined LDAP default servers
+ldap_default_servers = 192.168.1.101
+
+
+
+######################################################################
+# ACL CONFIGURATION #
+# Specifies access control lists for incoming SMTP mail #
+######################################################################
+
+begin acl
+
+# This access control list is used for every RCPT command in an incoming
+# SMTP message. The tests are run in order until the address is either
+# accepted or denied.
+
+acl_check_rcpt:
+
+ # Accept if the source is local SMTP (i.e. not over TCP/IP). We do this by
+ # testing for an empty sending host field.
+
+ accept hosts = :
+
+ # 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 = ^.*[@%!/|] : ^\\.
+
+ # Accept mail to postmaster in any local domain, regardless of the source,
+ # and without verifying the sender.
+
+ accept local_parts = postmaster
+ domains = +local_domains
+
+ # Deny unless the sender address can be verified.
+
+ require verify = sender
+
+ #############################################################################
+ # There are no 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 could get Exim to perform a DNS black list lookup at this point.
+ # The first one denies, while the second just warns.
+ #
+ # deny message = rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
+ # dnslists = black.list.example
+ #
+ # warn message = X-Warning: $sender_host_address is in a black list at $dnslist_domain
+ # log_message = found in $dnslist_domain
+ # dnslists = black.list.example
+ #############################################################################
+
+ # 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.
+
+ accept domains = +relay_to_domains
+ endpass
+ message = unrouteable address
+ verify = recipient
+
+ # If control reaches this point, the domain is neither in +local_domains
+ # nor in +relay_to_domains.
+
+ # Accept if the message comes from one of the hosts for which we are an
+ # outgoing relay. 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 = +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.
+
+ accept authenticated = *
+
+ # Reaching the end of the ACL causes a "deny", but we might as well give
+ # an explicit message.
+
+ deny message = relay not permitted
+
+
+
+######################################################################
+# ROUTERS CONFIGURATION #
+# Specifies how addresses are handled #
+######################################################################
+# THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT! #
+# An address is passed to each router in turn until it is accepted. #
+######################################################################
+
+begin routers
+
+# This router routes to remote hosts over SMTP by explicit IP address,
+# when an email address is given in "domain literal" form, for example,
+# <user@[192.168.35.64]>. The RFCs require this facility. However, it is
+# little-known these days, and has been exploited by evil people seeking
+# to abuse SMTP relays. Consequently it is commented out in the default
+# configuration. If you uncomment this router, you also need to uncomment
+# allow_domain_literals above, so that Exim can recognize the syntax of
+# domain literal addresses.
+
+# domain_literal:
+# driver = ipliteral
+# domains = ! +local_domains
+# transport = remote_smtp
+
+
+# This router routes addresses that are not in local domains by doing a DNS
+# lookup on the domain name. Any domain that resolves to 0.0.0.0 or to a
+# loopback interface address (127.0.0.0/8) is treated as if it had no DNS
+# entry. Note that 0.0.0.0 is the same as 0.0.0.0/32, which is commonly treated
+# as the local host inside the network stack. It is not 0.0.0.0/0, the default
+# route. If the DNS lookup fails, no further routers are tried because of
+# the no_more setting, and consequently the address is unrouteable.
+
+dnslookup:
+ driver = dnslookup
+ domains = ! +local_domains
+ transport = remote_smtp
+ ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 : 10.0.0.0/8 : 172.16.0.0/12
+ no_more
+
+
+# The remaining routers handle addresses in the local domain(s).
+
+
+# This router handles aliasing using a traditional /etc/aliases file.
+#
+##### NB You must ensure that /etc/aliases exists. It used to be the case
+##### NB that every Unix had that file, because it was the Sendmail default.
+##### NB These days, there are systems that don't have it. Your aliases
+##### NB file should at least contain an alias for "postmaster".
+#
+# If any of your aliases expand to pipes or files, you will need to set
+# up a user and a group for these deliveries to run under. You can do
+# this by uncommenting the "user" option below (changing the user name
+# as appropriate) and adding a "group" option if necessary. Alternatively, you
+# can specify "user" on the transports that are used. Note that the transports
+# listed below are the same as are used for .forward files; you might want
+# to set up different ones for pipe and file deliveries from aliases.
+
+system_aliases:
+ driver = redirect
+ allow_fail
+ allow_defer
+ data = ${lookup{$local_part}lsearch{/etc/exim/txt/aliases.txt}}
+# user = exim
+ file_transport = address_file
+ pipe_transport = address_pipe
+
+# This router matches local user mailboxes.
+# Domains set to $primary_hostname so that I can route stuff locally as need
+# be but prevent user@mylocaldomain.com from delivering locally when 'user'
+# also matches the Exchange lookup below.
+
+localuser:
+ driver = accept
+ check_local_user
+ domains = $primary_hostname
+ transport = local_delivery
+ no_more
+
+# Routers for lookups in LDAP on Exchange if they exist there then punt
+
+# First if it exists as a otherMailbox=smtp$user@example.com (Exchange's
+# format for aliases then substitute the canonical email address for this user
+# as defined by mail=
+
+exchangeothermailboxlookup:
+ driver = redirect
+ data = ${lookup ldap {ldap:///?mail?sub?(otherMailbox=smtp\$${quote_ldap:$local_part}@${quote_ldap:$domain})}}
+ domains = dbm;/etc/exim/db/localdomains.db
+ verify_recipient
+
+# This lookup verifies the mail=user@example.com format and if it exists
+# Pass to the the manualroute router which is used to punt to the internal
+# Exchange server as defined by domain.
+
+exchangemaillookup:
+ driver = redirect
+ data = ${lookup ldap {ldap:///?mail?sub?(mail=${quote_ldap:$local_part}@${quote_ldap:$domain})}}
+ domains = dbm;/etc/exim/db/localdomains.db
+ verify_recipient
+ self = pass
+ pass_router = exchangeroute
+ no_more
+
+# localdomains.db contain entries that look like:
+# example.com: 192.168.1.101
+# example.net: 192.168.1.102
+# etc.
+
+exchangeroute:
+ driver = manualroute
+ transport = remote_smtp
+ route_data = ${lookup{$domain}dbm{/etc/exim/db/localdomains.db}}
+
+######################################################################
+# 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
+
+
+# This transport is used for local delivery to user mailboxes in traditional
+# BSD mailbox format. By default it will be run under the uid and gid of the
+# local user, and requires the sticky bit to be set on the /var/mail directory.
+# Some systems use the alternative approach of running mail deliveries under a
+# particular group instead of using the sticky bit. The commented options below
+# show how this can be done.
+
+local_delivery:
+ driver = appendfile
+ file = /var/mail/$local_part
+ delivery_date_add
+ envelope_to_add
+ return_path_add
+# group = mail
+# mode = 0660
+
+
+# This transport is used for handling pipe deliveries generated by alias or
+# .forward files. If the pipe generates any standard output, it is returned
+# to the sender of the message as a delivery error. Set return_fail_output
+# instead of return_output if you want this to happen only when the pipe fails
+# to complete normally. You can set different transports for aliases and
+# forwards if you want to - see the references to address_pipe in the routers
+# section above.
+
+address_pipe:
+ driver = pipe
+ return_output
+
+
+# This transport is used for handling deliveries directly to files that are
+# generated by aliasing or forwarding.
+
+address_file:
+ driver = appendfile
+ delivery_date_add
+ envelope_to_add
+ return_path_add
+
+
+# This transport is used for handling autoreplies generated by the filtering
+# option of the userforward router.
+
+address_reply:
+ driver = autoreply
+
+
+
+######################################################################
+# RETRY CONFIGURATION #
+######################################################################
+
+begin retry
+
+# This single retry rule applies to all domains and all errors. It specifies
+# retries every 15 minutes for 2 hours, then increasing retry intervals,
+# starting at 1 hour and increasing each time by a factor of 1.5, up to 16
+# hours, then retries every 6 hours until 4 days have passed since the first
+# failed delivery.
+
+# Domain Error Retries
+# ------ ----- -------
+
+* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
+
+
+
+######################################################################
+# REWRITE CONFIGURATION #
+######################################################################
+
+# There are no rewriting specifications in this default configuration file.
+
+begin rewrite
+
+
+
+######################################################################
+# AUTHENTICATION CONFIGURATION #
+######################################################################
+
+# There are no authenticator specifications in this default configuration file.
+
+begin authenticators
+
+
+# End of Exim configuration file
--- /dev/null
+Date: Mon, 2 Dec 2002 10:35:06 +0000
+From: Mike Richardson <doctor@mcc.ac.uk>
+
+Hiya,
+
+I thought I'd submit this as an example of an authenticated mail hub
+configuration. Several people have asked for it so I thought it
+might be of interest.
+
+Authenticated mail hubs using LDAP to authenticate against which simply
+forward mail to central mailrouters. X headers are added for audit
+trail purposes.
+
+Config:
+#########################################################################
+
+acl_smtp_rcpt = acl_check_rcpt
+
+ignore_bounce_errors_after = 12h
+
+timeout_frozen_after = 3d
+
+# LDAP server:
+
+hide ldap_default_servers=ldap.your.site
+
+# SSL options. advertise TLS but don't insist on it.
+
+tls_advertise_hosts=*
+tls_certificate=/var/cert/securemail.your.site.cert
+tls_privatekey=/var/cert/securemail.your.site.key
+tls_verify_hosts= *
+
+# Remove the queue runner logs and add logging of the interface, protocols
+# and connections. Useful for debugging when users are having difficulty
+# configuring and connecting. Many ISPs use Transparent Proxying
+
+log_selector= +incoming_interface -queue_run +smtp_protocol_error
++smtp_syntax_error +smtp_connection
+
+# SMTP input limits. Some connections are reserved for local users.
+
+smtp_accept_max=200
+smtp_accept_queue=150
+smtp_accept_reserve=10
+smtp_reserve_hosts=130.88.0.0/16
+smtp_connect_backlog=100
+
+# Overloading
+
+queue_only_load=5
+deliver_queue_load_max=7
+
+# Message size limits
+
+message_size_limit=10M
+return_size_limit=65535
+
+# Spool space check
+
+check_spool_space=100M
+
+# directory splitting
+
+split_spool_directory
+
+# Parallel remote deliver
+
+remote_max_parallel = 10
+
+# My system filter is to create extra logging info for X-Mailer info.
+
+system_filter=/etc/systemfilter
+system_filter_user=exim
+
+# Listen of multiple interfaces to defeat transparent proxying
+
+local_interfaces = 130.88.200.47.25 : 130.88.200.47.465 : 130.88.200.47.587
+
+# Only accept local traffic and authenticated stuff.
+# Error message points to useful web page.
+
+acl_check_rcpt:
+
+ accept hosts = :
+ deny local_parts = ^.*[@%!/|]
+ require verify = sender
+
+ accept authenticated = *
+
+ deny message = Not authenticated, see http://www.useful.web.page/
+
+
+
+######################################################################
+# ROUTERS CONFIGURATION #
+# Specifies how addresses are handled #
+######################################################################
+
+begin routers
+
+# Manual route to force all traffic through our hubs which handle all
+# the alias expansion, domain routing etc.
+# I add an X header for audit trail purposes but no more information that
+# would be expected from a legitimate email. Don't want to upset the DPA
+# people
+
+smarthost:
+ driver = manualroute
+ headers_add =X-Authenticated-Sender: ${lookup ldap\
+{ldap:///o=ac,c=uk?cn?sub?(&(uid=$authenticated_id))}{$value}{no}} from \
+${sender_fullhost}\nX-Authenticated-From: ${lookup ldap\
+{ldap:///o=ac,c=uk?mail?sub?(&(uid=$authenticated_id))}{$value}{no}}
+ transport = remote_smtp
+ domains = ! +local_domains
+ route_list=* mailrouter.your.site
+ ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
+ no_more
+
+# All other routes as per normal...
+
+
+######################################################################
+# AUTHENTICATION CONFIGURATION #
+######################################################################
+
+# This only supports PLAIN and LOGIN due to the nature of our LDAP server.
+
+begin authenticators
+
+plain:
+ driver= plaintext
+ public_name = PLAIN
+ server_condition="${lookup ldap {user=\"${lookup \
+ldapdn{ldap:///o=ac,c=uk?sn?sub?(&(uid=$2))}{$value}{no}}\" pass=$3 \
+ldap:///o=ac,c=uk?sn?sub?(&(uid=$2))}{yes}{no}}"
+ server_set_id = $2
+
+login:
+ driver = plaintext
+ public_name= LOGIN
+ server_prompts = "Username:: : Password::"
+ server_condition="${lookup ldap {user=\"${lookup \
+ldapdn{ldap:///o=ac,c=uk?sn?sub?(&(uid=$1))}{$value}{no}}\" pass=$2 \
+ldap:///o=ac,c=uk?sn?sub?(&(uid=$1))}{yes}{no}}"
+ server_set_id=$1
+# End of Exim configuration file
+##########################################################################
--- /dev/null
+Date: Tue, 20 Aug 2002 07:33:36 -0700
+From: "Kevin P. Fleming" <kpfleming@cox.net>
+
+Here it is, for Exim 4.10 and Cyrus IMAPD 2.1.5 using db3/db4-format
+mailbox database. This configuration delivers the messages to Cyrus
+IMAPD using LMTP over a TCP/IP socket, so the cyrus.conf file needs to
+start lmtpd as "lmtpd -a" so the connection will be pre-authenticated
+(given that, it is also important that the cyrus.conf file restrict
+lmtpd to listening on 127.0.0.1 _only_, otherwise random users could
+submit messages directly to lmtpd).
+
+
+routers:
+
+# look in the Cyrus IMAPD mailboxes.db file for local_domains local
+# parts to be verified
+local_user_verify:
+ driver = accept
+ domains = +local_domains
+ local_part_suffix = +*
+ local_part_suffix_optional
+ condition = ${lookup{user.${local_part}} dbmnz {/storage/imap/mailboxes.db} {yes}{no}}
+ verify_only
+
+# rewrite local_domains local parts to be all lowercase
+lowercase_local:
+ driver = redirect
+ redirect_router = local_user
+ domains = +local_domains
+ data = ${lc:${local_part}}
+
+# deliver local_domains messages
+local_user:
+ driver = accept
+ domains = +local_domains
+ transport = local_delivery
+
+
+transport:
+
+# deliver messages to Cyrus IMAPD using LMTP over TCP/IP on the loopback
+interface
+local_delivery:
+ driver = smtp
+ protocol = lmtp
+ allow_localhost = yes
+ hosts = 127.0.0.1
+
--- /dev/null
+Date: Wed, 18 Sep 2002 15:22:44 +0100 (BST)
+From: Tony Finch <fanf2@cam.ac.uk>
+
+I wanted to be able to preserve the envelope contents (except for the return
+path when I'm feeling paranoid about error handling).
+
+Feel free to add this to the examples -- someone else might find it useful. I
+also have a complete configuration which I have been recommending to other
+people in Cambridge (although it could work elsewhere with tweaks) at
+http://www-uxsup.csx.cam.ac.uk/~fanf2/conf4.satellite.
+
+# Deliver a duplicate of some proportion of all messages to a special
+# machine specified in the file /MAIL_TAP_HOST, if it exists. The
+# probability of sending a message is the reciprocal of the second
+# number in the hash part of the condition. The address data is used
+# to prevent redirected addresses from being tapped twice. The
+# originating host and sender are recorded in extra headers. If the
+# delivery fails the bounce goes to a rubbish bin (although this means
+# that the traffic seen by the tap is not quite the same as the
+# traffic seen here).
+
+traffic_tap:
+ unseen
+ no_expn
+ no_verify
+ transport = smtp
+ driver = manualroute
+ require_files = /MAIL_TAP_HOST
+ route_data = ${readfile{/MAIL_TAP_HOST}{:}}
+ address_data = ${if!def:address_data{tapped}fail}
+ condition = ${if!eq{a}{${hash_1_1:$message_headers$message_body}}{no}{yes}}
+ headers_add = ${if!def:sender_host_address{}{X-Orig-Remote-Host: $sender_host_address}}\n\
+ X-Orig-Return-Path: $return_path
+ errors_to = YOUR_RUBBISH_BIN_ADDRESS_HERE
+
--- /dev/null
+From: Oliver Egginger <Oliver.Egginger@dvz.fh-giessen.de>
+Date: 21 May 2003 10:11:16 +0200
+
+Hi there,
+
+download the spamassassin package. See
+http://au.spamassassin.org/downloads.html
+
+Define a router in your Exim configuration file.
+For Exim 4 it could look like this:
+
+# Spam Assassin
+spamcheck_router:
+ no_verify
+ check_local_user
+ # When to scan a message :
+ # - it isn't already flagged as spam
+ # - it isn't already scanned
+ # - comes from ABC.DEF.GHI.JKL or MNO.PQR.STU.VWX
+ # - .spamcheck exists for this user
+ condition = \
+ "${if and { {!def:h_X-Spam-Flag:} \
+ {!eq {$received_protocol}{spam-scanned}} \
+ {or { {eq {$sender_host_address}{ABC.DEF.GHI.JKL}} \
+ {eq {$sender_host_address}{MNO.PQR.STU.VWX}} \
+ }\
+ }\
+ }\
+ {1}{0}\
+ }"
+ require_files = $home/.spamcheck
+ driver = accept
+ transport = spamcheck
+
+
+This router has two advantages (for us):
+
+1. You can define the sender host addresses from which you will scan the spam.
+In my example there are ABC.DEF.GHI.JKL and MNO.PQR.STU.VWX (you have to
+substiute this by your real IP-Adresses).
+
+2. The spamcheck router only runs in dependency of the existence of the
+.spamcheck file. So your users can decide whether or not they wont to use
+Spamassassin. Thats important for protection of privacy in germany.
+
+If you don't need this you can simplify the router, for example:
+
+# Spam Assassin
+spamcheck_router:
+ no_verify
+ check_local_user
+ # When to scan a message :
+ # - it isn't already flagged as spam
+ # - it isn't already scanned
+ condition = \
+ "${if and { {!def:h_X-Spam-Flag:} \
+ {!eq {$received_protocol}{spam-scanned}} \
+ }\
+ {1}{0}\
+ }"
+ driver = accept
+ transport = spamcheck
+
+
+In the end you will need a spamcheck transport. This one works well for us:
+
+# Spam Assassin
+spamcheck:
+ driver = pipe
+ command = /usr/exim/bin/exim -oMr spam-scanned -bS
+ use_bsmtp = true
+ transport_filter = /usr/bin/spamc
+ home_directory = "/tmp"
+ current_directory = "/tmp"
+ # 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
+ return_path_add = false
+ message_prefix =
+ message_suffix =
+
+
+Put the router and the transport on the right places in your exim conf and send
+the daemon a HUP signal. Thats all.
+
+- oliver
--- /dev/null
+From: Suresh Ramasubramanian <linux@frodo.hserus.net>
+Date: Mon, 11 Aug 2003 11:57:39 +0530
+
+I've been seeing a whole bunch of IPs that send me spam / virus mail and
+HELOing as one of my own IPs, or as HELO one.of.my.own.domains (or maybe
+HELO primary_hostname)
+
+On the other hand, I have users relaying through my box with AUTH, using
+mozilla, which HELO's as "HELO hserus.net" if a hserus.net user relays.
+
+Here's something to stop this stuff - in acl_check_rcpt:
+
+[snippet in exim configure file]
+
+ accept hosts = :
+
+ # Accept all authenticated senders
+ accept authenticated = *
+
+ # Spam control
+
+ # Be polite and say HELO. Reject anything from hosts that havn't given
+ # a valid HELO/EHLO to us.
+ deny condition = ${if \
+ or{{!def:sender_helo_name}{eq{$sender_helo_name}{}}}{yes}{no}}
+ message = RFCs mandate HELO/EHLO before mail can be sent
+
+ # Forged hostname - HELOs as my own hostname or domain
+ deny message = Forged hostname detected in HELO: $sender_helo_name
+ hosts = !+relay_from_hosts
+ log_message = Forged hostname detected in HELO: \
+ $sender_helo_name
+ condition = ${lookup {$sender_helo_name} \
+ lsearch{/usr/local/etc/exim/local_domains}{yes}{no}}
+
+ # Forged hostname -HELOs as one of my own IPs
+ deny message = Forged IP detected in HELO: $sender_helo_name
+ hosts = !+relay_from_hosts
+ log_message = Forged IP detected in HELO: $sender_helo_name
+ condition = ${if \
+ eq{$sender_helo_name}{$interface_address}{yes}{no}}
+
+[end snippet]
+
--- /dev/null
+From: David Woodhouse <dwmw2@infradead.org>
+Date: Thu, 18 Dec 2003 14:25:47 +0000
+
+Given a domain in DNS of the form...
+
+$ORIGIN vdns.infradead.org.mailtarget.
+fish 604800 IN TXT dwmw2@infradead.org
+
+(It doesn't _have_ to be in private namespace; you can put it anywhere but I
+prefer to have it private)
+
+The following routers use it to implement a virtual domain. You could of course
+omit the first and just make sure you have postmaster in all the zones you use
+this way...
+
+Rather than hardcoding the DNS domain to use in the router, we can put it into
+a flat file with the list of domains for which we should be doing this.
+
+We put this into /etc/exim/dns-virtual-domains:
+
+ vdns.infradead.org: vdns.infradead.org.mailtarget
+
+In the main section of the configuration file we have:
+
+domainlist dns_virtual_domains = lsearch;CONFDIR/dns-virtual-domains
+
+The following routers handle unqualified addresses, multiple TXT records, and
+entries of the form '@domain'. Also if we're not primary MX for the virtual
+domain in question we'll fall back to forwarding to a higher-priority MX host
+if the DNS isn't talking to us....
+
+virtual_postmaster:
+ driver = redirect
+ domains = +dns_virtual_domains
+ local_parts = postmaster:root:abuse:mailer-daemon
+ data = postmaster@$primary_hostname
+
+ # For virtual domains, look up the target in DNS and rewrite...
+
+dns_virtual_domains:
+ driver = redirect
+ domains = +dns_virtual_domains
+ check_ancestor
+ repeat_use
+ one_time
+ allow_defer
+ allow_fail
+ forbid_file
+ forbid_pipe
+ retry_use_local_part
+ qualify_preserve_domain
+
+ # Stash the lookup domain root for use in the next router.
+ address_data = ${lookup{$domain}lsearch{CONFDIR/dns-virtual-domains}}
+
+ # The lookup failure won't distinguish between absent record, absent
+ # domain, or other temporary failures. So we make this router just
+ # give up, and sort out the various failure modes later.
+
+ # The ${sg...} bits turn multiple TXT records (which Exim gives us
+ # separated by \n) into a comma-separated list, and also rewrite
+ # any element of that list of the form '@domain' (i.e. without a
+ # local part) to $local_part@domain, using the original local part
+ # from the address being routed, at the newly-provided domain.
+
+ # Addresses containing _only_ a localpart are qualified at the
+ # same domain as is being looked up, by qualify_preserve_domain
+ # above.
+ data = ${sg{\
+ ${sg{\
+ ${lookup dnsdb{txt=$local_part.$address_data}{$value}fail}\
+ }{\n}{,}}\
+ }{(,|^)[ ]*@}{\$1\$local_part@}}
+
+dns_virtual_failed:
+ driver = redirect
+ domains = +dns_virtual_domains
+ allow_fail
+ allow_defer
+ data = ${lookup dnsdb{ns=$address_data}\
+ # If NS lookup succeeded, the domain exists and we can find it.
+ # Therefore, the above lookup failure meant that the user
+ # just doesn't exist. Fail appropriately:
+ {:fail:Unknown user at virtual domain}\
+ # NS lookup failed. This means there's a DNS problem -- so we
+ # shouldn't fail the delivery; let the following routers handle
+ # it... Note "fail" not "{:fail:}". It means 'pass'. :)
+ fail}
+
+
+ # We have DNS problems. If we're actually _delivering_, then try to
+ # deliver to a higher-priority MX if one exists. Otherwise, we defer and
+ # let it stay on the queue until the problem is fixed.
+ # You may prefer to freeze or bounce in this situation; I don't.
+dns_virtual_relay:
+ driver = dnslookup
+ domains = +dns_virtual_domains
+ transport = remote_smtp
+ self = defer
+ no_verify
+ no_more
+
+ # On the other hand, if there's a DNS problem and we're only _verifying_,
+ # as we do when accepting incoming mail, then accept it for now and
+ # it'll get queued for when the DNS works again.
+dns_virtual_verify_fallback:
+ driver = accept
+ domains = +dns_virtual_domains
+ verify_only
+ no_more
+
+> Now I just need to investigate DDNS and see if it'll let individual
+> users update the TXT records for their own aliases in the DNS... :)
+
+This is remarkably simple to set up -- Google is your friend. I'm now
+able to set up HMAC-MD5 keys to 'own' certain mail domains, and the
+owners of those virtual mail domains can happily change the TXT records
+to their hearts content, without bugging me to make changes and roll out
+new alias files to all the MX hosts.
+
+A setuid app which is able to read the key file, and which will update
+the alias only for the user it's invoked by, is also fairly trivial to
+implement -- inspired by the 'cammail' alias system.
+
--- /dev/null
+From: Nathan Ollerenshaw <nathan@valuecommerce.co.jp>
+
+## I've been working quite hard to come up with a config that reasonably
+## matches the qmail-ldap setup, without the warts. I want to submit it
+## for inclusion in your config.samples archive, in case anyone else needs
+## to do the same as I. I hope its useful.
+##
+## A few notes; it supports catchalls but not dash extension addressing,
+## as I couldn't be bothered, and I'm unsure as to how many people
+## actually use the feature. Certainly nobody on my system. It supports
+## autoreplies, but not an autoreply on a catchall, because this just
+## kills your mailserver when someone does a dictionary spam attack
+## against a domain set up this way.
+
+
+######################################################################
+# Runtime configuration file for Exim #
+######################################################################
+
+#domainlist local_domains = @ : lsearch:/apps/conf/mail/locals
+domainlist local_domains = lsearch;/apps/conf/mail/locals
+domainlist relay_to_domains =
+
+# the pop-before-smtp package at http://popbsmtp.sourceforge.net/
+# creates the /etc/mail/popauth.db file for us. We have to use dbmnz
+# lookup type here.
+
+hostlist relay_from_hosts = 127.0.0.1 : net-dbmnz;/etc/mail/popauth.db
+primary_hostname = [[[SET THIS TO LOCAL HOST NAME]]]
+
+# LDAP settings
+
+# Set the following to your ldap server(s)
+ldap_default_servers = ldap::389
+BASEDN = [[[SET THIS TO YOUR BASE DN IN LDAP]]]
+
+acl_smtp_rcpt = acl_check_rcpt
+acl_smtp_data = acl_check_data
+
+exim_user = vmail
+exim_group = vmail
+trusted_users = vmail
+never_users = root
+host_lookup = *
+rfc1413_hosts = *
+rfc1413_query_timeout = 0s
+ignore_bounce_errors_after = 2d
+timeout_frozen_after = 7d
+bounce_return_body = false
+accept_8bitmime = true
+allow_mx_to_ip = true
+auto_thaw = 60m
+smtp_accept_max = 0
+smtp_load_reserve = 20
+delay_warning = 4h:8h:24h
+dns_again_means_nonexist = !+local_domains : !+relay_to_domains
+
+spamd_address = 127.0.0.1 783
+av_scanner = clamd:127.0.0.1 3310
+
+# Spool settings
+
+split_spool_directory = true
+check_spool_space = 100M
+check_spool_inodes = 1000
+
+# Logging - enable a bunch of extra useful stuff. Never know, could help
+# one day, and at least its better than qmail! Har har!
+
+log_selector = +delivery_size +received_sender +received_recipients \
+ +subject +sender_on_delivery
+
+# NOTE TO SELF: Lets use syslog and have all six mail servers log to a
+# central location so its easier to do statistics gathering and fault
+# analysis.
+
+# MACROS
+
+# Secret for all machines in the cluster. Change it to whatever you feel
+# is best.
+
+SECRET = Ni2opNyw2pNM3cmWn21nOSbwdq
+
+GET_ADDRESS_DATA = ${lookup ldap {\
+ ldap:///BASEDN??sub?(&(uid=${quote_ldap:$local_part}@${quote_ldap:$domain}))\
+ }\
+}
+
+GET_CATCHALL_DATA = ${lookup ldap {\
+ ldap:///BASEDN??sub?(&(uid=catchall@${quote_ldap:$domain}))\
+ }\
+}
+
+MSGCOOKIE = ${hmac{md5}{SECRET}{$body_linecount}}
+
+######################################################################
+# ROUTERS CONFIGURATION #
+# Specifies how addresses are handled #
+######################################################################
+
+begin routers
+
+dnslookup:
+ driver = dnslookup
+ domains = ! +local_domains
+ transport = remote_smtp
+ ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
+ no_more
+
+system_aliases:
+ driver = redirect
+ condition = ${if eq {{$primary_hostname}{$domain} {1}{0}} }
+ allow_fail
+ allow_defer
+ data = ${lookup{$local_part}lsearch{/etc/aliases}}
+ file_transport = address_file
+ pipe_transport = address_pipe
+
+# the forward router does the initial LDAP lookup. It then caches this in
+# $address_data for use by any of the other routers. Each router will fall
+# through if they then don't meet their condition.
+
+lookup:
+ driver = redirect
+ address_data = GET_ADDRESS_DATA
+ # data is intentionally left blank so that the router will decline
+ # we just want this router to do a lookup so the results are availble
+ # for the other routers.
+ data =
+
+# OK, this is where we start supporting crazy qmail-ldap stuff. First, we
+# check if the address has a deliveryMode of 'forwardonly'. forwardonly is
+# a misnomer, because its possible for and address to be a forward, a mailbox
+# and an autoreply. So, we make it do the forward, and check to see if it is
+# also a reply or localdelivery, if so we set unseen to yes to make Exim
+# copy the message and send it to the next router.
+
+forward:
+ driver = redirect
+ condition = ${if match {${extract{deliveryMode}{$address_data}}}{forwardonly} {1}{0}}
+ data = ${extract{mailForwardingAddress}{$address_data}}
+ unseen = ${if or {{match {${extract{deliveryMode}{$address_data}}}{reply}} \
+ {match {${extract{deliveryMode}{$address_data}}}{localdelivery}}} \
+ {yes}{no}}
+
+# Same deal, check if its a reply, if so we send it to the correct transport.
+# After, we see if it needs to go to localdelivery as well.
+
+reply:
+ driver = accept
+ condition = ${if match {${extract{deliveryMode}{$address_data}}}{reply} {1}{0}}
+ transport = auto_reply
+ unseen = ${if match {${extract{deliveryMode}{$address_data}}}{localdelivery} {yes}{no}}
+
+localdelivery:
+ driver = accept
+ condition = ${if match {${extract{deliveryMode}{$address_data}}}{localdelivery} {1}{0}}
+ transport = local_delivery
+
+# If we've reached this point, the account doesn't exist, so we need to
+# check to see if there is a catchall account, and if so do the usual for
+# it too. NOTE: we do not support auto-reply in a catch-all.
+#
+# This could, of course, be abused by someone assigning an auto-reply to
+# a forward_catchall.
+
+# NOTE TO SELF: See if reply router can be failed if an address comes from
+# a catchall.
+
+lookup_catchall:
+ driver = redirect
+ address_data = GET_CATCHALL_DATA
+ # data is intentionally left blank so that the router will decline
+ # just want this router to do a lookup.
+ data =
+ # could probably do a no_more = true based on the result of that LDAP
+ # lookup to skip the next few routers, but there is no point as they are
+ # not doing anything heavy so I'll just let them fall through and fail.
+
+# The catchall routers are exactly the same as the above routers, except
+# they make use of the GET_CATCHALL_DATA address_data to decide what to do
+# with the mail.
+
+forward_catchall:
+ driver = redirect
+ condition = ${if match {${extract{deliveryMode}{$address_data}}}{forwardonly} {1}{0}}
+ data = ${extract{mailForwardingAddress}{$address_data}}
+ unseen = ${if match {${extract{deliveryMode}{$address_data}}}{localdelivery} {yes}{no}}
+
+localdelivery_catchall:
+ driver = accept
+ condition = ${if match {${extract{deliveryMode}{$address_data}}}{localdelivery} {1}{0}}
+ transport = local_delivery
+
+######################################################################
+# TRANSPORTS CONFIGURATION #
+######################################################################
+
+begin transports
+
+remote_smtp:
+ driver = smtp
+
+# Deliver to the mailbox specified in the LDAP directory. We make sure
+# that quota is obeyed, and we try to send a messge to the user if it
+# gets to over 85%.
+
+local_delivery:
+ driver = appendfile
+ maildir_format
+ directory = ${extract{mailMessageStore}{$address_data}}/Maildir
+ create_directory
+ directory_mode = 0700
+ delivery_date_add
+ envelope_to_add
+ return_path_add
+ group = vmail
+ user = vmail
+ mode = 0600
+ quota = ${eval:${sg{${extract{1}{,}{${extract{mailQuota}{$address_data}}}}}{S}{}}/1024}K
+ maildir_use_size_file = true
+ quota_warn_threshold = 85%
+
+# We set this to iso-2022-jp because we're in japan. Set it to whatever.
+
+auto_reply:
+ driver = autoreply
+ subject = "[Auto-Reply] $header_subject"
+ headers = "Content-Type: text/plain; charset=iso-2022-jp"
+ to = "$sender_address"
+ text = ${extract{mailReplyText}{$address_data}}
+ from = $local_part@$domain
+
+
+######################################################################
+# ACL CONFIGURATION #
+# Specifies access control lists for incoming SMTP mail #
+######################################################################
+
+begin acl
+
+# You should probably set up exiscan-acl's mime check here to scan for viruses
+# and spam and reject at SMTP time. As I won't be doing that for a while, I've
+# left it as an exercise for the reader.
+
+acl_check_rcpt:
+ accept hosts = :
+ deny message = Restricted characters in address
+ domains = +local_domains
+ local_parts = ^[.] : ^.*[@%!/|]
+ deny message = Restricted characters in address
+ domains = !+local_domains
+ local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
+ accept local_parts = postmaster
+ domains = +local_domains
+ require verify = sender
+ accept domains = +local_domains
+ endpass
+ verify = recipient
+ accept domains = +relay_to_domains
+ endpass
+ verify = recipient
+ accept hosts = +relay_from_hosts
+ accept authenticated = *
+ deny message = relay not permitted
+
+acl_check_data:
+ require verify = header_syntax
+ message = This message has malformed headers.
+ deny message = This message contains malformed MIME ($demime_reason).
+ demime = *
+ condition = ${if >{$demime_errorlevel}{2}{1}{0}}
+ deny message = We do not accept ".$found_extension" attachments here as \
+ they are common file extensions for viruses. If you wish \
+ to send such an attachment, please zip it first.
+ demime = bat:btm:cmd:com:cpl:dll:exe:lnk:msi:pif:prf:reg:scr:vbs:url
+ accept
+
+begin retry
+
+# Address or Domain Error Retries
+# ----------------- ----- -------
+
+* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
+
+######################################################################
+# REWRITE CONFIGURATION #
+######################################################################
+
+# There are no rewriting specifications in this default configuration file.
+
+begin rewrite
+
+######################################################################
+# AUTHENTICATION CONFIGURATION #
+######################################################################
+
+# There are no authenticator specifications in this default configuration file.
+
+begin authenticators
+
+plain:
+ driver = plaintext
+ public_name = PLAIN
+ server_condition = ${if ldapauth {user="uid=${quote_ldap_dn:$2},BASEDN" \
+ pass=${quote:$3} ldap:///}{yes}{no}}
+ server_set_id = $2
+
+
+login:
+ driver = plaintext
+ public_name = LOGIN
+ server_prompts = Username:: : Password::
+ server_condition = ${if ldapauth {user="uid=${quote_ldap_dn:$1},BASEDN" \
+ pass=${quote:$2} ldap:///}{yes}{no}}
+ server_set_id = $1
+
+######################################################################
+# CONFIGURATION FOR local_scan() #
+######################################################################
+
+# begin local_scan
+
+# End of Exim configuration file
--- /dev/null
+From: Ephraim Silverberg <ephraim@cs.huji.ac.il>
+Date: Tue, 17 Feb 1998 12:55:55 +0200
+
+We're using Exim 1.82 and have written a message filter to intercept spam
+messages that RBL doesn't catch. Since we have met with reasonable success
+since installing (and refining) the filter -- 566 genuine spam messages
+intercepted during a time period where there were 67 RBL rejections -- I
+thought that the rest of the list may be interested in reviewing our filter
+as a starting point for their own system message filter.
+
+There are a number of caveats, however:
+
+1. The suspected spam is not automatically rejected as RBL hosts are, but
+ is saved to a folder that should be read/writable by the mail
+ administrators. The reason for this is that the filter catches also
+ some legitimate mail and these messages should be bounced to their
+ originally intended recipient(s) (ala X-Envelope-To:) and the filter
+ refined and/or the databases (described below) updated.
+
+2. My filter traps blank/non-existent To: lines as well as To: lines
+ contained in From: lines, but firsts exempts the following categories
+ from this check: mailing lists, local mail, mail originating in the
+ country (e.g. in our case *.il) and mail coming from autosupport servers.
+
+Beyond implicit checks, it uses four DBM databases: two that exempt the
+message from any spam (beyond RBL) checks (software servers and strange mailing
+lists need to be here) -- one based on $sender_address and the other on
+$header_to: lines -- and, conversely, two databases for known spammers that
+have valid mail headers that aren't caught by implicit checks. All entries
+in these databases are lowercase so that we don't need two lines for
+'friend@public.com' and 'Friend@Public.com'.
+
+The sample filter package is at ftp://ftp.cs.huji.ac.il/pub/exim/spam_filter/
+
+Comments and suggestions are welcome.
--- /dev/null
+Date: Tue, 03 Mar 1998 15:45:24 -0500
+From: Dan Birchall <djb@16straight.com>
+
+History:
+
+In early 1997, I wrote a little PERL program which refused
+mail from unknown addresses until they mailed me promising
+not to spam me. (This ran on my account as an end-user
+solution.) It was very effective, but didn't scale well.
+
+Recently, I'd been thinking of adding some similar
+functionality to my Exim filter file. Someone on another
+list mentioned that they were going to work on doing the
+same in their Sendmail config, and since I'd already
+thought through how to do it in Exim, and knew it'd be
+slightly easier than falling out of bed, I went ahead and
+did it. I mentioned having done it, and Piete bugged me
+to send it here too. :)
+
+Structure:
+
+There are two (optionally three) flat files involved, plus
+a system-wide filter file and one (optionally two) shell
+script(s).
+
+The first flat file contains a list of recipient e-mail
+addresses handled by my server, with parameters stating
+whether they do or do not wish to be afforded some degree
+of protection from spam through various filters. An
+excerpt:
+
+djb@16straight.com: spam=no
+djb@mule.16straight.com: spam=no untrusted=no
+djb@scream.org: spam=no relay=no untrusted=no
+
+Various filters in my filter file read this, and based
+on the values of certain parameters, will take certain
+measures to prevent spam from reaching an address. This
+particular filter works on the "untrusted" parameter.
+
+The second flat file contains a list of IP addresses for
+hosts that the server has been instructed to trust. (At
+this point, this is a system-wide list; if a host is
+trusted, it's trusted for all addresses. It should be
+fairly similar to arrange for some sort of user-specific
+list, but I haven't had the need.) An excerpt:
+
+206.214.98.16: good=yes
+205.180.57.68: good=yes
+204.249.49.75: good=yes
+
+The filter is as follows:
+
+if
+${lookup{$recipients:untrusted}lsearch{/usr/exim/lists/shield}{$value}}
+is "no"
+and
+${lookup{$sender_host_address:good}lsearch{/usr/exim/lists/good_hosts}{$value}}
+is ""
+then freeze endif
+
+Basically, if $recipients is found in the first file, with
+an "untrusted=no" parameter, and the sending host's IP
+address is *not* in the second file, or does not have a
+"good=yes" parameter next to it, the message is frozen.
+
+I then come along as root and run this script, with the
+Exim message ID as the only argument:
+
+echo -n `grep host_address /usr/exim/spool/input/$1-H |cut -f2 -d" "` >>
+/usr/exim/lists/good_hosts
+echo ": good=yes" >> /usr/exim/lists/good_hosts
+sendmail -M $1
+
+This adds the sending host's IP to the good_hosts file and
+forces delivery of the message.
+
+Options:
+
+The other optional file is a blacklist; the other optional
+script puts the sending host's IP in *that* file and deletes
+the message.
+
+This is just yet another fun little way to play with spam.
+(Looks like meat, tastes like play-doh... or is it the
+other way around?)
+
+Bugs:
+
+Yes, there are weaknesses. Specifically:
+
+* multi-address $recipients will probably get by this
+* scalability is always a concern
+* large ISP's that generate lots of mail _and_ spam...
+
+This is near the top of my filter file, though, and
+there are several other filters below it to catch any
+stuff it might miss.
--- /dev/null
+Date: Sat, 4 Apr 1998 07:23:39 +0200 (GMT+0200)
+From: "F. Jacot Guillarmod" <Jacot@ru.ac.za>
+
+Here's four checks installed in our system wide filter that knock out
+a lot of otherwise hard to detect rubbish - and would handle the above
+example. The most interesting one is the hotmail.com "validity check".
+
+# ===========================================================================
+# authenticated sender, but not from pegasus
+#-------------------------------------------
+elif "$h_comments" contains "authenticated sender" and
+ "$h_x-mailer" does not contain "pegasus" then
+
+ log "$tod_log $message_id SPAMAUTHS: sender=$sender_address \
+ subject=$header_subject: recipients_count=$recipients_count \
+ recipients=$recipients"
+ save /usr/local/lib/mail/spam
+
+# claims to be from hotmail.com
+#------------------------------
+elif "$h_from" contains "hotmail.com" and
+ "${if !def:header_x-originating-ip {nospam}}" is nospam then
+
+ log "$tod_log $message_id SPAMHOTMAIL: sender=$sender_address \
+ subject=$header_subject: recipients_count=$recipients_count \
+ recipients=$recipients"
+ save /usr/local/lib/mail/spam
+
+# claims to be from juno.com
+#------------------------------
+elif "$h_from" contains "juno.com" and
+ "${if def:header_x-mailer {juno} {spam}}" is spam then
+
+ log "$tod_log $message_id SPAMJUNO: sender=$sender_address \
+ subject=$header_subject: recipients_count=$recipients_count \
+ recipients=$recipients"
+ save /usr/local/lib/mail/spam
+
+# spam X-UIDL header found
+# ------------------------
+elif "${if def:header_x-uidl {spam}}" is spam then
+
+ log "$tod_log $message_id SPAM-X-UIDL: sender=$sender_address \
+ subject=$header_subject: recipients_count=$recipients_count \
+ recipients=$recipients"
+ save /usr/local/lib/mail/spam
+# ===========================================================================
+
+
+The following rule seems to work (but I don't use it):
+
+# either To: is contained in From: or there is no To: line
+# --------------------------------------------------------
+elif $h_from contains $h_to then
+
+ log "$tod_log $message_id SPAM-TOEQFRM: sender=$sender_address \
+ subject=$header_subject: recipients_count=$recipients_count \
+ recipients=$recipients"
+ save /usr/local/lib/mail/spam
+# --------------------------------------------------------
+
+
+
+Here's parts of my personal .forward file - I'm relying on the system wide exim
+configs to zap spam, and only do the old fashioned stuff to whatever gets
+through:
+
+#==========================================================================
+# Exim filter <<== do not edit or remove this line
+
+if error_message then finish endif
+
+logfile $home/eximfilter.log
+
+# Mail from support system
+if $header_subject contains "[Help #"
+then
+ save $home/Mail/in.support
+
+# Mail from squid mailing list to local newsgroup
+elif $header_subject contains "squid-users-digest"
+then
+ deliver "<ru-list-squid@quagga.ru.ac.za>"
+
+# Mail from exim-users mailing list to local newsgroup
+elif $return_path contains "exim-users-request"
+then
+ deliver "<ru-list-exim-users@quagga.ru.ac.za>"
+
+# Stuff to be thrown away
+if $header_subject contains "Warning From uucp"
+then
+ seen finish
+endif
+
+#==========================================================================
+
--- /dev/null
+Date: Tue, 23 Nov 1999 02:49:32 +0200
+From: Vadim Vygonets <vadik@cs.huji.ac.il>
+
+This is an Exim filter snippet to change locally-generated
+Message-Id: and Resent-Message-Id: headers to world-unique values.
+
+
+# Exim filter
+
+# Copyright (c) 1999
+# Hans Matzen <hans@tm.informatik.uni-frankfurt.de>,
+# Vadim Vygonets <vadik@vygo.net>. All rights reserved.
+
+#################################################################
+# Change locally-generated Message-Id: and Resent-Message-Id:
+# headers to world-unique values.
+
+# Notes:
+# Change every occurence of "home.dom" to your home domain.
+# Change every occurence of "uniqie.remote.dom" to some unique value.
+
+# Unique values, as Vadik explained in his message to exim-users,
+# can be chosen in different ways:
+
+### The ideal way is to choose "hostnames" in existing domains whose
+### admins you know, and you will be sure that no hostname ending
+### with ".nonexistant.friendly.dom" will ever appear on this planet,
+### not even on someone else's message IDs.
+
+### Another ideas include putting after your hostname things like:
+### .972.2.6412694.phone
+### .29.32.columbia.street.jerusalem.96583.israel.addr
+### .1122.3576.3847.1446.visa.01.2002.expiration.date.vadim.vygonets.name.credit.card
+
+# This snippet provides to schemes to do such rewriting. The
+# first scheme is to have mapping from local hostnames to unique
+# "Message-Id domains". The second scheme is to use one unique
+# "Message-Id domain", inserting the original "domain" into the
+# "local-part" of the new Message-Id header.
+
+# Precaution
+headers remove "X-Vygo-Net-Temporary-Message-Id"
+
+# Change Message-Id:
+if "${if def:h_Message-Id: {yes}}" is yes and
+ ${lc:${domain:$h_Message-Id:}} is "home.dom" or
+ ${lc:${domain:$h_Message-Id:}} ends ".home.dom" then
+# This is if you want to have a file mapping each hostname to a unique
+# Message-Id domain part, or, if it fails, preserves the original domain part:
+# headers add "X-Vygo-Net-Temporary-Message-Id: <${local_part:$h_Message-Id:}@${lookup{${domain:$h_Message-Id:}}lsearch{/var/exim/msgid-hosts}{$value}{${domain:$h_Message-Id:}}}>\n"
+# This rewrites Message-Id as <local_part.domain@unique.domain>:
+ headers add "X-Vygo-Net-Temporary-Message-Id: <${local_part:$h_Message-Id:}.${domain:$h_Message-Id:}@unique.remote.dom>\n"
+ headers remove "Message-Id"
+ headers add "Message-Id: $h_X-Vygo-Net-Temporary-Message-Id:"
+ headers remove "X-Vygo-Net-Temporary-Message-Id"
+endif
+
+# Change Resent-Message-Id:
+if "${if def:h_Resent-Message-Id: {yes}}" is yes and
+ ${lc:${domain:$h_Resent-Message-Id:}} is "home.dom" or
+ ${lc:${domain:$h_Resent-Message-Id:}} ends ".home.dom" then
+# This is if you want to have a file mapping each hostname to a unique
+# Message-Id domain part, or, if it fails, preserves the original domain part:
+# headers add "X-Vygo-Net-Temporary-Message-Id: <${local_part:$h_Resent-Message-Id:}@${lookup{${domain:$h_Resent-Message-Id:}}lsearch{/var/exim/msgid-hosts}{$value}{${domain:$h_Resent-Message-Id:}}}>\n"
+# This rewrites Message-Id as <local_part.domain@unique.domain>:
+ headers add "X-Vygo-Net-Temporary-Message-Id: <${local_part:$h_Resent-Message-Id:}.${domain:$h_Resent-Message-Id:}@unique.remote.dom>\n"
+ headers remove "Resent-Message-Id"
+ headers add "Resent-Message-Id: $h_X-Vygo-Net-Temporary-Message-Id:"
+ headers remove "X-Vygo-Net-Temporary-Message-Id"
+endif
+
--- /dev/null
+/*
+ * uvscan local_scan() function for Exim (requires at least Exim v4.14)
+ * known to work with VirusScan for Linux v4.16.0 (Scan engine v4.2.40)
+ * but should be OK with other platforms
+ *
+ * this file is free software (license=GNU GPLv2) and comes with no
+ * guarantees--if it breaks, you get to keep the pieces (maybe not the mail)!
+ *
+ * by (ie patches / flames to): mb/local_scan@dcs.qmul.ac.uk, 2003-05-02
+ * (original version on 2002-05-25)
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <string.h>
+#include "local_scan.h"
+
+/*
+ * remember to set LOCAL_SCAN_HAS_OPTIONS=yes in Local/Makefile
+ * otherwise you get stuck with the compile-time defaults
+ */
+
+static uschar *uvscan_binary = US"/usr/local/uvscan/uvscan";
+static uschar *data_directory = US"/usr/local/uvscan";
+
+optionlist local_scan_options[] = { /* alphabetical order */
+ { "data_directory", opt_stringptr, &data_directory },
+ { "uvscan_binary", opt_stringptr, &uvscan_binary }
+};
+
+int local_scan_options_count = sizeof(local_scan_options)/sizeof(optionlist);
+
+/* log headers in rejectlog or not? */
+
+//#define VIRUS_IN_MAIL LOCAL_SCAN_REJECT
+#define VIRUS_IN_MAIL LOCAL_SCAN_REJECT_NOLOGHDR
+
+/*
+ * buffer is used both for file copying and catching uvscan's output
+ * BUFSIZE = 1024 should always be fine
+ */
+
+#define BUFSIZE 1024
+
+/* some number which uvscan doesn't return */
+#define MAGIC 123
+
+/*
+ * some macros to make the main function more obvious
+ * NB bailing out might leave tempfiles hanging around
+ * (and open fds, but no need to be worried about that)
+ */
+
+#define BAIL(btext) { log_write(0, LOG_MAIN, "UVSCAN ERROR: "btext); \
+ *return_text = "local scanning problem: please try again later"; \
+ return LOCAL_SCAN_TEMPREJECT; }
+
+#define DEBUG(dtext) if ((debug_selector & D_local_scan) != 0) \
+ { debug_printf(dtext); sleep(1); }
+ /* sleep useful for running exim -d */
+
+#define RESULT(rtext) header_add(32, \
+ "X-uvscan-result: "rtext" (%s)\n", message_id);
+
+#define FREEZE(ftext) { header_add(32, \
+ "X-uvscan-warning: frozen for manual attention (%s)\n", message_id); \
+ RESULT(ftext); *return_text = ftext; return LOCAL_SCAN_ACCEPT_FREEZE; }
+
+/* OK, enough waffle. On with the show! */
+
+int local_scan(int fd, uschar **return_text)
+{
+ char tf[] = "/tmp/local_scan.XXXXXX"; /* should this be tunable? */
+ int tmpfd, bytesin, bytesout, pid, status, pipe_fd[2];
+ fd_set fds;
+ static uschar buffer[BUFSIZE];
+
+ DEBUG("entered uvscan local_scan() function");
+
+ /*
+ * I set majordomo to resend using -oMr lsmtp
+ * (and yes, I know majordomo isn't actually using SMTP..)
+ * no point in scanning these beasties twice
+ */
+
+ if(!strcmp(received_protocol, "lsmtp"))
+ return LOCAL_SCAN_ACCEPT;
+
+ /* create a file to copy the data into */
+
+ if ((tmpfd = mkstemp(tf)) == -1)
+ BAIL("mkstemp failed");
+
+ DEBUG("made tmp file");
+
+ /* copy said file BUFSIZE at a time */
+
+ while ((bytesin = read(fd, buffer, BUFSIZE)) > 0) {
+ bytesout = write(tmpfd, buffer, bytesin);
+ if (bytesout < 1)
+ BAIL("writing to tmp file");
+ }
+ if (bytesin < 0)
+ BAIL("reading from spool file");
+
+ close(tmpfd);
+
+ if(pipe(pipe_fd) == -1)
+ BAIL("making pipe");
+
+ /* fork and scan */
+
+ if((pid = fork()) == -1)
+ BAIL("couldn't fork");
+
+ if(pid == 0) {
+ close(1); /* close stdout */
+ if(dup2(pipe_fd[1],1) == -1) /* duplicate write as stdout */
+ BAIL("dup2 (stdout) failed");
+ if(fcntl(1,F_SETFD,0) == -1) /* fd to NOT close on exec() */
+ BAIL("fcntl (stdout) failed");
+
+ execl(uvscan_binary, uvscan_binary, "--mime", "--secure",
+ "-d", data_directory, tf, NULL);
+ DEBUG("execl failed");
+ _exit(MAGIC);
+ }
+
+ if(waitpid(pid, &status, 0) < 1)
+ BAIL("couldn't wait for child");
+
+ DEBUG("about to unlink");
+
+ if(unlink(tf) == -1)
+ FREEZE("couldn't unlink tmp file");
+
+ DEBUG("unlinked :)");
+
+ /*
+ * choose what to do based on the return code of uvscan
+ * RESULT() or FREEZE() according to personal taste
+ */
+
+ if(WIFEXITED(status) != 0)
+ switch(WEXITSTATUS(status)) {
+ case 0: RESULT("clean"); break;
+ case 2: RESULT("driver integrity check failed"); break;
+ case 6: FREEZE("general problem occurred"); break;
+ case 8: RESULT("could not find a driver"); break;
+ case 12: FREEZE("failed to clean file"); break;
+ case 13:
+ // RESULT("virus detected"); /* were we to accept */
+ DEBUG("about to read from uvscan process");
+ FD_ZERO(&fds);
+ FD_SET(pipe_fd[0], &fds);
+ if(select(pipe_fd[0]+1, &fds, NULL, NULL, NULL)) {
+ /* last NULL above means wait forever! */
+ DEBUG("select returned non-zero");
+ if((bytesin = read(pipe_fd[0], buffer,
+ BUFSIZE - 1)) > 0) {
+ buffer[bytesin] = (uschar)0;
+ *return_text = buffer + 22;
+ /* 22 was empirically found ;) */
+ return VIRUS_IN_MAIL;
+ } else
+ BAIL("reading from uvscan process");
+ }
+ break;
+ case 15: FREEZE("self-check failed"); break;
+ case 19: FREEZE("virus detected and cleaned"); break;
+ case MAGIC: RESULT("couldn't run uvscan"); break;
+ default:
+ RESULT("unknown error code");
+ header_add(32, "X-uvscan-status: %d\n",
+ WEXITSTATUS(status));
+ break;
+ }
+ else
+ BAIL("child exited abnormally");
+
+ return LOCAL_SCAN_ACCEPT;
+}
--- /dev/null
+This script patches an Exim binary in order to change the compiled-in
+configuration file name. See FAQ 0065 for a situation in which this might
+be a useful thing to do.
+
+============================================================
+#!/usr/local/bin/perl
+#
+# Patch the config file location in exim so as to avoid using
+# exim -C and thus having problems with vacation messages etc.
+#
+# Placed in the public domain.
+
+# This is the default in exim RPMS.
+my $oldconf = "/etc/exim/exim4.conf";
+
+die "Usage: $0 infile outfile configfile\n" unless (@ARGV == 3);
+my ($in, $out, $newconf) = @ARGV;
+
+# We mustn't make our string longer than the original!
+die "configfile location must be ".length($oldconf)." chars long or less\n"
+ if (length($newconf) > length($oldconf));
+
+# Get original details.
+my @stat = (stat($in));
+die "stat($in): $!\n" if (@stat == 0);
+
+# Get original binary.
+open(F, "<$in") || die "Can't read $in\n";
+read(F, $exim, $stat[7]) || die "Can't read $in\n";
+die "Didn't read full data\n" unless (length($exim) == $stat[7]);
+close(F);
+
+# Find the old config location.
+my $pos = 0;
+my @positions = ();
+while (($pos = index($exim, $oldconf."\0", $pos)) >= 0)
+{
+ print "Config file name found at byte offset $pos\n";
+ push(@positions, $pos);
+ $pos++;
+}
+
+die "Old config location ($oldconf) not found\n" if (@positions == 0);
+
+# We could be clever here and try to isolate the correct instance,
+# but for now I'm going to assume it's the only instance.
+die "Too many possible config locations found\n" if (@positions > 1);
+
+# Patch in the new config location
+substr($exim, $positions[0], length($newconf)+1) = $newconf."\0";
+
+# Write out the patched version.
+open(F, ">$out") || die "Can't write $out\n";
+print F $exim;
+close(F);
+
+# Set permissions on new copy to match old.
+chmod($stat[2] & 07777, $out);
+
+# Print the config file path.
+$out = "./".$out unless ($out =~ m#/#);
+print <<EOF;
+
+Trying to run '$out -bP configure_file'. If it has worked
+either it will be printed below or you will get a LOG: MAIN PANIC
+about it (if the config file doesn't already exist)
+
+EOF
+system($out, "-bP", "configure_file");
+============================================================
--- /dev/null
+From: John Jetmore <jetmore@cinergycom.com>
+Date: Wed, 24 Sep 2003 13:12:58 -0500 (CDT)
+
+I'm sure that everyone who's interested in something like this has already
+come up with their own way to do this, but here's my solution:
+
+When I moved from smail to exim I built a program that took individual
+config pieces stripped all the comments and built a config file. As a
+bonus, it also runs exim -C <testfile> -bV on the new file and reports any
+config errors before copying it over the old config. In addition to just
+being familiar in general w/ all the files being broken up according to
+their major categories, I also got the benfit of being able to have config
+pieces that were easily updatable (just replace the whole file and rebuild
+the configure file).
+
+The script has some site-specific stuff hard coded, but it's easily
+fixable. Essentially in my exim configd I have a directory called
+subconfigure, which can contain directories named \d\d.\w+. Mine
+currently contains:
+10.general/ 30.routers/ 50.retry/ 70.authenticators/
+20.acls/ 40.transports/ 60.rewrite/ 80.local_scan/
+
+Each of these directories can contain files in the form \d\d.\w+. For
+instance, my 30.routers contains:
+00.begin 80.l_user_delivery_normal _50.l_mx
+10.r_forcepaths _12.r_static_route_junk _60.l_psp
+15.r_stalemail _17.r_internal_route _72.l_aliases_list
+33.r_mailrtrd_router _20.r_conditionalforce _74.l_aliases_isp
+40.r_standard _31.r_mailrtrd_bypass_spam _76.l_aliases_mer
+70.l_aliases _39.r_smarthost _80.l_user_delivery_isp
+
+those files prefixed by "_" will not be used to build the live configure
+file. They are "turned off". This allows me to keep a general list of
+configure pieces that are easily updatable but not necessarily every rule
+is used on every machine. Not every file contains a single router - for
+instance 60.l_psp is our virtual hosting solution and contains 10 routers.
+They're just grouped by logical role.
+
+All of these sub pieces are built in to the configure file w/ a shell
+script called mkconfigure, inline below. Again, my assumption is that
+anyone who wants a system like this built it for themselves, but it
+would be kind of fun to flesh this script out to be more generic.
+Maybe post it and some samples on a webpage. Or no one responds to this
+and I shut up about it =).
+
+This system is way overkill for some people (for instance, my home machine
+uses a single configure file because I don't do that much special with
+it), but it's useful in a larger system role.
+
+--John
+
+mkconfigure:
+
+#!/bin/ksh
+
+# I have found that our custom set up of exim's configure file is overly
+# confusing. To help alleviate this, I have broken the file out into its
+# core pieces (general, tansports, directors, routers, retry, rewrite, and
+# authentication), and then each of those into logical sub-pieces (SIS,
+# for instance. This program is to take all of those sub pieces and put
+# them back together into the file that exim understands.
+
+# No one should every touch the 'configure' file from now on, one should
+# instead manipulate the files in the subconfigure directory and run this
+# program
+
+# jetmore 20011119
+
+EXIMD=$1
+CONFIGSUFF=$2
+
+if [ "X$EXIMD" == "X" ] ; then
+ EXIMD=/local/exim
+fi
+if [ ! -d "$EXIMD" ] ; then
+ echo "$EXIMD is not a directory" >&2
+ exit 1
+fi
+ETCD=$EXIMD/etc
+SUBCD=$ETCD/subconfigure$CONFIGSUFF
+CONFIGF=$ETCD/configure$CONFIGSUFF
+
+if [ ! -d $SUBCD ] ; then
+ echo "$SUBCD is not a directory" >&2
+ exit 1
+fi
+
+GREP=/bin/grep
+
+# initialize the temporary config file in case some trash got left around
+cat /dev/null > $CONFIGF.t
+
+# print the banner to the temp config file
+echo >> $CONFIGF.t
+echo "#########################################################" >> $CONFIGF.t
+echo "# DO NOT DIRECTLY MANIPULATE THIS FILE " >> $CONFIGF.t
+echo "# " >> $CONFIGF.t
+echo "# if you need to make configuration change, do so in " >> $CONFIGF.t
+echo "# $SUBCD and run the mkconfigure" >> $CONFIGF.t
+echo "# command. Changes made to this file will be lost " >> $CONFIGF.t
+echo "# " >> $CONFIGF.t
+echo "# See jetmore w/ questions " >> $CONFIGF.t
+echo "#########################################################" >> $CONFIGF.t
+echo >> $CONFIGF.t
+
+# get the major categories
+for CAT in $SUBCD/[0-9]*
+do
+ # print which category we're in
+ echo >> $CONFIGF.t
+ echo "## major category $CAT" >> $CONFIGF.t
+ echo >> $CONFIGF.t
+
+ # get the subcategories
+ for SUBCAT in $CAT/[0-9]*
+ do
+ # print which sub category we're in
+ echo "## sub category $SUBCAT" >> $CONFIGF.t
+ echo >> $CONFIGF.t
+
+ # place the contents of any non-comment line into the configure file
+ $GREP -v "^ *#" $SUBCAT >> $CONFIGF.t
+ echo >> $CONFIGF.t
+ done
+done
+
+# check and make sure there aren't any typos in the new config file
+$EXIMD/bin/exim -C $CONFIGF.t -bV > $CONFIGF.test 2>&1
+if [ "$?" -eq "1" ] ; then
+ #/bin/rm $CONFIGF.t
+ echo
+ echo "There is a problem with the configure file. "
+ echo "moving paniclog to paniclog.mkfail"
+ echo "$CONFIGF.test has details:"
+ echo
+ echo #####################################################################
+ cat $CONFIGF.test
+ echo #####################################################################
+ echo
+ echo "$CONFIGF not changed!"
+ /bin/mv -f /log/exim/paniclog /log/exim/paniclog.mkfail
+ exit 1
+fi
+/bin/rm $CONFIGF.test
+
+/bin/mv $CONFIGF.t $CONFIGF
+echo "$CONFIGF updated successfully."
+echo "Don't forget to HUP the mail daemon"
+exit 0
+