+++ /dev/null
-Postfix CA-2003-12 Preliminary REJECT pattern
-=============================================
-
-CERT advisory CA-2003-12 concerns a Sendmail buffer overflow exploit
-that can happen with message headers containing the 0xff byte value.
-
-At this time, 8-bit text in message headers violates Internet email
-standards. A properly implemented mail client encodes 8-bit message
-header text as 7-bit text.
-
-According to documentation from Sendmail, some exploits can be
-stopped by configuring a gateway MTA to remove 0xff bytes from
-message headers. This provides partial protection, because downstream
-Sendmail systems may still use untrusted information from the DNS
-while (re)writing message headers.
-
-For the same reason, configuring a gateway MTA to limit the length
-of message headers would be a partial solution for downstream
-Sendmail systems.
-
-Using Postfix to block 0xff in message headers
-==============================================
-
-One quick way to stop 0xff characters in message headers is to
-specify a header_checks REGEXP pattern and action. Specifying
-numerical character codes in REGEXP patterns turns out to be painful.
-Here is a somewhat clumsy method to specify a 0xff matching REGEXP:
-
-perl -e 'print "/\xff/ REJECT Possible CA-2003-12 exploit\n"' > /etc/postfix/block255
-
-/etc/postfix/main.cf:
- header_checks = regexp:/etc/postfix/block255 ...other_files...
-
-The pattern was tested with FreeBSD 4, Redhat 8, Solaris 9, all on Intel.
-
-Raw binary data such as 0xff may cause trouble with text editors.
-This is why the above example uses a separate file for blocking
-the 0xff character instead of appending the pattern to an existing
-header_checks file.
-
-The equivalent PCRE pattern may be easier to specify, but PCRE
-support is not universally available with Postfix.
Safety: add warnings to postmap and postalias when table
lookup results in an empty string.
+20040110
+
+ Example: script to run qmail-local from Postfix by Ron
+ Bickers.
+
+ Change: queue minfree limit is now 1.5 * message size limit.
+ Files: smtpd/smtpd_check.c.
+
+20040115
+
+ Bugfix: allow delivery concurrency to increase even while
+ mail is deferred, as long as the delivery agent does not
+ report really serious trouble with the destination. Files:
+ *qmgr/qmgr_deliver.c.
+
+ Bugfix: report lost connection and timeout as a serious
+ destination problem. Files: [sl]mtp/[sl]mtp_trouble.c.
+
+ Cleanup: in postfix-files, symbolic links and hard links
+ are now first-class entries with explicit mention of
+ source and destination pathnames. Files: postfix-install,
+ conf/postfix-files, conf/post-install.
+
+20040116
+
+ Cleanup: sendmail -v caused one mail delivery reports upon
+ every delivery attempt, not just the first one. The fix is
+ to "kill" a queue file record after the first delivery
+ attempt. Files: *qmgr/qmgr_active.c, *qmgr/qmgr_message.c,
+ global/rec_type.c.
+
Open problems:
Low: in the SMTP client, pass the session, request and
SHELL = /bin/sh
WARN = -Wmissing-prototypes -Wformat
-OPTS = 'CC=$(CC)'
+OPTS = 'CC=$(CC) -DSNAPSHOT'
DIRS = src/util src/global src/dns src/master src/postfix src/smtpstone \
src/sendmail src/error src/pickup src/cleanup src/smtpd src/local \
src/lmtp src/trivial-rewrite src/qmgr src/oqmgr src/smtp src/bounce \
makefiles Makefiles:
set -e; for i in $(DIRS); do \
(set -e; echo "[$$i]"; cd $$i; rm -f Makefile; \
- $(MAKE) -f Makefile.in Makefile MAKELEVEL=) || exit 1; \
+ $(MAKE) $(OPTS) -f Makefile.in Makefile MAKELEVEL=) || exit 1; \
done;
rm -f Makefile; (set -e; $(SHELL) makedefs && cat Makefile.in) >Makefile
(echo "# Do not edit -- this file documents how Postfix was built for your machine."; $(SHELL) makedefs) >makedefs.tmp
--- /dev/null
+SHELL = /bin/sh
+WARN = -Wmissing-prototypes -Wformat
+OPTS = 'CC=$(CC) -DSNAPSHOT'
+DIRS = src/util src/global src/dns src/master src/postfix src/smtpstone \
+ src/sendmail src/error src/pickup src/cleanup src/smtpd src/local \
+ src/lmtp src/trivial-rewrite src/qmgr src/oqmgr src/smtp src/bounce \
+ src/pipe src/showq src/postalias src/postcat src/postconf src/postdrop \
+ src/postkick src/postlock src/postlog src/postmap src/postqueue \
+ src/postsuper src/qmqpd src/spawn src/flush src/verify \
+ src/virtual src/proxymap src/anvil
+MANDIRS = proto man html
+
+default: update
+
+makefiles Makefiles:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; rm -f Makefile; \
+ $(MAKE) $(OPTS) -f Makefile.in Makefile MAKELEVEL=) || exit 1; \
+ done;
+ rm -f Makefile; (set -e; $(SHELL) makedefs && cat Makefile.in) >Makefile
+ (echo "# Do not edit -- this file documents how Postfix was built for your machine."; $(SHELL) makedefs) >makedefs.tmp
+ set +e; if cmp makedefs.tmp conf/makedefs.out; then rm makedefs.tmp; \
+ else mv makedefs.tmp conf/makedefs.out; fi >/dev/null 2>/dev/null
+
+update printfck tests:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) $(OPTS) $@ MAKELEVEL=) || exit 1; \
+ done
+
+manpages:
+ set -e; for i in $(MANDIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) -f Makefile.in $(OPTS) MAKELEVEL=) || exit 1; \
+ done
+
+printfck: update
+
+install: update
+ $(SHELL) postfix-install
+
+upgrade: update
+ $(SHELL) postfix-install -non-interactive
+
+depend clean:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) $@) || exit 1; \
+ done
+
+depend_update:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) depend && $(MAKE) $(OPTS) update) \
+ || exit 1; \
+ done
+
+tidy: clean
+ rm -f Makefile */Makefile src/*/Makefile
+ cp Makefile.init Makefile
+ rm -f bin/[!CRS]* lib/[!CRS]* include/[!CRS]* libexec/[!CRS]* \
+ junk */junk */*/junk \
+ *core */*core */*/*core \
+ .nfs* */.nfs* */*/.nfs* \
+ .pure */.pure */*/.pure \
+ *.out */*.out */*/*.out \
+ *.tmp */*.tmp */*/*.tmp \
+ *.a */*.a */*/*.a \
+ *~ */*~ */*/*~ \
+ *- */*- */*/*- \
+ *.orig */*.orig */*/*.orig \
+ *.bak */*.bak */*/*.bak \
+ make.err */make.err */*/make.err \
+ *.gmon */*.gmon */*/*.gmon \
+ conf/main.cf.default
+ find . -type s -print | xargs rm -f
+ find . -type d -print | xargs chmod 755
+ find . -type f -print | xargs chmod a+r
--- /dev/null
+SHELL = /bin/sh
+WARN = -Wmissing-prototypes -Wformat
+OPTS = 'CC=$(CC)'
+DIRS = src/util src/global src/dns src/master src/postfix src/smtpstone \
+ src/sendmail src/error src/pickup src/cleanup src/smtpd src/local \
+ src/lmtp src/trivial-rewrite src/qmgr src/oqmgr src/smtp src/bounce \
+ src/pipe src/showq src/postalias src/postcat src/postconf src/postdrop \
+ src/postkick src/postlock src/postlog src/postmap src/postqueue \
+ src/postsuper src/qmqpd src/spawn src/flush src/verify \
+ src/virtual src/proxymap src/anvil
+MANDIRS = proto man html
+
+default: update
+
+makefiles Makefiles:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; rm -f Makefile; \
+ $(MAKE) $(OPTS) -f Makefile.in Makefile MAKELEVEL=) || exit 1; \
+ done;
+ rm -f Makefile; (set -e; $(SHELL) makedefs && cat Makefile.in) >Makefile
+ (echo "# Do not edit -- this file documents how Postfix was built for your machine."; $(SHELL) makedefs) >makedefs.tmp
+ set +e; if cmp makedefs.tmp conf/makedefs.out; then rm makedefs.tmp; \
+ else mv makedefs.tmp conf/makedefs.out; fi >/dev/null 2>/dev/null
+
+update printfck tests:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) $(OPTS) $@ MAKELEVEL=) || exit 1; \
+ done
+
+manpages:
+ set -e; for i in $(MANDIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) -f Makefile.in $(OPTS) MAKELEVEL=) || exit 1; \
+ done
+
+printfck: update
+
+install: update
+ $(SHELL) postfix-install
+
+upgrade: update
+ $(SHELL) postfix-install -non-interactive
+
+depend clean:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) $@) || exit 1; \
+ done
+
+depend_update:
+ set -e; for i in $(DIRS); do \
+ (set -e; echo "[$$i]"; cd $$i; $(MAKE) depend && $(MAKE) $(OPTS) update) \
+ || exit 1; \
+ done
+
+tidy: clean
+ rm -f Makefile */Makefile src/*/Makefile
+ cp Makefile.init Makefile
+ rm -f bin/[!CRS]* lib/[!CRS]* include/[!CRS]* libexec/[!CRS]* \
+ junk */junk */*/junk \
+ *core */*core */*/*core \
+ .nfs* */.nfs* */*/.nfs* \
+ .pure */.pure */*/.pure \
+ *.out */*.out */*/*.out \
+ *.tmp */*.tmp */*/*.tmp \
+ *.a */*.a */*/*.a \
+ *~ */*~ */*/*~ \
+ *- */*- */*/*- \
+ *.orig */*.orig */*/*.orig \
+ *.bak */*.bak */*/*.bak \
+ make.err */make.err */*/make.err \
+ *.gmon */*.gmon */*/*.gmon \
+ conf/main.cf.default
+ find . -type s -print | xargs rm -f
+ find . -type d -print | xargs chmod 755
+ find . -type f -print | xargs chmod a+r
syslog daemon, or by running some daemon processes under control
of an interactive debugger.
-2 - Verbose logging for specific SMTP connections
+The text assumes that the Postfix main.cf and master.cf configuration
+files are stored in directory /etc/postfix. You can use the command
+"postconf config_directory" to find out the actual location of this
+directory on your machine.
+
+2 - Try turning off chroot operation in master.cf
+=================================================
+
+A common mistake is to turn on chroot operation in the master.cf
+file without going through all the necessary steps to set up a
+chroot environment. This causes Postfix daemon processes to fail
+due to all kinds of missing files.
+
+Inspect master.cf for any chrooted processes, save a copy of the
+master.cf file, and edit the entries that have chroot operation
+turned on. After executing the commands "postfix stop" and "postfix
+start", see if the problem has gone away.
+
+If turning off chrooted operation made the problem go away, then
+congratulations. Leaving Postfix running in this way is adequate
+for most sites. If you prefer chrooted operation, see the Postfix
+INSTALL file for information about how to prepare Postfix for
+chrooted operation.
+
+3 - Look for obvious signs of trouble
+=====================================
+
+Postfix logs all failed and successful deliveries to a logfile.
+The file is usually called /var/log/maillog or /var/log/mail; the
+exact pathname is defined in the syslog.conf file.
+
+First look for errors that prevent Postfix from working at all:
+
+ % egrep '(warning|error|fatal|panic):' /some/log/file | more
+
+Note: the most important message is near the BEGINNING of the output.
+Error messages that come later are less useful.
+
+"PANIC" messages indicate a problem in the software itself that
+only a programmer can fix. Postfix cannot proceed until this is
+fixed.
+
+"FATAL" messages are the result of mssing files, incorrect permissions,
+incorrect configuration file settings. Postfix cannot proceed until
+this is fixed.
+
+"ERROR" messages report a fatal or non-fatal error condition.
+
+"WARNING" messages indicate non-fatal errors. These are problems
+that you may not be able to fix (such as a broken DNS server
+elsewhere on the network) but may also indicate local configuration
+errors that could become a problem later.
+
+4 - Verbose logging for specific SMTP connections
=================================================
In /etc/postfix/main.cf, list the remote site name or address in
You can specify one or more hosts, domains, addresses or net/masks.
-2b - Record the SMTP connection with a sniffer
-==============================================
+5 - Record the SMTP connection with a sniffer
+=============================================
This example uses tcpdump. In order to record a conversation you
need to specify a large enough buffer or else you will miss some
tcpdump -w /file/name -s 2000 host hostname and port 25
Run this for a while, stop with Ctrl-C when done. To view the data
-use a binary viewer, or use my tcpdumpx utility that is available
-from ftp://ftp.porcupine.org/pub/debugging.
+use a binary viewer, or ethereal, or use my tcpdumpx utility that
+is available from ftp://ftp.porcupine.org/pub/debugging.
-3 - Making Postfix daemon programs more verbose
+6 - Making Postfix daemon programs more verbose
===============================================
Append one or more -v options to selected daemon definitions in
/etc/postfix/master.cf and type "postfix reload". This will cause
a lot of activity to be logged to the syslog daemon.
-4 - Manually tracing a Postfix daemon process
+7 - Manually tracing a Postfix daemon process
=============================================
Some systems allow you to inspect a running process with a system
can get without running an interactive debugger program, as described
in a later section.
-5 - Automatically tracing a Postfix daemon process
+8 - Automatically tracing a Postfix daemon process
==================================================
Postfix can attach a call tracer whenever a daemon process starts.
Type "postfix reload" and watch the logfile.
-6 - Running daemon programs under a debugger
+9 - Running daemon programs under a debugger
============================================
Append a -D option to the suspect command in /etc/postfix/master.cf,
xxgdb) or a file is created (if using gdb in non-interactive
mode).
-7 - Unreasonable behavior
-=========================
+10 - Unreasonable behavior
+==========================
Sometimes the behavior exhibit by Postfix just does not match the
source code. Why can a program deviate from the instructions given
it is queued.
An external content filter receives unfiltered mail from Postfix
-and does one of the following:
+(as described further below) and does one of the following:
1 - Re-inject the mail back into Postfix, perhaps after changing
content.
3 - Send the mail somewhere else.
This document describes two approaches to content filtering: simple
-and advanced. Both filter all the mail by default.
+and advanced. Both approaches filter all the mail by default.
-At the end are examples that show how to filter only mail from
-users, how to use different filters for different domains that you
-provide MX service for, and how to set up selective filtering on
-the basis of message envelope and/or header/body patterns.
+At the end are examples that show 1) how to filter only mail from
+remote users only, 2) how to use different filters for different
+domains that you provide MX service for, and 3) how to set up
+selective filtering on the basis of message envelope and/or
+header/body patterns.
Simple content filtering example
================================
-The first example is simple to set up. It uses a shell script that
-receives unfiltered mail from the Postfix pipe delivery agent, and
-that feeds filtered mail back into the Postfix sendmail command.
+The first example is simple to set up. A shell script receives
+unfiltered mail from the Postfix pipe delivery agent, and feeds
+filtered mail back into the Postfix sendmail command.
-Only mail arriving via SMTP will be content filtered.
+This means that mail submitted via the Postfix sendmail command
+cannot be content filtered.
..................................
: Postfix :
| |
+-Postfix sendmail<----filter script<--+
-Mail is filtered by a /some/where/filter program. This can be a
-simple shell script like this:
+In this example, mail is filtered by a /some/where/filter program.
+This can be a simple shell script like this:
#!/bin/sh
content through a third-party content filter program.
- If the mail cannot be captured to file, mail delivery is deferred
- by terminating with exit status 75 (EX_TEMPFAIL). Postfix will
- try again after some delay.
+ by terminating with exit status 75 (EX_TEMPFAIL). Postfix places
+ the message in the deferred mail queue and tries again later.
- If the content filter program finds a problem, the mail is bounced
by terminating with exit status 69 (EX_UNAVAILABLE). Postfix
1 - Create a dedicated local user account called "filter". This
user handles all potentially dangerous mail content - that is
why it should be a separate account. Do not use "nobody", and
- most certainly do not use "root" or "postfix". The user will
- never log in, and can be given a "*" password and non-existent
- shell and home directory.
+ most certainly do not use "root" or "postfix". The "filter"
+ user will never log in, and can be given a "*" password and
+ non-existent shell and home directory.
2 - Create a directory /var/spool/filter that is accessible only
to the "filter" user. This is where the content filtering script
3 - Define the content filter in the Postfix master file:
/etc/postfix/master.cf:
- filter unix - n n - - pipe
+ # =============================================================
+ # service type private unpriv chroot wakeup maxproc command
+ # (yes) (yes) (yes) (never) (100)
+ # =============================================================
+ filter unix - n n - 10 pipe
flags=Rq user=filter argv=/somewhere/filter -f ${sender} -- ${recipient}
+Instead of a limit of 10 concurrent processes, use whatever process
+limit is feasible for your machine. Content inspection software
+can gobble up a lot of system resources, so you don't want to have
+too much of it running at the same time.
+
To turn on content filtering for mail arriving via SMTP only, append
"-o content_filter=filter:dummy" to the master.cf entry that defines
the Postfix SMTP server:
/etc/postfix/master.cf:
- smtp inet ...stuff... smtpd
+ # =============================================================
+ # service type private unpriv chroot wakeup maxproc command
+ # (yes) (yes) (yes) (never) (100)
+ # =============================================================
+ smtp inet ...other stuff here, do not change... smtpd
-o content_filter=filter:dummy
The content_filter configuration parameter accepts the same syntax
Advanced content filtering example
===================================
-The second example is more complex, but can give much better
-performance, and is less likely to bounce mail when the machine
-runs into a resource problem. This approach uses content filtering
-software that can receive and deliver mail via SMTP.
-
-Some Anti-virus software is built to receive and deliver mail via
-SMTP and is ready to use as an external content filter.
+The second example is more complex, but can give better performance,
+and is less likely to bounce mail when the machine runs into some
+resource problem. This approach requires content filtering software
+that can receive and deliver mail via SMTP.
For non-SMTP capable content filtering software, Bennett Todd's
SMTP proxy implements a nice PERL/SMTP content filtering framework.
The example given here filters all mail, including mail that arrives
via SMTP and mail that is locally submitted via the Postfix sendmail
-command.
+command. See examples near the end of this document for how to
+exclude local users from filtering.
You can expect to lose about a factor of two in Postfix performance
-for transit mail that arrives and leaves via SMTP, provided that
-the content filter creates no temporary files. Each temporary file
-created by the content filter adds another factor to the performance
-loss.
+for mail that arrives and leaves via SMTP, provided that the content
+filter creates no temporary files. Each temporary file created by
+the content filter adds another factor to the performance loss.
-We will set up a content filtering program that receives SMTP mail
-via localhost port 10025, and that submits SMTP mail back into
-Postfix via localhost port 10026.
+In the text that follows we will set up a content filtering program
+that receives SMTP mail via localhost port 10025, and that submits
+SMTP mail back into Postfix via localhost port 10026.
..................................
: Postfix :
content_filter = scan:localhost:10025
receive_override_options = no_address_mappings
-The first line causes Postfix to add one extra content filtering
-record to each incoming mail message, with content scan:localhost:10025.
-The content filtering records are added by the smtpd, pickup and
-qmqpd servers.
+- The "content_filter" line causes Postfix to add one content
+ filtering record to each incoming mail message, with content
+ scan:localhost:10025. The content filtering records are added
+ by the smtpd, pickup and qmqpd servers.
-The second line disables address mapping before the content filter,
-so that the content filter sees the original mail addresses instead
-of the result of virtual alias expansion, canonical mapping, address
-masquerading, etc.
+- The "receive_override_options" line disables address manipulation
+ before the content filter, so that the content filter sees the
+ original mail addresses instead of the result of virtual alias
+ expansion, canonical mapping, automatic bcc, address masquerading,
+ etc.
-Content filtering information is stored in queue files; this is
-how Postfix keeps track of what mail needs filtering. When a queue
+To turn off content filtering, delete or comment out the two above
+main.cf lines. All the changes made in the text below have no effect
+when content filtering is turned off.
+
+Content filter information is stored in queue files; this is how
+Postfix keeps track of what mail needs filtering. When a queue
file contains content filter information, the queue manager will
deliver the mail to the specified content filter regardless of its
final destination.
# service type private unpriv chroot wakeup maxproc command
# (yes) (yes) (yes) (never) (100)
# =============================================================
- scan unix - - n - 10 smtp
+ scan unix - - n - 10 smtp
-o smtp_send_xforward_command=yes
-Instead of a limit of 10 concurrent processes, use whatever process
-limit is feasible for your machine. Content inspection software
-can gobble up a lot of system resources, so you don't want to have
-too much of it running at the same time.
+- Instead of a limit of 10 concurrent processes, use whatever
+ process limit is feasible for your machine. Content inspection
+ software can gobble up a lot of system resources, so you don't
+ want to have too much of it running at the same time.
-With "-o smtp_send_xforward_command=yes", the scan transport will
-try to forward the original client name and IP address to the
-after-filter smtpd so that filtered mail is logged with the real
-client name IP address. See sample-smtp.cf and smtp(8).
+- With "-o smtp_send_xforward_command=yes", the scan transport will
+ try to forward the original client name and IP address to the
+ after-filter smtpd process, so that filtered mail is logged with
+ the real client name IP address. See sample-smtp.cf and smtp(8).
The content filter can be set up with the Postfix spawn service,
which is the Postfix equivalent of inetd. For example, to instantiate
up to 10 content filtering processes on demand:
-/etc/postfix/master.cf:
- # ===================================================================
- # service type private unpriv chroot wakeup maxproc command
- # (yes) (yes) (yes) (never) (100)
- # ===================================================================
- localhost:10025 inet n n n - 10 spawn
- user=filter argv=/some/where/filter localhost 10026
-
-"filter" is a dedicated local user account. The user will never
-log in, and can be given a "*" password and non-existent shell and
-home directory. This user handles all potentially dangerous mail
-content - that is why it should be a separate account.
-
-In the above example, Postfix listens on port localhost:10025. If
-you want to have your filter listening on port localhost:10025
-instead of Postfix, then you must run your filter as a stand-alone
-program.
-
-The example here assumes that the /some/where/filter command is a
-PERL script. PERL has modules that make talking SMTP easy. The
-command-line specifies that mail should be sent back into Postfix
-via localhost port 10026.
+ /etc/postfix/master.cf:
+ # ===================================================================
+ # service type private unpriv chroot wakeup maxproc command
+ # (yes) (yes) (yes) (never) (100)
+ # ===================================================================
+ localhost:10025 inet n n n - 10 spawn
+ user=filter argv=/some/where/filter localhost 10026
+
+- "filter" is a dedicated local user account. The user will never
+ log in, and can be given a "*" password and non-existent shell
+ and home directory. This user handles all potentially dangerous
+ mail content - that is why it should be a separate account.
+
+- In the above example, Postfix listens on port localhost:10025.
+ If you want to have your filter listening on port localhost:10025
+ instead of Postfix, then you must run your filter as a stand-alone
+ program, and not use the Postfix spawn service.
The simplest content filter just copies SMTP commands and data
between its inputs and outputs. If it has a problem, all it has to
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-Note: do not use spaces around the "=" or "," characters.
+- Note: do not use spaces around the "=" or "," characters.
-This SMTP server has the same process limit as the "filter" master.cf
-entry.
+- Note: the SMTP server must not have a smaller same process limit
+ than the "filter" master.cf entry.
-The "-o content_filter=" overrides main.cf and requests no content
-filtering for incoming mail. This is required or else mail will
-stay in the content filtering loop.
+- The "-o content_filter=" overrides main.cf and requests no content
+ filtering for incoming mail. This is required or else mail will
+ stay in the content filtering loop.
-The "-o receive_override_options" overrides main.cf. It is
-complementary to the options that are specified in main.cf:
+- The "-o receive_override_options" overrides main.cf. It is
+ complementary to the options that are specified in main.cf:
-- Disable attempts to find out if a recipient is unknown, and
- disable header/body checks. This work was already done before
- the content filter and repeating it would be wasteful.
+ - Disable attempts to find out if a recipient is unknown, and
+ disable header/body checks. This work was already done before
+ the content filter and repeating it would be wasteful.
-- Enable virtual alias expansion, canonical mappings, address
- masquerading, and other address mappings.
+ - Enable virtual alias expansion, canonical mappings, address
+ masquerading, and other address mappings.
-These receive override options are either implemented by the SMTP
-server itself, or they are passed on to the cleanup server.
+ These receive override options are either implemented by the SMTP
+ server itself, or they are passed on to the cleanup server.
-The "-o smtpd_xxx_restrictions" and "-o mynetworks=127.0.0.0/8"
-override main.cf and turn off UCE controls that would only waste
-time here.
+- The "-o smtpd_xxx_restrictions" and "-o mynetworks=127.0.0.0/8"
+ override main.cf turn off junk mail controls that would only
+ waste time here.
+
+- With "-o smtpd_authorized_xforward_hosts=mynetworks=127.0.0.0/8",
+ the scan transport will try to forward the original client name
+ and IP address to the after-filter smtpd process, so that filtered
+ mail is logged with the real client name IP address. See
+ sample-smtpd.cf and smtpd(8).
Filtering mail from outside users only
======================================
-The easiest approach is to configure ONE Postfix instance with TWO
-SMTP server addresses in master.cf:
+The easiest approach is to configure ONE Postfix instance with
+multiple SMTP server IP addresses in master.cf:
-- One SMTP server address for inside users only that never invokes
- content filtering.
+- Two SMTP server IP addresses for inside users only that never
+ invoke content filtering.
- One SMTP server address for outside users that always invokes
content filtering.
-o receive_override_options=no_address_mappings
After this, you can follow the same procedure as outlined in the
-"advanced" content filtering example above, except that you do not
-need to specify "content_filter" or "receive_override_options" in
-the main.cf file.
+"advanced" or "simple" content filtering examples above, except
+that you do not need to specify "content_filter" settings in the
+main.cf file.
Getting really nasty
====================
The above filtering configurations are static. Mail that follows
a given path is either always filtered or it is never filtered. As
of Postfix 2.0 you can also turn on content filtering on the fly.
-The Postfix UCE features allow you to specify a filtering action
-on the fly:
FILTER foo:bar
--- /dev/null
+Purpose of this document
+========================
+
+This document gives an overview of how to use Postfix for hosting
+multiple Internet domains, both for final delivery on the machine
+itself and for the purpose of forwarding to destinations elsewhere.
+
+It not only describes delivery mechanisms that are already built
+into Postfix, but also gives pointers for using non-Postfix mail
+delivery software.
+
+The following topics are covered:
+
+- Preliminaries
+ - Local files versus databases
+ - Canonical versus hosted domains
+- As simple as can be: shared domains, UNIX system accounts
+- Postfix virtual alias domains: separate domains, UNIX system accounts
+- Postfix virtual mailbox domains: separate domains, non-UNIX accounts
+- Non-Postfix mailbox store: separate domains, non-UNIX accounts
+- Mail forwarding domains
+- Aliases, mailing lists, etc.
+
+Preliminaries: local files versus databases
+===========================================
+
+The examples in this text use table lookups from local files.
+These are easy to debug with the postmap "-q" command option.
+
+Example: postmap -q info@example.com hash:/etc/postfix/virtual
+
+See LDAP_README, MYSQL_README and PGSQL_README for how to replace
+local files by databases. The reader is strongly advised to make
+the system work with local files before migrating to database files,
+and to use the postmap "-q" command option to verify that database
+lookups produce the exact same results as local file lookup.
+
+Example: postmap -q info@example.com ldap:/etc/postfix/virtual.cf
+
+Preliminaries: canonical versus hosted domains
+==============================================
+
+Most Postfix systems do final email delivery for only a few domain
+names. These include the names of the machine that Postfix runs
+on, and sometimes include their parent domain. The remainder of
+this document will refer to these domains as the canonical domains.
+
+Besides the canonical domains, Postfix can be configured to do
+final delivery for any number of additional domains. These domains
+are called hosted, because they are not directly associated with
+the name of the machine itself.
+
+As simple as can be: shared domains, UNIX system accounts
+=========================================================
+
+The simplest method to host an additional domain is to add the
+domain name to the domains listed in the Postfix mydestination
+configuration parameter, and to add the user names to the UNIX
+password file.
+
+This approach makes no distinction between canonical and hosted
+domains. Each username can receive mail in every domain.
+
+In the examples we will use "example.com" as the domain that is
+being hosted on the local Postfix machine.
+
+/etc/postfix/main.cf:
+ mydestination = $myhostname localhost.$mydomain ... example.com
+
+The downside of this approach is a total lack of separation: mail
+for info@my.host.name is delivered to the same UNIX system account
+as mail for info@example.com.
+
+Another downside of listing all users in the UNIX password file is
+that administration of large numbers of users becomes inconvenient.
+
+Postfix virtual ALIAS domains: separate domains, UNIX system accounts
+=====================================================================
+
+The approach described in this section maintains separation between
+email addresses in canonical and hosted domains, while still using
+UNIX system accounts.
+
+With virtual alias domains, each hosted address is aliased to a
+UNIX system account. The example below shows how to use this
+mechanism for the example.com domain.
+
+/etc/postfix/main.cf:
+ virtual_alias_domains = example.com ...other hosted domains...
+ virtual_alias_maps = hash:/etc/postfix/virtual
+
+/etc/postfix/virtual:
+ postmaster@example.com postmaster
+ info@example.com joe
+ sales@example.com jane
+ # Uncomment entry below to implement a catch-all address
+ # @example.com jim
+ ...virtual aliases for other domains...
+
+The virtual_alias_domains setting tells Postfix that example.com
+is a so-called virtual alias domain. If you omit this setting then
+Postfix will reject mail (relay access denied) or will not be able
+to deliver it (mail for example.com loops back to myself).
+
+NEVER list a virtual alias domain name as a mydestination domain!
+
+The /etc/postfix/virtual file contains the virtual aliases. With
+the example above, mail for postmaster@example.com goes to the
+local postmaster, while mail for info@example.com goes to the UNIX
+account joe, and mail for sales@example.com goes to the UNIX account
+jane. Mail for all other addresses in example.com is rejected with
+the error message "User unknown".
+
+The commented out entry (text after #) shows how one would implement
+a catch-all virtual alias that receives mail for every example.com
+address not listed in the virtual alias file. This is not without
+risk. Spammers nowadays try to send mail from (or mail to) every
+possible name that they can think of. A catch-all mailbox is likely
+to receive many spam messages, and many bounces for spam messages
+that were sent in the name of anything@example.com.
+
+Execute the command "postmap /etc/postfix/virtual" after changing
+the virtual file, and execute the command "postfix reload" after
+changing the main.cf file.
+
+Note: virtual aliases can resolve to a local address or to a remote
+address, or both. They don't have to resolve to UNIX system accounts
+on your machine.
+
+More details about the virtual alias file are given in the virtual(5)
+manual page, including multiple addresses on the right-hand side.
+
+Virtual aliasing solves one problem: it allows each domain to have
+its own info mail address. But there still is one drawback: each
+virtual address is aliased to a UNIX system account. As you add
+more virtual addresses you also add more UNIX system accounts.
+The next section eliminates this problem.
+
+Postfix virtual MAILBOX domains: separate domains, non-UNIX accounts
+====================================================================
+
+As a system hosts more and more domains and users, it becomes
+less desirable to give everyone their own UNIX system account.
+
+With the Postfix virtual delivery agent, every recipient address
+can have its own virtual mailbox. Unlike virtual alias domains,
+there is no translation from recipient addresses into different
+addresses.
+
+The Postfix virtual delivery agent looks up the user mailbox
+pathname, uid and gid via separate tables that are searched with
+the recipient's mail address. Maildir style delivery is turned on
+by terminating the mailbox pathname with "/".
+
+If you find the idea of multiple tables bothersome, remember that
+you can migrate the information (once it works), to an SQL database.
+If you take that route, be sure to review the "local files versus
+databases" section at the top of this document.
+
+Here is an example of a virtual mailbox domain example.com:
+
+/etc/postfix/main.cf:
+ virtual_mailbox_domains = example.com ...other domains...
+ virtual_mailbox_base = /var/mail/vhosts
+ virtual_mailbox_maps = hash:/etc/postfix/vmailbox
+ virtual_minimum_uid = 100
+ virtual_uid_maps = static:5000
+ virtual_gid_maps = static:5000
+ virtual_alias_maps = hash:/etc/postfix/virtual
+
+/etc/postfix/vmailbox:
+ info@example.com example.com/info
+ sales@example.com example.com/sales/
+ # Comment out the entry below to implement a catch-all.
+ # @example.com example.com/catchall
+ ...virtual mailboxes for other domains...
+
+/etc/postfix/virtual:
+ postmaster@example.com postmaster
+
+This example assumes that main.cf lists the value of myorigin in
+the mydestination parameter setting. If that is not the case,
+specify an explicit domain name on the right-hand side of the
+virtual alias table entries.
+
+The virtual_mailbox_domains setting tells Postfix that example.com
+is a so-called virtual mailbox domain. If you omit this setting
+then Postfix will reject mail (relay access denied) or will not be
+able to deliver it (mail for example.com loops back to myself).
+
+NEVER list a virtual MAILBOX domain name as a mydestination domain!
+
+NEVER list a virtual MAILBOX domain name as a virtual ALIAS domain!
+
+The virtual_mailbox_base parameter specifies a prefix for all
+virtual mailbox pathnames. This is a safety mechanism in case
+someone makes a mistake. It prevents mail from being delivered all
+over the file system.
+
+The virtual_mailbox_maps parameter specifies the lookup table with
+mailbox (or maildir) pathnames, indexed by the virtual mail address.
+In this example, mail for info@example.com goes to the mailbox at
+/var/mail/vhosts/example.com/info while mail for sales@example.com
+goes to the maildir located at /var/mail/vhosts/example.com/sales/.
+
+The virtual_minimum_uid prevents specifies a lower bound on the
+mailbox or maildir owner's UID. This is a safety mechanism in case
+someone makes a mistake. It prevents mail from being written to
+sensitive files.
+
+In the above example, the virtual_uid_maps and virtual_gid_maps
+parameters specify that all the virtual mailboxes are owned by a
+fixed uid and gid 5000. If this is not what you want, specify
+lookup tables that are searched by the recipient's mail address.
+
+The commented out entry (text after #) shows how one would implement
+a catch-all virtual mailbox address. Be prepared to receive a lot
+of spam, as well as bounced spam that was sent in the name of
+anything@example.com.
+
+NEVER put a virtual MAILBOX wild-card in the virtual ALIAS file!!
+
+As you see above, it is possible to mix virtual aliases with virtual
+mailboxes. We use this feature to redirect mail for example.com's
+postmaster address to the local postmaster. You can use the same
+mechanism to redirect an addresses to a remote address.
+
+This approach maintains separation between canonical domains and
+hosted domains by listing the domain names in mydestination and
+virtual_mailbox_domains, respectively.
+
+The separation between hosted domains is maintained by listing the
+full email addresses in the virtual mailbox map.
+
+Execute the command "postmap /etc/postfix/virtual" after changing
+the virtual file, execute "postmap /etc/postfix/vmailbox" after
+changing the vmailbox file, and execute the command "postfix reload"
+after changing the main.cf file.
+
+Note: mail delivery happens with the recipient's UID/GID privileges.
+Postfix will not create mailDIRs; you must create them in advance
+before you can use them. Postfix may be able to create mailBOX
+files by itself, depending on directory write permissions, but it
+is safer to create mailBOX files ahead of time.
+
+More details about the virtual mailbox delivery agent are given
+in the file VIRTUAL_MAILBOX_README, and in the virtual(8) manual
+page.
+
+Non-Postfix mailbox store: separate domains, non-UNIX accounts
+==============================================================
+
+This is a variation on the Postfix virtual mailbox domain mechanism.
+Again, every hosted address can have its own mailbox.
+
+While non-Postfix software is being used for final delivery, some
+Postfix concepts are still needed in order to glue everything
+together. For additional background on this glue you may want to
+take a look at the ADDRESS_CLASS_README file.
+
+The text in this section describes what things should look like
+from Postfix's point of view. See LMTP_README or MAILDROP_README
+for specific information about Cyrus or about Courier maildrop.
+
+Here is an example for a hosted domain example.com that delivers
+to a non-Postfix delivery agent:
+
+/etc/postfix/main.cf:
+ virtual_transport = ...see below...
+ virtual_mailbox_domains = example.com ...other domains...
+ virtual_mailbox_maps = hash:/etc/postfix/vmailbox
+ virtual_alias_maps = hash:/etc/postfix/virtual
+
+/etc/postfix/vmailbox:
+ info@example.com whatever
+ sales@example.com whatever
+ # Comment out the entry below to implement a catch-all.
+ # You also need to configure the mailbox store to accept all addresses.
+ # @example.com whatever
+ ...virtual mailboxes for other domains...
+
+/etc/postfix/virtual:
+ postmaster@example.com postmaster
+
+This example assumes that main.cf lists the value of myorigin in
+the mydestination parameter setting. If that is not the case,
+specify an explicit domain name on the right-hand side of any
+virtual alias table entries.
+
+With delivery to a non-Postfix mailbox store for hosted domains,
+the virtual_transport parameter usually specifies the Postfix LMTP
+client, or the name of a master.cf entry that executes non-Postfix
+software via the pipe delivery agent. Typical examples:
+
+ virtual_transport = lmtp:unix:/path/name (uses UNIX-domain socket)
+ virtual_transport = lmtp:hostname:port (uses TCP socket)
+ virtual_transport = maildrop: (uses pipe(8) to command)
+
+Postfix comes ready with support for LMTP. And an example maildrop
+delivery method is already defined in the default Postfix master.cf
+file.
+
+In the main.cf file example above, the virtual_mailbox_domains
+setting tells Postfix that example.com is delivered via the
+virtual_transport that was discussed in the previous paragraph. If
+you omit this virtual_mailbox_domains setting then Postfix will
+either reject mail (relay access denied) or will not be able to
+deliver it (mail for example.com loops back to myself).
+
+NEVER list a virtual MAILBOX domain name as a mydestination domain!
+
+NEVER list a virtual MAILBOX domain name as a virtual ALIAS domain!
+
+The virtual_mailbox_maps parameter above specifies the lookup table
+with all valid recipient addresses. The lookup result is ignored
+by Postfix. In the above example, info@example.com and sales@example.com
+are listed as valid addresses, and mail for anything else is rejected
+with "User unknown". If you intend to use LDAP, MySQL or PgSQL
+instead of local files, be sure to review the "local files versus
+databases" section at the top of this document!
+
+The commented out entry (text after #) shows how one would inform
+Postfix of the existence of a catch-all address. Again, the lookup
+result is ignored by Postfix.
+
+NEVER put a virtual MAILBOX wild-card in the virtual ALIAS file!!
+
+Note: if you specify a wildcard in virtual_mailbox_maps, then you
+still need to configure the non-Postfix mailbox store to receive
+mail for any address in that domain.
+
+As you see above, it is possible to mix virtual aliases with virtual
+mailboxes. We use this feature to redirect mail for example.com's
+postmaster address to the local postmaster. You can use the same
+mechanism to redirect any addresses to a local or remote address.
+
+Execute the command "postmap /etc/postfix/virtual" after changing
+the virtual file, execute "postmap /etc/postfix/vmailbox" after
+changing the vmailbox file, and execute the command "postfix reload"
+after changing the main.cf file.
+
+Mail forwarding domains
+=======================
+
+Some providers host domains that have no (or only a few) local
+mailboxes. The main purpose of these domains is to forward mail
+elsewhere. The following example shows how to set up example.com
+as a mail forwarding domain:
+
+/etc/postfix/main.cf:
+ virtual_alias_domains = example.com ...other hosted domains...
+ virtual_alias_maps = hash:/etc/postfix/virtual
+
+/etc/postfix/virtual:
+ postmaster@example.com postmaster
+ joe@example.com joe@somewhere
+ jane@example.com jane@somewhere-else
+ # Uncomment entry below to implement a catch-all address
+ # @example.com jim@yet-another-site
+ ...virtual aliases for other domains...
+
+The virtual_alias_domains setting tells Postfix that example.com
+is a so-called virtual alias domain. If you omit this setting then
+Postfix will reject mail (relay access denied) or will not be able
+to deliver it (mail for example.com loops back to myself).
+
+NEVER list a virtual alias domain name as a mydestination domain!
+
+The /etc/postfix/virtual file contains the virtual aliases. With
+the example above, mail for postmaster@example.com goes to the
+local postmaster, while mail for joe@example.com goes to the remote
+address joe@somewhere, and mail for jane@example.com goes to the
+remote address jane@somewhere-else. Mail for all other addresses
+in example.com is rejected with the error message "User unknown".
+
+The commented out entry (text after #) shows how one would implement
+a catch-all virtual alias that receives mail for every example.com
+address not listed in the virtual alias file. This is not without
+risk. Spammers nowadays try to send mail from (or mail to) every
+possible name that they can think of. A catch-all mailbox is likely
+to receive many spam messages, and many bounces for spam messages
+that were sent in the name of anything@example.com.
+
+Execute the command "postmap /etc/postfix/virtual" after changing
+the virtual file, and execute the command "postfix reload" after
+changing the main.cf file.
+
+More details about the virtual alias file are given in the virtual(5)
+manual page, including multiple addresses on the right-hand side.
+
+Aliases, mailing lists, etc.
+============================
+
+The examples that were given above already show how to direct mail
+for virtual postmaster addresses to a local postmaster. You can
+use the same method to direct mail for any address to a local or
+remote address.
+
+There is one major limitation: virtual aliases and virtual mailboxes
+can't directly deliver to mailing list managers such as majordomo.
+The solution is to set up virtual aliases that direct virtual
+addresses to the local delivery agent:
+
+/etc/postfix/main.cf:
+ virtual_alias_maps = hash:/etc/postfix/virtual
+
+/etc/postfix/virtual:
+ listname-request@example.com listname-request
+ listname@example.com listname
+ owner-listname@example.com owner-listname
+
+/etc/aliases:
+ listname: "|/some/where/majordomo/wrapper ..."
+ owner-listname: ...
+ listname-request: ...
+
+This example assumes that main.cf lists the value of myorigin in
+the mydestination parameter setting. If that is not the case,
+specify an explicit domain name on the right-hand side of the
+virtual alias table.
+
+More information about the Postfix local delivery agent can be
+found in the local(8) manual page.
WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
===============================================================
The content filtering approach described in this document is suitable
-only for low-traffic sites. It performs poorly under high load. See
-the "Pros ans Cons" section below for details.
+only for low-traffic sites. See the "Pros ans Cons" section below
+for details.
Purpose of the before-queue content filter feature
==================================================
The before-queue content filter functions just like the after-queue
content filter. In many cases you can use the same content filtering
-software, with some limitations as discussed in the "Pros and Cons"
+software, within the limitations as discussed in the "Pros and Cons"
section below.
Using the SMTP pass-through proxy feature
#
smtp inet n - n - 20 smtpd
-o smtpd_proxy_filter=localhost:10025
+ -o smtpd_client_connection_count_limit=10
#
# After-filter SMTP server. Receive mail from the content filter
# on localhost port 10026.
only 20. This prevents a burst of mail from running your system
into the ground with too many content filter processes.
+- The "-o smtpd_client_connection_count_limit=10" prevents one
+ SMTP client from using up all 20 SMTP server processes. This
+ limit is not necessary if you receive all mail from a trusted
+ relay host.
+
- The "-o smtpd_proxy_filter=localhost:10025" tells the before
filter SMTP server that it should give incoming mail to the
content filter that listens on localhost port 10025.
real-time content filter.
- When a future Postfix version supports DSN, but the content filter
-does not announce DSN support in the EHLO reply, then the before-filter
-SMTP server would have to either 1) suppress the DSN feature in
-its EHLO announcement, or 2) duplicate all the work that needs to
-be done when delivering DSN-aware mail to a non-DSN destination.
+ does not announce DSN support in the EHLO reply, then the
+ before-filter SMTP server would have to either 1) suppress the
+ DSN feature in its EHLO announcement, or 2) duplicate all the
+ work that needs to be done when delivering DSN-aware mail to a
+ non-DSN destination.
- When the content filter does not announce 8BITMIME support in
-the EHLO reply, then the before-filter SMTP server would have to
-either 1) suppress the 8BITMIME feature in its EHLO announcement,
-or 2) convert the content to quoted-printable before giving it to
-the content filter.
+ the EHLO reply, then the before-filter SMTP server would have to
+ either 1) suppress the 8BITMIME feature in its EHLO announcement,
+ or 2) convert the content to quoted-printable before giving it
+ to the content filter.
- Performance: when Postfix has to suppress elements from the
-before-filter EHLO reply because they are incompatible with the
-real-time content filter, then Postfix has to connect to the content
-filter as soon as the client sends a valid EHLO command. This wastes
-a lot of resources when all the MAIL FROM or RCPT TO commands are
-rejected.
+ before-filter EHLO reply because they are incompatible with the
+ real-time content filter, then Postfix has to connect to the
+ content filter as soon as the client sends a valid EHLO command.
+ This wastes a lot of resources when all the MAIL FROM or RCPT TO
+ commands are rejected.
+
+Therefore, the Postfix SMTP server cannot be transparent with
+respect to the before-queue content filter.
-This code was created by Andrew McNamara <andrew@connect.com.au>
-and adapted to snapshot 20001121 by Xavier Beaudouin. It was merged
-with mainstream Postfix for snapshot 20010128 by Wietse.
-
-See the VIRTUAL_README file for an overview of how you can host
+This document describes the Postfix virtual delivery agent. See
+the HOSTING_README file for an overview of all methods to host
multiple domains with one Postfix system.
+The virtual delivery was created by Andrew McNamara and adapted by
+Xavier Beaudouin. It was merged with mainstream Postfix by Wietse.
+
Purpose of this software
========================
You can use the virtual delivery agent for mailbox delivery of some
or all domains that are handled by a machine.
-This mechanism is different from virtual alias domains. Those
-are implemented by translating every recipient address into a
-different address. For that, see the virtual(5) manual page.
-
With the virtual delivery agent, every recipient adress can have
its own mailbox. There is no translation from recipient addresses
-into different addresses.
+into other mail addresses.
+
+This mechanism is different from virtual alias domains (described
+in virtual(5)). Those are implemented by translating every recipient
+address into a different address.
-This is what Andrew McNamara wrote when he made the virtual delivery
-agent available.
+This an updated version of what Andrew McNamara wrote when he made
+the virtual delivery agent available.
"This code is designed for ISP's who offer virtual mail hosting.
It looks up the user mailbox location, uid and gid via separate
+++ /dev/null
-Purpose of this document
-========================
-
-This document describes how to configure one Postfix system for
-final mail delivery of multiple Internet domains, using the mailbox
-and maildir delivery mechanisms that are already built into Postfix.
-
-See the LMTP_README file for an example of final delivery with
-third-party mailstores such as Cyrus.
-
-Preliminaries: local files versus databases
-===========================================
-
-The examples in this text use table lookups from local files.
-These are easy to debug with the postmap "-q" command option.
-
-Example: postmap -q info@example.com hash:/etc/postfix/virtual
-
-See LDAP_README, MYSQL_README and PGSQL_README for how to replace
-local files by databases. The reader is strongly advised to make
-the system work with local files before migrating to database files,
-and to use the postmap "-q" command option to verify that database
-lookups produce the exact same results as local file lookup.
-
-Example: postmap -q info@example.com:ldap:/etc/postfix/virtual.cf
-
-Preliminaries: canonical versus virtual domains
-===============================================
-
-Each Postfix system does final delivery for a small number of
-canonical domains; usually these are the names of the machine that
-Postfix runs on. Sometimes the list of canonical domains also
-includes the parent domain of the machine name.
-
-Postfix can be configured to do final delivery for additional
-domains. The domains are called virtual, because they are not
-associated with the name of the machine itself.
-
-Postfix understands two types of virtual domain:
-
-- The virtual alias domain, where each virtual address is aliased
- to a different (remote or local) address.
-
-- The virtual mailbox domain, where each virtual address can have
- its own mailbox.
-
-A third type, the "sendmail style virtual domain" was described
-with older Postfix versions. It will not be discussed here in order
-to avoid a lot of confusion.
-
-Shared domains, UNIX system accounts
-====================================
-
-The simplest method to host an additional domain is to specify the
-user names in the UNIX password file and to specify the domain name
-in the Postfix mydestination configuration parameter.
-
-In the examples we will use "example.com" as the domain that is
-being hosted on the local Postfix machine.
-
-/etc/postfix/main.cf:
- mydestination = $myhostname localhost.$mydomain ... example.com
-
-The downside of this approach is a total lack of separation: mail
-for info@my.host.name is delivered to the same UNIX system account
-as mail for info@example.com. If different domains need to have
-different "info" mailboxes, then you can use one of the methods
-described in the remainder of this document.
-
-Another downside of listing all users in the UNIX password file is
-that administration of large numbers of users becomes inconvenient.
-
-Virtual ALIAS domains: separate domains, UNIX system accounts
-=============================================================
-
-The simplest method to host separate domains is to create so-called
-virtual aliases that redirect mail from each virtual address to
-its own UNIX account.
-
-The example below shows how to set up the example.com domain
-as a so-called virtual alias domain:
-
-/etc/postfix/main.cf:
- virtual_alias_domains = example.com ...other domains...
- virtual_alias_maps = hash:/etc/postfix/virtual
-
-/etc/postfix/virtual:
- postmaster@example.com postmaster
- info@example.com joe
- sales@example.com jane
- # Uncomment entry below to implement a catch-all address
- # @example.com jim
- ...virtual aliases for other domains...
-
-The virtual_alias_domains setting tells Postfix that example.com
-is a so-called virtual alias domain. If you omit this step then
-Postfix will either reject mail (relay access denied) or will not
-be able to deliver it (mail for example.com loops back to myself).
-
-The /etc/postfix/virtual file contains the virtual aliases. With
-the example above, mail for postmaster@example.com goes to the
-local postmaster, while mail for info@example.com goes to the UNIX
-account joe, and mail for sales@example.com goes to the UNIX account
-jane. Mail for all other addresses in example.com is rejected with
-the error message "User unknown".
-
-The commented out entry (text after #) shows how one would implement
-a catch-all virtual alias that receives mail for every example.com
-address not listed in the virtual alias file. This is not without
-risk. Spammers nowadays try to send mail from (or mail to) every
-possible name that they can think of. A catch-all mailbox is likely
-to receive many spam messages, and many bounces for spam messages
-that were sent in the name of anything@example.com.
-
-Execute the command "postmap /etc/postfix/virtual" after changing
-the virtual file, and execute the command "postfix reload" after
-changing the main.cf file.
-
-Note: virtual aliases can resolve to a local address or to a remote
-address, or both. They don't have to resolve to UNIX system accounts
-on your machine.
-
-More details about the virtual alias file are given in the virtual(5)
-manual page, including multiple addresses on the right-hand side.
-
-Virtual aliasing solves one problem: it allows each domain to have
-its own info mail address. Virtual aliasing to UNIX system accounts
-still has the drawback that every user has to be listed in the UNIX
-password file. The next section eliminates this problem.
-
-Virtual MAILBOX domains: separate domains, non-UNIX accounts
-============================================================
-
-As a system hosts more and more domains and users, it becomes
-unpractical to give everyone their own UNIX system account.
-
-With the Postfix virtual delivery agent, every recipient address
-can have its own virtual mailbox. Unlike virtual alias domains,
-there is no translation from recipient addresses into different
-addresses.
-
-The Postfix virtual delivery agent looks up the user mailbox
-pathname, uid and gid via separate tables that are searched with
-the recipient's mail address. Maildir style delivery is turned on
-by terminating the mailbox pathname with "/".
-
-Here is an example of a virtual mailbox domain example.com:
-
-/etc/postfix/main.cf:
- virtual_mailbox_base = /var/mail/vhosts
- virtual_mailbox_maps = hash:/etc/postfix/vmailbox
- virtual_mailbox_domains = example.com ...other domains...
- virtual_minimum_uid = 100
- virtual_uid_maps = static:5000
- virtual_gid_maps = static:5000
- virtual_alias_maps = hash:/etc/postfix/virtual
-
-/etc/postfix/vmailbox:
- info@example.com example.com/info
- sales@example.com example.com/sales/
- # Comment out the entry below to implement a catch-all.
- # @example.com example.com/catchall
- ...virtual mailboxes for other domains...
-
-/etc/postfix/virtual:
- postmaster@example.com postmaster
-
-The virtual_mailbox_base parameter specifies a prefix for all
-virtual mailbox pathnames. This is a safety mechanism that prevents
-mail from being delivered all over the file system.
-
-The virtual_mailbox_maps parameter specifies the lookup table with
-mailbox (or maildir) pathnames, indexed by the virtual mail address.
-In this example, mail for info@example.com goes to the mailbox at
-/var/mail/vhosts/example.com/info while mail for sales@example.com
-goes to the maildir located at /var/mail/vhosts/example.com/sales/.
-
-The virtual_minimum_uid prevents specifies a lower bound on the
-mailbox or maildir owner's UID. This is a safety mechanism that
-prevents mail from being written to sensitive files.
-
-In the above example, the virtual_uid_maps and virtual_gid_maps
-parameters specify that all the virtual mailboxes are owned by a
-fixed uid and gid 5000. If this is not what you want, specify
-lookup tables that are searched by the recipient's mail address.
-
-The commented out entry (text after #) shows how one would implement
-a catch-all virtual mailbox address. Be prepared to receive a lot
-of spam, as well as bounced spam that was sent in the name of
-anything@example.com.
-
-NEVER put a virtual MAILBOX wild-card in the virtual ALIAS file!!
-
-As you see above, it is possible to mix virtual aliases with virtual
-mailboxes. We use this feature to redirect mail for example.com's
-postmaster address to the local postmaster.
-
-Execute the command "postmap /etc/postfix/virtual" after changing
-the virtual file, execute "postmap /etc/postfix/vmailbox" after
-changing the vmailbox file, and execute the command "postfix reload"
-after changing the main.cf file.
-
-Note: mail delivery happens with the UID/GID privileges of the
-recipient. You must create maildirs in advance before you can use
-them. Depending on directory permissions, Postfix may be able to
-create mailbox files by itself, but it is safer to create them
-ahead of time.
-
-More details about the virtual mailbox delivery agent are given
-in the file VIRTUAL_MAILBOX_README, and in the virtual(8) manual
-page.
-
-Aliases, mailing lists, etc.
-============================
-
-The examples above already show how to direct mail for virtual
-postmaster addresses to a local postmaster. The same method can be
-used to direct mail for other virtual addresses to a local or remote
-address.
-
-Virtual aliases can't directly deliver to mailing list managers
-such as majordomo. One solution is to set up a transport mapping
-that directs the mail to the Postfix local delivery agent, and to
-use the local alias file for delivery to the mailing list manager:
-
-/etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
-
-/etc/postfix/transport:
- listname-request@example.com local:
- listname@example.com local:
- owner-listname@example.com local:
-
-/etc/aliases:
- listname: "|/some/where/majordomo/wrapper ..."
- owner-listname: ...
- listname-request: ...
-
-You can achieve the same result with virtual aliases that direct
-virtual addresses to the local delivery agent:
-
-/etc/postfix/main.cf:
- virtual_alias_maps = hash:/etc/postfix/virtual
-
-/etc/postfix/virtual:
- listname-request@example.com listname-request
- listname@example.com listname
- owner-listname@example.com owner-listname
-
-/etc/aliases:
- listname: "|/some/where/majordomo/wrapper ..."
- owner-listname: ...
- listname-request: ...
-
-Either approach will do the job.
-
-More information about the Postfix local delivery agent can be
-found in the local(8) manual page.
Incompatible changes with Postfix snapshot 2.0.16-2004XXXX
==========================================================
-The SMTP server no longer accept sender addresses that match a
+Queue files creates with "sendmail -v" are no longer compatible
+with earlier Postfix 2.x versions. A new record type, "killed",
+was introduced in order to avoid repeated mail delivery notification
+reports with mail that could not be delivered due to a temproary
+error condition.
+
+The format of the postfix-files file has changed. There is a new
+type for hard links. With hard or symbolic link entries, the first
+field is now the destination pathname and the "owner" field is now
+the origin pathname, while "group" and "permissions" are ignored.
+
+The SMTP server no longer accepts sender addresses that match a
local, virtual or relay domain while the address is not listed as
valid in the corresponding local, virtual or relay recipient table.
This is not configurable.
[$]*) ;;
*) continue;;
esac
+ # Skip hard links and symbolic links.
+ case $type in
+ [hl]) continue;;
+ [df]) ;;
+ *) echo unknown type $type for $path in $config_directory/postfix-files1>&2; exit 1;;
+ esac
# Expand $name, and canonicalize null fields.
for name in path owner group flags
do
# Turn on safety nets for new features that could bounce mail that
# would be accepted by a previous Postfix version.
+ # This safety net is also documented in LOCAL_RECIPIENT_README.
unknown_local=unknown_local_recipient_reject_code
has_lrm=`$POSTCONF -n local_recipient_maps`
# File types:
# d=directory
# f=regular file
-# l=symlink
+# h=hard link (*)
+# l=symbolic link (*)
+#
+# (*) With hard links and symbolic links, the owner field becomes the
+# source pathname, while the group and permissions are ignored.
#
# File flags:
# No flag means the flag is not active.
$daemon_directory/trivial-rewrite:f:root:-:755
$daemon_directory/verify:f:root:-:755
$daemon_directory/virtual:f:root:-:755
-$nqmgr_path:l:root:-:755
+$daemon_directory/nqmgr:h:$daemon_directory/qmgr
$command_directory/postalias:f:root:-:755
$command_directory/postcat:f:root:-:755
$command_directory/postconf:f:root:-:755
$command_directory/postdrop:f:root:$setgid_group:2755:u
$command_directory/postqueue:f:root:$setgid_group:2755:u
$sendmail_path:f:root:-:755
-$newaliases_path:l:root:-:755
-$mailq_path:l:root:-:755
+$newaliases_path:l:$sendmail_path
+$mailq_path:l:$sendmail_path
$config_directory/LICENSE:f:root:-:644
$config_directory/access:f:root:-:644:p
$config_directory/aliases:f:root:-:644:p
$manpage_directory/man8/virtual.8:f:root:-:644
$sample_directory/sample-aliases.cf:f:root:-:644
$sample_directory/sample-auth.cf:f:root:-:644
-$sample_directory/sample-canonical.cf:f:root:-:644
+$sample_directory/sample-canonical.cf:f:root:-:644:o
$sample_directory/sample-compatibility.cf:f:root:-:644
$sample_directory/sample-debug.cf:f:root:-:644
$sample_directory/sample-filter.cf:f:root:-:644
$readme_directory/DEBUG_README:f:root:-:644
$readme_directory/ETRN_README:f:root:-:644
$readme_directory/FILTER_README:f:root:-:644
+$readme_directory/HOSTING_README:f:root:-:644
$readme_directory/INSTALL:f:root:-:644
$readme_directory/LDAP_README:f:root:-:644
$readme_directory/LINUX_README:f:root:-:644
$readme_directory/UUCP_README:f:root:-:644
$readme_directory/VERP_README:f:root:-:644
$readme_directory/VIRTUAL_MAILBOX_README:f:root:-:644
-$readme_directory/VIRTUAL_README:f:root:-:644
+$readme_directory/VIRTUAL_README:f:root:-:644:o
$readme_directory/XCLIENT_README:f:root:-:644
$readme_directory/XFORWARD_README:f:root:-:644
+++ /dev/null
-# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF
-# HERE JUST SERVES AS AN EXAMPLE.
-#
-# This file contains example settings of Postfix configuration
-# parameters that control canonical address map lookups.
-
-# The canonical_maps parameter specifies optional address mapping
-# lookup tables. The mapping is applied to both sender and recipient
-# addresses, in both envelopes and in headers. This is typically used
-# to clean up dirty addresses from legacy mail systems, or to replace
-# login names by Firstname.Lastname. See canonical(5) for details.
-#
-# By default, no canonical address mapping is done.
-#
-# If you use this feature, run "postmap /etc/postfix/canonical" to
-# build the necessary DBM or DB file after every change. The changes
-# will become visible after a minute or so. Use "postfix reload"
-# to eliminate the delay.
-#
-#canonical_maps = dbm:/etc/postfix/canonical
-#canonical_maps = hash:/etc/postfix/canonical
-#canonical_maps = hash:/etc/postfix/canonical, nis:canonical
-#canonical_maps = hash:/etc/postfix/canonical, netinfo:/canonical
-canonical_maps =
-
-# The recipient_canonical_maps parameter specifies optional address
-# mapping lookup tables for envelope and header RECIPIENT addresses.
-#
-# By default, no recipient-only address mapping is done.
-#
-# $recipient_canonical_maps is used before $canonical_maps lookups.
-#
-#recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
-recipient_canonical_maps =
-
-# The sender_canonical_maps parameter specifies optional address
-# mapping lookup tables for envelope and header SENDER addresses.
-#
-# For example, you want to rewrite the SENDER address user@ugly.domain
-# to user@pretty.domain, while still being able to send mail to the
-# RECIPIENT address user@ugly.domain.
-#
-# By default, no sender-only address mapping is done.
-#
-# $sender_canonical_maps is used before $canonical_maps lookups.
-#
-#sender_canonical_maps = hash:/etc/postfix/sender_canonical
-sender_canonical_maps =
# parameters that control compatibility with broken software.
# The broken_sasl_auth_clients controls inter-operability with SMTP
-# clients that do not recognize that Postfix supports RFC 2554 (AUTH
+# clients that implement an obsolete version of RFC 2554 (the AUTH
# command). Examples of such clients are MicroSoft Outlook Express
# version 4 and MicroSoft Exchange version 5.0.
#
smtp_always_send_ehlo = yes
# The smtp_never_send_ehlo parameter specifies that the SMTP client
-# should never send EHLO at the start of an SMTP session.
+# should never send EHLO at the start of an SMTP session. This turns
+# off advanced features and can solve an inter-operability problem.
#
smtp_never_send_ehlo = no
#
# By default, Postfix moves on the the next mail exchanger. Specify
# "smtp_skip_5xx_greeting = no" if Postfix should bounce the mail
-# immediately.
+# immediately. The default setting is incorrect, but it is what a
+# lot of people expect to happen.
#
smtp_skip_5xx_greeting = yes
# By default, Postfix SMTPD allows RFC822 syntax in MAIL FROM and RCPT TO.
#
strict_rfc821_envelopes = no
+
+# The smtp_pix_workaround_sleep_time parameter specifies how long
+# the Postfix SMTP client pauses before sending .<CR><LF>, in order
+# to work around the PIX firewall <CR><LF>.<CR><LF> bug.
+#
+# The default delay is 10 seconds. Choosing a too short time makes
+# this workaround ineffective while sending large messages over slow
+# network connections.
+#
+smtp_pix_workaround_delay_time = 10s
+
+# The smtp_pix_workaround_threshold_time parameter specifies how
+# long a message must be queued before the PIX firewall <CR><LF>.<CR><LF>
+# bug workaround is turned on.
+#
+# By default, the workaround is turned off for mail that is queued
+# for less than 500 seconds. In other words, the workaround is normally
+# turned off for the first delivery attempt.
+#
+# Specify 0 to enable the PIX firewall <CR><LF>.<CR><LF> bug workaround
+# upon the first delivery attempt.
+#
+smtp_pix_workaround_threshold_time = 500s
#
# pgsql config file for alias lookups on postfix
-# comments are ok.
#
# the user name and password to log into the pgsql server
#
# Specify 0 when mail delivery should be tried only once.
#
-bounce_queue_lifetime = $maximal_queue_lifetime
+bounce_queue_lifetime = 5d
# The minimal_backoff_time parameter specifies the minimal time
# between attempts to deliver a deferred message. This parameter
# The relocated_maps parameter specifies optional lookup tables with
# new contact information for users or even domains that no longer
-# exist.
+# exist. The format is documented in relocated(5).
#
# By default, this feature is disabled.
#
# on the number of Postfix child processes that provide a given
# service.
#
-default_process_limit = 50
+default_process_limit = 100
# The deliver_lock_attempts parameter limits the number of attempts
# to acquire an exclusive lock on a mailbox or other file.
#
qmgr_message_recipient_limit = 20000
-# (nqmgr only)
+# (not applicable to the oqmgr queue manager)
# The default_recipient_limit parameter is the default value for
# per-transport limit imposed on the number of in-memory recipients.
# These limits take priority over the global qmgr_message_recipient_limit
#
default_recipient_limit = 10000
-# (nqmgr only)
+# (not applicable to the oqmgr queue manager)
# The default_extra_recipient_limit parameter is the default value for
# extra per-transport limit imposed on the number of in-memory recipients.
# This extra recipient space is reserved for the cases when the scheduler
#
default_extra_recipient_limit = 1000
-# (nqmgr only)
+# (not applicable to the oqmgr queue manager)
# The qmgr_message_recipient_minimum parameter specifies the minimum
# amount of in-memory recipients for any message. This takes
# priority over any other in-memory recipient limits (i.e., global
# the SMTP server to decide if it will accept any mail at all.
#
# By default, the SMTP server rejects MAIL FROM commands when the
-# amount of free space is less than 2*$message_size_limit.
+# amount of free space is less than 1.5*$message_size_limit.
#
# To specify a higher minimum free space limit, specify a value that
-# is at least 2*$message_size_limit.
+# is at least 1.5*$message_size_limit.
#
queue_minfree = 0
#append_dot_mydomain = no
append_dot_mydomain = yes
+# The canonical_maps parameter specifies optional address mapping
+# lookup tables. The mapping is applied to both sender and recipient
+# addresses, in both envelopes and in headers. This is typically used
+# to clean up dirty addresses from legacy mail systems, or to replace
+# login names by Firstname.Lastname. See canonical(5) for details.
+#
+# By default, no canonical address mapping is done.
+#
+# If you use this feature, run "postmap /etc/postfix/canonical" to
+# build the necessary DBM or DB file after every change. The changes
+# will become visible after a minute or so. Use "postfix reload"
+# to eliminate the delay.
+#
+#canonical_maps = dbm:/etc/postfix/canonical
+#canonical_maps = hash:/etc/postfix/canonical
+#canonical_maps = hash:/etc/postfix/canonical, nis:canonical
+#canonical_maps = hash:/etc/postfix/canonical, netinfo:/canonical
+canonical_maps =
+
+# The recipient_canonical_maps parameter specifies optional address
+# mapping lookup tables for envelope and header RECIPIENT addresses.
+#
+# By default, no recipient-only address mapping is done.
+#
+# $recipient_canonical_maps is used before $canonical_maps lookups.
+#
+#recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
+recipient_canonical_maps =
+
+# The sender_canonical_maps parameter specifies optional address
+# mapping lookup tables for envelope and header SENDER addresses.
+#
+# For example, you want to rewrite the SENDER address user@ugly.domain
+# to user@pretty.domain, while still being able to send mail to the
+# RECIPIENT address user@ugly.domain.
+#
+# By default, no sender-only address mapping is done.
+#
+# $sender_canonical_maps is used before $canonical_maps lookups.
+#
+#sender_canonical_maps = hash:/etc/postfix/sender_canonical
+sender_canonical_maps =
+
# The empty_address_recipient specifies the destination for mail from
# <> that is undeliverable (typically, bounce notifications and
# other notifications). By default, such mail is sent to MAILER-DAEMON.
# described in the respective sample-transportname.cf file.
# The default_delivery_slot_cost parameter controls how often
-# is the scheduler allowed to preempt one message with another.
+# the scheduler is allowed to preempt one message with another.
#
# Each transport maintains so-called "available delivery slot counter" for
# each message. One message can be preempted by another one when the other
# The best_mx_transport parameter controls what happens when the
# local system is listed as the best MX host for a destination. By
# default, Postfix reports a "mail loops back to myself" error and
-# bounces the message. Specify "best_mx_transport = local" to pass
-# the mail to the local delivery agent. You can specify any transport
-# that is defined in the master.cf file.
+# returns the message as undeliverable.
+#
+# Specify, for example, "best_mx_transport = local" to pass the mail
+# to the local delivery agent. You can specify any message delivery
+# transport that is defined in the master.cf file.
+#
+# However, this feature is expensive because it ties up an SMTP client
+# process until the mail is delivered. It is better to list all hosted
+# domains in a table. Use a database is necessary.
#
# best_mx_transport =
# By default, mail is bounced when a destination is not found, and
# delivery is deferred if a destination is unreachable.
#
-# In the case of SMTP, specify a domain, host, host:port, [host]:port,
-# [address] or [address]:port; the form [host] turns off MX lookups.
-# If you specify multiple SMTP destinations, Postfix will try them
-# in the specified order.
+# The fallback relays must be SMTP destinations. Specify a domain,
+# host, host:port, [host]:port, [address] or [address]:port; the form
+# [host] turns off MX lookups. If you specify multiple SMTP
+# destinations, Postfix will try them in the specified order.
#
fallback_relay =
# The ignore_mx_lookup_error parameter controls what happens when a
-# name server fails to respond to an MX lookup request. By default,
+# name server does not respond to an MX lookup request. By default,
# Postfix defers delivery and tries again after some delay. Specify
# "ignore_mx_lookup_error = yes" to force an A record lookup instead.
#
# The smtp_bind_address parameter specifies a numerical network
# address that the client should bind to when making a connection.
-# This can be used in the main.cf file, or in the master.cf file,
+#
+# This can be specified in the main.cf file for all SMTP clients, or
+# it can be specified in the master.cf file for a specific client,
# for example:
#
-# smtp ... smtp -o smtp_bind_address=111.222.333.444
+# /etc/postfix/master.cf:
+# smtp ... smtp -o smtp_bind_address=11.22.33.44
#
-#smtp_bind_address=111.222.333.444
+#smtp_bind_address=11.22.33.44
# The smtp_defer_if_no_mx_address_found parameter controls what
# Postfix will do when no MX record resolves to an IP address (Postfix
# always ignores MX records with equal or worse preference than the
-# local MTA).
+# local MTA itself).
#
# The default (no) is to return the mail as undeliverable. With older
# Postfix versions the default was to keep trying to deliver the mail
# The smtp_mx_session_limit parameter limits the number of SMTP
# sessions per delivery request before giving up or delivering to a
-# fall-back relay host, ignoring IP addresses that fail to complete
-# the SMTP initial handshake.
+# fall-back relay host. This restriction ignores IP addresses that
+# fail to complete the SMTP initial handshake.
#
# By default, Postfix SMTP client gives up or delivers to fall-back
# relay after two SMTP sessions.
smtp_mx_session_limit = 2
# The smtp_send_xforward_command parameter controls whether the Postfix
-# SMTP client will send an XFORWARD command to the SMTP server, when
-# the ESMTP HELO response of the remote host indicates XFORWARD support.
-# This allows an "smtp" delivery agent, used for content filter
-# message injection, to forward the name, address, protocol and HELO
+# SMTP client will use the non-standard XFORWARD feature when it talks
+# to an SMTP server that announces XFORWARD support.
+#
+# This allows an "smtp" delivery agent, used for injecting mail into
+# a content filter, to forward the name, address, protocol and HELO
# name of the original client to the content filter and downstream
-# queuing SMTP server. Before you change the value to yes, it is best
-# to make sure your content filter supports this command.
+# queuing SMTP server. This can produce more useful logging than
+# localhost[127.0.0.1] etc.
#
smtp_send_xforward_command = no
# in the EHLO or HELO command.
#
# The default value is the machine hostname. Specify a hostname or
-# [ip.address]. This can be used in the main.cf file, or in the
-# master.cf file, for example:
+# [ip.address].
+#
+# This can be specified in the main.cf file for all SMTP clients, or
+# it can be specified in the master.cf file for a specific client,
+# for example:
#
+# /etc/postfix/master.cf:
# smtp ... smtp -o smtp_helo_name=foo.bar.com
#
-#smtp_helo_name = $myhostname
+smtp_helo_name = $myhostname
# The smtp_skip_4xx_greeting parameter controls what happens when
# an SMTP server greets us with a 4XX status code (go away, try
#
# By default, Postfix moves on the the next mail exchanger. Specify
# "smtp_skip_5xx_greeting = no" if Postfix should bounce the mail
-# immediately.
+# immediately. The default setting is incorrect, but it is what a
+# lot of people expect to happen.
#
smtp_skip_5xx_greeting = yes
# The smtp_destination_concurrency_limit parameter limits the number
# of parallel deliveries to the same destination via the smtp delivery
-# agent.
+# agent. This limit is enforced by the queue manager.
#
# The default limit is the default_destination_concurrency_limit
# parameter. It is probably safer to limit the concurrency to 10.
smtp_destination_concurrency_limit = 20
# The smtp_destination_recipient_limit parameter limits the number
-# of recipients per delivery via the smtp delivery agent.
+# of recipients per delivery via the smtp delivery agent. This limit
+# is enforced by the queue manager.
#
# The default is taken from the default_destination_recipient_limit
# parameter.
# when the SMTP client looks up a host. This parameter is ignored
# when DNS lookups are disabled.
#
-# The default is to use both DNS and the native naming service which
-# (also) uses /etc/hosts.
+# The default is to use DNS.
#
# Specify "dns" if hosts can be found in the DNS (preferred).
-# Specify "dns, native" if some hosts are not in the DNS.
# Specify "native" to use the native naming service only.
+# Specify "dns, native" if some hosts are not in the DNS.
#
-#smtp_host_lookup = dns
-smtp_host_lookup = dns, native
+#smtp_host_lookup = dns, native
+smtp_host_lookup = dns
#
# TIMEOUT CONTROLS
# for sending the SMTP HELO or EHLO command, and for receiving the
# server response.
#
-# In case of problems the client does NOT try the next address on
-# the mail exchanger list.
-#
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is s (seconds).
#
# for sending the SMTP XFORWARD command, and for receiving the server
# response.
#
-# In case of problems the client does NOT try the next address on
-# the mail exchanger list.
-#
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is s (seconds).
#
# for sending the SMTP MAIL FROM command, and for receiving the server
# response.
#
-# In case of problems the client does NOT try the next address on
-# the mail exchanger list.
-#
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is s (seconds).
#
# for sending the SMTP RCPT TO command, and for receiving the server
# response.
#
-# In case of problems the client does NOT try the next address on
-# the mail exchanger list.
-#
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is s (seconds).
#
# timeout for sending the SMTP DATA command, and for receiving the
# server response.
#
-# In case of problems the client does NOT try the next address on
-# the mail exchanger list.
-#
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is s (seconds).
#
# stalls for more than $smtp_data_xfer_timeout the SMTP client
# terminates the transfer.
#
-# In case of problems the client does NOT try the next address on
-# the mail exchanger list.
-#
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is s (seconds).
#
# When no response is received within the deadline, a warning is
# logged that the mail may be delivered multiple times.
#
-# In case of problems the client does NOT try the next address on
-# the mail exchanger list.
-#
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is s (seconds).
#
# connection attempts any client is allowed to make to this service
# per time unit.
#
-# The time unit is specified with the client_connection_rate_time_unit
+# The time unit is specified with the rate_limiter_time_unit
# configuration parameter, and defaults to one minute.
#
# By default, every client can make as many connections as Postfix
--- /dev/null
+From: Ron Bickers <rbickers-list-postfix@logicetc.com>
+
+For the archives (or for comment):
+
+I now have mailbox_command = /usr/local/libexec/postqmail-local and
+postqmail-local looks like this (minus some mailer wrapping):
+
+ #!/bin/sh
+ export PATH=$PATH:/usr/local/bin:/var/qmail/bin
+ tail +2 | seekablepipe qmail-local -- \
+ "$USER" "$HOME" "$LOCAL" "${EXTENSION:+-}" "$EXTENSION"
+ "$DOMAIN""$SENDER" ./Maildir/
+ e=$?
+ (($e == 111)) && exit 75
+ (($e == 100)) && exit 77
+ exit $e
to this program. Use the <b>postfix reload</b> command after a
configuration change.
- <b>client_connection_rate_time_unit</b>
+ <b>rate_limiter_time_unit</b>
The unit of time over which connection rates are
calculated.
<p>
+<a href="#hangup">Limiting the number of connections per client</a>
+
+<p>
+
<a href="#slowdown">Slowing down bad clients</a>
</ul>
-<a name="process"><h2> Process limits</h2>
+<a name="process"><h2> Process limits</h2></a>
The <b>default_process_limit</b> parameter (default: 100) gives
direct control over inbound and outbound delivery rates. This
</dl>
-<a name="destination"><h2> Destination concurrency</h2>
+<a name="destination"><h2> Destination concurrency</h2></a>
So, you have this huge mailhub with tons of disk and memory, and
have configured Postfix to run up to 1000 SMTP client processes at
to noticeably load a system without bringing it to its knees. Be
careful when changing this to a much larger number.
-<a name="recipients"><h2> Recipient limits</h2>
+<a name="recipients"><h2> Recipient limits</h2></a>
The <b>default_destination_recipient_limit</b> parameter (default:
50) controls how many recipients a Postfix delivery agent (<b>smtp</b>,
exists just to protect the local mail system against a malicious
or confused client.
-<a name="postponing"><h2> Always postponing delivery</h2>
+<a name="postponing"><h2> Always postponing delivery</h2></a>
The <b>defer_transports</b> parameter allows you to specify what
mail should always be deferred until Postfix is explicitly asked
</dl>
-<a name="backoff"><h2> Backoff from unreachable hosts</h2>
+<a name="backoff"><h2> Backoff from unreachable hosts</h2></a>
When a Postfix delivery agent (<b>smtp, local, uucp,</b> etc.)
is unable to deliver a message it may blame the message itself or
<dl>
-<dt> <b>queue_run_delay</b> (default: 1000 seconds) <dd> How
-often the queue manager scans the queue for deferred mail.
+<dt> <a name="queue_run_delay"> <b>queue_run_delay</b></a> (default:
+1000 seconds) <dd> How often the queue manager scans the queue for
+deferred mail.
<p>
-<dt> <b>maximal_queue_lifetime</b> (default: 5 days) <dd> How
-long a message stays in the queue before it is sent back as
-undeliverable. Specify 0 for mail that should be returned
-immediately after the first unsuccessful delivery attempt.
+<dt> <a name="maximal_queue_lifetime"> <b>maximal_queue_lifetime</b></a>
+(default: 5 days) <dd> How long a message stays in the queue before
+it is sent back as undeliverable. Specify 0 for mail that should
+be returned immediately after the first unsuccessful delivery
+attempt.
<p>
-<dt> <b>bounce_queue_lifetime</b> (default: $maximal_queue_lifetime)
-<dd> How long a bounce message stays in the queue before it is
-considered undeliverable. Specify 0 for mail that should be returned
-immediately after the first unsuccessful delivery attempt.
+<dt> <a name="bounce_queue_lifetime"> <b>bounce_queue_lifetime</b></a>
+(default: $maximal_queue_lifetime) <dd> How long a bounce message
+stays in the queue before it is considered undeliverable. Specify
+0 for mail that should be returned immediately after the first
+unsuccessful delivery attempt.
<p>
-<dt> <b>minimal_backoff_time</b> (default: 1000 seconds) <dd> The
-minimal amount of time a message won't be looked at, and the minimal
-amount of time to stay away from a "dead" destination.
+<dt> <a name="minimal_backoff_time"> <b>minimal_backoff_time</b></a>
+(default: 1000 seconds) <dd> The minimal amount of time a message
+won't be looked at, and the minimal amount of time to stay away
+from a "dead" destination.
<p>
-<dt> <b>maximal_backoff_time</b> (default: 4000 seconds) <dd> The
-maximal amount of time a message won't be looked at after a delivery
-failure.
+<dt> <a name="maximal_backoff_time"> <b>maximal_backoff_time</b></a>
+(default: 4000 seconds) <dd> The maximal amount of time a message
+won't be looked at after a delivery failure.
<p>
-<dt> <b>qmgr_message_recipient_limit</b> (default: 20000) <dd> The
+<dt> <a name="qmgr_message_recipient_limit">
+<b>qmgr_message_recipient_limit</b></a> (default: 20000) <dd> The
size of many in-memory queue manager data structures. Among others,
this parameter limits the size of the short-term, in-memory "dead"
list. Destinations that don't fit the list are not added.
</dl>
-<a name="slowdown"><h2> Slowing down bad clients</h2>
+<a name="hangup"><h2>Limiting the number of connections per client</h2></a>
-First of all, no defense will protect against an all-out denial of
-service attack. I just don't want to raise impossible expectations.
-But there are a few simple things one can do in order to deal with
-confused or malicious client programs.
+First of all, no Postfix defense will protect against an all-out
+denial of service attack. I just don't want to raise impossible
+expectations. But there are a few simple things one can do in
+order to deal with confused or malicious client programs.
<p>
-Some defenses are part of a more general strategy: for example,
-how long a line of text may be before it is broken up into pieces,
-and how much text may be carried in a multi-line message header.
-See the <a href="resource.html">resource controls</a> documentation
-for details.
+The Postfix <a href="smtpd.8.html">SMTP server</a> can limit the
+number of connections that an SMTP client is allowed to make,
+simultaneously or within an interval of time. The configuration
+parameters that control this are:
<p>
-The Postfix <a href="smtpd.8.html">SMTP server</a> increments a
-per-session error counter whenever a client request is unrecognized
-or unimplemented, or whenever a client request violates <a
-href="uce.html">UCE restrictions</a> or other reasons. The error
-counter is reset when a message is transferred successfully.
+<dl>
+
+<dt> <a name="smtpd_client_connection_count_limit">
+<b>smtpd_client_connection_count_limit</b></a> (default: 50) <dd>
+An upper bound on the number of simultaneous connections that an
+SMTP client is allowed to make. When a client exceeds the limit
+Postfix replies with a 421 status code and breaks the connection.
+To avoid wasting time, specify <b>smtpd_error_sleep_time = 0</b>.
<p>
-As the per-session error count increases, the SMTP server changes
-behavior. The idea is to limit the damage by slowing down the
-client. The behavior is controlled by the following parameters:
+<dt> <a name="smtpd_client_connection_rate_limit">
+<b>smtpd_client_connection_rate_limit</b></a> (default: unlimited)
+<dd> An upper bound on the number of subsequent connections that
+an SMTP client is allowed to make per unit time. When a client
+exceeds the limit Postfix replies with a 421 status code and breaks
+the connection. To avoid wasting time, specify <b>smtpd_error_sleep_time
+= 0</b>.
<p>
-<dl>
+<dt> <a name="smtpd_client_connection_limit_exceptions">
+<b>smtpd_client_connection_limit_exceptions</b></a> (default:
+<b>$mynetworks</b>) <dd> A description of SMTP clients that are
+excluded from connection count and rate limits. By default,
+local or trusted clients are excluded.
+
+<p>
+
+<dt> <a name="rate_limiter_time_unit"> <b>rate_limiter_time_unit</b></a>
+(default: 60s) <dd> The time unit for computing the client connection
+and other rates.
+
+</dl>
-<a name="smtpd_error_sleep_time">
-<dt> <b>smtpd_error_sleep_time</b> (default: 1 second) <dd> When
-the per-session error count is small, the SMTP server pauses only
-when reporting a problem to a client. The purpose is to prevent
-naive clients from going into a fast <i>connect-error-disconnect</i>
-loop.
+<a name="slowdown"><h2> Slowing down bad clients</h2></a>
+
+The Postfix <a href="smtpd.8.html">SMTP server</a> increments a
+per-session error counter whenever a client request is unrecognized
+or unimplemented, whenever a client request violates <a
+href="uce.html">UCE restrictions</a>, or for other reasons that
+cause Postfix to report an error of some kind. The error counter
+is reset after a message is transferred successfully.
<p>
-<a name="smtpd_soft_error_limit">
+As the per-session error count increases, the SMTP server changes
+behavior and inserts delays before responding. The idea is to
+limit the damage by slowing down the client. The downside is that
+this ties up Postfix resources that can no longer be used by
+legitimate clients. Sites that are concerned about performance
+may want to turn off the delays altogether.
-<dt> <b>smtpd_soft_error_limit</b> (default: 10) <dd> When the
-per-session error count exceeds this value, the SMTP server sleeps
-<b>error_count</b> seconds before responding to a client request.
+<p>
+
+The behavior is controlled by the following parameters:
<p>
-<a name="smtpd_hard_error_limit">
+<dl>
-<dt> <b>smtpd_hard_error_limit</b> (default: 20) <dd> When
-the per-session error count exceeds this value, the SMTP server
-disconnects.
+<dt> <a name="smtpd_error_sleep_time"> <b>smtpd_error_sleep_time</b></a>
+(default: 1 second) <dd> When the per-session error count is small,
+the SMTP server pauses only when reporting a problem to a client.
+The purpose is to prevent naive clients from going into a fast
+<i>connect-error-disconnect</i> loop.
-</dl>
+<p>
+
+<dt> <a name="smtpd_soft_error_limit"> <b>smtpd_soft_error_limit</b></a>
+(default: 10) <dd> When the per-session error count exceeds this
+value, the SMTP server sleeps <b>error_count</b> seconds before
+responding to a client request.
<p>
-Unfortunately, the Postfix SMTP server does not yet know how to
-limit the number of connections <i> from the same client</i>,
-other than by limiting the total number of SMTP server processes
-(see <a href="#process">process limit</a>). Things could be worse:
-some mailers don't even implement an SMTP server process limit.
-That's of course no excuse. I'm still looking for a good solution.
+
+<dt> <a name="smtpd_hard_error_limit"> <b>smtpd_hard_error_limit</b></a>
+(default: 20) <dd> When the per-session error count exceeds this
+value, the SMTP server disconnects.
+
+</dl>
<hr>
<b>smtpd_client_connection_rate_limit</b>
The maximal number of connections per unit time
- (specified with <b>connection_rate_time_unit</b>) that any
+ (specified with <b>rate_limiter_time_unit</b>) that any
client is allowed to make to this service. When a
client exceeds the limit, the SMTP server logs a
warning with the client name/address and the ser-
ARFL = $ARFL
RANLIB = $RANLIB
SYSLIBS = $AUXLIBS $SYSLIBS
-CC = $CC -DSNAPSHOT $CCARGS
+CC = $CC $CCARGS
OPT = $OPT
DEBUG = $DEBUG
AWK = $AWK
The following \fBmain.cf\fR parameters are especially relevant to
this program. Use the \fBpostfix reload\fR command after
a configuration change.
-.IP \fBclient_connection_rate_time_unit\fR
+.IP \fBrate_limiter_time_unit\fR
The unit of time over which connection rates are calculated.
.IP \fBclient_connection_status_update_time\fR
Time interval for logging the maximal connection count
name/address and the service name as configured in master.cf.
.IP \fBsmtpd_client_connection_rate_limit\fR
The maximal number of connections per unit time (specified
-with \fBconnection_rate_time_unit\fR) that any client
+with \fBrate_limiter_time_unit\fR) that any client
is allowed to make to this service. When a client exceeds
the limit, the SMTP server logs a warning with the client
name/address and the service name as configured in master.cf.
'`
ln -s $link $tempdir/junk || exit 1
mv -f $tempdir/junk $2 || {
- echo $0: Error: your mv command is unable to rename symlinks. 1>&2
+ echo $0: Error: your mv command has trouble renaming symlinks. 1>&2
echo If you run Linux, upgrade to GNU fileutils-4.0 or better, 1>&2
echo or choose a tempdir that is in the same file system as $2. 1>&2
+ echo If you run FreeBSD, upgrade to version 5 or better. 1>&2
exit 1
}
}
COMMAND_DIRECTORY=$install_root$command_directory
QUEUE_DIRECTORY=$install_root$queue_directory
SENDMAIL_PATH=$install_root$sendmail_path
-NEWALIASES_PATH=$install_root$newaliases_path
-MAILQ_PATH=$install_root$mailq_path
MANPAGE_DIRECTORY=$install_root$manpage_directory
SAMPLE_DIRECTORY=$install_root$sample_directory
README_DIRECTORY=$install_root$readme_directory
};;
esac
+ # Save source path before it is clobbered.
+
+ case $type in
+ [hl]) eval source=$owner;;
+ esac
+
# If installing from source code, apply special permissions or ownership.
# If building a package, don't apply special permissions or ownership.
group=;;
esac
- # Create directory.
case $type in
- d) eval path=$install_root$path
- test "$path" = "${install_root}no" -o -d $path || {
- mkdir -p $path || exit 1
- test -z "$owner" || chown $owner $path || exit 1
- test -z "$group" || chgrp $group $path || exit 1
- chmod $mode $path || exit 1
- }
- continue;;
- [fl]) ;;
- *) echo $0: Error: unknown type for $path in conf/postfix-files; exit 1;;
- esac
- # Install or replace file.
+ # Create/update directory.
- echo $path | (IFS=/ read prefix file; IFS="$BACKUP_IFS"
+ d) eval path=$install_root$path
+ test "$path" = "${install_root}no" -o -d $path || {
+ mkdir -p $path || exit 1
+ test -z "$owner" || chown $owner $path || exit 1
+ test -z "$group" || chgrp $group $path || exit 1
+ chmod $mode $path || exit 1
+ }
+ continue;;
+
+ # Create/update regular file.
+
+ f) echo $path | (IFS=/ read prefix file; IFS="$BACKUP_IFS"
case $prefix in
'$daemon_directory')
compare_or_replace $mode "$owner" "$group" libexec/$file \
check_parent $SENDMAIL_PATH || exit 1
compare_or_replace $mode "$owner" "$group" bin/sendmail \
$SENDMAIL_PATH || exit 1;;
- '$mailq_path')
- check_parent $MAILQ_PATH || exit 1
- compare_or_symlink $SENDMAIL_PATH $MAILQ_PATH || exit 1;;
- '$nqmgr_path')
- compare_or_hardlink $DAEMON_DIRECTORY/qmgr \
- $DAEMON_DIRECTORY/nqmgr || exit 1;;
- '$newaliases_path')
- check_parent $NEWALIASES_PATH || exit 1
- compare_or_symlink $SENDMAIL_PATH $NEWALIASES_PATH || exit 1;;
'$manpage_directory')
check_parent $MANPAGE_DIRECTORY/$file || exit 1
compare_or_replace $mode "$owner" "$group" man/$file \
test "$readme_directory" = "no" ||
compare_or_replace $mode "$owner" "$group" README_FILES/$file \
$README_DIRECTORY/$file || exit 1;;
- *) echo $0: Error: unknown entry $path in conf/postfix-files; exit 1;;
- esac) || exit 1
-done
+ *) echo $0: Error: unknown entry $path in conf/postfix-files 1>&2
+ exit 1;;
+ esac) || exit 1
+ continue;;
+
+ # Hard link
+
+ h) eval dest_path=$install_root$path
+ check_parent $dest_path || exit 1
+ eval source_path=$install_root$source
+ compare_or_hardlink $source_path $dest_path || exit 1
+ continue;;
+
+ # Symbolic link
+
+ l) eval dest_path=$install_root$path
+ check_parent $dest_path || exit 1
+ eval source_path=$install_root$source
+ compare_or_symlink $source_path $dest_path || exit 1
+ continue;;
+
+ *) echo $0: Error: unknown type $type for $path in conf/postfix-files 1>&2
+ exit 1;;
+ esac
+
+ done
# Save the installation parameters to main.cf even when they haven't
# changed from their current default. Defaults can change between
/* The following \fBmain.cf\fR parameters are especially relevant to
/* this program. Use the \fBpostfix reload\fR command after
/* a configuration change.
-/* .IP \fBclient_connection_rate_time_unit\fR
+/* .IP \fBrate_limiter_time_unit\fR
/* The unit of time over which connection rates are calculated.
/* .IP \fBclient_connection_status_update_time\fR
/* Time interval for logging the maximal connection count
flush_clnt.o: ../../include/iostuff.h
flush_clnt.o: ../../include/attr.h
flush_clnt.o: mail_flush.h
-flush_clnt.o: flush_clnt.h
flush_clnt.o: mail_params.h
+flush_clnt.o: domain_list.h
+flush_clnt.o: ../../include/match_list.h
+flush_clnt.o: ../../include/match_ops.h
+flush_clnt.o: match_parent_style.h
+flush_clnt.o: flush_clnt.h
header_opts.o: header_opts.c
header_opts.o: ../../include/sys_defs.h
header_opts.o: ../../include/msg.h
mail_dict.o: ../../include/vbuf.h
mail_dict.o: ../../include/argv.h
mail_dict.o: ../../include/msg.h
+mail_dict.o: dict_proxy.h
mail_dict.o: dict_ldap.h
mail_dict.o: dict_mysql.h
mail_dict.o: dict_pgsql.h
extern int var_max_queue_time;
#define VAR_DSN_QUEUE_TIME "bounce_queue_lifetime"
-#define DEF_DSN_QUEUE_TIME "$" VAR_MAX_QUEUE_TIME /* XXX no time unit */
+#define DEF_DSN_QUEUE_TIME "5d"
extern int var_dsn_queue_time;
#define VAR_DELAY_WARN_TIME "delay_warning_time"
#define DEF_SMTPD_HOGGERS "$" VAR_MYNETWORKS
extern char *var_smtpd_hoggers;
-#define VAR_ANVIL_TIME_UNIT "client_connection_rate_time_unit"
+#define VAR_ANVIL_TIME_UNIT "rate_limiter_time_unit"
#define DEF_ANVIL_TIME_UNIT "60s"
extern int var_anvil_time_unit;
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20040105"
+#define MAIL_RELEASE_DATE "20040116"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
REC_TYPE_ORCP, "original_recipient",
REC_TYPE_WARN, "warning_message_time",
REC_TYPE_ATTR, "named_attribute",
+ REC_TYPE_KILL, "killed_record",
REC_TYPE_MESG, "message_content",
REC_TYPE_CONT, "unterminated_text",
REC_TYPE_NORM, "regular_text",
* record group contains data records with the message content. The last
* record group is optional; it contains information extracted from message
* headers, such as recipients, errors-to and return-receipt.
+ *
+ * Note: REC_TYPE_FILT and REC_TYPE_CONT are encoded with the same 'L'
+ * constant, and it is too late to change that now.
*/
#define REC_TYPE_SIZE 'C' /* first record, created by cleanup */
#define REC_TYPE_TIME 'T' /* time stamp, required */
#define REC_TYPE_ORCP 'O' /* original recipient, optional */
#define REC_TYPE_WARN 'W' /* warning message time */
#define REC_TYPE_ATTR 'A' /* named attribute for extensions */
+#define REC_TYPE_KILL 'K' /* killed record */
#define REC_TYPE_RDR '>' /* redirect target */
#define REC_TYPE_FLGS 'f' /* cleanup processing flags */
* have to read all the queue file records before starting delivery. This
* is often the case with list mail, where such optimization is desirable.
*/
-#define REC_TYPE_ENV_RECIPIENT "MDRO"
-#define REC_TYPE_EXT_RECIPIENT "EDRO"
+#define REC_TYPE_ENV_RECIPIENT "MDROK"
+#define REC_TYPE_EXT_RECIPIENT "EDROK"
/*
* The types of records that I expect to see while processing different
* Note: REC_TYPE_FILT and REC_TYPE_CONT are encoded with the same 'L'
* constant, and it is too late to change that now.
*/
-#define REC_TYPE_ENVELOPE "MCTFILSDROWVA>"
+#define REC_TYPE_ENVELOPE "MCTFILSDROWVA>K"
#define REC_TYPE_CONTENT "XLN"
-#define REC_TYPE_EXTRACT "EDROPreAFIL>"
+#define REC_TYPE_EXTRACT "EDROPreAFIL>K"
/*
* The subset of inputs that the postdrop command allows.
request->arrival_time,
"%s", vstring_str(why));
}
+ if (request->hop_status == 0)
+ request->hop_status = mystrdup(vstring_str(why));
/*
* Cleanup.
int flags; /* delivery problems */
int qflags; /* queuing flags */
int tflags; /* tracing flags */
+ long tflags_offset; /* offset for killing */
int rflags; /* queue file read flags */
VSTREAM *fp; /* open queue file or null */
int refcount; /* queue entries */
extern void qmgr_message_free(QMGR_MESSAGE *);
extern void qmgr_message_update_warn(QMGR_MESSAGE *);
+extern void qmgr_message_kill_record(QMGR_MESSAGE *, long);
extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int);
extern QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *);
char *myname = "qmgr_active_done_2_generic";
const char *path;
struct stat st;
+ int status;
/*
* A delivery agent marks a queue file as corrupt by changing its
* trace information. This will block for 10 seconds when the qmgr FIFO
* is full.
*/
- if (message->tflags & (DEL_REQ_FLAG_EXPAND | DEL_REQ_FLAG_RECORD))
- message->flags |= trace_flush(message->tflags,
- message->queue_name,
- message->queue_id,
- message->encoding,
- message->sender);
+ if (message->tflags & (DEL_REQ_FLAG_EXPAND | DEL_REQ_FLAG_RECORD)) {
+ status = trace_flush(message->tflags,
+ message->queue_name,
+ message->queue_id,
+ message->encoding,
+ message->sender);
+ if (status == 0 && message->tflags_offset)
+ qmgr_message_kill_record(message, message->tflags_offset);
+ message->flags |= status;
+ }
/*
* If we get to this point we have tried all recipients for this message.
* No problems detected. Mark the transport and queue as alive. The queue
* itself won't go away before we dispose of the current queue entry.
*/
- if (status == 0) {
+ if (VSTRING_LEN(reason) == 0) {
qmgr_transport_unthrottle(transport);
qmgr_queue_unthrottle(queue);
}
/*
/* void qmgr_message_update_warn(message)
/* QMGR_MESSAGE *message;
+/*
+/* void qmgr_message_kill_record(message, offset)
+/* QMGR_MESSAGE *message;
+/* long offset;
/* DESCRIPTION
/* This module performs en-gross operations on queue messages.
/*
/*
/* qmgr_message_update_warn() takes a closed message, opens it, updates
/* the warning field, and closes it again.
+/*
+/* qmgr_message_kill_record() takes a closed message, opens it, updates
+/* the record type at the given offset to "killed", and closes the file.
+/* A killed envelope record is ignored. Killed records are not allowed
+/* inside the message content.
/* DIAGNOSTICS
/* Warnings: malformed message file. Fatal errors: out of memory.
/* SEE ALSO
message->flags = 0;
message->qflags = qflags;
message->tflags = 0;
+ message->tflags_offset = 0;
message->rflags = QMGR_READ_FLAG_DEFAULT;
message->fp = 0;
message->refcount = 0;
/* Optional tracing flags. */
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
+ if (message->tflags == DEL_REQ_FLAG_RECORD)
+ message->tflags_offset = curr_offset;
+ else
+ message->tflags_offset = 0;
}
continue;
}
qmgr_message_close(message);
}
+/* qmgr_message_kill_record - mark one message record as killed */
+
+void qmgr_message_kill_record(QMGR_MESSAGE *message, long offset)
+{
+ if (offset <= 0)
+ msg_panic("qmgr_message_kill_record: bad offset 0x%lx", offset);
+ if (qmgr_message_open(message)
+ || rec_put_type(message->fp, REC_TYPE_KILL, offset) < 0
+ || vstream_fflush(message->fp))
+ msg_fatal("update queue file %s: %m", VSTREAM_PATH(message->fp));
+ qmgr_message_close(message);
+}
+
/* qmgr_message_sort_compare - compare recipient information */
static int qmgr_message_sort_compare(const void *p1, const void *p2)
int flags; /* delivery problems */
int qflags; /* queuing flags */
int tflags; /* tracing flags */
+ long tflags_offset; /* offset for killing */
int rflags; /* queue file read flags */
VSTREAM *fp; /* open queue file or null */
int refcount; /* queue entries */
extern void qmgr_message_free(QMGR_MESSAGE *);
extern void qmgr_message_update_warn(QMGR_MESSAGE *);
+extern void qmgr_message_kill_record(QMGR_MESSAGE *, long);
extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int);
extern QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *);
char *myname = "qmgr_active_done_2_generic";
const char *path;
struct stat st;
+ int status;
/*
* A delivery agent marks a queue file as corrupt by changing its
* trace information. This will block for 10 seconds when the qmgr FIFO
* is full.
*/
- if (message->tflags & (DEL_REQ_FLAG_EXPAND | DEL_REQ_FLAG_RECORD))
- message->flags |= trace_flush(message->tflags,
- message->queue_name,
- message->queue_id,
- message->encoding,
- message->sender);
+ if (message->tflags & (DEL_REQ_FLAG_EXPAND | DEL_REQ_FLAG_RECORD)) {
+ status = trace_flush(message->tflags,
+ message->queue_name,
+ message->queue_id,
+ message->encoding,
+ message->sender);
+ if (status == 0 && message->tflags_offset)
+ qmgr_message_kill_record(message, message->tflags_offset);
+ message->flags |= status;
+ }
/*
* If we get to this point we have tried all recipients for this message.
* No problems detected. Mark the transport and queue as alive. The queue
* itself won't go away before we dispose of the current queue entry.
*/
- if (status == 0) {
+ if (VSTRING_LEN(reason) == 0) {
qmgr_transport_unthrottle(transport);
qmgr_queue_unthrottle(queue);
}
/*
/* void qmgr_message_update_warn(message)
/* QMGR_MESSAGE *message;
+/*
+/* void qmgr_message_kill_record(message, offset)
+/* QMGR_MESSAGE *message;
+/* long offset;
/* DESCRIPTION
/* This module performs en-gross operations on queue messages.
/*
/*
/* qmgr_message_update_warn() takes a closed message, opens it, updates
/* the warning field, and closes it again.
+/*
+/* qmgr_message_kill_record() takes a closed message, opens it, updates
+/* the record type at the given offset to "killed", and closes the file.
+/* A killed envelope record is ignored. Killed records are not allowed
+/* inside the message content.
/* DIAGNOSTICS
/* Warnings: malformed message file. Fatal errors: out of memory.
/* SEE ALSO
message->flags = 0;
message->qflags = qflags;
message->tflags = 0;
+ message->tflags_offset = 0;
message->rflags = QMGR_READ_FLAG_DEFAULT;
message->fp = 0;
message->refcount = 0;
/* Optional tracing flags. */
else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
+ if (message->tflags == DEL_REQ_FLAG_RECORD)
+ message->tflags_offset = curr_offset;
+ else
+ message->tflags_offset = 0;
}
continue;
}
qmgr_message_close(message);
}
+/* qmgr_message_kill_record - mark one message record as killed */
+
+void qmgr_message_kill_record(QMGR_MESSAGE *message, long offset)
+{
+ if (offset <= 0)
+ msg_panic("qmgr_message_kill_record: bad offset 0x%lx", offset);
+ if (qmgr_message_open(message)
+ || rec_put_type(message->fp, REC_TYPE_KILL, offset) < 0
+ || vstream_fflush(message->fp))
+ msg_fatal("update queue file %s: %m", VSTREAM_PATH(message->fp));
+ qmgr_message_close(message);
+}
+
/* qmgr_message_sort_compare - compare recipient information */
static int qmgr_message_sort_compare(const void *p1, const void *p2)
"%s", vstring_str(why));
SMTP_RCPT_DROP(state, rcpt);
}
+ /* XXX This assumes no fall-back relay. */
+ if (request->hop_status == 0)
+ request->hop_status = mystrdup(vstring_str(why));
}
/*
/* name/address and the service name as configured in master.cf.
/* .IP \fBsmtpd_client_connection_rate_limit\fR
/* The maximal number of connections per unit time (specified
-/* with \fBconnection_rate_time_unit\fR) that any client
+/* with \fBrate_limiter_time_unit\fR) that any client
/* is allowed to make to this service. When a client exceeds
/* the limit, the SMTP server logs a warning with the client
/* name/address and the service name as configured in master.cf.
&& anvil_clnt_connect(anvil_clnt, service, state->addr,
&count, &crate) == ANVIL_STAT_OK) {
if (var_smtpd_cconn_limit > 0 && count > var_smtpd_cconn_limit) {
- smtpd_chat_reply(state, "450 Too many connections from %s",
+ smtpd_chat_reply(state, "421 Too many connections from %s",
state->addr);
msg_warn("Too many connections: %d from %s for service %s",
count, state->addr, service);
break;
}
if (var_smtpd_crate_limit > 0 && crate > var_smtpd_crate_limit) {
- smtpd_chat_reply(state, "450 Too many connections from %s",
+ smtpd_chat_reply(state, "421 Too many connections from %s",
state->addr);
msg_warn("Too frequent connections: %d from %s for service %s",
crate, state->addr, service);
*/
if (var_queue_minfree > 0
&& var_message_limit > 0
- && var_queue_minfree / 2 < var_message_limit)
- msg_warn("%s(%lu) should be at least 2*%s(%lu)",
+ && var_queue_minfree / 1.5 < var_message_limit)
+ msg_warn("%s(%lu) should be at least 1.5*%s(%lu)",
VAR_QUEUE_MINFREE, (unsigned long) var_queue_minfree,
VAR_MESSAGE_LIMIT, (unsigned long) var_message_limit);
* Check the hostnames first, then the addresses.
*/
for (server = server_list; server != 0; server = server->next) {
+ if (msg_verbose)
+ msg_info("%s: %s hostname check: %s",
+ myname, dns_strtype(type), (char *) server->data);
+ if ((status = check_domain_access(state, table, (char *) server->data,
+ FULL, &found, reply_name, reply_class,
+ def_acl)) != 0 || found)
+ CHECK_SERVER_RETURN(status);
h_errno = 0; /* XXX */
if ((hp = gethostbyname((char *) server->data)) == 0) {
msg_warn("Unable to look up %s host %s for %s %s: %s",
hp->h_addrtype, hp->h_length, (char *) server->data);
continue; /* XXX */
}
- if (msg_verbose)
- msg_info("%s: %s hostname check: %s",
- myname, dns_strtype(type), (char *) server->data);
- if ((status = check_domain_access(state, table, (char *) server->data,
- FULL, &found, reply_name, reply_class,
- def_acl)) != 0 || found)
- CHECK_SERVER_RETURN(status);
if (msg_verbose)
msg_info("%s: %s host address check: %s",
myname, dns_strtype(type), (char *) server->data);