]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.6-20090404
authorWietse Venema <wietse@porcupine.org>
Sat, 4 Apr 2009 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:35:13 +0000 (06:35 +0000)
81 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/Makefile.in
postfix/README_FILES/BUILTIN_FILTER_README
postfix/README_FILES/MULTI_INSTANCE_README [new file with mode: 0644]
postfix/README_FILES/OVERVIEW
postfix/README_FILES/STANDARD_CONFIGURATION_README
postfix/README_FILES/STRESS_README
postfix/RELEASE_NOTES
postfix/WISHLIST
postfix/conf/postfix-files
postfix/conf/postfix-script
postfix/conf/postmulti-script [new file with mode: 0644]
postfix/html/BUILTIN_FILTER_README.html
postfix/html/MULTI_INSTANCE_README.html [new file with mode: 0644]
postfix/html/Makefile.in
postfix/html/OVERVIEW.html
postfix/html/STANDARD_CONFIGURATION_README.html
postfix/html/STRESS_README.html
postfix/html/cleanup.8.html
postfix/html/lmtp.8.html
postfix/html/mailq.1.html
postfix/html/newaliases.1.html
postfix/html/postconf.5.html
postfix/html/postfix-manuals.html
postfix/html/postfix-wrapper.5.html
postfix/html/postfix.1.html
postfix/html/postmulti.1.html [new file with mode: 0644]
postfix/html/sendmail.1.html
postfix/html/smtp.8.html
postfix/html/verify.8.html
postfix/makedefs
postfix/man/Makefile.in
postfix/man/man1/postmulti.1 [new file with mode: 0644]
postfix/man/man1/sendmail.1
postfix/man/man5/postconf.5
postfix/man/man5/postfix-wrapper.5
postfix/man/man8/cleanup.8
postfix/man/man8/smtp.8
postfix/man/man8/verify.8
postfix/mantools/postlink
postfix/proto/BUILTIN_FILTER_README.html
postfix/proto/MULTI_INSTANCE_README.html [new file with mode: 0644]
postfix/proto/Makefile.in
postfix/proto/OVERVIEW.html
postfix/proto/STANDARD_CONFIGURATION_README.html
postfix/proto/STRESS_README.html
postfix/proto/postconf.proto
postfix/proto/postfix-wrapper
postfix/src/cleanup/cleanup.c
postfix/src/cleanup/cleanup_init.c
postfix/src/cleanup/cleanup_message.c
postfix/src/dns/test_dns_lookup.c
postfix/src/global/dict_ldap.c
postfix/src/global/mail_conf_nint.c
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/oqmgr/qmgr_transport.c
postfix/src/postfix/postfix.c
postfix/src/postmulti/.indent.pro [new symlink]
postfix/src/postmulti/Makefile.in [new file with mode: 0644]
postfix/src/postmulti/postmulti.c [new file with mode: 0644]
postfix/src/qmgr/qmgr.h
postfix/src/qmgr/qmgr_entry.c
postfix/src/qmgr/qmgr_job.c
postfix/src/qmgr/qmgr_queue.c
postfix/src/qmgr/qmgr_transport.c
postfix/src/sendmail/sendmail.c
postfix/src/smtp/Makefile.in
postfix/src/smtp/lmtp_params.c
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp_rcpt.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_chat.c
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_proxy.c
postfix/src/util/inet_listen.c
postfix/src/util/inet_windowsize.c
postfix/src/verify/verify.c
postfix/src/xsasl/xsasl_cyrus_server.c

index 134180a348c8a0237d77ef9003da66e3c0978cc8..32dcd9910000ddc3dea3312464aa13866e6acd14 100644 (file)
 -THTABLE_INFO
 -TINET_ADDR_LIST
 -TINET_PROTO_INFO
+-TINSTANCE
+-TINST_SELECTION
 -TINT32_TYPE
 -TINTV
 -TINT_TABLE
 -TMYSQL
 -TMYSQL_NAME
 -TNAMADR_LIST
+-TNAME_ASSIGNMENT
 -TNAME_CODE
 -TNAME_MASK
 -TPEER_NAME
 -TPLPGSQL
 -TPOSTMAP_KEY_STATE
 -TPOST_MAIL_STATE
+-TPRIVATE_STR_TABLE
 -TQMGR_ENTRY
 -TQMGR_FEEDBACK
 -TQMGR_JOB
 -TSCAN_INFO
 -TSCAN_OBJ
 -TSESSION
+-TSHARED_PATH
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
index 44cc0077e0316799e885314c9daa24a21274917c..790ecad505dc99fa5f040aac9d639d1c4721ac3e 100644 (file)
@@ -14983,3 +14983,100 @@ Apologies for any names omitted.
        Feature: stress-dependent smtpd_timeout (normal: 300s,
        overload: 10s), smtpd_hard_error_limit (normal: 20, overload:
        1) and smtpd_junk_command_limit (normal: 100, overload: 1).
+       Files: global/mail_params.h, global/mail_conf_nint.c,
+       master/*_server.c, smtpd/smtpd.c.
+
+20090213
+
+       Fine tuning: don't enforce smtpd_junk_command_limit for
+       XCLIENT and XFORWARD commands.  These commands can be issued
+       only by authorized clients. File: src/smtpd/smtpd.c.
+
+20090215
+
+       Feature: the Postfix SMTP server hangs up after replying
+       with "521". This makes overload handling more effective. 
+       See also RFC 1846.  File: smtpd/smtpd.c.
+
+       Feature: postmulti mult-instance manager command, very
+       lightly tested. The MULTI_INSTANCE_README still needs to
+       be proofread.  Originally by Victor Duchovni.  Files:
+       src/postmulti/*, proto/MULTI_INSTANCE_README.html,
+       conf/postmulti-script.
+
+20090216-24
+
+       Cleanup: assorted code cleanups in postmulti.  File:
+       src/postmulti/postmulti.c.
+
+20090223
+
+       Cleanup: multiple instances of the same global.  Files:
+       util/inet_windowsize.c, util/inet_listen.c.
+
+20090228
+
+       Cleanup: the Postfix SMTP server now maintains a per-session
+       "improper command pipelining detected" flag. This flag can
+       be tested at any time with reject_unauth_pipelining, and
+       is raised whenever a client command is followed by unexpected
+       commands or message content.  Files: smtpd/smtpd.c,
+       smtpd/smtpd_check.c.
+
+       Logging: the Postfix SMTP server now logs the first command
+       pipelining transgression as "improper command pipelining
+       after <command> from <hostname>[<hostaddress>]".
+
+       Cleanup: after DATA command failure, log "(approximately
+       XX bytes)" only if Postfix actually accepted the DATA
+       command.  File: smtpd/smtpd.c.
+
+20090303
+
+       Cleanup: word smithing of "sendmail -bv" probe message.
+       File: sendmail/sendmail.c.
+
+       Cleanup: OpenLDAP now provides a sane solution for conflicts
+       with PAM ldap-over-tls. Victor Duchovni.  File: global/dict_ldap.c.
+
+20900304
+
+       Cleanup: skip over suspended or throttled queues while
+       looking for delivery requests. File: *qmgr/qmgr_transport.c.
+
+20090305
+
+       Bugfix: in the "new queue manager", the _destination_rate_delay
+       code needed to postpone the job scheduler updates after
+       delivery completion, otherwise the scheduler could loop on
+       blocked jobs.  Victor & Wietse.  File: qmgr/qmgr_entry.c,
+       qmgr/qmgr_queue.c, qmgr/qmgr_job.c.
+
+       Cleanup: report a "queue file write error", instead of
+       passing though bogus 2xx replies from proxy filters to SMTP
+       clients.  File: smtpd/smtpd_proxy.c.
+
+20090307
+
+       Cleanup: with "lmtp_assume_final = yes", the Postfix LMTP
+       delivery agent assumes that delivery is final when talking
+       to an LMTP server that announces no DSN support.  Otherwise,
+       the Postfix LMTP delivery agent assumes that delivery is
+       "relayed", to maintain compatibility with simple LMTP-based
+       content filters.  Based on code by Michel Sebastien, ATOS
+       Origin.  File: smtp/smtp_rcpt.c.
+
+20090310
+
+       Bugfix: Postfix used mumble_concurrency_failed_cohort_limit
+       instead of mumble_destination_concurrency_failed_cohort_limit
+       as documented. File: global/mail_params.h.
+
+20090330
+
+       Cleanup: add (Resent-) From:, Date:, Message-ID: or To:
+       headers only when clients match $local_header_rewrite_clients.
+       Specify "always_add_missing_headers = yes" for backwards
+       compatibility.  Adding such headers to remote mail can break
+       DKIM signatures that cover headers that are not present.
+       File: cleanup/cleanup_message.c.
index 99b798e16571befe7bd15c8e4734fe31e7c6d5aa..87a77d8dafa8a7e5db4a4ec7cd203c4144d40511 100644 (file)
@@ -8,10 +8,12 @@ DIRS  = src/util src/global src/dns src/tls src/xsasl src/milter src/master \
        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 src/scache src/discard src/tlsmgr
+       src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr \
+       src/postmulti
 MANDIRS        = proto man html
 LIBEXEC        = libexec/post-install libexec/postfix-files libexec/postfix-script \
-       libexec/postfix-wrapper libexec/main.cf libexec/master.cf
+       libexec/postfix-wrapper libexec/main.cf libexec/master.cf \
+       libexec/postmulti-script
 
 default: update
 
@@ -33,34 +35,25 @@ update printfck tests root_tests:
 update: $(LIBEXEC)
 
 libexec/post-install: conf/post-install
-       # XXX Work around broken hardlink implementations
-       rm -f $@
-       cp $? $@
+       rm -f $@ && ln -sf ../$? $@
 
 libexec/postfix-files: conf/postfix-files
-       # XXX Work around broken hardlink implementations
-       rm -f $@
-       cp $? $@
+       rm -f $@ && ln -sf ../$? $@
 
 libexec/postfix-script: conf/postfix-script
-       # XXX Work around broken hardlink implementations
-       rm -f $@
-       cp $? $@
+       rm -f $@ && ln -sf ../$? $@
 
 libexec/postfix-wrapper: conf/postfix-wrapper
-       # XXX Work around broken hardlink implementations
-       rm -f $@
-       cp $? $@
+       rm -f $@ && ln -sf ../$? $@
 
 libexec/main.cf: conf/main.cf
-       # XXX Work around broken hardlink implementations
-       rm -f $@
-       cp $? $@
+       rm -f $@ && ln -sf ../$? $@
 
 libexec/master.cf: conf/master.cf
-       # XXX Work around broken hardlink implementations
-       rm -f $@
-       cp $? $@
+       rm -f $@ && ln -sf ../$? $@
+
+libexec/postmulti-script: conf/postmulti-script
+       rm -f $@ && ln -sf ../$? $@
 
 manpages:
        set -e; for i in $(MANDIRS); do \
index e0c73526be65a0230b0092761c905c7de2b19fbe..de8fa7dd8c6f9ba85180cb7a717d95ea20236944 100644 (file)
@@ -213,8 +213,8 @@ all mail and complicate Postfix maintenance.
 
 C\bCo\bon\bnf\bfi\big\bgu\bur\bri\bin\bng\bg h\bhe\bea\bad\bde\ber\br/\b/b\bbo\bod\bdy\by c\bch\bhe\bec\bck\bks\bs f\bfo\bor\br m\bma\bai\bil\bl f\bfr\bro\bom\bm o\bou\but\bts\bsi\bid\bde\be u\bus\bse\ber\brs\bs o\bon\bnl\bly\by
 
-The following information applies to Postfix 2.1. Earlier Postfix versions do
-not support the receive_override_options feature.
+The following information applies to Postfix 2.1 and later. Earlier Postfix
+versions do not support the receive_override_options feature.
 
 The easiest approach is to configure ONE Postfix instance with multiple SMTP
 server IP addresses in master.cf:
@@ -235,6 +235,9 @@ server IP addresses in master.cf:
         pickup         fifo  n       -       n       60      1       pickup
             -o receive_override_options=no_header_body_checks
 
+  * Add some firewall rule to prevent access to 1.2.3.4:smtp from the outside
+    world.
+
   * One SMTP server address for mail from outside users with header/body
     filtering turned on via main.cf.
 
diff --git a/postfix/README_FILES/MULTI_INSTANCE_README b/postfix/README_FILES/MULTI_INSTANCE_README
new file mode 100644 (file)
index 0000000..80a086c
--- /dev/null
@@ -0,0 +1,979 @@
+M\bMa\ban\bna\bag\bgi\bin\bng\bg m\bmu\bul\blt\bti\bip\bpl\ble\be P\bPo\bos\bst\btf\bfi\bix\bx i\bin\bns\bst\bta\ban\bnc\bce\bes\bs o\bon\bn a\ba s\bsi\bin\bng\bgl\ble\be h\bho\bos\bst\bt
+
+-------------------------------------------------------------------------------
+
+O\bOv\bve\ber\brv\bvi\bie\bew\bw
+
+This document is a guide to managing multiple Postfix instances on a single
+host using the postmulti(1) instance manager. Multi-instance support is
+available with Postfix version 2.6 and later. See the postfix-wrapper(5) manual
+page for background on the instance management framework, and on how to deploy
+a custom instance manager.
+
+Topics covered in this document:
+
+  * Why multiple Postfix instances
+  * Null-client instances versus service instances
+  * Multi-instance walk-through
+  * Components of a Postfix system
+  * The default Postfix instance
+  * Instance groups
+  * Multi-instance configuration parameters
+  * Using the postmulti(1) command
+  * Credits
+
+W\bWh\bhy\by m\bmu\bul\blt\bti\bip\bpl\ble\be P\bPo\bos\bst\btf\bfi\bix\bx i\bin\bns\bst\bta\ban\bnc\bce\bes\bs
+
+Postfix is a general-purpose mail system that can be configured to serve a
+variety of needs. Examples of Postfix applications are:
+
+  * Local mail submission for shell users and system processes.
+
+  * Incoming (MX host) email from the Internet.
+
+  * Outbound mail relay for a corporate network.
+
+  * Authenticated submission for roaming users.
+
+  * Before/after content-filter mail.
+
+A single Postfix configuration can provide many or all of these services, but a
+complex interplay of settings may be required, for example with master.cf
+options overriding main.cf settings. In this document we take the view that
+multiple Postfix instances may be a simpler way to configure a multi-function
+Postfix system. With multiple Postfix instances, each instance has its own
+directories for configuration, queue and data files, but it shares all Postfix
+program and documentation files with other instances.
+
+Since there is no single right way to configure your system, we recommend that
+you choose what makes you most comfortable. If different Postfix services don't
+involve incompatible main.cf or master.cf settings, and if they can be combined
+together without complex tricks, then a single monolithic configuration may be
+the simplest approach.
+
+The purpose of multi-instance support in Postfix is not to force you to create
+multiple Postfix instances, but rather to give you a choice. Multiple instances
+give you the freedom to tune each Postfix instance to a single task that it
+does well and to combine instances into complete systems.
+
+With the introduction of the postmulti(1) utility and the reduction of the per-
+instance configuration footprint of a secondary Postfix instance to just a
+main.cf and master.cf file (other files are now in shared locations), we hope
+that multiple instances will be easier to use than ever before.
+
+N\bNu\bul\bll\bl-\b-c\bcl\bli\bie\ben\bnt\bt i\bin\bns\bst\bta\ban\bnc\bce\bes\bs v\bve\ber\brs\bsu\bus\bs s\bse\ber\brv\bvi\bic\bce\be i\bin\bns\bst\bta\ban\bnc\bce\bes\bs
+
+In the multi-instance approach to configuring Postfix, the first simplification
+is with the default local-submission Postfix instance.
+
+Most UNIX systems require support for email submission with the sendmail(1)
+command so that system processes such as cron jobs can send status reports, and
+so that system users can send email with command-line utilities. Such email can
+be handled with a null-client Postfix configuration that forwards all mail to a
+central mail hub. The null client will typically either not run an SMTP
+listener at all (master_service_disable = inet), or it will listen only on the
+loopback interface (inet_interfaces = loopback-only).
+
+When implementing specialized servers for inbound Internet email, outbound
+MTAs, internal mail hubs, and so on, we recommend using a null client for local
+submission and creating single-function secondary Postfix instances to serve
+the specialized needs.
+
+    Note: usually, you need to use different "myhostname" settings when you run
+    multiple instances on the same host. Otherwise, there will be false "mail
+    loops back to myself" alarms when one instance tries to send mail into
+    another instance. Typically, the null-client instance will use the system's
+    hostname, and other instances will use their own dedicated "myhostname"
+    settings. Different names are not needed when instances send mail to each
+    other with a protocol other than SMTP, or with SMTP over a TCP port other
+    than 25 as is usual with SMTP-based content filters.
+
+M\bMu\bul\blt\bti\bi-\b-i\bin\bns\bst\bta\ban\bnc\bce\be w\bwa\bal\blk\bk-\b-t\bth\bhr\bro\bou\bug\bgh\bh
+
+Before discussing the fine details of multi-instance operation we first show
+the steps for creating a border mail server. This server has with a null-client
+Postfix instance for local submission, an input Postfix instance to receive
+mail from the Internet, plus an advanced SMTP content-filter and an output
+Postfix instance to deliver filtered email to its internal destination.
+
+S\bSe\bet\btt\bti\bin\bng\bg u\bup\bp t\bth\bhe\be n\bnu\bul\bll\bl-\b-c\bcl\bli\bie\ben\bnt\bt P\bPo\bos\bst\btf\bfi\bix\bx i\bin\bns\bst\bta\ban\bnc\bce\be
+
+On a border mail hub, while mail from the Internet requires a great deal of
+scrutiny, locally submitted messages are typically limited to mail from cron
+jobs and other system services. In this regard the border MTA is not different
+from other Unix hosts in your environment. For this reason, it will submit
+locally-generated email to the internal mail hub. We start the construction of
+the border mail server with the default instance, which will be a local-
+submission null client:
+
+    /etc/postfix/main.cf:
+        # We are mta1.example.com
+        #
+        myhostname = mta1.example.com
+        mydomain = example.com
+
+        # Flat user-account namespace in example.com:
+        #
+        #   user@example.com not user@host.example.com
+        #
+        myorigin = $mydomain
+
+        # Postfix 2.6+, disable inet services, specifically disable smtpd(8)
+        #
+        master_service_disable = inet
+
+        # No local delivery:
+        #
+        mydestination =
+        local_transport = error:5.1.1 Mailbox unavailable
+        alias_database =
+        alias_maps =
+        local_recipient_maps =
+
+        # Send everything to the internal mailhub
+        #
+        relayhost = [mailhub.example.com]
+
+        # Indexed table macro:
+        # (use "hash", ... when cdb is not available)
+        #
+        default_database_type = cdb
+        indexed = ${default_database_type}:${config_directory}/
+
+        # Expose origin host of mail from "root", ...
+        #
+        smtp_generic_maps = ${indexed}generic
+
+        # Send messages addressed to "root", ... to the MTA support team
+        #
+        virtual_alias_maps = ${indexed}virtual
+
+    /etc/postfix/generic:
+        # The smarthost supports "+" addressing (recipient_delimiter = +).
+        # Mail from "root" exposes the origin host, without replies
+        # and bounces going back to the same host.
+        #
+        # On clustered MTAs this file is typically machine-built from
+        # a template file. The build process expands the template into
+        # "mtaadmin+root=mta1"
+        #
+        root           mtaadmin+root=mta1
+
+    /etc/postfix/virtual:
+        # Caretaker aliases:
+        #
+        root           mtaadmin
+        postmaster     root
+
+You would typically also add a Makefile, to automatically run postmap(1)
+commands when source files change. This Makefile also creates a "generic"
+database when none exists.
+
+    /etc/postfix/Makefile:
+        MTAADMIN=mtaadmin
+
+        all: virtual.cdb generic.cdb
+
+        generic: Makefile
+           @echo Creating $@
+           @rm -f $@.tmp
+           @printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` > $@.tmp
+           @mv $@.tmp generic
+
+        %.cdb: %
+           postmap cdb:$<
+
+Construct the "virtual" and "generic" databases (the latter is created by
+running "make"), then start and test the null-client:
+
+    # cd /etc/postfix; make
+    # postfix start
+    # sendmail -i -f root -t <<EOF
+    From: root
+    To: root
+    Subject: test
+
+    testing
+    EOF
+
+The test message should be delivered the members of the "mtaadmin" address
+group (or whatever address group you choose) with the following headers:
+
+    From: mtaadmin+root=mta1@example.com
+    To: mtadmin+root=mta1@example.com
+    Subject: test
+
+S\bSe\bet\btt\bti\bin\bng\bg u\bup\bp t\bth\bhe\be "\b"o\bou\but\btp\bpu\but\bt"\b" P\bPo\bos\bst\btf\bfi\bix\bx i\bin\bns\bst\bta\ban\bnc\bce\be
+
+With the null-client instance out of the way, we can create the MTA "output"
+instance that will deliver filtered mail to the inside network. We add the
+"output" instance first, because the output instance needs to be up and running
+before the input instance can be fully tested, and when the system boots, the
+"output" instance must start before the input instance. We will put the output
+and input instances into a single instance group named "mta".
+
+Just once, when adding the first secondary instance, enable multi-instance
+support in the default (null-client) instance:
+
+    # postmulti -e init
+
+Then create the output instance:
+
+    # postmulti -I postfix-out -G mta -e create
+
+The instance configuration directory defaults to /etc/postfix-out, more
+precisely, the "postfix-out" subdirectory of the parent directory of the
+default-instance configuration directory. The new instance will be created in a
+"disabled" state:
+
+    /etc/postfix-out/main.cf
+        #
+        # ... "stock" main.cf settings ...
+        #
+        multi_instance_name = postfix-out
+        queue_directory = /var/spool/postfix-out
+        data_directory = /var/lib/postfix-out
+        #
+        multi_instance_enable = no
+        master_service_disable = inet
+        authorized_submit_users =
+
+This instance has a "stock" master.cf file, and its queue and data directories,
+also named "postfix-out", will be located in the same parent directories as the
+corresponding directories of the default instance (e.g., /var/spool/postfix-out
+and /var/lib/postfix-out).
+
+While this instance is immediately safe to start, it is not yet usefully
+configured. It needs to be customized to fit the role of a post-filter re-
+injection SMTP service. Typical additions include:
+
+    /etc/postfix-out/master.cf:
+        # Replace default "smtp inet" entry with one listening on port 10026.
+        127.0.0.1:10026     inet  n       -       n       -       -       smtpd
+
+    /etc/postfix-out/main.cf
+        # ...
+
+        # Comment out if you don't use IPv6 internally
+        # inet_protocols = ipv4
+        inet_interfaces = loopback-only
+        mynetworks_style = host
+        smtpd_authorized_xforward_hosts = $mynetworks
+
+        # Don't anvil(8) control the re-injection port.
+        #
+        smtpd_client_connection_count_limit = 0
+        smtpd_client_event_limit_exceptions = $mynetworks
+
+        # Best practice when inet_interfaces is set, as this is not a
+        # "secondary IP personality" configuration.
+        #
+        smtp_bind_address = 0.0.0.0
+
+        # All header rewriting happens upstream
+        #
+        local_header_rewrite_clients =
+
+        # No local delivery on border gateway
+        #
+        mydestination =
+        alias_maps =
+        alias_database =
+        local_recipient_maps =
+        local_transport = error:5.1.1 Mailbox unavailable
+
+        # May need a recipient_delimiter for per-user transport lookups:
+        #
+        recipient_delimiter = +
+
+        # Only one (unrestricted client)
+        # With multiple instances, rarely need "-o param=value" overrides
+        # in master.cf, each instance gets its own main.cf file.
+        #
+        smtpd_recipient_restrictions = permit_mynetworks, reject
+
+        # Tolerate occasional high latency in the  content filter.
+        #
+        smtpd_timeout = 1200s
+
+        # Best when empty, with all parent domain matches explicit.
+        #
+        parent_domain_matches_subdomains =
+
+        # Use the "relay" transport for inbound mail, and the default
+        # "smtp" transport for outbound mail (bounces, ...). The latter
+        # won't starve the former of delivery agent slots.
+        #
+        relay_domains = example.com, .example.com
+
+        # With xforward, match the input instance setting, if you
+        # want "yes", set both to "yes".
+        #
+        smtpd_client_port_logging = no
+
+        # Transport settings ...
+        # Message size limit
+        # Concurrency tuning for "relay" and "smtp" transport
+        # ...
+
+With the "output" configuration in place, enable and start the instance:
+
+    1 # postmulti -i postfix-out -x postconf -e \
+    2     "master_service_disable =" "authorized_submit_users = root"
+    3 # postmulti -i postfix-out -e enable
+    4 # postmulti -i postfix-out -p start
+
+This uses the postmulti(1) command to invoke postconf(1) in the context
+(MAIL_CONFIG=/etc/postfix-out) of the output instance.
+
+  * Lines 1-2: With "authorized_submit_users = root", the superuser can test
+    the postix-out instance with "postmulti -i postfix-out -x sendmail -bv
+    recipient...", but otherwise local submission remains disabled.
+
+  * Lines 1-2: With "master_service_disable =", the "inet" listeners are re-
+    enabled.
+
+  * Line 3: The output instance is enabled for multi-instance start/stop.
+
+  * Line 4: The output instance is started.
+
+Test the output instance by submitting probe messages via "sendmail -bv" and
+"telnet". For production systems, in-depth configuration tests should be done
+on a lab system. The simple tests just suggested will only confirm successful
+deployment of a configuration that should already be known good.
+
+S\bSe\bet\btt\bti\bin\bng\bg u\bup\bp t\bth\bhe\be c\bco\bon\bnt\bte\ben\bnt\bt-\b-f\bfi\bil\blt\bte\ber\br p\bpr\bro\box\bxy\by
+
+With the output instance ready, deploy your content-filter proxy. Most proxies
+will need their own /etc/rc* start/stop script. Some proxies, however, are
+started on demand by the Postfix spawn(8) service, in which case you need to
+add the relevant spawn(8) entry to the output instance master.cf file.
+
+Configure the proxy to listen on 127.0.0.1:10025 and to re-inject filtered
+email to 127.0.0.1:10026. Start the proxy service if necessary, then test the
+proxy via "telnet" or automated SMTP injectors. The proxy should support the
+following ESMTP features: DSN, 8BITMIME, and XFORWARD. In addition, the proxy
+should support multiple mail deliveries within an SMTP session.
+
+S\bSe\bet\btt\bti\bin\bng\bg u\bup\bp t\bth\bhe\be i\bin\bnp\bpu\but\bt P\bPo\bos\bst\btf\bfi\bix\bx i\bin\bns\bst\bta\ban\bnc\bce\be
+
+The input Postfix instance receives mail from the network and sends it through
+the content filter. Now we create the input instance, also part of the "mta"
+instance group:
+
+    # postmulti -I postfix-in -G mta -e create
+
+The new instance configuration directory defaults to /etc/postfix-in, more
+precisely, the "postfix-in" subdirectory of the parent directory of the
+default-instance configuration directory. The new instance will be created in a
+"disabled" state:
+
+    /etc/postfix-in/main.cf
+        #
+        # ... "stock" main.cf settings ...
+        #
+        multi_instance_name = postfix-in
+        queue_directory = /var/spool/postfix-in
+        data_directory = /var/lib/postfix-in
+        #
+        multi_instance_enable = no
+        master_service_disable = inet
+        authorized_submit_users =
+
+As before, make appropriate changes to main.cf and master.cf to make the
+instance production ready. Consider setting "soft_bounce = yes" during the
+first few hours of deployment, so you can iron-out any unexpected "kinks".
+
+Manual testing can start with:
+
+    /etc/postfix-in/main.cf
+        # Accept only local traffic, but allow impersonation:
+        inet_interfaces = 127.0.0.1
+        smtpd_authorized_xclient_hosts = 127.0.0.1
+
+This allows you to use the Postfix-specific XCLIENT SMTP command to safely
+simulate connections from remote systems before any remote systems are able to
+connect. If the test results look good, revert the above settings to the
+required production values. Typical settings in the pre-filter input instance
+include:
+
+    /etc/postfix-in/main.cf
+        #
+        # ...
+        #
+
+        # No local delivery on border gateway
+        #
+        mydestination =
+        alias_maps =
+        alias_database =
+        local_recipient_maps =
+        local_transport = error:5.1.1 Mailbox unavailable
+
+        # Don't rewrite remote headers
+        #
+        local_header_rewrite_clients =
+
+        # All recipients of not yet filtered email go to the same filter
+    together.
+        #
+        # With multiple instances, the content-filter is specified
+        # via transport settings not the "content_filter" transport
+        # switch override! Here the filter listens on local port 10025.
+        #
+        # If you need to route some users or recipient domains directly to the
+        # output instance bypassing the filter, just define a transport table
+        # with suitable entries.
+        #
+        default_transport = smtp:[127.0.0.1]:10025
+        relay_transport = $default_transport
+        virtual_transport = $default_transport
+        transport_maps =
+
+        # Pass original client log information through the filter.
+        #
+        smtp_send_xforward_command = yes
+
+        # Avoid splitting the envelope and scanning messages multiple times.
+        # Match the re-injection server's recipient limit.
+        #
+       smtp_destination_recipient_limit = 1000
+
+        # Tolerate occasional high latency in the content filter.
+        #
+        smtp_data_done_timeout = 1200s
+
+        # With xforward, match the output instance setting, if you
+        # want "yes", set both to "yes".
+        #
+        smtpd_client_port_logging = no
+
+        # ... Lots of settings for inbound MX host ...
+
+With the "input" instance configured, enable and start it:
+
+    # postmulti -i postfix-in -x postconf -e \
+        "master_service_disable =" "authorized_submit_users = root"
+    # postmulti -i postfix-in -e enable
+    # postmulti -i postfix-in -p start
+
+That's it. You now have a 3-instance configuration. A null-client sending all
+locally submitted mail to the internal mail hub and a pair of "mta" instances
+that receive mail from the Internet, pass it through a content-filter, and then
+deliver it to the internal destination.
+
+Running "postfix start" or "postfix stop" will now start/stop all three Postfix
+instances. You can use "postfix -c /config/path start" to start just one
+instance, or use the instance name (or instance group name) via postmulti(1):
+
+    # postmulti -i - -p stop
+    # postmulti -g mta -p status
+    # postmulti -i postfix-out -p flush
+    # postmulti -i postfix-in -p reload
+    # ...
+
+This example ends the multi-instance "walk through". The remainder of this
+document provides background information on Postfix multi-instance support
+features and options.
+
+C\bCo\bom\bmp\bpo\bon\bne\ben\bnt\bts\bs o\bof\bf a\ba P\bPo\bos\bst\btf\bfi\bix\bx s\bsy\bys\bst\bte\bem\bm
+
+A Postfix system consists of the following components:
+
+Shared among all instances:
+
+  * Command-line utilities for administrators and users installed in
+    $command_directory, $sendmail_path, $mailq_path and $newaliases_path.
+
+  * Daemon executables, and run-time support files installed in
+    $daemon_directory.
+
+  * Bundled documentation, installed in $html_directory, $manpage_directory and
+    $readme_directory.
+
+  * Entries in /etc/passwd and /etc/group for the $mail_owner user and
+    $setgid_group group. The the $mail_owner user provides the mail system with
+    a protected (non-root) execution context. The $setgid_group group is used
+    exclusively to support the setgid postdrop(1) and postqueue(1) utilities
+    (it m\bmu\bus\bst\bt n\bno\bot\bt be the primary group or secondary group of any users,
+    including the $mail_owner user).
+
+Private to each instance:
+
+  * The main.cf, master.cf (and other optional) configuration files in
+    $config_directory.
+
+  * The maildrop, incoming, active, deferred and hold queues in
+    $queue_directory (which contains additional directories needed by Postfix,
+    and which optionally doubles as a chroot jail for Postfix daemon
+    processes).
+
+  * Various caches (TLS session, address verification, ...) in $data_directory.
+
+The Postfix configuration parameters mentioned above are collectively referred
+to as "installation parameters". Their default values are set when the Postfix
+software is built from source, and all but one may be optionally set to a non-
+default value via the main.cf file. The one parameter that (catch-22) cannot be
+set in main.cf is $config_directory, as this defines the location of the
+main.cf file itself.
+
+Though config_directory cannot be set in main.cf, postfix(1) and most of the
+other command-line Postfix utilities allow you to specify a non-default
+configuration directory via a command line option (typically -\b-c\bc) or via the
+MAIL_CONFIG environment variable. In this way, it is possible to have multiple
+configuration directories on the same machine, and to have multiple running
+master(8) daemons each with its own configuration files, queue directory and
+data directory.
+
+These multiple running copies of master(8) share the base Postfix software.
+They do not (and cannot) share their configuration directories, queue
+directories or data directories.
+
+Each combination of configuration directory, together with the queue directory
+and data directory (specified in the corresponding main.cf file) make up a
+Postfix i\bin\bns\bst\bta\ban\bnc\bce\be.
+
+T\bTh\bhe\be d\bde\bef\bfa\bau\bul\blt\bt P\bPo\bos\bst\btf\bfi\bix\bx i\bin\bns\bst\bta\ban\bnc\bce\be
+
+One Postfix instance is special: this is the instance whose configuration
+directory is the default one compiled into the Postfix utilities. The location
+of the default configuration directory is typically /etc/postfix, and can be
+queried via the "postconf -d config_directory" command. We call the instance
+with this configuration directory the "default instance".
+
+The default instance is responsible for local mail submission. The setgid
+postdrop(1) utility is used by the sendmail(1) local submission program to
+spool messages into the m\bma\bai\bil\bld\bdr\bro\bop\bp sub-directory of the queue directory of the
+default instance.
+
+Even in the rare case when "sendmail -C" is used to submit local mail into a
+non-default Postfix instance, for security reasons, postdrop(1) will consult
+the default main.cf file to check the validity of the requested non-default
+configuration directory.
+
+So, while in most other respects, all instances are equal, the default instance
+is "more equal than others". You may choose to create additional instances, but
+you must have at least the default instance, with its configuration directory
+in the default compiled-in location.
+
+I\bIn\bns\bst\bta\ban\bnc\bce\be g\bgr\bro\bou\bup\bps\bs
+
+The postmulti(1) multi-instance manager supports the notion of an instance
+"group". Typically, the member instances of an instance group constitute a
+logical service, and are expected to all be running or all be stopped.
+
+In many cases a single Postfix instance will be a complete logical "service".
+You should define such instances as stand-alone instances that are not members
+of any instance "group". The null-client instance is an example of a non-group
+instance.
+
+When a logical service consists of multiple Postfix instances, often a pair of
+pre-filter and post-filter instances with a content filter proxy between them,
+the related instances should be members of a single instance group (however,
+the content filter usually has its own start/stop procedure that is separate
+from any Postfix instance).
+
+The default instance main.cf file's $multi_instance_directories configuration
+parameter lists the configuration directories of all secondary (non-default)
+instances. Together with the default instance, these secondary instances are
+managed by the multi-instance manager. Instances are started in the order
+listed, and stopped in the opposite order. For instances that are members of a
+service "group", you should arrange to start the service back-to-front, with
+the output stages started and ready to receive mail before the input stages are
+started.
+
+M\bMu\bul\blt\bti\bi-\b-i\bin\bns\bst\bta\ban\bnc\bce\be c\bco\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn p\bpa\bar\bra\bam\bme\bet\bte\ber\brs\bs
+
+multi_instance_wrapper
+    This default-instance configuration parameter must be set to a suitable
+    multi-instance manager's "wrapper" program that controls the starting,
+    stopping, etc. of a multi-instance Postfix system. To use the postmulti(1)
+    manager described in this document, this parameter should be set with the
+    "postmulti -e init" command.
+
+multi_instance_directories
+    This default-instance configuration parameter specifies an optional list of
+    the secondary instances controlled via the multi-instance manager.
+    Instances are listed in their "start" order, with the default instance
+    always started first (if enabled). If $multi_instance_directories is left
+    empty, the postfix(1) command runs with multi-instance support turned off,
+    and none of the multi_instance_ configuration parameters will have any
+    effect.
+
+    Do not assign a non-empty list of secondary instance configuration
+    directories to multi_instance_directories until you have configured a
+    suitable multi_instance_wrapper setting! This is best accomplished via the
+    "postmulti -e init" command.
+
+multi_instance_name
+    Each Postfix instance may be assigned a distinct name (with "postfix -
+    e create/import/assign -I name..."). This name can be used with the
+    postmulti(1) command-line utility to perform tasks on the instance by name
+    (rather than the full pathname of its configuration directory). Choose a
+    name that concisely captures the role of the instance (it must start with
+    "postfix-"). It is an error for two instances to have the same
+    $multi_instance_name. You can leave an instance "nameless" by leaving this
+    parameter at the default empty setting.
+
+    To avoid confusion in your logs, if you don't assign each secondary
+    instance a non-empty (distinct) $multi_instance_name, you should make sure
+    that the $syslog_name setting is different for each instance. The
+    $syslog_name parameter defaults to $multi_instance_name when the latter is
+    non-empty. If at all possible, the syslog_name should start with "postfix-
+    ", this helps log parsers to identify log entries from secondary Postfix
+    instances.
+
+multi_instance_group
+    Each Postfix instance may be assigned an "instance group" name (with
+    "postfix -e create/import/assign -G name..."). The default (empty) value of
+    multi_instance_group parameter indicates a stand-alone instance that is not
+    part of any group. The group name can be used with the postmulti(1)
+    command-line utility to perform a task on the members of a group by name.
+    Choose a single-word group name that concisely captures the role of the
+    group.
+
+multi_instance_enable
+    This parameter controls whether a Postfix instance will be started by a
+    Postfix multi-instance manager. The default value is "no". The instance can
+    be started explicitly with "postfix -c /path/to/config/directory"; this is
+    useful for testing.
+
+    When an instance is disabled, the postfix(1) "start" command is replaced by
+    "check".
+
+    Some postfix(1) commands (such as "stop", "flush", ...) require a running
+    Postfix instance, and skip instances that are disabled.
+
+    Other postfix(1) commands (such as "status", "set-permissions", "upgrade-
+    configuration", ...) do not require a running Postfix system, and apply to
+    all instances whether enabled or not.
+
+The postmulti(1) utility can be used to create (or destroy) instances. It can
+also be used to "import" or "deport" existing instances into or from the list
+of managed instances. When using postmulti(1) to manage instances, the above
+configuration parameters are managed for you automatically. See below.
+
+U\bUs\bsi\bin\bng\bg t\bth\bhe\be p\bpo\bos\bst\btm\bmu\bul\blt\bti\bi(\b(1\b1)\b) c\bco\bom\bmm\bma\ban\bnd\bd
+
+  * Initializing the multi-instance manager
+  * Listing managed instances
+  * Starting or stopping a multi-instance system
+  * Ad-hoc multi-instance operations
+  * Creating a new Postfix instance
+  * Destroying a Postfix instance
+  * Importing an existing Postfix instance
+  * Deporting a managed Postfix instance
+  * Assigning a new name or group name
+  * Enabling/disabling managed instances
+
+I\bIn\bni\bit\bti\bia\bal\bli\biz\bzi\bin\bng\bg t\bth\bhe\be m\bmu\bul\blt\bti\bi-\b-i\bin\bns\bst\bta\ban\bnc\bce\be m\bma\ban\bna\bag\bge\ber\br
+
+Before postmulti(1) is used for the first time, you must install it as the
+multi_instance_wrapper for your Postfix system and enable multi-instance
+operation of the default Postfix instance. You can then proceed to add new or
+existing instances to the multi-instance configuration. This initial
+installation is accomplished as follows:
+
+        # postmulti -e init
+
+This updates the default instance main.cf file as follows:
+
+        # Use postmulti(1) as a postfix-wrapper(5)
+        #
+        multi_instance_wrapper = ${command_directory}/postmulti -p --
+
+        # Configure the default instance to start when in multi-instance mode
+        #
+        multi_instance_enable = yes
+
+If you prefer, you can make these changes by editing the default main.cf
+directly, or by using "postconf -e".
+
+L\bLi\bis\bst\bti\bin\bng\bg m\bma\ban\bna\bag\bge\bed\bd i\bin\bns\bst\bta\ban\bnc\bce\bes\bs
+
+The list of managed instances consists of the default instance and the
+additional instances whose configuration directories are listed (in start
+order) under the multi_instance_directories parameter of the default main.cf
+configuration file.
+
+You can list selected instances, groups of instances or all instances by
+specifying only the instance matching options with the "-l" option. The "-a"
+option is assumed if no other instance selection options are specified (this
+behavior changes with the "-e" option). As a special case, even if it has an
+explicit name, the default instance can always be selected via "-i -".
+
+    # postmulti -l -a
+    # postmulti -l -g a_group
+    # postmulti -l -i an_instance
+
+The output is one line per instance (in "postfix start" order):
+
+     _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b 
+    |n\bna\bam\bme\be   |g\bgr\bro\bou\bup\bp|e\ben\bna\bab\bbl\ble\bed\bd|c\bco\bon\bnf\bfi\big\bg_\b_d\bdi\bir\bre\bec\bct\bto\bor\bry\by    |
+    |_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+    |-      |-    |yes    |/etc/postfix        |
+    |_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+    |mta-out|mta  |yes    |/etc/postfix/mta-out|
+    |_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+    |mta-in |mta  |yes    |/etc/postfix-mta-in |
+    |_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+    |msa-out|msa  |yes    |/etc/postfix-msa-out|
+    |_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+    |msa-in |msa  |yes    |/etc/postfix-msa-in |
+    |_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+    |test   |-    |no     |/etc/postfix-test   |
+    |_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+
+The first line showing the column headings is not part of the output. When
+either the instance name or the instance group is not set, it is shown as a "-
+".
+
+When selecting an existing instance via the "-i" option, you can always use the
+full pathname of its configuration directory instead of the instance (short)
+name. This is the only way to select a non-default nameless instance. The
+default instance can be selected via "-i -", whether it has a name or not.
+
+To list instances in reverse start order, include the "-R" option together with
+the instance selection options.
+
+S\bSt\bta\bar\brt\bti\bin\bng\bg o\bor\br s\bst\bto\bop\bpp\bpi\bin\bng\bg a\ba m\bmu\bul\blt\bti\bi-\b-i\bin\bns\bst\bta\ban\bnc\bce\be s\bsy\bys\bst\bte\bem\bm
+
+To start, stop, reload, etc. the complete (already configured as above) multi-
+instance system just use postfix(1) as you would with a single-instance system.
+The Postfix multi-instance wrapper framework insulates Postfix init.d start and
+package upgrade scripts from the details of multi-instance management!
+
+The -\b-p\bp option of postmulti(1) turns on postfix(1) compatibility mode. With this
+option the remaining arguments are exactly those supported by postfix(1), but
+commands are applied to all instances or all enabled instances as appropriate.
+As described above, this switch is required when using postmulti(1) as the
+multi_instance_wrapper.
+
+If you want to specify a subset of instances by name, or group name, or run
+arbitrary commands (not just "postfix stop/start/etc. in the context
+(MAIL_CONFIG environment variable setting) of a particular instance or group of
+instances, then you can use the instance-aware postmulti(1) utility directly.
+
+A\bAd\bd-\b-h\bho\boc\bc m\bmu\bul\blt\bti\bi-\b-i\bin\bns\bst\bta\ban\bnc\bce\be o\bop\bpe\ber\bra\bat\bti\bio\bon\bns\bs
+
+The postmulti(1) command can be used by the administrator to run arbitrary
+commands in the context of one or more Postfix instances. The most common use-
+case is stopping or starting a group of Postfix instances:
+
+    # postmulti -g mygroup -p start
+    # postmulti -g mygroup -p flush
+    # postmulti -g mygroup -p reload
+    # postmulti -g mygroup -p status
+    # postmulti -g mygroup -p stop
+    # postmulti -g mygroup -p upgrade-configuration
+
+The -\b-p\bp option is essentially a short-hand for a leading p\bpo\bos\bst\btf\bfi\bix\bx command
+argument, but with appropriate additional options turned on depending on the
+first argument. In the case of "start", disabled instances are "checked"
+(postfix check) rather than simply skipped.
+
+The resulting command is executed for each candidate instance with the
+M\bMA\bAI\bIL\bL_\b_C\bCO\bON\bNF\bFI\bIG\bG environment variable set to the configuration directory of the
+corresponding Postfix instance.
+
+The postmulti(1) utility is able to launch commands other than postfix(1), Use
+the -\b-x\bx option to ask postmulti to execute an ad-hoc command for all instances,
+a group of instances, or just one instance. With ad-hoc commands the
+multi_instance_enable parameter is ignored: the command is unconditionally
+executed for the instances selected via -a, -g or -i. In addition to
+MAIL_CONFIG, the following instance parameters are exported into the command
+environment:
+
+    command_directory=$command_directory
+    daemon_directory=$daemon_directory
+    config_directory=$config_directory
+    queue_directory=$queue_directory
+    data_directory=$data_directory
+    multi_instance_name=$multi_instance_name
+    multi_instance_group=$multi_instance_group
+    multi_instance_enable=$multi_instance_enable
+
+The config_directory setting is of course the same as MAIL_CONFIG, and is
+arguably redundant, but leaving it in is less surprising. If you want to skip
+disabled instances, just check multi_instance_enable environment variable and
+exit if it is set to "no".
+
+The ability to run ad-hoc commands opens up a wealth of additional
+possibilities:
+
+  * Specify an instance by name rather than configuration directory when using
+    sendmail(1) to send a verification probe:
+
+        $ postmulti -i postfix-myinst -x sendmail -bv test@example.net
+
+  * Display non-default main.cf settings of all Postfix instances. This uses an
+    inline shell script to package together multiple shell commands to execute
+    for each instance:
+
+        $ postmulti -x sh -c 'echo "-- $MAIL_CONFIG"; postconf -n'
+
+  * Put all mail in enabled member instances of a group on hold:
+
+        # postmulti -g group_name -x \
+            sh -c 'test $multi_instance_enable = yes && postsuper -h ALL'
+
+  * Show top 10 domains in the deferred queue of all instances:
+
+        # postmulti -x sh -c 'echo "-- $MAIL_CONFIG"; qshape deferred | head -
+        12'
+
+C\bCr\bre\bea\bat\bti\bin\bng\bg a\ba n\bne\bew\bw P\bPo\bos\bst\btf\bfi\bix\bx i\bin\bns\bst\bta\ban\bnc\bce\be
+
+The postmulti(1) command can be used to create additional Postfix instances.
+New instances are created with local submission and all "inet" services
+disabled via the following non-default parameter settings in the main.cf file:
+
+    authorized_submit_users =
+    master_service_disable = inet
+
+The above settings ensure that new instances are safe to start immediately:
+they will not conflict with inet listeners in existing Postfix instances. They
+will also not accept any mail until they are fully configured, at which point
+you can do away with one or both of the above safety measures.
+
+The postmulti(1) command encourages a preferred way of organizing the
+configuration directories, queue directories and data directories of non-
+default instances. If the default instance settings are:
+
+    config_directory = /conf-path/postfix
+    queue_directory = /queue-path/postfix
+    data_directory = /data-path/postfix
+
+A newly-created instance named postfix-myinst will by default have:
+
+    multi_instance_enable = no
+    multi_instance_name = postfix-myinst
+    config_directory = /conf-path/postfix-myinst
+    queue_directory = /queue-path/postfix-myinst
+    data_directory = /data-path/postfix-myinst
+
+You can override any of these defaults when creating the instance, but unless
+you want to spread instance queue directories over multiple file-systems, use
+the default naming strategy. It keeps the multiple instances organized in a
+uniform, predictable fashion.
+
+When specifying the instance name later, you can refer to it either as
+"postfix-myinst", or via the full path of the configuration directory.
+
+To create a new instance just use the -\b-e\be c\bcr\bre\bea\bat\bte\be option:
+
+    # postmulti -I postfix-myinst -e create
+
+If the new instance is to belong to a group of related instances that implement
+a single logical service, assign it to a group:
+
+    # postmulti -I postfix-myinst -G mygroup -e create
+
+If you want to override the conventional values of the instance installation
+parameters, specify their values on the command-line:
+
+    # postmulti [-I postfix-myinst] [-G mygroup] -e create \
+       "config_directory = /path/to/config_directory" \
+       "queue_directory = /path/to/queue_directory" \
+       "data_directory = /path/to/data_directory"
+
+A note on the -\b-I\bI and -\b-G\bG options above. These are always used to assign a name
+or group name to an instance, while the -\b-i\bi and -\b-g\bg options always select
+existing instances. By default, the configuration directories of newly managed
+instances are appended to the instance list. You can use the "-i" or "-g" or "-
+a" options to insert the new instance before the specified instance or group,
+or at the beginning of the instance list (multi_instance_directories parameter
+of the default instance).
+
+If you do specify a name (use "-I" with a name that is not "-") for the new
+instance, you may omit any of the 3 instance installation parameters whose
+instance-name based value is acceptable. Otherwise, all three instance
+installation parameters are required. You should set the "syslog_name"
+explicitly in the main.cf file of a "nameless" instance, in order to avoid
+confusion in the mail logs when multiple instances are in use.
+
+D\bDe\bes\bst\btr\bro\boy\byi\bin\bng\bg a\ba P\bPo\bos\bst\btf\bfi\bix\bx i\bin\bns\bst\bta\ban\bnc\bce\be
+
+If you no longer need an instance, you can destroy it via:
+
+    # postmulti -i postfix-myinst -p stop
+    # postmulti -i postfix-myinst -e disable
+    # postmulti -i postfix-myinst -e destroy
+
+The instance must be stopped, disabled and have no queued messages. This is
+expected to fully delete a just created instance that has never been used. If
+the instance is not freshly created, files added after the instance was created
+will remain in the configuration, queue or data directories, in which case the
+corresponding directory may not be fully removed and a warning to that effect
+will be displayed. You can complete the destruction of the instance manually by
+removing any unwanted remnants of the instance-specific "private" directories.
+
+I\bIm\bmp\bpo\bor\brt\bti\bin\bng\bg a\ban\bn e\bex\bxi\bis\bst\bti\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx i\bin\bns\bst\bta\ban\bnc\bce\be
+
+If you already have an existing secondary Postfix instance that is not yet
+managed via postmulti(1), you can "import" it into the list of managed
+instances. If your instance is already using the default configuration
+directory naming scheme, just specify the corresponding instance name (the
+multi_instance_name parameter in its configuration file will be adjusted to
+match this name if necessary):
+
+    # postmulti -I postfix-myinst [-G mygroup] -e import
+
+Otherwise, you must specify the location of its configuration directory:
+
+    # postmulti [-I postfix-myinst] [-G mygroup] -e import \
+       "config_directory = /path/of/config_directory"
+
+When the instance is imported, you can assign a name or a group. As with
+"create", you can control the placement of the new instance in the start order
+by using "-i", "-g" or "-a" to prepend before the selected instance or
+instances.
+
+An imported instance is usually not multi-instance "enabled", unless it was
+part of a multi-instance configuration at an earlier time. If it is fully
+configured and ready to run, don't forget to enable it and if necessary start
+it. When other enabled instances are already running, new instances need to be
+started individually when they are first created or imported.
+
+To find out what instances are running, use:
+
+    # postfix status
+
+D\bDe\bep\bpo\bor\brt\bti\bin\bng\bg a\ba m\bma\ban\bna\bag\bge\bed\bd P\bPo\bos\bst\btf\bfi\bix\bx i\bin\bns\bst\bta\ban\bnc\bce\be
+
+You can "deport" an existing instance from the list of managed instances. This
+does not destroy the instance, rather the instance just becomes a stand-alone
+Postfix instance not registered with the multi-instance manager. postmulti(1)
+will refuse to "deport" an instance that is not stopped and disabled.
+
+    # postmulti -i postfix-myinst -p stop
+    # postmulti -i postfix-myinst -e disable
+    # postmulti -i postfix-myinst -e deport
+
+A\bAs\bss\bsi\big\bgn\bni\bin\bng\bg a\ba n\bne\bew\bw n\bna\bam\bme\be o\bor\br g\bgr\bro\bou\bup\bp n\bna\bam\bme\be
+
+You can assign a new name or new group to a managed instance. Use "-" as the
+new value to assign the instance to no group or make it nameless. To specify a
+nameless secondary instance use the configuration directory path instead of the
+old name:
+
+    # postmulti -i postfix-old [-I postfix-new] [-G newgroup] -e assign
+
+E\bEn\bna\bab\bbl\bli\bin\bng\bg/\b/d\bdi\bis\bsa\bab\bbl\bli\bin\bng\bg m\bma\ban\bna\bag\bge\bed\bd i\bin\bns\bst\bta\ban\bnc\bce\bes\bs
+
+You can enable or disable a managed instance. As documented in postfix-wrapper
+(5), disabled instances are skipped with actions that start, stop or control
+running Postfix instances.
+
+    # postmulti -i postfix-myinst -e enable
+    # postmulti -i postfix-myinst -e disable
+
+C\bCr\bre\bed\bdi\bit\bts\bs
+
+Wietse Venema created Postfix, designed and implemented the multi-instance
+wrapper framework and provided design feedback that made the postmulti(1)
+utility much more general and useful than originally envisioned.
+
+The postmulti(1) utility was developed by Victor Duchovni of Morgan Stanley,
+who also wrote the initial version of this document.
+
index 2cfc28a9d353157bb49938e118e399319651d252..9b01a8439747e664ad1be83f85812dacebf1f7e6 100644 (file)
@@ -390,6 +390,10 @@ all named postsomething.
   * The postmap(1) command maintains Postfix lookup tables such as canonical
     (5), virtual(5) and others. It is a cousin of the UNIX makemap command.
 
+  * The postmulti(1) command repeats the "postfix start" etc. command for each
+    Postfix instance, and supports creation, deletion etc. of Postfix
+    instances. For a tutorial, see MULTI_INSTANCE_README.
+
   * The postqueue(1) command is the privileged command that is run by Postfix
     sendmail(1) and mailq(1) in order to flush or list the mail queue.
 
index 861f2dac9a041bff5d716d725da8ea66b2515dc0..b47c6f01f33ed6a47645a43f622fb98bafca4bff 100644 (file)
@@ -69,7 +69,7 @@ only parameters that are not left at their default settings.
     1 /etc/postfix/main.cf:
     2     myorigin = $mydomain
     3     relayhost = $mydomain
-    4     inet_interfaces = 127.0.0.1
+    4     inet_interfaces = loopback-only
     5     local_transport = error:local delivery is disabled
     6
     7 /etc/postfix/master.cf:
index 576613726290106bf60eea89ca5dce5873900c6e..ebf3095e8f8567b2112618124221e3b96dd51284 100644 (file)
@@ -157,16 +157,17 @@ Under conditions of overload you can improve Postfix SMTP server responsiveness
 by hanging up on suspicious clients, so that other clients get a chance to talk
 to Postfix.
 
-  * Use "421" reply codes for botnet-related RBLs or for selected non-RBL
-    restrictions. This causes Postfix 2.3 and later to disconnect immediately
-    without waiting for the remote SMTP client to send a QUIT command.
+  * Use "521" reply codes (Postfix 2.6 and later) for botnet-related RBLs or
+    for selected non-RBL restrictions. With Postfix 2.3-2.5 use "421" for a
+    similar result. The Postfix SMTP server will disconnect immediately without
+    waiting for the remote SMTP client to send a QUIT command.
 
     You can set individual reject codes for RBLs, and for individual responses
     from a specific RBL. We'll use zen.spamhaus.org as an example; by the time
     you read this document, details may have changed. Right now, their
     documents say that a response of 127.0.0.10 or 127.0.0.11 indicates a
     dynamic client IP address, which means that the machine is probably running
-    a bot of some kind. To give a 421 response instead of the default 554
+    a bot of some kind. To give a 521 response instead of the default 554
     response, use something like:
 
      1  /etc/postfix/main.cf:
@@ -179,22 +180,23 @@ to Postfix.
      8      rbl_reply_maps = hash:/etc/postfix/rbl_reply_maps
      9
     10  /etc/postfix/rbl_reply_maps:
-    11      zen.spamhaus.org=127.0.0.10 421 4.7.1 Service unavailable;
+    11      zen.spamhaus.org=127.0.0.10 521 4.7.1 Service unavailable;
     12       $rbl_class [$rbl_what] blocked using
     13       $rbl_domain${rbl_reason?; $rbl_reason}
     14
-    15      zen.spamhaus.org=127.0.0.11 421 4.7.1 Service unavailable;
+    15      zen.spamhaus.org=127.0.0.11 521 4.7.1 Service unavailable;
     16       $rbl_class [$rbl_what] blocked using
     17       $rbl_domain${rbl_reason?; $rbl_reason}
 
     Although the above shows three RBL lookups (lines 4-6), Postfix will still
     only do a single DNS query, so the performance difference is negligible.
 
-    The down-side of sending 421 instead of the default 554 is that it works
-    only for zombies and other malware. If the client is running a real MTA,
-    then it may connect again several times until the mail expires in its
-    queue. When this is a problem, stick with the default 554 reply, and use
-    "smtpd_hard_error_limit = 1" as described below.
+    With Postfix 2.3-2.5, use 421 (reply code 521 will not cause Postfix to
+    disconnect). The down-side of sending 421 is that it works only for zombies
+    and other malware. If the client is running a real MTA, then it may connect
+    again several times until the mail expires in its queue. When this is a
+    problem, stick with the default 554 reply, and use "smtpd_hard_error_limit
+    = 1" as described below.
 
     With Postfix 2.5, or with earlier releases that contain the stress-adaptive
     behavior patch, you can turn on the above under overload by replacing line
index 138bea346919fcc90739891addccd4994a8d3b0a..cf51d3ffd999556c432f618a2cdf6f1197c3948a 100644 (file)
@@ -11,10 +11,22 @@ instead, a new snapshot is released.
 The mail_release_date configuration parameter (format: yyyymmdd)
 specifies the release date of a stable release or snapshot release.
 
+Incompatibility with snapshot 20090330
+======================================
+
+Postfix now adds (Resent-) From:, Date:, Message-ID: or To: headers
+only when clients match $local_header_rewrite_clients.  Specify
+"always_add_missing_headers = yes" for backwards compatibility.
+Adding such headers can break DKIM signatures that cover headers
+that are not present.
+
+This changes the appearance of Postfix logging: some messages will
+no longer log a message-id=<...text...> line.
+
 Major changes with snapshot 20090212
 ====================================
 
-Stress-depdent behavior by default. Under conditions of overload,
+Stress-dependent behavior by default. Under conditions of overload,
 smtpd_timeout is reduced from 300s to to 10s, smtpd_hard_error_limit
 is reduced from 20 to 1, and smtpd_junk_command_limit is reduced
 from 100 to 1. This will reduce the delays for most legitimate mail.
index 821ecf894f1cddff4472f05299b5b543360e00b4..84f31dd8bb10a83424e193ce317766a9e75ddd12 100644 (file)
@@ -1,5 +1,49 @@
 Wish list:
 
+       "postconf -N" option to print user-defined parameter names
+       (these have no defaults, since they exist only when 
+       specified in main.cf or with "-o name=value").
+
+       Make the "unknown recipient" test configurable as
+       first|last|never, with "yes"=="last" for backwards
+       compatibility. The "first" setting is good for performance
+       (stress=yes) when all users are defined in local files.
+
+       Make the double-bounce address time-dependent (with 24-hour
+       grace period).  Spammers appear to use this address to avoid
+       DATA command rejects. Avoiding DATA rejects means they can
+       pipeline the entire SMTP session without triggering huge
+       numbers of protocol errors. They can still trigger "improper
+       command pipelining after DATA" alarms, but that requires
+       non-default main.cf settings.
+
+       Cleanup: make DNSBL query format configurable beyond the
+       client's reversed IP address.
+
+       With 'final delivery' in the LMTP client, need an option
+       to also add delivered-to and other pipe(8) features.
+       This requires making mail_copy() more generic.
+
+       To work around historical AWK's limit of 10 open files,
+       pipe all output into a shell and have the shell open files.
+       It's too much pain to find out whose AWK is old and where
+       if any they keep the XPG4 compliant version.
+
+       Cleanup: modernize the "add missing From: header" code, to
+       ``phrase <addr>'' form. Most likely, quote the entire phrase
+       if it contains any text that is special, then rfc822_externalize
+       the whole thing.
+
+       SMTP server: make the server_addr and server_port port
+       available to policy server, Dovecot, and perhaps Milters.
+
+       Maybe change maps_rbl_reject_code default to 521, and
+       update wording in STRESS_README.
+
+       reject_unlisted_recipient = (yes | late | early | no) with
+       yes===late, for backwards compatibility. Ditto for
+       reject_unlisted_sender.
+
        Set a flag when a remote SMTP client speaks before the
        Postfix SMTP server sends the 220 greeting.
 
@@ -190,11 +234,6 @@ Wish list:
        playing with the soft_error test in the smtp_trouble.c
        module, and avoiding delivery to backup MX hosts.
 
-       In the SMTP server, set a "pipelining detected" flag at the
-       start of a session and at protocol synchronization points,
-       so that reject_unauth_pipelining can be specified in any
-       access rule.
-
        Centralize main.cf parameter input so that defaults work
        consistently. What about parameter names that are prefixed
        with mail delivery transport names?
index 617ebface05f6f31f1ddfbc8a88d9afa78ab3383..7ff93eafa2e5a054ae6c1e0d5118357c8141ce0b 100644 (file)
@@ -81,6 +81,7 @@ $daemon_directory/post-install:f:root:-:755
 $daemon_directory/postfix-files:f:root:-:644
 $daemon_directory/postfix-script:f:root:-:755
 $daemon_directory/postfix-wrapper:f:root:-:755
+$daemon_directory/postmulti-script:f:root:-:755
 $daemon_directory/proxymap:f:root:-:755
 $daemon_directory/qmgr:f:root:-:755
 $daemon_directory/qmqpd:f:root:-:755
@@ -103,6 +104,7 @@ $command_directory/postkick:f:root:-:755
 $command_directory/postlock:f:root:-:755
 $command_directory/postlog:f:root:-:755
 $command_directory/postmap:f:root:-:755
+$command_directory/postmulti:f:root:-:755
 $command_directory/postsuper:f:root:-:755
 $command_directory/postdrop:f:root:$setgid_group:2755:u
 $command_directory/postqueue:f:root:$setgid_group:2755:u
@@ -146,6 +148,7 @@ $manpage_directory/man1/postkick.1:f:root:-:644
 $manpage_directory/man1/postlock.1:f:root:-:644
 $manpage_directory/man1/postlog.1:f:root:-:644
 $manpage_directory/man1/postmap.1:f:root:-:644
+$manpage_directory/man1/postmulti.1:f:root:-:644
 $manpage_directory/man1/postqueue.1:f:root:-:644
 $manpage_directory/man1/postsuper.1:f:root:-:644
 $manpage_directory/man1/sendmail.1:f:root:-:644
@@ -255,6 +258,7 @@ $readme_directory/LOCAL_RECIPIENT_README:f:root:-:644
 $readme_directory/MACOSX_README:f:root:-:644:o
 $readme_directory/MAILDROP_README:f:root:-:644
 $readme_directory/MILTER_README:f:root:-:644
+$readme_directory/MULTI_INSTANCE_README:f:root:-:644
 $readme_directory/MYSQL_README:f:root:-:644
 $readme_directory/NFS_README:f:root:-:644
 $readme_directory/OVERVIEW:f:root:-:644
@@ -304,6 +308,7 @@ $html_directory/LINUX_README.html:f:root:-:644
 $html_directory/LOCAL_RECIPIENT_README.html:f:root:-:644
 $html_directory/MAILDROP_README.html:f:root:-:644
 $html_directory/MILTER_README.html:f:root:-:644
+$html_directory/MULTI_INSTANCE_README.html:f:root:-:644
 $html_directory/MYSQL_README.html:f:root:-:644
 $html_directory/NFS_README.html:f:root:-:644
 $html_directory/OVERVIEW.html:f:root:-:644
@@ -371,6 +376,7 @@ $html_directory/postkick.1.html:f:root:-:644
 $html_directory/postlock.1.html:f:root:-:644
 $html_directory/postlog.1.html:f:root:-:644
 $html_directory/postmap.1.html:f:root:-:644
+$html_directory/postmulti.1.html:f:root:-:644
 $html_directory/postqueue.1.html:f:root:-:644
 $html_directory/postsuper.1.html:f:root:-:644
 $html_directory/qshape.1.html:f:root:-:644
index 7f9926100c7eef692f962812e9a62575508a8fc4..30ddf1cbc221f9aa877f9827e991d67e50e5a4f8 100644 (file)
@@ -75,7 +75,8 @@ def_config_directory=`$command_directory/postconf -dh config_directory` || {
 
 # If this is a secondary instance, don't touch shared files.
 
-instances=`$command_directory/postconf -c $def_config_directory \
+instances=`test ! -f $def_config_directory/main.cf ||
+    $command_directory/postconf -c $def_config_directory \
     -h multi_instance_directories | sed 's/,/ /'` || {
        $FATAL cannot execute $command_directory/postconf!
        exit 1
@@ -337,7 +338,7 @@ post-install)
        ;;
 
 *)
-
+       $ERROR "unknown command: '$1'"
        $FATAL "usage: postfix start (or stop, reload, abort, flush, check, status, set-permissions, upgrade-configuration)"
        exit 1
        ;;
diff --git a/postfix/conf/postmulti-script b/postfix/conf/postmulti-script
new file mode 100644 (file)
index 0000000..3f1333b
--- /dev/null
@@ -0,0 +1,300 @@
+#! /bin/sh
+
+umask 022
+
+# postmulti(1) contract:
+#
+# Arguments:
+#  postmulti-script -e <edit_command>
+#
+# Environment:
+#
+# All actions:
+#
+#  MAIL_CONFIG                 - config_directory of primary instance
+#  command_directory           - From primary instance
+#  daemon_directory            - From primary instance
+#  config_directroy            - config_directory of target instance
+#  queue_directory             - queue_directory of target instance
+#  data_directory              - data_directory of target instance
+#
+# Create, destroy, import and deport:
+#
+#  multi_instance_directories  - New value for primary instance
+#
+# Create, import and assign (unset == nochange, "-" == clear):
+#
+#  multi_instance_group                - New value for target instance
+#  multi_instance_name         - New value for target instance
+
+: ${MAIL_CONFIG:?"do not invoke this command directly"}
+: ${command_directory:?"do not invoke this command directly"}
+: ${daemon_directory:?"do not invoke this command directly"}
+
+USAGE="$0 -e create|destroy|import|deport|enable|disable|assign|init"
+usage() { echo "$0: Error: Usage: $USAGE" >&2; exit 1; }
+
+TAG="$MAIL_LOGTAG/postmulti-script"
+fatal() { postlog -p fatal -t "$TAG" "$1"; exit 1; }
+
+# args: add|del $dir
+#
+update_cfdirs() {
+    op=$1
+    dir=$2
+
+    alt=`postconf -h alternate_config_directories` || return 1
+
+    shift $#   # Needed on SunOS where bare "set --" is NOP!
+    IFS="$IFS,"; set -- $alt; IFS="$BACKUP_IFS"
+    keep=
+    found=
+    # Portability: SunOS "sh" needs 'in "$@"' for one-line for-loop.
+    for d in "$@"; do [ "$d" = "$dir" ] && found=1 || keep="$keep $d"; done
+
+    set -- "multi_instance_directories = $multi_instance_directories"
+
+    case $op in
+    add) test -n "$found" ||
+        set -- "$@" "alternate_config_directories =$keep $dir";;
+    del) test -n "$found" &&
+        set -- "$@" "alternate_config_directories =$keep";;
+      *) return 1;;            # XXX: Internal error
+    esac
+    postconf -e "$@" || return 1
+}
+
+assign_names() {
+    # Set the instance name and group
+    #
+    test -n "$multi_instance_name" && {
+       test "$multi_instance_name" = "-" && multi_instance_name=
+       set -- "$@" "multi_instance_name = $multi_instance_name"
+    }
+    test -n "$multi_instance_group" && {
+       test "$multi_instance_group" = "-" && multi_instance_group=
+       set -- "$@" "multi_instance_group = $multi_instance_group"
+    }
+    test $# -eq 0 || postconf -c "$config_directory" -e "$@" || return 1
+}
+
+# Process command-line options and parameter settings. Work around
+# brain damaged shells. "IFS=value command" should not make the
+# IFS=value setting permanent. But some broken standard allows it.
+
+BACKUP_IFS="$IFS"
+action=
+
+while getopts ":e:" opt
+do
+    case $opt in
+    e) action="$OPTARG";;
+    *) usage;;
+    esac
+done
+shift `expr $OPTIND - 1`
+
+# Check for valid action and required instance name
+case "$action" in
+ create|import|destroy|deport|enable|disable|assign|init) ;;
+                                                      *) usage;;
+esac
+test $# -eq 0 || usage
+
+case $action in
+init)
+    postconf -e \
+       'multi_instance_wrapper = ${command_directory}/postmulti -p --' \
+       'multi_instance_enable = yes'
+    exit $? ;;
+esac
+
+: ${config_directory:?"Invalid empty target instance config_directory"}
+
+case $action in
+create|import)
+
+    # Atomically install stock main.cf/master.cf files. We install the
+    # master.cf file last. Once it is present the instance is complete.
+    #
+    test -f $config_directory/main.cf -a \
+        -f $config_directory/master.cf || {
+
+       test "$action" = "create" || {
+           test -f $config_directory/main.cf ||
+               fatal "'$config_directory' lacks a main.cf file"
+           test -f $config_directory/master.cf ||
+               fatal "'$config_directory' lacks a master.cf file"
+       }
+
+       # Create instance-specific directories
+       #
+       test -d $config_directory ||
+           { (umask 022; mkdir -p $config_directory) || exit 1; }
+       test -d $queue_directory ||
+           { (umask 022; mkdir -p $queue_directory) || exit 1; }
+       test -d $data_directory ||
+           { (umask 077; mkdir -p $data_directory) || exit 1; }
+
+       tmpdir=$config_directory/.tmp
+       (umask 077; mkdir -p $tmpdir) || exit 1
+       cp -p $daemon_directory/main.cf $tmpdir/main.cf || exit 1
+
+       # Shared install parameters are cloned from user-specified values in
+       # the default instance, but only if explicitly set there. Otherwise,
+       # they are commented out in the new main.cf file.
+       #
+       SHARED_PARAMETERS="
+           command_directory
+           daemon_directory
+           mail_owner
+           setgid_group
+           sendmail_path
+           mailq_path
+           newaliases_path
+           html_directory
+           manpage_directory
+           sample_directory
+           readme_directory
+       "
+
+       shift $#        # Needed on SunOS where bare "set --" is NOP!
+       comment_out=
+       for p in $SHARED_PARAMETERS; do
+           val=`postconf -nh $p` || exit 1
+           test -n "$val" && { set -- "$@" "$p = $val"; continue; }
+           comment_out="$comment_out $p"
+       done
+
+       # First comment-out any parameters that take default values
+       test -n "$comment_out" && {
+           postconf -c $tmpdir -# $comment_out || exit 1
+       }
+
+       # Now add instance-specific and non-default values.
+       # By default, disable inet services and local submission
+       # in new instances
+       #
+       postconf -c $tmpdir -e \
+           "queue_directory = $queue_directory" \
+           "data_directory = $data_directory" \
+           "authorized_submit_users =" \
+           "master_service_disable = inet" \
+           "$@" || exit 1
+
+
+       cp -p $daemon_directory/master.cf $tmpdir/master.cf || exit 1
+       mv $tmpdir/main.cf $config_directory/main.cf || exit 1
+       mv $tmpdir/master.cf $config_directory/master.cf || exit 1
+       rmdir $tmpdir 2>/dev/null
+    }
+
+    # Set instance name and group
+    #
+    assign_names || exit 1
+
+    # Update multi_instance_directories
+    # and drop from alternate_config_directories
+    #
+    # XXX: Must happen before set-permissions below, otherwise instance
+    # is treated as a non-slave instance by post-install via postfix(1).
+    #
+    update_cfdirs del $config_directory || exit 1
+
+    # Update permissions of private files. Verifies existence of
+    # queue_directory and data_directory, ...
+    #
+    # XXX: Must happen after instance list updates above, otherwise instance
+    # is treated as a non-slave instance by post-install via postfix(1).
+    #
+    postfix -c $config_directory set-permissions || exit 1
+    ;;
+
+deport)
+    # Deporting an already deleted instance?
+    #
+    [ -f "$config_directory/main.cf" ] || {
+       update_cfdirs del $config_directory
+       exit $?
+    }
+
+    postfix -c "$config_directory" status >/dev/null 2>&1 &&
+       fatal "Instance '$config_directory' is not stopped"
+
+    # Update multi_instance_directories
+    # and add to alternate_config_directories
+    #
+    update_cfdirs add $config_directory || exit 1
+    ;;
+
+destroy)
+    # Locate the target instance
+    #
+    [ -f "$config_directory/main.cf" ] ||
+       fatal "$config_directory/main.cf file not found"
+
+    postfix -c "$config_directory" status >/dev/null 2>&1 &&
+       fatal "Instance '$config_directory' is not stopped"
+
+    # XXX: Internal "postfix /some/cmd" interface via /bin/env for execvp().
+    #
+    for q in maildrop incoming active deferred hold
+    do
+       postfix -c "$config_directory" /bin/env \
+           find "$q" ! -name "$q" ! -name "?" -perm 0700 -print |
+           grep "^" >/dev/null &&
+           fatal "Instance '$config_directory' $q queue is not empty"
+    done
+
+    # Update multi_instance directories
+    # and also (just in case) drop from alternate_config_directories
+    #
+    update_cfdirs del $config_directory || exit 1
+
+    # Change default personalities:
+    MAIL_CONFIG="$config_directory"; export MAIL_CONFIG
+
+    # Full steam ahead, instance will be at least partly destroyed!
+
+    # Try to remove data_directory, but not sub-directories.
+    # Note: care with "$TAG" insertion into sh -c 'script'.
+    #
+    postfix /bin/sh -c \
+       'cd $data_directory; rm -f -- *; cd ..; rmdir $data_directory; \
+         PATH=$command_directory:$PATH; export PATH; \
+        test -d $data_directory && \
+            postlog -p warn -t "'"$TAG"'" \
+               "$data_directory partly removed" 2>&1' 2>/dev/null
+
+    # Remove Postfix-owned files in the queue directory.
+    # Remove all files in the "pid" sub-directory.
+    # Remove empty directories.
+    # Note: care with "$TAG" insertion into sh -c 'script'.
+    postfix /bin/sh -c \
+       'find . -user $mail_owner ! -type d -exec rm -f -- "{}" ";"; \
+        find . -depth -user $mail_owner -type d -exec rmdir -- "{}" ";"; \
+        rm -f -- pid/*; rmdir *; cd ..; rmdir $queue_directory; \
+         PATH=$command_directory:$PATH; export PATH; \
+        test -d $queue_directory && \
+            postlog -p warn -t "'"$TAG"'" \
+               "$queue_directory partly removed" 2>&1' 2>/dev/null
+
+    # In the configuration directory remove just the main.cf and master.cf
+    # files.
+    rm -f -- "$MAIL_CONFIG/master.cf" "$MAIL_CONFIG/main.cf" 2>/dev/null
+    rmdir -- "$MAIL_CONFIG" 2>/dev/null
+    test -d "$MAIL_CONFIG" && \
+        postlog -p warn -t "$TAG" \
+           "$MAIL_CONFIG partly removed" 2>&1
+    ;;
+enable)
+    postconf -c "$config_directory" -e \
+       "multi_instance_enable = yes" || exit 1;;
+disable)
+    postconf -c "$config_directory" -e \
+       "multi_instance_enable = no" || exit 1;;
+assign)
+    assign_names || exit 1;;
+esac
+
+exit 0
index 91a9aeeee5442fd50950533c93437c793a6b9e33..22418cdce9f3ff76979f2aae7ec7df339f8254df 100644 (file)
@@ -218,9 +218,9 @@ header/body checks for mail to some domains only</a>".  </p>
 
 <li> <p> Header/body checks do not decode message headers or message
 body content. For example, if text in the message body is BASE64
-encoded (<a href="http://www.faqs.org/rfcs/rfc2045.html">RFC 2045</a>) then your regular expressions will have to match
+encoded (<a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a>) then your regular expressions will have to match
 the BASE64 encoded form. Likewise, message headers with encoded
-non-ASCII characters (<a href="http://www.faqs.org/rfcs/rfc2047.html">RFC 2047</a>) need to be matched in their encoded
+non-ASCII characters (<a href="http://tools.ietf.org/html/rfc2047">RFC 2047</a>) need to be matched in their encoded
 form. </p>
 
 <li> <p> Header/body checks cannot filter on a combination of
@@ -348,7 +348,8 @@ Such rules slow down all mail and complicate Postfix maintenance.
 
 <h2><a name="remote_only">Configuring header/body checks for mail from outside users only</a></h2>
 
-<p> The following information applies to Postfix 2.1. Earlier
+<p> The following information applies to Postfix 2.1 and later.
+Earlier
 Postfix versions do not support the <a href="postconf.5.html#receive_override_options">receive_override_options</a> feature.
 </p>
 
@@ -375,6 +376,9 @@ service with header/body filtering turned off.  </p>
         -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=<a href="postconf.5.html#no_header_body_checks">no_header_body_checks</a>
 </pre>
 
+<li> <p> Add some firewall rule to prevent access to 1.2.3.4:smtp
+from the outside world. </p>
+
 <li> <p> One SMTP server address for mail from outside users with
 header/body filtering turned on via <a href="postconf.5.html">main.cf</a>. </p>
 
diff --git a/postfix/html/MULTI_INSTANCE_README.html b/postfix/html/MULTI_INSTANCE_README.html
new file mode 100644 (file)
index 0000000..502b22d
--- /dev/null
@@ -0,0 +1,1272 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Managing multiple Postfix instances on a single host</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Managing
+multiple Postfix instances on a single host</h1>
+
+<hr>
+
+<h2>Overview </h2>
+
+<p> This document is a guide to managing multiple Postfix instances
+on a single host using the <a href="postmulti.1.html">postmulti(1)</a> instance manager. Multi-instance
+support is available with Postfix version 2.6 and later.  See the
+<a href="postfix-wrapper.5.html">postfix-wrapper(5)</a> manual page for background on the instance
+management framework, and on how to deploy a custom instance manager.
+</p>
+
+<p> Topics covered in this document: </p>
+
+<ul>
+
+<li><a href="#why"> Why multiple Postfix instances </a> 
+
+<li><a href="#split"> Null-client instances versus service instances </a>
+
+<li><a href="#quick"> Multi-instance walk-through  </a> 
+
+<li><a href="#parts"> Components of a Postfix system </a> 
+
+<li><a href="#default"> The default Postfix instance </a> 
+
+<li><a href="#group"> Instance groups </a>
+
+<li><a href="#params"> Multi-instance configuration parameters </a>
+
+<li><a href="#how"> Using the postmulti(1) command </a>
+
+<li><a href="#credits"> Credits </a>
+
+</ul>
+
+<h2><a name="why"> Why multiple Postfix instances </a></h2>
+
+<p> Postfix is a general-purpose mail system that can be configured
+to serve a variety of needs. Examples of Postfix applications are: </p>
+
+<ul>
+
+<li><p> Local mail submission for shell users and system processes. </p>
+
+<li><p> Incoming (MX host) email from the Internet. </p>
+
+<li><p> Outbound mail relay for a corporate network. </p>
+
+<li><p> Authenticated submission for roaming users. </p>
+
+<li><p> Before/after content-filter mail. </p>
+
+</ul>
+
+<p> A single Postfix configuration can provide many or all of these
+services, but a complex interplay of settings may be required, for
+example with <a href="master.5.html">master.cf</a> options overriding <a href="postconf.5.html">main.cf</a> settings. In this
+document we take the view that multiple Postfix instances may be a
+simpler way to configure a multi-function Postfix system.  With
+multiple Postfix instances, each instance has its own directories
+for configuration, queue and data files, but it shares all Postfix
+program and documentation files with other instances. </p>
+
+<p> Since there is no single right way to configure your system,
+we recommend that you choose what makes you most comfortable. If
+different Postfix services don't involve incompatible <a href="postconf.5.html">main.cf</a> or
+<a href="master.5.html">master.cf</a> settings, and if they can be combined together without
+complex tricks, then a single monolithic configuration may be the
+simplest approach. </p>
+
+<p> The purpose of multi-instance support in Postfix is not to force
+you to create multiple Postfix instances, but rather to give you a
+choice. Multiple instances give you the freedom to tune each Postfix
+instance to a single task that it does well and to combine instances
+into complete systems. </p>
+
+<p> With the introduction of the <a href="postmulti.1.html">postmulti(1)</a> utility and the reduction
+of the per-instance configuration footprint of a secondary Postfix
+instance to just a <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> file (other files are now in
+shared locations), we hope that multiple instances will be easier to
+use than ever before. </p>
+
+<h2><a name="split"> Null-client instances versus service instances </a></h2>
+
+<p> In the multi-instance approach to configuring Postfix, the first
+simplification is with the default local-submission Postfix instance.
+</p>
+
+<p> Most UNIX systems require support for email submission with the
+<a href="sendmail.1.html">sendmail(1)</a> command so that system processes such as cron jobs can
+send status reports, and so that system users can send email with
+command-line utilities.  Such email can be handled with a <a
+href="STANDARD_CONFIGURATION_README.html#null_client">null-client</a>
+Postfix configuration that forwards all mail to a central mail hub.
+The null client will typically either not run an SMTP listener at
+all (<a href="postconf.5.html#master_service_disable">master_service_disable</a> = inet), or it will listen only on the
+loopback interface (<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> = loopback-only). </p>
+
+<p> When implementing specialized servers for inbound Internet
+email, outbound MTAs, internal mail hubs, and so on, we recommend
+using a null client for local submission and creating single-function
+secondary Postfix instances to serve the specialized needs. </p>
+
+<blockquote>
+
+<p> Note: usually, you need to use different "<a href="postconf.5.html#myhostname">myhostname</a>" settings
+when you run multiple instances on the same host. Otherwise, there
+will be false "mail loops back to myself" alarms when one instance
+tries to send mail into another instance.  Typically, the null-client
+instance will use the system's hostname, and other instances will
+use their own dedicated "<a href="postconf.5.html#myhostname">myhostname</a>" settings. Different names are
+not needed when instances send mail to each other with a protocol
+other than SMTP, or with SMTP over a TCP port other than 25 as is
+usual with SMTP-based content filters.  </p>
+
+</blockquote>
+
+<h2><a name="quick"> Multi-instance walk-through </a></h2>
+
+<p> Before discussing the fine details of multi-instance operation
+we first show the steps for creating a border mail server. This
+server has with a null-client Postfix instance for local submission,
+an input Postfix instance to receive mail from the Internet, plus
+an <a href="FILTER_README.html#advanced_filter">advanced</a> SMTP
+content-filter and an output Postfix instance to deliver filtered
+email to its internal destination. </p>
+
+<h3>Setting up the null-client Postfix instance </h3>
+
+<p> On a border mail hub, while mail from the Internet requires a
+great deal of scrutiny, locally submitted messages are typically
+limited to mail from cron jobs and other system services. In this
+regard the border MTA is not different from other Unix hosts in
+your environment. For this reason, it will submit locally-generated
+email to the internal mail hub. We start the construction of the
+border mail server with the <a href="#default_instance">default</a>
+instance, which will be a local-submission <a
+href="STANDARD_CONFIGURATION_README.html#null_client">null client</a>:
+</p>
+
+<blockquote>
+<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+    # We are mta1.example.com
+    #
+    <a href="postconf.5.html#myhostname">myhostname</a> = mta1.example.com
+    <a href="postconf.5.html#mydomain">mydomain</a> = example.com
+
+    # Flat user-account namespace in example.com:
+    #
+    #   user@example.com not user@host.example.com
+    #
+    <a href="postconf.5.html#myorigin">myorigin</a> = $<a href="postconf.5.html#mydomain">mydomain</a>
+
+    # Postfix 2.6+, disable inet services, specifically disable <a href="smtpd.8.html">smtpd(8)</a>
+    #
+    <a href="postconf.5.html#master_service_disable">master_service_disable</a> = inet
+
+    # No local delivery:
+    #
+    <a href="postconf.5.html#mydestination">mydestination</a> =
+    <a href="postconf.5.html#local_transport">local_transport</a> = <a href="error.8.html">error</a>:5.1.1 Mailbox unavailable
+    <a href="postconf.5.html#alias_database">alias_database</a> =
+    <a href="postconf.5.html#alias_maps">alias_maps</a> =
+    <a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> =
+
+    # Send everything to the internal mailhub
+    #
+    <a href="postconf.5.html#relayhost">relayhost</a> = [mailhub.example.com]
+
+    # Indexed table macro:
+    # (use "hash", ... when <a href="CDB_README.html">cdb</a> is not available)
+    #
+    <a href="postconf.5.html#default_database_type">default_database_type</a> = cdb
+    indexed = ${<a href="postconf.5.html#default_database_type">default_database_type</a>}:${<a href="postconf.5.html#config_directory">config_directory</a>}/
+
+    # Expose origin host of mail from "root", ...
+    #
+    <a href="postconf.5.html#smtp_generic_maps">smtp_generic_maps</a> = ${indexed}generic
+
+    # Send messages addressed to "root", ... to the MTA support team
+    #
+    <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = ${indexed}virtual
+
+/etc/postfix/generic:
+    # The smarthost supports "+" addressing (<a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> = +).
+    # Mail from "root" exposes the origin host, without replies
+    # and bounces going back to the same host.
+    #
+    # On clustered MTAs this file is typically machine-built from
+    # a template file. The build process expands the template into
+    # "mtaadmin+root=mta1"
+    #
+    root       mtaadmin+root=mta1
+
+/etc/postfix/<a href="virtual.8.html">virtual</a>:
+    # Caretaker aliases:
+    #
+    root       mtaadmin
+    postmaster root
+</pre>
+</blockquote>
+
+<p> You would typically also add a Makefile, to automatically run
+<a href="postmap.1.html">postmap(1)</a> commands when source files change. This Makefile also
+creates a "generic" database when none exists. </p>
+
+<blockquote>
+<pre>
+/etc/postfix/Makefile:
+    MTAADMIN=mtaadmin
+
+    all: virtual.cdb generic.cdb
+
+    generic: Makefile
+           @echo Creating $@
+           @rm -f $@.tmp
+           @printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` &gt; $@.tmp
+           @mv $@.tmp generic
+
+    %.<a href="CDB_README.html">cdb</a>: %
+           postmap <a href="CDB_README.html">cdb</a>:$&lt;
+</pre>
+</blockquote>
+
+<p> Construct the "virtual" and "generic" databases (the latter is
+created by running "make"), then start and test the null-client:
+</p>
+
+<blockquote>
+<pre>
+# cd /etc/postfix; make
+# postfix start
+# sendmail -i -f root -t &lt;&lt;EOF
+From: root
+To: root
+Subject: test
+
+testing
+EOF
+</pre>
+</blockquote>
+
+<p> The test message should be delivered the members of the "mtaadmin"
+address group (or whatever address group you choose) with the
+following headers: </p>
+
+<blockquote>
+<pre>
+From: mtaadmin+root=mta1@example.com
+To: mtadmin+root=mta1@example.com
+Subject: test
+</pre>
+</blockquote>
+
+<h3>Setting up the "output" Postfix instance </h3>
+
+<p> With the null-client instance out of the way, we can create the
+MTA "output" instance that will deliver filtered mail to the inside
+network. We add the "output" instance first, because the output
+instance needs to be up and running before the input instance can
+be fully tested, and when the system boots, the "output" instance
+must start before the input instance. We will put the output and
+input instances into a single instance group named "mta".  </p>
+
+<p> Just once, when adding the first secondary instance, enable
+multi-instance support in the default (null-client) instance: </p>
+
+<blockquote>
+<pre>
+# postmulti -e init
+</pre>
+</blockquote>
+
+<p> Then create the output instance: <p>
+
+<blockquote>
+<pre>
+# postmulti -I postfix-out -G mta -e create
+</pre>
+</blockquote>
+
+<p> The instance configuration directory defaults to /etc/postfix-out,
+more precisely, the "postfix-out" subdirectory of the parent directory
+of the default-instance configuration directory. The new instance will
+be created in a "disabled" state: </p>
+
+<blockquote>
+<pre>
+/etc/postfix-out/<a href="postconf.5.html">main.cf</a>
+    #
+    # ... "stock" <a href="postconf.5.html">main.cf</a> settings ...
+    #
+    <a href="postconf.5.html#multi_instance_name">multi_instance_name</a> = postfix-out
+    <a href="postconf.5.html#queue_directory">queue_directory</a> = /var/spool/postfix-out
+    <a href="postconf.5.html#data_directory">data_directory</a> = /var/lib/postfix-out
+    #
+    <a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = no
+    <a href="postconf.5.html#master_service_disable">master_service_disable</a> = inet
+    <a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> =
+</pre>
+</blockquote>
+
+<p> This instance has a "stock" <a href="master.5.html">master.cf</a> file, and its queue and
+data directories, also named "postfix-out", will be located in the
+same parent directories as the corresponding directories of the
+default instance (e.g., /var/spool/postfix-out and /var/lib/postfix-out).
+</p>
+
+<p> While this instance is immediately safe to start, it is not yet
+usefully configured. It needs to be customized to fit the role of a
+post-filter re-injection SMTP service. Typical additions include: </p>
+
+<blockquote>
+<pre>
+/etc/postfix-out/<a href="master.5.html">master.cf</a>:
+    # Replace default "smtp inet" entry with one listening on port 10026.
+    127.0.0.1:10026     inet  n       -       n       -       -       smtpd
+
+/etc/postfix-out/<a href="postconf.5.html">main.cf</a>
+    # ...
+
+    # Comment out if you don't use IPv6 internally
+    # <a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv4
+    <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> = loopback-only
+    <a href="postconf.5.html#mynetworks_style">mynetworks_style</a> = host
+    <a href="postconf.5.html#smtpd_authorized_xforward_hosts">smtpd_authorized_xforward_hosts</a> = $<a href="postconf.5.html#mynetworks">mynetworks</a>
+
+    # Don't <a href="anvil.8.html">anvil(8)</a> control the re-injection port.
+    #
+    <a href="postconf.5.html#smtpd_client_connection_count_limit">smtpd_client_connection_count_limit</a> = 0
+    <a href="postconf.5.html#smtpd_client_event_limit_exceptions">smtpd_client_event_limit_exceptions</a> = $<a href="postconf.5.html#mynetworks">mynetworks</a>
+
+    # Best practice when <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> is set, as this is not a
+    # "secondary IP personality" configuration.
+    #
+    <a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> = 0.0.0.0
+
+    # All header rewriting happens upstream
+    #
+    <a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> =
+
+    # No local delivery on border gateway
+    #
+    <a href="postconf.5.html#mydestination">mydestination</a> =
+    <a href="postconf.5.html#alias_maps">alias_maps</a> =
+    <a href="postconf.5.html#alias_database">alias_database</a> =
+    <a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> =
+    <a href="postconf.5.html#local_transport">local_transport</a> = <a href="error.8.html">error</a>:5.1.1 Mailbox unavailable
+
+    # May need a <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> for per-user transport lookups:
+    #
+    <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> = +
+
+    # Only one (unrestricted client)
+    # With multiple instances, rarely need "-o param=value" overrides
+    # in <a href="master.5.html">master.cf</a>, each instance gets its own <a href="postconf.5.html">main.cf</a> file.
+    #
+    <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>, reject
+
+    # Tolerate occasional high latency in the  content filter.
+    #
+    <a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a> = 1200s
+
+    # Best when empty, with all parent domain matches explicit.
+    #
+    <a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> =
+
+    # Use the "relay" transport for inbound mail, and the default
+    # "smtp" transport for outbound mail (bounces, ...). The latter
+    # won't starve the former of delivery agent slots.
+    #
+    <a href="postconf.5.html#relay_domains">relay_domains</a> = example.com, .example.com
+
+    # With xforward, match the input instance setting, if you
+    # want "yes", set both to "yes".
+    #
+    <a href="postconf.5.html#smtpd_client_port_logging">smtpd_client_port_logging</a> = no
+
+    # Transport settings ...
+    # Message size limit
+    # Concurrency tuning for "relay" and "smtp" transport
+    # ...
+</pre>
+</blockquote>
+
+<p> With the "output" configuration in place, enable and start the
+instance: </p>
+
+<blockquote>
+<pre>
+1 # postmulti -i postfix-out -x postconf -e \
+2     "<a href="postconf.5.html#master_service_disable">master_service_disable</a> =" "<a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> = root"
+3 # postmulti -i postfix-out -e enable
+4 # postmulti -i postfix-out -p start
+</pre>
+</blockquote>
+
+<p> This uses the <a href="postmulti.1.html">postmulti(1)</a> command to invoke <a href="postconf.1.html">postconf(1)</a> in the
+context (MAIL_CONFIG=/etc/postfix-out) of the output instance.  </p>
+
+<ul>
+
+<li> <p> Lines 1-2: With "<a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> = root", the
+superuser can test the postix-out instance with "postmulti -i
+postfix-out -x sendmail -bv recipient...", but otherwise local
+submission remains disabled.  </p>
+
+<li> <p> Lines 1-2: With "<a href="postconf.5.html#master_service_disable">master_service_disable</a> =", the "inet"
+listeners are re-enabled. </p>
+
+<li> <p> Line 3: The output instance is enabled for multi-instance
+start/stop. </p>
+
+<li> <p> Line 4: The output instance is started. </p>
+
+</ul>
+
+<p> Test the output instance by submitting probe messages via "sendmail
+-bv" and "telnet". For production systems, in-depth configuration tests
+should be done on a lab system. The simple tests just suggested will only
+confirm successful deployment of a configuration that should already be
+known good. </p>
+
+<h3> Setting up the content-filter proxy </h3>
+
+<p> With the output instance ready, deploy your content-filter
+proxy.  Most proxies will need their own /etc/rc* start/stop script.
+Some proxies, however, are started on demand by the Postfix <a href="spawn.8.html">spawn(8)</a>
+service, in which case you need to add the relevant <a href="spawn.8.html">spawn(8)</a> entry
+to the output instance <a href="master.5.html">master.cf</a> file.  </p>
+
+<p> Configure the proxy to listen on 127.0.0.1:10025 and to re-inject
+filtered email to 127.0.0.1:10026.  Start the proxy service if
+necessary, then test the proxy via "telnet" or automated SMTP
+injectors. The proxy should support the following ESMTP features:
+DSN, 8BITMIME, and XFORWARD. In addition, the proxy should support
+multiple mail deliveries within an SMTP session. </p>
+
+<h3> Setting up the input Postfix instance </h3>
+
+<p> The input Postfix instance receives mail from the network and
+sends it through the content filter. Now we create the input instance,
+also part of the "mta" instance group: </p>
+
+<blockquote>
+<pre>
+# postmulti -I postfix-in -G mta -e create
+</pre>
+</blockquote>
+
+<p> The new instance configuration directory defaults to /etc/postfix-in,
+more precisely, the "postfix-in" subdirectory of the parent directory
+of the default-instance configuration directory. The new instance will
+be created in a "disabled" state: </p>
+
+<blockquote>
+<pre>
+/etc/postfix-in/<a href="postconf.5.html">main.cf</a>
+    #
+    # ... "stock" <a href="postconf.5.html">main.cf</a> settings ...
+    #
+    <a href="postconf.5.html#multi_instance_name">multi_instance_name</a> = postfix-in
+    <a href="postconf.5.html#queue_directory">queue_directory</a> = /var/spool/postfix-in
+    <a href="postconf.5.html#data_directory">data_directory</a> = /var/lib/postfix-in
+    #
+    <a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = no
+    <a href="postconf.5.html#master_service_disable">master_service_disable</a> = inet
+    <a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> =
+</pre>
+</blockquote>
+
+<p> As before, make appropriate changes to <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> to
+make the instance production ready. Consider setting "<a href="postconf.5.html#soft_bounce">soft_bounce</a> = yes"
+during the first few hours of deployment, so you can iron-out any unexpected
+"kinks". </p>
+
+<p> Manual testing can start with:
+
+<blockquote>
+<pre>
+/etc/postfix-in/<a href="postconf.5.html">main.cf</a>
+    # Accept only local traffic, but allow impersonation:
+    <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> = 127.0.0.1
+    <a href="postconf.5.html#smtpd_authorized_xclient_hosts">smtpd_authorized_xclient_hosts</a> = 127.0.0.1
+</pre>
+</blockquote>
+
+<p> This allows you to use the Postfix-specific <a
+href="XCLIENT_README.html">XCLIENT</a> SMTP command to safely
+simulate connections from remote systems before any remote systems
+are able to connect. If the test results look good, revert the above
+settings to the required production values. Typical settings in the
+pre-filter input instance include: </p>
+
+<blockquote>
+<pre>
+/etc/postfix-in/<a href="postconf.5.html">main.cf</a>
+    #
+    # ... 
+    #
+
+    # No local delivery on border gateway
+    #
+    <a href="postconf.5.html#mydestination">mydestination</a> =
+    <a href="postconf.5.html#alias_maps">alias_maps</a> =
+    <a href="postconf.5.html#alias_database">alias_database</a> =
+    <a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> =
+    <a href="postconf.5.html#local_transport">local_transport</a> = <a href="error.8.html">error</a>:5.1.1 Mailbox unavailable
+
+    # Don't rewrite remote headers
+    #
+    <a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> =
+
+    # All recipients of not yet filtered email go to the same filter together.
+    #
+    # With multiple instances, the content-filter is specified
+    # via transport settings not the "<a href="postconf.5.html#content_filter">content_filter</a>" transport
+    # switch override! Here the filter listens on local port 10025.
+    #
+    # If you need to route some users or recipient domains directly to the
+    # output instance bypassing the filter, just define a transport table
+    # with suitable entries.
+    #
+    <a href="postconf.5.html#default_transport">default_transport</a> = <a href="smtp.8.html">smtp</a>:[127.0.0.1]:10025
+    <a href="postconf.5.html#relay_transport">relay_transport</a> = $<a href="postconf.5.html#default_transport">default_transport</a>
+    <a href="postconf.5.html#virtual_transport">virtual_transport</a> = $<a href="postconf.5.html#default_transport">default_transport</a>
+    <a href="postconf.5.html#transport_maps">transport_maps</a> =
+
+    # Pass original client log information through the filter.
+    #
+    <a href="postconf.5.html#smtp_send_xforward_command">smtp_send_xforward_command</a> = yes
+
+    # Avoid splitting the envelope and scanning messages multiple times.
+    # Match the re-injection server's recipient limit.
+    #
+       <a href="postconf.5.html#smtp_destination_recipient_limit">smtp_destination_recipient_limit</a> = 1000
+
+    # Tolerate occasional high latency in the content filter.
+    #
+    <a href="postconf.5.html#smtp_data_done_timeout">smtp_data_done_timeout</a> = 1200s
+
+    # With xforward, match the output instance setting, if you
+    # want "yes", set both to "yes".
+    #
+    <a href="postconf.5.html#smtpd_client_port_logging">smtpd_client_port_logging</a> = no
+
+    # ... Lots of settings for inbound MX host ...
+</pre>
+</blockquote>
+
+<p> With the "input" instance configured, enable and start it: </p>
+
+<blockquote>
+<pre>
+# postmulti -i postfix-in -x postconf -e \
+    "<a href="postconf.5.html#master_service_disable">master_service_disable</a> =" "<a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> = root"
+# postmulti -i postfix-in -e enable
+# postmulti -i postfix-in -p start
+</pre>
+</blockquote>
+
+<p> That's it. You now have a 3-instance configuration. A null-client
+sending all locally submitted mail to the internal mail hub and a pair of
+"mta" instances that receive mail from the Internet, pass it through a
+content-filter, and then deliver it to the internal destination. </p>
+
+<p> Running "postfix start" or "postfix stop" will now start/stop all
+three Postfix instances. You can use "postfix -c /config/path start"
+to start just one instance, or use the instance name (or instance
+group name) via <a href="postmulti.1.html">postmulti(1)</a>: </p>
+
+<blockquote>
+<pre>
+# postmulti -i - -p stop
+# postmulti -g mta -p status
+# postmulti -i postfix-out -p flush
+# postmulti -i postfix-in -p reload
+# ...
+</pre>
+</blockquote>
+
+<p> This example ends the multi-instance "walk through". The remainder
+of this document provides background information on Postfix
+multi-instance support features and options. </p>
+
+<h2><a name="parts"> Components of a Postfix system </a></h2>
+
+<p> A Postfix system consists of the following components: </p>
+
+<p> Shared among all instances: </p>
+
+<ul>
+
+<li><p> Command-line utilities for administrators and users installed in
+$<a href="postconf.5.html#command_directory">command_directory</a>, $<a href="postconf.5.html#sendmail_path">sendmail_path</a>, $<a href="postconf.5.html#mailq_path">mailq_path</a> and $<a href="postconf.5.html#newaliases_path">newaliases_path</a>. </p>
+
+<li><p> Daemon executables, and run-time support files installed in
+$<a href="postconf.5.html#daemon_directory">daemon_directory</a>. </p>
+
+<li><p> Bundled documentation, installed in $<a href="postconf.5.html#html_directory">html_directory</a>,
+$<a href="postconf.5.html#manpage_directory">manpage_directory</a> and $<a href="postconf.5.html#readme_directory">readme_directory</a>. </p>
+
+<li><p> Entries in /etc/passwd and /etc/group for the $<a href="postconf.5.html#mail_owner">mail_owner</a> user and
+$<a href="postconf.5.html#setgid_group">setgid_group</a> group. The the $<a href="postconf.5.html#mail_owner">mail_owner</a> user provides the mail system
+with a protected (non-root) execution context. The $<a href="postconf.5.html#setgid_group">setgid_group</a> group
+is used exclusively to support the setgid <a href="postdrop.1.html">postdrop(1)</a> and <a href="postqueue.1.html">postqueue(1)</a>
+utilities (it <b>must not</b> be the primary group or secondary group
+of any users, including the $<a href="postconf.5.html#mail_owner">mail_owner</a> user). </p>
+
+</ul>
+
+<p> Private to each instance: </p>
+
+<ul>
+
+<li><p> The <a href="postconf.5.html">main.cf</a>, <a href="master.5.html">master.cf</a> (and other optional) configuration
+files in $<a href="postconf.5.html#config_directory">config_directory</a>. </p>
+
+<li> <p> The <a href="QSHAPE_README.html#maildrop_queue">maildrop</a>, incoming, active, deferred and <a href="QSHAPE_README.html#hold_queue">hold queues</a>
+in $<a href="postconf.5.html#queue_directory">queue_directory</a> (which contains additional directories needed
+by Postfix, and which optionally doubles as a chroot jail for Postfix
+daemon processes). </p>
+
+<li> <p> Various caches (TLS session, address verification, ...)
+in $<a href="postconf.5.html#data_directory">data_directory</a>. </p>
+
+</ul>
+
+<p> The Postfix configuration parameters mentioned above are
+collectively referred to as "installation parameters". Their default
+values are set when the Postfix software is built from source, and
+all but one may be optionally set to a non-default value via the
+<a href="postconf.5.html">main.cf</a> file.  The one parameter that (catch-22) cannot be set in
+<a href="postconf.5.html">main.cf</a> is $<a href="postconf.5.html#config_directory">config_directory</a>, as this defines the location of the
+<a href="postconf.5.html">main.cf</a> file itself. </p>
+
+<p> Though <a href="postconf.5.html#config_directory">config_directory</a> cannot be set in <a href="postconf.5.html">main.cf</a>, <a href="postfix.1.html">postfix(1)</a> and
+most of the other command-line Postfix utilities allow you to specify a
+non-default configuration directory via a command line option (typically
+<b>-c</b>) or via the MAIL_CONFIG environment variable. In this way,
+it is possible to have multiple configuration directories on the same
+machine, and to have multiple running <a href="master.8.html">master(8)</a> daemons each with its
+own configuration files, queue directory and data directory. </p>
+
+<p> These multiple running copies of <a href="master.8.html">master(8)</a> share the base Postfix
+software. They do not (and cannot) share their configuration
+directories, queue directories or data directories. </p>
+
+<p> Each combination of configuration directory, together with the queue
+directory and data directory (specified in the corresponding <a href="postconf.5.html">main.cf</a> file)
+make up a Postfix <b>instance</b>. </p>
+
+<h2><a name="default"> The default Postfix instance </a></h2>
+
+<p> One Postfix instance is special: this is the instance whose
+configuration directory is the default one compiled into the Postfix
+utilities. The location of the default configuration directory is
+typically /etc/postfix, and can be queried via the "postconf -d
+<a href="postconf.5.html#config_directory">config_directory</a>" command.  We call the instance with this configuration
+directory the "default instance". </p>
+
+<p> The default instance is responsible for local mail submission. The
+setgid <a href="postdrop.1.html">postdrop(1)</a> utility is used by the <a href="sendmail.1.html">sendmail(1)</a> local submission
+program to spool messages into the <b>maildrop</b> sub-directory of the
+queue directory of the default instance. </p>
+
+<p> Even in the rare case when "sendmail -C" is used to submit local mail
+into a non-default Postfix instance, for security reasons, <a href="postdrop.1.html">postdrop(1)</a>
+will consult the default <a href="postconf.5.html">main.cf</a> file to check the validity of the
+requested non-default configuration directory. </p>
+
+<p> So, while in most other respects, all instances are equal, the
+default instance is "more equal than others". You may choose to create
+additional instances, but you must have at least the default instance,
+with its configuration directory in the default compiled-in location. </p>
+
+<h2><a name="group"> Instance groups </a></h2>
+
+<p> The <a href="postmulti.1.html">postmulti(1)</a> multi-instance manager supports the notion of an
+instance "group". Typically, the member instances of an instance group
+constitute a logical service, and are expected to all be running or all
+be stopped. </p>
+
+<p> In many cases a single Postfix instance will be a complete logical
+"service". You should define such instances as stand-alone instances
+that are not members of any instance "group". The null-client
+instance is an example of a non-group instance. </p>
+
+<p> When a logical service consists of multiple Postfix instances,
+often a pair of pre-filter and post-filter instances with a content
+filter proxy between them, the related instances should be members
+of a single instance group (however, the content filter usually has
+its own start/stop procedure that is separate from any Postfix
+instance).  </p>
+
+<p> The default instance <a href="postconf.5.html">main.cf</a> file's $<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a>
+configuration parameter lists the configuration directories of all
+secondary (non-default) instances. Together with the default instance,
+these secondary instances are managed by the multi-instance manager.
+Instances are started in the order listed, and stopped in the
+opposite order. For instances that are members of a service "group",
+you should arrange to start the service back-to-front, with the
+output stages started and ready to receive mail before the input
+stages are started. </p>
+
+<h2><a name="params"> Multi-instance configuration parameters </a></h2>
+
+<dl>
+
+<dt> <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> </dt> 
+
+<dd> <p> This default-instance configuration parameter must be set
+to a suitable multi-instance manager's "wrapper" program that
+controls the starting, stopping, etc. of a multi-instance Postfix
+system. To use the <a href="postmulti.1.html">postmulti(1)</a> manager described in this document,
+this parameter should be set with the "<a href="#init">postmulti
+-e init</a>" command.  </p> </dd>
+
+<dt> <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> </dt>
+
+<dd> <p> This default-instance configuration parameter specifies
+an optional list of the secondary instances controlled via the
+multi-instance manager. Instances are listed in their "start" order,
+with the default instance always started first (if enabled). If
+$<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> is left empty, the <a href="postfix.1.html">postfix(1)</a> command
+runs with multi-instance support turned off, and none of the
+multi_instance_ configuration parameters will have any effect. </p>
+
+<p> Do not assign a non-empty list of secondary instance configuration
+directories to <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> until you have configured a
+suitable <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> setting! This is best accomplished via
+the "<a href="#init">postmulti -e init</a>" command.
+</p> </dd>
+
+<dt> <a href="postconf.5.html#multi_instance_name">multi_instance_name</a> </dt>
+
+<dd> <p> Each Postfix instance may be assigned a distinct name (with
+"postfix -e create/import/assign -I <i>name</i>..."). This name can
+be used with the <a href="postmulti.1.html">postmulti(1)</a> command-line utility to perform tasks
+on the instance by name (rather than the full pathname of its
+configuration directory). Choose a name that concisely captures the
+role of the instance (it must start with "postfix-").  It is an
+error for two instances to have the same $<a href="postconf.5.html#multi_instance_name">multi_instance_name</a>.  You
+can leave an instance "nameless" by leaving this parameter at the
+default empty setting. </p>
+
+<p> To avoid confusion in your logs, if you don't assign each
+secondary instance a non-empty (distinct) $<a href="postconf.5.html#multi_instance_name">multi_instance_name</a>, you
+should make sure that the $<a href="postconf.5.html#syslog_name">syslog_name</a> setting is different for
+each instance. The $<a href="postconf.5.html#syslog_name">syslog_name</a> parameter defaults to $<a href="postconf.5.html#multi_instance_name">multi_instance_name</a>
+when the latter is non-empty. If at all possible, the <a href="postconf.5.html#syslog_name">syslog_name</a>
+should start with "postfix-", this helps log parsers to identify
+log entries from secondary Postfix instances.  </p> </dd>
+
+<dt> <a href="postconf.5.html#multi_instance_group">multi_instance_group</a> </dt>
+
+<dd> <p> Each Postfix instance may be assigned an "instance group"
+name (with "postfix -e create/import/assign -G <i>name</i>...").
+The default (empty) value of <a href="postconf.5.html#multi_instance_group">multi_instance_group</a> parameter indicates
+a stand-alone instance that is not part of any group. The group
+name can be used with the <a href="postmulti.1.html">postmulti(1)</a> command-line utility to
+perform a task on the members of a group by name. Choose a single-word
+group name that concisely captures the role of the group.  </p>
+</dd>
+
+<dt> <a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> </dt>
+
+<dd> <p> This parameter controls whether a Postfix instance will
+be started by a Postfix multi-instance manager.  The default value
+is "no". The instance can be started explicitly with "postfix -c
+/path/to/config/directory"; this is useful for testing.  </p>
+
+<p> When an instance is disabled, the <a href="postfix.1.html">postfix(1)</a> "start" command
+is replaced by "check". </p>
+
+<p> Some <a href="postfix.1.html">postfix(1)</a> commands (such as "stop", "flush", ...) require
+a running Postfix instance, and skip instances that are disabled.
+</p>
+
+<p> Other <a href="postfix.1.html">postfix(1)</a> commands (such as "status", "set-permissions",
+"upgrade-configuration", ...) do not require a running Postfix
+system, and apply to all instances whether enabled or not.  </p>
+</dd>
+
+</dl>
+
+<p> The <a href="postmulti.1.html">postmulti(1)</a> utility can be used to create (or destroy) instances.
+It can also be used to "import" or "deport" existing instances into or
+from the list of managed instances. When using <a href="postmulti.1.html">postmulti(1)</a> to manage
+instances, the above configuration parameters are managed for you
+automatically. See below. </p>
+
+<h2><a name="how"> Using the postmulti(1) command </a></h2>
+
+<ul>
+
+<li><a href="#init"> Initializing the multi-instance manager </a>
+
+<li><a href="#list"> Listing managed instances </a>
+
+<li><a href="#start"> Starting or stopping a multi-instance system </a>
+
+<li><a href="#adhoc"> Ad-hoc multi-instance operations </a>
+
+<li><a href="#create"> Creating a new Postfix instance </a>
+
+<li><a href="#destroy"> Destroying a Postfix instance </a>
+
+<li><a href="#import"> Importing an existing Postfix instance </a>
+
+<li><a href="#deport"> Deporting a managed Postfix instance </a>
+
+<li><a href="#assign"> Assigning a new name or group name </a>
+
+<li><a href="#enable"> Enabling/disabling managed instances </a>
+
+</ul>
+
+<h3><a name="init"> Initializing the multi-instance manager </a></h3>
+
+<p> Before <a href="postmulti.1.html">postmulti(1)</a> is used for the first time, you must install
+it as the <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> for your Postfix system and enable
+multi-instance operation of the default Postfix instance. You can then
+proceed to add <a href="#create">new</a> or <a href="#import">existing</a>
+instances to the multi-instance configuration. This initial installation
+is accomplished as follows: </p>
+
+<blockquote>
+<pre>
+    # postmulti -e init
+</pre>
+</blockquote>
+
+<p> This updates the default instance <a href="postconf.5.html">main.cf</a> file as follows: </p>
+
+<blockquote>
+<pre>
+    # Use <a href="postmulti.1.html">postmulti(1)</a> as a <a href="postfix-wrapper.5.html">postfix-wrapper(5)</a>
+    #
+    <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> = ${<a href="postconf.5.html#command_directory">command_directory</a>}/postmulti -p --
+
+    # Configure the default instance to start when in multi-instance mode
+    #
+    <a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = yes
+</pre>
+</blockquote>
+
+<p> If you prefer, you can make these changes by editing the default
+<a href="postconf.5.html">main.cf</a> directly, or by using "postconf -e". </p>
+
+<h3><a name="list"> Listing managed instances </a></h3>
+
+<p> The list of managed instances consists of the default instance and
+the additional instances whose configuration directories are listed
+(in start order) under the <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter of the
+default <a href="postconf.5.html">main.cf</a> configuration file.  </p>
+
+<p> You can list selected instances, groups of instances or all
+instances by specifying only the instance matching options with the
+"-l" option.  The "-a" option is assumed if no other instance
+selection options are specified (this behavior changes with the
+"-e" option).  As a special case, even if it has an explicit name,
+the default instance can always be selected via "-i -". </p>
+
+<blockquote>
+<pre>
+# postmulti -l -a
+# postmulti -l -g a_group
+# postmulti -l -i an_instance
+</pre>
+</blockquote>
+
+<p> The output is one line per instance (in "postfix start" order):
+</p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th align="left">name</th> <th align="left">group</th> <th
+align="left">enabled</th> <th align="left"><a href="postconf.5.html#config_directory">config_directory</a></th>
+</tr>
+
+<tr> <td>-</td> <td>-</td> <td>yes</td> <td>/etc/postfix
+
+<tr> <td>mta-out</td> <td>mta</td> <td>yes</td> <td>/etc/postfix/mta-out
+
+<tr> <td>mta-in</td> <td>mta</td> <td>yes</td> <td>/etc/postfix-mta-in
+
+<tr> <td>msa-out</td> <td>msa</td> <td>yes</td> <td>/etc/postfix-msa-out
+
+<tr> <td>msa-in</td> <td>msa</td> <td>yes</td> <td>/etc/postfix-msa-in
+
+<tr> <td>test</td> <td>-</td> <td>no</td> <td>/etc/postfix-test
+
+</table>
+
+</blockquote>
+
+<p> The first line showing the column headings is not part of the
+output. When either the instance name or the instance group is not
+set, it is shown as a "-". </p>
+
+<p> When selecting an existing instance via the "-i" option, you
+can always use the full pathname of its configuration directory
+instead of the instance (short) name. This is the only way to select
+a non-default nameless instance. The default instance can be selected
+via "-i -", whether it has a name or not. </p>
+
+<p> To list instances in reverse start order, include the "-R"
+option together with the instance selection options. </p>
+
+<h3><a name="start"> Starting or stopping a multi-instance system
+</a></h3>
+
+<p> To start, stop, reload, etc. the complete (already configured as
+above) multi-instance system just use <a href="postfix.1.html">postfix(1)</a> as you would with a
+single-instance system. The Postfix multi-instance wrapper framework
+insulates Postfix init.d start and package upgrade scripts from the
+details of multi-instance management! </p>
+
+<p> The <b>-p</b> option of <a href="postmulti.1.html">postmulti(1)</a> turns on <a href="postfix.1.html">postfix(1)</a> compatibility
+mode. With this option the remaining arguments are exactly those supported
+by <a href="postfix.1.html">postfix(1)</a>, but commands are applied to all instances or all enabled
+instances as appropriate. As described above, this switch is required
+when using <a href="postmulti.1.html">postmulti(1)</a> as the <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a>. </p>
+
+<p> If you want to specify a subset of instances by name, or group name,
+or run arbitrary commands (not just "postfix stop/start/etc. in the
+context (MAIL_CONFIG environment variable setting) of a particular
+instance or group of instances, then you can use the instance-aware
+<a href="postmulti.1.html">postmulti(1)</a> utility directly. </p>
+
+<h3><a name="adhoc"> Ad-hoc multi-instance operations </a></h3>
+
+<p> The <a href="postmulti.1.html">postmulti(1)</a> command can be used by the administrator to run arbitrary
+commands in the context of one or more Postfix instances. The most common
+use-case is stopping or starting a group of Postfix instances: </p>
+
+<blockquote>
+<pre>
+# postmulti -g mygroup -p start
+# postmulti -g mygroup -p flush
+# postmulti -g mygroup -p reload
+# postmulti -g mygroup -p status
+# postmulti -g mygroup -p stop
+# postmulti -g mygroup -p upgrade-configuration
+</pre>
+</blockquote>
+
+<p> The <b>-p</b> option is essentially a short-hand for a leading
+<b>postfix</b> command argument, but with appropriate additional options
+turned on depending on the first argument. In the case of "start",
+disabled instances are "checked" (postfix check) rather than simply
+skipped. </p>
+
+<p> The resulting command is executed for each candidate instance with
+the <b>MAIL_CONFIG</b> environment variable set to the configuration
+directory of the corresponding Postfix instance. </p>
+
+<p> The <a href="postmulti.1.html">postmulti(1)</a> utility is able to launch commands other than
+<a href="postfix.1.html">postfix(1)</a>, Use the <b>-x</b> option to ask postmulti to execute an
+ad-hoc command for all instances, a group of instances, or just one
+instance. With ad-hoc commands the <a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> parameter
+is ignored: the command is unconditionally executed for the instances
+selected via -a, -g or -i. In addition to MAIL_CONFIG, the following
+instance parameters are exported into the command environment: </p>
+
+<blockquote>
+<pre>
+<a href="postconf.5.html#command_directory">command_directory</a>=$<a href="postconf.5.html#command_directory">command_directory</a>
+<a href="postconf.5.html#daemon_directory">daemon_directory</a>=$<a href="postconf.5.html#daemon_directory">daemon_directory</a>
+<a href="postconf.5.html#config_directory">config_directory</a>=$<a href="postconf.5.html#config_directory">config_directory</a>
+<a href="postconf.5.html#queue_directory">queue_directory</a>=$<a href="postconf.5.html#queue_directory">queue_directory</a>
+<a href="postconf.5.html#data_directory">data_directory</a>=$<a href="postconf.5.html#data_directory">data_directory</a>
+<a href="postconf.5.html#multi_instance_name">multi_instance_name</a>=$<a href="postconf.5.html#multi_instance_name">multi_instance_name</a>
+<a href="postconf.5.html#multi_instance_group">multi_instance_group</a>=$<a href="postconf.5.html#multi_instance_group">multi_instance_group</a>
+<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a>=$<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a>
+</pre>
+</blockquote>
+
+<p> The <a href="postconf.5.html#config_directory">config_directory</a> setting is of course the same as MAIL_CONFIG,
+and is arguably redundant, but leaving it in is less surprising. If
+you want to skip disabled instances, just check <a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a>
+environment variable and exit if it is set to "no". </p>
+
+<p> The ability to run ad-hoc commands opens up a wealth of additional
+possibilities: </p>
+
+<ul>
+
+<li><p> Specify an instance by name rather than configuration directory
+when using <a href="sendmail.1.html">sendmail(1)</a> to send a verification probe: </p>
+
+<blockquote>
+<pre>
+$ postmulti -i postfix-myinst -x sendmail -bv test@example.net
+</pre>
+</blockquote>
+
+<li><p> Display non-default <a href="postconf.5.html">main.cf</a> settings of all Postfix instances.
+This uses an inline shell script to package together multiple shell
+commands to execute for each instance: </p>
+
+<blockquote>
+<pre>
+$ postmulti -x sh -c 'echo "-- $MAIL_CONFIG"; postconf -n'
+</pre>
+</blockquote>
+
+<li><p> Put all mail in enabled member instances of a group on hold: </p>
+
+<blockquote>
+<pre>
+# postmulti -g group_name -x \
+    sh -c 'test $<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = yes &amp;&amp; postsuper -h ALL'
+</pre>
+</blockquote>
+
+<li><p> Show top 10 domains in the <a href="QSHAPE_README.html#deferred_queue">deferred queue</a> of all instances:
+</p>
+
+<blockquote>
+<pre>
+# postmulti -x sh -c 'echo "-- $MAIL_CONFIG"; qshape deferred | head -12'
+</pre>
+</blockquote>
+
+</ul>
+
+<h3><a name="create"> Creating a new Postfix instance </a></h3>
+
+<p> The <a href="postmulti.1.html">postmulti(1)</a> command can be used to create additional Postfix
+instances. New instances are created with local submission and all "inet"
+services disabled via the following non-default parameter settings in
+the <a href="postconf.5.html">main.cf</a> file: </p>
+
+<blockquote>
+<pre>
+<a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> =
+<a href="postconf.5.html#master_service_disable">master_service_disable</a> = inet
+</pre>
+</blockquote>
+
+<p> The above settings ensure that new instances are safe to start
+immediately: they will not conflict with inet listeners in existing
+Postfix instances.  They will also not accept any mail until they are
+fully configured, at which point you can do away with one or both of
+the above safety measures. </p>
+
+<p> The <a href="postmulti.1.html">postmulti(1)</a> command encourages a preferred way of organizing
+the configuration directories, queue directories and data directories
+of non-default instances. If the default instance settings are: </p>
+
+<blockquote>
+<pre>
+<a href="postconf.5.html#config_directory">config_directory</a> = /conf-path/postfix
+<a href="postconf.5.html#queue_directory">queue_directory</a> = /queue-path/postfix
+<a href="postconf.5.html#data_directory">data_directory</a> = /data-path/postfix
+</pre>
+</blockquote>
+
+<p> A newly-created instance named <i>postfix-myinst</i> will by default
+have: </p>
+
+<blockquote>
+<pre>
+<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = no
+<a href="postconf.5.html#multi_instance_name">multi_instance_name</a> = postfix-myinst
+<a href="postconf.5.html#config_directory">config_directory</a> = /conf-path/postfix-myinst
+<a href="postconf.5.html#queue_directory">queue_directory</a> = /queue-path/postfix-myinst
+<a href="postconf.5.html#data_directory">data_directory</a> = /data-path/postfix-myinst
+</pre>
+</blockquote>
+
+<p> You can override any of these defaults when creating the instance,
+but unless you want to spread instance queue directories over multiple
+file-systems, use the default naming strategy. It keeps the multiple
+instances organized in a uniform, predictable fashion. </p>
+
+<p> When specifying the instance name later, you can refer to it
+either as "postfix-myinst", or via the full path of the configuration
+directory. </p>
+
+<p> To create a new instance just use the <b>-e create</b> option: </p>
+
+<blockquote>
+<pre>
+# postmulti -I postfix-myinst -e create
+</pre>
+</blockquote>
+
+<p> If the new instance is to belong to a group of related instances that
+implement a single logical service, assign it to a group: </p>
+
+<blockquote>
+<pre>
+# postmulti -I postfix-myinst -G mygroup -e create
+</pre>
+</blockquote>
+
+<p> If you want to override the conventional values of the instance
+installation parameters, specify their values on the command-line: </p>
+
+<blockquote>
+<pre>
+# postmulti [-I postfix-myinst] [-G mygroup] -e create \
+       "<a href="postconf.5.html#config_directory">config_directory</a> = /path/to/config_directory" \
+       "<a href="postconf.5.html#queue_directory">queue_directory</a> = /path/to/queue_directory" \
+       "<a href="postconf.5.html#data_directory">data_directory</a> = /path/to/data_directory"
+</pre>
+</blockquote>
+
+<p> A note on the <b>-I</b> and <b>-G</b> options above. These are always
+used to assign a name or group name to an instance, while the <b>-i</b>
+and <b>-g</b> options always select existing instances.  By default,
+the configuration directories of newly managed instances are appended
+to the instance list. You can use the "-i" or "-g" or "-a" options to
+insert the new instance before the specified instance or group, or at
+the beginning of the instance list (<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter
+of the default instance). </p>
+
+<p> If you do specify a name (use "-I" with a name that is not "-")
+for the new instance, you may omit any of the 3 instance installation
+parameters whose instance-name based value is acceptable. Otherwise, all
+three instance installation parameters are required. You should set the
+"<a href="postconf.5.html#syslog_name">syslog_name</a>" explicitly in the <a href="postconf.5.html">main.cf</a> file of a "nameless" instance,
+in order to avoid confusion in the mail logs when multiple instances
+are in use. </p>
+
+<h3><a name="destroy"> Destroying a Postfix instance </a></h3>
+
+<p> If you no longer need an instance, you can destroy it via: </p>
+
+<blockquote>
+<pre>
+# postmulti -i postfix-myinst -p stop
+# postmulti -i postfix-myinst -e disable
+# postmulti -i postfix-myinst -e destroy
+</pre>
+</blockquote>
+
+<p> The instance must be stopped, disabled and have no queued messages.
+This is expected to fully delete a just created instance that has never
+been used. If the instance is not freshly created, files added after
+the instance was created will remain in the configuration, queue or
+data directories, in which case the corresponding directory may not
+be fully removed and a warning to that effect will be displayed. You
+can complete the destruction of the instance manually by removing any
+unwanted remnants of the instance-specific "private" directories. </p>
+
+<h3><a name="import"> Importing an existing Postfix instance </a></h3>
+
+<p> If you already have an existing secondary Postfix instance that is
+not yet managed via <a href="postmulti.1.html">postmulti(1)</a>, you can "import" it into the list
+of managed instances. If your instance is already using the default
+configuration directory naming scheme, just specify the corresponding
+instance name (the <a href="postconf.5.html#multi_instance_name">multi_instance_name</a> parameter in its configuration
+file will be adjusted to match this name if necessary): </p>
+
+<blockquote>
+<pre>
+# postmulti -I postfix-myinst [-G mygroup] -e import
+</pre>
+</blockquote>
+
+<p> Otherwise, you must specify the location of its configuration
+directory: </p>
+
+<blockquote>
+<pre>
+# postmulti [-I postfix-myinst] [-G mygroup] -e import \
+       "<a href="postconf.5.html#config_directory">config_directory</a> = /path/of/config_directory"
+</pre>
+</blockquote>
+
+<p> When the instance is imported, you can assign a name or a group. As
+with <a href="#create">"create"</a>, you can control the placement of the
+new instance in the start order by using "-i", "-g" or "-a" to prepend
+before the selected instance or instances. </p>
+
+<p> An imported instance is usually not multi-instance "enabled",
+unless it was part of a multi-instance configuration at an earlier
+time.  If it is fully configured and ready to run, don't forget
+to <a href="#enable">enable</a> it and if necessary start it. When
+other enabled instances are already running, new instances need to
+be started individually when they are first created or imported.
+</p>
+
+<p> To find out what instances are running, use: </p>
+
+<blockquote>
+<pre>
+# postfix status
+</pre>
+</blockquote>
+
+<h3><a name="deport"> Deporting a managed Postfix instance </a></h3>
+
+<p> You can "deport" an existing instance from the list of managed
+instances.  This does not destroy the instance, rather the instance
+just becomes a stand-alone Postfix instance not registered with the
+multi-instance manager. <a href="postmulti.1.html">postmulti(1)</a> will refuse to "deport" an
+instance that is not stopped and disabled. </p>
+
+<blockquote>
+<pre>
+# postmulti -i postfix-myinst -p stop
+# postmulti -i postfix-myinst -e disable
+# postmulti -i postfix-myinst -e deport
+</pre>
+</blockquote>
+
+<h3><a name="assign"> Assigning a new name or group name </a></h3>
+
+<p> You can assign a new name or new group to a managed instance.
+Use "-" as the new value to assign the instance to no group or make it
+nameless. To specify a nameless secondary instance use the configuration
+directory path instead of the old name: </p>
+
+<blockquote>
+<pre>
+# postmulti -i postfix-old [-I postfix-new] [-G newgroup] -e assign
+</pre>
+</blockquote>
+
+<h3><a name="enable"> Enabling/disabling managed instances </a></h3>
+
+<p> You can enable or disable a managed instance. As documented in
+<a href="postfix-wrapper.5.html">postfix-wrapper(5)</a>, disabled instances are skipped with actions
+that <a href="postconf.5.html#postmulti_start_commands">start</a>,
+<a href="postconf.5.html#postmulti_start_commands">stop</a> or <a
+href="postconf.5.html#postmulti_control_commands">control</a> running
+Postfix instances. </p>
+
+<blockquote>
+<pre>
+# postmulti -i postfix-myinst -e enable
+# postmulti -i postfix-myinst -e disable
+</pre>
+</blockquote>
+
+<h2><a name="credits"> Credits </a></h2>
+
+<p> Wietse Venema created Postfix, designed and implemented the
+multi-instance wrapper framework and provided design feedback that made
+the <a href="postmulti.1.html">postmulti(1)</a> utility much more general and useful than originally
+envisioned. </p>
+
+<p> The <a href="postmulti.1.html">postmulti(1)</a> utility was developed by Victor Duchovni of Morgan
+Stanley, who also wrote the initial version of this document. </p>
+
+</body> </html>
index fadc13b6a35b97ea1fee13f48ad5430b445f9d94..7d20df6bba0dbb5e4fa33edfa61c0ef5da053895 100644 (file)
@@ -10,9 +10,10 @@ DAEMONS      =  bounce.8.html cleanup.8.html defer.8.html error.8.html local.8.html \
        scache.8.html discard.8.html tlsmgr.8.html
 COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
        postconf.1.html postfix.1.html postkick.1.html postlock.1.html \
-       postlog.1.html postdrop.1.html postmap.1.html sendmail.1.html \
-       postqueue.1.html postsuper.1.html smtp-source.1.html \
-       smtp-sink.1.html qmqp-source.1.html qmqp-sink.1.html \
+       postlog.1.html postdrop.1.html postmap.1.html postmulti.1.html \
+       postqueue.1.html postsuper.1.html sendmail.1.html \
+       smtp-source.1.html smtp-sink.1.html \
+       qmqp-source.1.html qmqp-sink.1.html \
        qshape.1.html
 CONFIG = access.5.html aliases.5.html canonical.5.html relocated.5.html \
        transport.5.html virtual.5.html pcre_table.5.html regexp_table.5.html \
@@ -177,6 +178,10 @@ postmap.1.html: ../src/postmap/postmap.c
        PATH=../mantools:$$PATH; \
        srctoman $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
 
+postmulti.1.html: ../src/postmulti/postmulti.c
+       PATH=../mantools:$$PATH; \
+       srctoman $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
+
 postqueue.1.html: ../src/postqueue/postqueue.c
        PATH=../mantools:$$PATH; \
        srctoman $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@
index 5c8ff198f1f70397b6199c1974706be60ed74bf5..7a332d9c14d1bfb89467dafbdf8ef9e1b715be41 100644 (file)
@@ -728,6 +728,11 @@ for shell scripts. </p>
 such as <a href="canonical.5.html">canonical(5)</a>, <a href="virtual.5.html">virtual(5)</a> and others. It is a cousin of the
 UNIX makemap command. </p>
 
+<li> <p> The <a href="postmulti.1.html">postmulti(1)</a> command repeats the "postfix start" etc.
+command for each Postfix instance, and supports creation, deletion
+etc. of Postfix instances. For a tutorial, see <a href="MULTI_INSTANCE_README.html">MULTI_INSTANCE_README</a>.
+</p>
+
 <li> <p> The <a href="postqueue.1.html">postqueue(1)</a> command is the privileged command that
 is run by Postfix <a href="sendmail.1.html">sendmail(1)</a> and <a href="mailq.1.html">mailq(1)</a> in order to flush or
 list the
index ef7365d864bd191b958ed6e2d11c9a6a87c76f0c..12d22ca066161dc8c9fe80128f6766fccca2ceca 100644 (file)
@@ -111,7 +111,7 @@ their default settings. </p>
 1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
 2     <a href="postconf.5.html#myorigin">myorigin</a> = $<a href="postconf.5.html#mydomain">mydomain</a>
 3     <a href="postconf.5.html#relayhost">relayhost</a> = $<a href="postconf.5.html#mydomain">mydomain</a>
-4     <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> = 127.0.0.1
+4     <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> = loopback-only
 5     <a href="postconf.5.html#local_transport">local_transport</a> = <a href="error.8.html">error</a>:local delivery is disabled
 6 
 7 /etc/postfix/<a href="master.5.html">master.cf</a>:
index 809f1c4f3e5c174eabbfdbdffb0d6102c2066972..0a090a2c34636bf517a79136a754ad3909a2aa87 100644 (file)
@@ -226,10 +226,11 @@ clients get a chance to talk to Postfix.  </p>
 
 <ul>
 
-<li> <p> Use "421" reply codes for botnet-related RBLs or for
-selected non-RBL restrictions. This causes Postfix 2.3 and later
-to disconnect immediately without waiting for the remote SMTP
-client to send a QUIT command. </p>
+<li> <p> Use "521" reply codes (Postfix 2.6 and later) for
+botnet-related RBLs or for selected non-RBL restrictions. With
+Postfix 2.3-2.5 use "421" for a similar result. The Postfix SMTP
+server will disconnect immediately without waiting for the remote
+SMTP client to send a QUIT command. </p>
 
 <p> You can set individual reject codes for RBLs, and for individual
 responses from a specific RBL. We'll use zen.spamhaus.org as an
@@ -237,7 +238,7 @@ example; by the time you read this document, details may have
 changed.  Right now, their documents say that a response of 127.0.0.10
 or 127.0.0.11 indicates a dynamic client IP address, which means
 that the machine is probably running a bot of some kind.  To give
-a 421 response instead of the default 554 response, use something
+a 521 response instead of the default 554 response, use something
 like: </p>
 
 <pre>
@@ -251,11 +252,11 @@ like: </p>
  8      <a href="postconf.5.html#rbl_reply_maps">rbl_reply_maps</a> = hash:/etc/postfix/rbl_reply_maps
  9  
 10  /etc/postfix/rbl_reply_maps:
-11      zen.spamhaus.org=127.0.0.10 421 4.7.1 Service unavailable;
+11      zen.spamhaus.org=127.0.0.10 521 4.7.1 Service unavailable;
 12       $rbl_class [$rbl_what] blocked using
 13       $rbl_domain${rbl_reason?; $rbl_reason}
 14  
-15      zen.spamhaus.org=127.0.0.11 421 4.7.1 Service unavailable;
+15      zen.spamhaus.org=127.0.0.11 521 4.7.1 Service unavailable;
 16       $rbl_class [$rbl_what] blocked using
 17       $rbl_domain${rbl_reason?; $rbl_reason}
 </pre>
@@ -264,7 +265,8 @@ like: </p>
 will still only do a single DNS query, so the performance difference
 is negligible. </p>
 
-<p> The down-side of sending 421 instead of the default 554 is that
+<p> With Postfix 2.3-2.5, use 421 (reply code 521 will not cause
+Postfix to disconnect). The down-side of sending 421 is that
 it works only for zombies and other malware. If the client is running
 a real MTA, then it may connect again several times until the mail
 expires in its queue. When this is a problem, stick with the default
index 57236fc7cc31fe044acabfcf64fbe06a02990257..4eabdae18029d57aee0cd8f51b2b3005e3a17747 100644 (file)
@@ -95,41 +95,47 @@ CLEANUP(8)                                                          CLEANUP(8)
               and is always turned on  with  older  Postfix  ver-
               sions).
 
+       Available in Postfix version 2.6 and later:
+
+       <b><a href="postconf.5.html#always_add_missing_headers">always_add_missing_headers</a> (no)</b>
+              Always  add (Resent-) From:, To:, Date: or Message-
+              ID headers when not present.
+
 <b>BUILT-IN CONTENT FILTERING CONTROLS</b>
-       Postfix  built-in  content  filtering  is  meant to stop a
-       flood of worms or viruses. It is  not  a  general  content
+       Postfix built-in content filtering  is  meant  to  stop  a
+       flood  of  worms  or  viruses. It is not a general content
        filter.
 
        <b><a href="postconf.5.html#body_checks">body_checks</a> (empty)</b>
-              Optional  lookup  tables  for content inspection as
+              Optional lookup tables for  content  inspection  as
               specified in the <a href="header_checks.5.html"><b>body_checks</b>(5)</a> manual page.
 
        <b><a href="postconf.5.html#header_checks">header_checks</a> (empty)</b>
-              Optional lookup tables for  content  inspection  of
-              primary  non-MIME  message headers, as specified in
+              Optional  lookup  tables  for content inspection of
+              primary non-MIME message headers, as  specified  in
               the <a href="header_checks.5.html"><b>header_checks</b>(5)</a> manual page.
 
        Available in Postfix version 2.0 and later:
 
        <b><a href="postconf.5.html#body_checks_size_limit">body_checks_size_limit</a> (51200)</b>
               How much text in a message body segment (or attach-
-              ment,  if you prefer to use that term) is subjected
+              ment, if you prefer to use that term) is  subjected
               to <a href="postconf.5.html#body_checks">body_checks</a> inspection.
 
        <b><a href="postconf.5.html#mime_header_checks">mime_header_checks</a> ($<a href="postconf.5.html#header_checks">header_checks</a>)</b>
-              Optional lookup tables for  content  inspection  of
-              MIME  related  message headers, as described in the
+              Optional  lookup  tables  for content inspection of
+              MIME related message headers, as described  in  the
               <a href="header_checks.5.html"><b>header_checks</b>(5)</a> manual page.
 
        <b><a href="postconf.5.html#nested_header_checks">nested_header_checks</a> ($<a href="postconf.5.html#header_checks">header_checks</a>)</b>
-              Optional lookup tables for  content  inspection  of
-              non-MIME  message  headers in attached messages, as
+              Optional  lookup  tables  for content inspection of
+              non-MIME message headers in attached  messages,  as
               described in the <a href="header_checks.5.html"><b>header_checks</b>(5)</a> manual page.
 
        Available in Postfix version 2.3 and later:
 
        <b><a href="postconf.5.html#message_reject_characters">message_reject_characters</a> (empty)</b>
-              The set of characters that Postfix will  reject  in
+              The  set  of characters that Postfix will reject in
               message content.
 
        <b><a href="postconf.5.html#message_strip_characters">message_strip_characters</a> (empty)</b>
@@ -138,23 +144,23 @@ CLEANUP(8)                                                          CLEANUP(8)
 
 <b>BEFORE QUEUE MILTER CONTROLS</b>
        As of version 2.3, Postfix supports the Sendmail version 8
-       Milter  (mail  filter) protocol. When mail is not received
-       via the <a href="smtpd.8.html">smtpd(8)</a> server, the <a href="cleanup.8.html">cleanup(8)</a> server will  simu-
-       late  SMTP events to the extent that this is possible. For
+       Milter (mail filter) protocol. When mail is  not  received
+       via  the <a href="smtpd.8.html">smtpd(8)</a> server, the <a href="cleanup.8.html">cleanup(8)</a> server will simu-
+       late SMTP events to the extent that this is possible.  For
        details see the <a href="MILTER_README.html">MILTER_README</a> document.
 
        <b><a href="postconf.5.html#non_smtpd_milters">non_smtpd_milters</a> (empty)</b>
               A list of Milter (mail filter) applications for new
-              mail  that does not arrive via the Postfix <a href="smtpd.8.html"><b>smtpd</b>(8)</a>
+              mail that does not arrive via the Postfix  <a href="smtpd.8.html"><b>smtpd</b>(8)</a>
               server.
 
        <b><a href="postconf.5.html#milter_protocol">milter_protocol</a> (2)</b>
-              The mail filter protocol version and optional  pro-
-              tocol  extensions  for  communication with a Milter
+              The  mail filter protocol version and optional pro-
+              tocol extensions for communication  with  a  Milter
               (mail filter) application.
 
        <b><a href="postconf.5.html#milter_default_action">milter_default_action</a> (tempfail)</b>
-              The default action  when  a  Milter  (mail  filter)
+              The  default  action  when  a  Milter (mail filter)
               application is unavailable or mis-configured.
 
        <b><a href="postconf.5.html#milter_macro_daemon_name">milter_macro_daemon_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
@@ -166,55 +172,55 @@ CLEANUP(8)                                                          CLEANUP(8)
               cations.
 
        <b><a href="postconf.5.html#milter_connect_timeout">milter_connect_timeout</a> (30s)</b>
-              The  time  limit  for  connecting to a Milter (mail
-              filter) application, and for  negotiating  protocol
+              The time limit for connecting  to  a  Milter  (mail
+              filter)  application,  and for negotiating protocol
               options.
 
        <b><a href="postconf.5.html#milter_command_timeout">milter_command_timeout</a> (30s)</b>
-              The  time  limit  for  sending an SMTP command to a
+              The time limit for sending an  SMTP  command  to  a
               Milter (mail filter) application, and for receiving
               the response.
 
        <b><a href="postconf.5.html#milter_content_timeout">milter_content_timeout</a> (300s)</b>
-              The  time  limit  for  sending message content to a
+              The time limit for sending  message  content  to  a
               Milter (mail filter) application, and for receiving
               the response.
 
-       <b><a href="postconf.5.html#milter_connect_macros">milter_connect_macros</a> (see postconf -n output)</b>
-              The  macros  that  are sent to Milter (mail filter)
-              applications after completion of  an  SMTP  connec-
+       <b><a href="postconf.5.html#milter_connect_macros">milter_connect_macros</a> (see 'postconf -d' output)</b>
+              The macros that are sent to  Milter  (mail  filter)
+              applications  after  completion  of an SMTP connec-
               tion.
 
-       <b><a href="postconf.5.html#milter_helo_macros">milter_helo_macros</a> (see postconf -n output)</b>
-              The  macros  that  are sent to Milter (mail filter)
+       <b><a href="postconf.5.html#milter_helo_macros">milter_helo_macros</a> (see 'postconf -d' output)</b>
+              The macros that are sent to  Milter  (mail  filter)
               applications after the SMTP HELO or EHLO command.
 
-       <b><a href="postconf.5.html#milter_mail_macros">milter_mail_macros</a> (see postconf -n output)</b>
-              The macros that are sent to  Milter  (mail  filter)
+       <b><a href="postconf.5.html#milter_mail_macros">milter_mail_macros</a> (see 'postconf -d' output)</b>
+              The  macros  that  are sent to Milter (mail filter)
               applications after the SMTP MAIL FROM command.
 
-       <b><a href="postconf.5.html#milter_rcpt_macros">milter_rcpt_macros</a> (see postconf -n output)</b>
-              The  macros  that  are sent to Milter (mail filter)
+       <b><a href="postconf.5.html#milter_rcpt_macros">milter_rcpt_macros</a> (see 'postconf -d' output)</b>
+              The macros that are sent to  Milter  (mail  filter)
               applications after the SMTP RCPT TO command.
 
-       <b><a href="postconf.5.html#milter_data_macros">milter_data_macros</a> (see postconf -n output)</b>
-              The macros that are sent to  version  4  or  higher
-              Milter  (mail  filter)  applications after the SMTP
+       <b><a href="postconf.5.html#milter_data_macros">milter_data_macros</a> (see 'postconf -d' output)</b>
+              The  macros  that  are  sent to version 4 or higher
+              Milter (mail filter) applications  after  the  SMTP
               DATA command.
 
-       <b><a href="postconf.5.html#milter_unknown_command_macros">milter_unknown_command_macros</a> (see postconf -n output)</b>
-              The macros that are sent to  version  3  or  higher
-              Milter  (mail filter) applications after an unknown
+       <b><a href="postconf.5.html#milter_unknown_command_macros">milter_unknown_command_macros</a> (see 'postconf -d' output)</b>
+              The  macros  that  are  sent to version 3 or higher
+              Milter (mail filter) applications after an  unknown
               SMTP command.
 
-       <b><a href="postconf.5.html#milter_end_of_data_macros">milter_end_of_data_macros</a> (see postconf -n output)</b>
-              The macros that are sent to  Milter  (mail  filter)
+       <b><a href="postconf.5.html#milter_end_of_data_macros">milter_end_of_data_macros</a> (see 'postconf -d' output)</b>
+              The  macros  that  are sent to Milter (mail filter)
               applications after the message end-of-data.
 
        Available in Postfix version 2.5 and later:
 
-       <b><a href="postconf.5.html#milter_end_of_header_macros">milter_end_of_header_macros</a> (see postconf -n output)</b>
-              The  macros  that  are sent to Milter (mail filter)
+       <b><a href="postconf.5.html#milter_end_of_header_macros">milter_end_of_header_macros</a> (see 'postconf -d' output)</b>
+              The macros that are sent to  Milter  (mail  filter)
               applications after the end of the message header.
 
 <b>MIME PROCESSING CONTROLS</b>
@@ -232,27 +238,27 @@ CLEANUP(8)                                                          CLEANUP(8)
               will handle.
 
        <b><a href="postconf.5.html#strict_8bitmime">strict_8bitmime</a> (no)</b>
-              Enable both  <a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a>  and  strict_8bit-
+              Enable  both  <a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a>  and strict_8bit-
               mime_body.
 
        <b><a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a> (no)</b>
               Reject mail with 8-bit text in message headers.
 
        <b><a href="postconf.5.html#strict_8bitmime_body">strict_8bitmime_body</a> (no)</b>
-              Reject  8-bit  message body text without 8-bit MIME
+              Reject 8-bit message body text without  8-bit  MIME
               content encoding information.
 
        <b><a href="postconf.5.html#strict_mime_encoding_domain">strict_mime_encoding_domain</a> (no)</b>
               Reject mail with invalid Content-Transfer-Encoding:
-              information  for  the message/* or multipart/* MIME
+              information for the message/* or  multipart/*  MIME
               content types.
 
        Available in Postfix version 2.5 and later:
 
        <b><a href="postconf.5.html#detect_8bit_encoding_header">detect_8bit_encoding_header</a> (yes)</b>
               Automatically detect 8BITMIME body content by look-
-              ing  at Content-Transfer-Encoding: message headers;
-              historically, this behavior was  hard-coded  to  be
+              ing at Content-Transfer-Encoding: message  headers;
+              historically,  this  behavior  was hard-coded to be
               "always on".
 
 <b>AUTOMATIC BCC RECIPIENT CONTROLS</b>
@@ -260,31 +266,31 @@ CLEANUP(8)                                                          CLEANUP(8)
        mail enters the mail system:
 
        <b><a href="postconf.5.html#always_bcc">always_bcc</a> (empty)</b>
-              Optional address  that  receives  a  "blind  carbon
+              Optional  address  that  receives  a  "blind carbon
               copy" of each message that is received by the Post-
               fix mail system.
 
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#sender_bcc_maps">sender_bcc_maps</a> (empty)</b>
-              Optional BCC  (blind  carbon-copy)  address  lookup
+              Optional  BCC  (blind  carbon-copy)  address lookup
               tables, indexed by sender address.
 
        <b><a href="postconf.5.html#recipient_bcc_maps">recipient_bcc_maps</a> (empty)</b>
-              Optional  BCC  (blind  carbon-copy)  address lookup
+              Optional BCC  (blind  carbon-copy)  address  lookup
               tables, indexed by recipient address.
 
 <b>ADDRESS TRANSFORMATION CONTROLS</b>
-       Address rewriting is delegated to  the  <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a>
-       daemon.   The  <a href="cleanup.8.html"><b>cleanup</b>(8)</a>  server  implements table driven
+       Address  rewriting  is delegated to the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a>
+       daemon.  The <a href="cleanup.8.html"><b>cleanup</b>(8)</a>  server  implements  table  driven
        address mapping.
 
        <b><a href="postconf.5.html#empty_address_recipient">empty_address_recipient</a> (MAILER-DAEMON)</b>
-              The  recipient  of  mail  addressed  to  the   null
+              The   recipient  of  mail  addressed  to  the  null
               address.
 
        <b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b>
-              Optional  address mapping lookup tables for message
+              Optional address mapping lookup tables for  message
               headers and envelopes.
 
        <b><a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> (empty)</b>
@@ -295,49 +301,49 @@ CLEANUP(8)                                                          CLEANUP(8)
               Optional address mapping lookup tables for envelope
               and header sender addresses.
 
-       <b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a>    (envelope_sender,     header_sender,</b>
+       <b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a>     (envelope_sender,    header_sender,</b>
        <b>header_recipient)</b>
               What addresses are subject to address masquerading.
 
        <b><a href="postconf.5.html#masquerade_domains">masquerade_domains</a> (empty)</b>
-              Optional  list of domains whose subdomain structure
+              Optional list of domains whose subdomain  structure
               will be stripped off in email addresses.
 
        <b><a href="postconf.5.html#masquerade_exceptions">masquerade_exceptions</a> (empty)</b>
-              Optional list of user names that are not  subjected
-              to  address  masquerading,  even when their address
+              Optional  list of user names that are not subjected
+              to address masquerading, even  when  their  address
               matches $<a href="postconf.5.html#masquerade_domains">masquerade_domains</a>.
 
        <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
-              What address lookup tables copy an  address  exten-
+              What  address  lookup tables copy an address exten-
               sion from the lookup key to the lookup result.
 
        Available before Postfix version 2.0:
 
        <b><a href="postconf.5.html#virtual_maps">virtual_maps</a> (empty)</b>
               Optional lookup tables with a) names of domains for
-              which all addresses are  aliased  to  addresses  in
-              other  local  or  remote  domains, and b) addresses
-              that are aliased to addresses  in  other  local  or
+              which  all  addresses  are  aliased to addresses in
+              other local or remote  domains,  and  b)  addresses
+              that  are  aliased  to  addresses in other local or
               remote domains.
 
        Available in Postfix version 2.0 and later:
 
        <b><a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> ($<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b>
-              Optional  lookup  tables  that  alias specific mail
-              addresses or  domains  to  other  local  or  remote
+              Optional lookup tables  that  alias  specific  mail
+              addresses  or  domains  to  other  local  or remote
               address.
 
        Available in Postfix version 2.2 and later:
 
-       <b><a href="postconf.5.html#canonical_classes">canonical_classes</a>   (envelope_sender,  envelope_recipient,</b>
+       <b><a href="postconf.5.html#canonical_classes">canonical_classes</a>  (envelope_sender,   envelope_recipient,</b>
        <b>header_sender, header_recipient)</b>
-              What   addresses   are  subject  to  <a href="postconf.5.html#canonical_maps">canonical_maps</a>
+              What  addresses  are  subject   to   <a href="postconf.5.html#canonical_maps">canonical_maps</a>
               address mapping.
 
        <b><a href="postconf.5.html#recipient_canonical_classes">recipient_canonical_classes</a>           (envelope_recipient,</b>
        <b>header_recipient)</b>
-              What addresses  are  subject  to  <a href="postconf.5.html#recipient_canonical_maps">recipient_canoni</a>-
+              What  addresses  are  subject  to <a href="postconf.5.html#recipient_canonical_maps">recipient_canoni</a>-
               <a href="postconf.5.html#recipient_canonical_maps">cal_maps</a> address mapping.
 
        <b><a href="postconf.5.html#sender_canonical_classes">sender_canonical_classes</a> (envelope_sender, header_sender)</b>
@@ -345,15 +351,15 @@ CLEANUP(8)                                                          CLEANUP(8)
               address mapping.
 
        <b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
-              Don't rewrite message headers from  remote  clients
+              Don't  rewrite  message headers from remote clients
               at all when this parameter is empty; otherwise, re-
-              write message  headers  and  append  the  specified
+              write  message  headers  and  append  the specified
               domain name to incomplete addresses.
 
 <b>RESOURCE AND RATE CONTROLS</b>
        <b><a href="postconf.5.html#duplicate_filter_limit">duplicate_filter_limit</a> (1000)</b>
-              The  maximal  number of addresses remembered by the
-              address duplicate filter  for  <a href="aliases.5.html"><b>aliases</b>(5)</a>  or  <a href="virtual.5.html"><b>vir-</b></a>
+              The maximal number of addresses remembered  by  the
+              address  duplicate  filter  for  <a href="aliases.5.html"><b>aliases</b>(5)</a> or <a href="virtual.5.html"><b>vir-</b></a>
               <a href="virtual.5.html"><b>tual</b>(5)</a> alias expansion, or for <a href="showq.8.html"><b>showq</b>(8)</a> queue dis-
               plays.
 
@@ -362,16 +368,16 @@ CLEANUP(8)                                                          CLEANUP(8)
               message header.
 
        <b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b>
-              The  maximal  number  of Received:  message headers
+              The maximal number of  Received:   message  headers
               that is allowed in the primary message headers.
 
        <b><a href="postconf.5.html#in_flow_delay">in_flow_delay</a> (1s)</b>
-              Time to pause before accepting a new message,  when
+              Time  to pause before accepting a new message, when
               the message arrival rate exceeds the message deliv-
               ery rate.
 
        <b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
-              The maximal size in bytes of a  message,  including
+              The  maximal  size in bytes of a message, including
               envelope information.
 
        Available in Postfix version 2.0 and later:
@@ -389,35 +395,35 @@ CLEANUP(8)                                                          CLEANUP(8)
               will handle.
 
        <b><a href="postconf.5.html#queue_file_attribute_count_limit">queue_file_attribute_count_limit</a> (100)</b>
-              The maximal number of (name=value) attributes  that
+              The  maximal number of (name=value) attributes that
               may be stored in a Postfix queue file.
 
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#virtual_alias_expansion_limit">virtual_alias_expansion_limit</a> (1000)</b>
-              The  maximal number of addresses that virtual alias
+              The maximal number of addresses that virtual  alias
               expansion produces from each original recipient.
 
        <b><a href="postconf.5.html#virtual_alias_recursion_limit">virtual_alias_recursion_limit</a> (1000)</b>
-              The maximal nesting depth of virtual  alias  expan-
+              The  maximal  nesting depth of virtual alias expan-
               sion.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The  default  location  of  the Postfix <a href="postconf.5.html">main.cf</a> and
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
               <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
-              How much time a Postfix daemon process may take  to
-              handle  a  request  before  it  is  terminated by a
+              How  much time a Postfix daemon process may take to
+              handle a request  before  it  is  terminated  by  a
               built-in watchdog timer.
 
        <b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
-              The maximal number  of  digits  after  the  decimal
+              The  maximal  number  of  digits  after the decimal
               point when logging sub-second delay values.
 
        <b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b>
-              The  time  after which the sender receives the mes-
+              The time after which the sender receives  the  mes-
               sage headers of mail that is still queued.
 
        <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
@@ -425,13 +431,13 @@ CLEANUP(8)                                                          CLEANUP(8)
               over an internal communication channel.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The  maximum  amount  of  time that an idle Postfix
-              daemon process waits  for  an  incoming  connection
+              The maximum amount of time  that  an  idle  Postfix
+              daemon  process  waits  for  an incoming connection
               before terminating voluntarily.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The  maximal  number of incoming connections that a
-              Postfix daemon process will service  before  termi-
+              The maximal number of incoming connections  that  a
+              Postfix  daemon  process will service before termi-
               nating voluntarily.
 
        <b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
@@ -439,19 +445,19 @@ CLEANUP(8)                                                          CLEANUP(8)
 
        <b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
               The domain name that locally-posted mail appears to
-              come from, and that locally posted mail  is  deliv-
+              come  from,  and that locally posted mail is deliv-
               ered to.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The  process  ID  of  a  Postfix  command or daemon
+              The process ID  of  a  Postfix  command  or  daemon
               process.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The process name of a  Postfix  command  or  daemon
+              The  process  name  of  a Postfix command or daemon
               process.
 
        <b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
-              The  location of the Postfix top-level queue direc-
+              The location of the Postfix top-level queue  direc-
               tory.
 
        <b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
@@ -461,15 +467,15 @@ CLEANUP(8)                                                          CLEANUP(8)
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
-       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
-              The  mail  system  name  that  is  prepended to the
-              process name in syslog  records,  so  that  "smtpd"
+       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
+              The mail system  name  that  is  prepended  to  the
+              process  name  in  syslog  records, so that "smtpd"
               becomes, for example, "postfix/smtpd".
 
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b>
-              Enable   support   for  the  X-Original-To  message
+              Enable  support  for  the   X-Original-To   message
               header.
 
 <b>FILES</b>
@@ -493,7 +499,7 @@ CLEANUP(8)                                                          CLEANUP(8)
        <a href="CONTENT_INSPECTION_README.html">CONTENT_INSPECTION_README</a> content inspection
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index 77d0625202a3337f8f4e889c86e664b7c5313567..1588febfa98ad977e9f7aa9bba2a2e4a05976f1c 100644 (file)
@@ -730,76 +730,82 @@ SMTP(8)                                                                SMTP(8)
               The time limit for sending or receiving information
               over an internal communication channel.
 
+       <b><a href="postconf.5.html#lmtp_assume_final">lmtp_assume_final</a> (no)</b>
+              When  an  LMTP  server  announces  no  DSN support,
+              assume that the server performs final delivery, and
+              send   "delivered"  delivery  status  notifications
+              instead of "relayed".
+
        <b><a href="postconf.5.html#lmtp_tcp_port">lmtp_tcp_port</a> (24)</b>
-              The  default  TCP port that the Postfix LMTP client
+              The default TCP port that the Postfix  LMTP  client
               connects to.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The maximum amount of time  that  an  idle  Postfix
-              daemon  process  waits  for  an incoming connection
+              The  maximum  amount  of  time that an idle Postfix
+              daemon process waits  for  an  incoming  connection
               before terminating voluntarily.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The maximal number of incoming connections  that  a
-              Postfix  daemon  process will service before termi-
+              The  maximal  number of incoming connections that a
+              Postfix daemon process will service  before  termi-
               nating voluntarily.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The process ID  of  a  Postfix  command  or  daemon
+              The  process  ID  of  a  Postfix  command or daemon
               process.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The  process  name  of  a Postfix command or daemon
+              The process name of a  Postfix  command  or  daemon
               process.
 
        <b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
               The network interface addresses that this mail sys-
-              tem  receives  mail on by way of a proxy or network
+              tem receives mail on by way of a proxy  or  network
               address translation unit.
 
        <b><a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> (empty)</b>
-              An optional  numerical  network  address  that  the
-              Postfix  SMTP  client should bind to when making an
+              An  optional  numerical  network  address  that the
+              Postfix SMTP client should bind to when  making  an
               IPv4 connection.
 
        <b><a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> (empty)</b>
-              An optional  numerical  network  address  that  the
-              Postfix  SMTP  client should bind to when making an
+              An  optional  numerical  network  address  that the
+              Postfix SMTP client should bind to when  making  an
               IPv6 connection.
 
        <b><a href="postconf.5.html#smtp_helo_name">smtp_helo_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
-              The hostname to send in the SMTP EHLO or HELO  com-
+              The  hostname to send in the SMTP EHLO or HELO com-
               mand.
 
        <b><a href="postconf.5.html#lmtp_lhloname">lmtp_lhlo_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
               The hostname to send in the LMTP LHLO command.
 
        <b><a href="postconf.5.html#smtp_host_lookup">smtp_host_lookup</a> (dns)</b>
-              What  mechanisms  when the Postfix SMTP client uses
+              What mechanisms when the Postfix SMTP  client  uses
               to look up a host's IP address.
 
        <b><a href="postconf.5.html#smtp_randomize_addresses">smtp_randomize_addresses</a> (yes)</b>
-              Randomize the order  of  equal-preference  MX  host
+              Randomize  the  order  of  equal-preference MX host
               addresses.
 
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
-       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
-              The  mail  system  name  that  is  prepended to the
-              process name in syslog  records,  so  that  "smtpd"
+       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
+              The mail system  name  that  is  prepended  to  the
+              process  name  in  syslog  records, so that "smtpd"
               becomes, for example, "postfix/smtpd".
 
        Available with Postfix 2.2 and earlier:
 
        <b><a href="postconf.5.html#fallback_relay">fallback_relay</a> (empty)</b>
-              Optional  list of relay hosts for SMTP destinations
+              Optional list of relay hosts for SMTP  destinations
               that can't be found or that are unreachable.
 
        Available with Postfix 2.3 and later:
 
        <b><a href="postconf.5.html#smtp_fallback_relay">smtp_fallback_relay</a> ($<a href="postconf.5.html#fallback_relay">fallback_relay</a>)</b>
-              Optional list of relay hosts for SMTP  destinations
+              Optional  list of relay hosts for SMTP destinations
               that can't be found or that are unreachable.
 
 <b>SEE ALSO</b>
@@ -820,7 +826,7 @@ SMTP(8)                                                                SMTP(8)
        <a href="TLS_README.html">TLS_README</a>, Postfix STARTTLS howto
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
index ce6de4e40ee4d717f266052afa85ee4e6314e717..c4efe7302a1e96ad3e295cbae143231adcc2ec23 100644 (file)
@@ -450,7 +450,7 @@ SENDMAIL(1)                                                        SENDMAIL(1)
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
-       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
+       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
               The  mail  system  name  that  is  prepended to the
               process name in syslog  records,  so  that  "smtpd"
               becomes, for example, "postfix/smtpd".
@@ -477,7 +477,7 @@ SENDMAIL(1)                                                        SENDMAIL(1)
        <a href="VERP_README.html">VERP_README</a>, Postfix VERP howto
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index ce6de4e40ee4d717f266052afa85ee4e6314e717..c4efe7302a1e96ad3e295cbae143231adcc2ec23 100644 (file)
@@ -450,7 +450,7 @@ SENDMAIL(1)                                                        SENDMAIL(1)
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
-       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
+       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
               The  mail  system  name  that  is  prepended to the
               process name in syslog  records,  so  that  "smtpd"
               becomes, for example, "postfix/smtpd".
@@ -477,7 +477,7 @@ SENDMAIL(1)                                                        SENDMAIL(1)
        <a href="VERP_README.html">VERP_README</a>, Postfix VERP howto
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index 8caab334cb1fdf6e949ee161331296c40ae96c78..487e5abb863f4595e506cb0550429bbea2a94f69 100644 (file)
@@ -677,6 +677,18 @@ and <a href="postdrop.1.html">postdrop(1)</a>.
 </p>
 
 
+</DD>
+
+<DT><b><a name="always_add_missing_headers">always_add_missing_headers</a>
+(default: no)</b></DT><DD>
+
+<p> Always add (Resent-) From:, To:, Date: or Message-ID: headers
+when not present.  Postfix 2.6 and later add these headers only
+when clients match the <a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> parameter
+setting.  Earlier Postfix versions always add these headers; this
+may break DKIM signatures that cover non-existent headers. </p>
+
+
 </DD>
 
 <DT><b><a name="always_bcc">always_bcc</a>
@@ -3432,6 +3444,18 @@ This feature is available in Postfix 2.1 and later.
 this length; upon delivery, long lines are reconstructed.  </p>
 
 
+</DD>
+
+<DT><b><a name="lmtp_assume_final">lmtp_assume_final</a>
+(default: no)</b></DT><DD>
+
+<p> When an LMTP server announces no DSN support, assume that the
+server performs final delivery, and send "delivered" delivery status
+notifications instead of "relayed". The default setting is backwards
+compatible to avoid the infinetisimal possibility of breaking
+existing LMTP-based content filters. </p>
+
+
 </DD>
 
 <DT><b><a name="lmtp_bind_address">lmtp_bind_address</a>
@@ -5810,11 +5834,16 @@ Postfix instance, and that are started, stopped, etc., together
 with the default Postfix instance.  Specify a list of pathnames
 separated by comma or whitespace.  </p>
 
-<p> When the list of non-default Postfix configuration directories
-is non-empty, the <a href="postfix.1.html">postfix(1)</a> command will invoke the multi-instance
-manager specified with the <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> parameter to
-execute commands on the default instance and on all additional
-Postfix instances.  </p>
+<p> When $<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> is empty, the <a href="postfix.1.html">postfix(1)</a> command
+runs in single-instance mode and operates on a single Postfix
+instance only. Otherwise, the <a href="postfix.1.html">postfix(1)</a> command runs in multi-instance
+mode and invokes the multi-instance manager specified with the
+<a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> parameter. The multi-instance manager in
+turn executes <a href="postfix.1.html">postfix(1)</a> commands for the default instance and for
+all Postfix instances in $<a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a>.  </p>
+
+<p> Currently, this parameter setting is ignored except for the
+default <a href="postconf.5.html">main.cf</a> file. </p>
 
 <p> This feature is available in Postfix 2.6 and later. </p>
 
@@ -6320,6 +6349,43 @@ is rejected by the <b><a href="postconf.5.html#reject_plaintext_session">reject_
 <p> This feature is available in Postfix 2.3 and later. </p>
 
 
+</DD>
+
+<DT><b><a name="postmulti_control_commands">postmulti_control_commands</a>
+(default: reload flush)</b></DT><DD>
+
+<p> The <a href="postfix.1.html">postfix(1)</a> commands that the <a href="postmulti.1.html">postmulti(1)</a> instance manager
+treats as "control" commands, that operate on running instances. For
+these commands, disabled instances are skipped. </p>
+
+<p> This feature is available in Postfix 2.6 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="postmulti_start_commands">postmulti_start_commands</a>
+(default: start)</b></DT><DD>
+
+<p> The <a href="postfix.1.html">postfix(1)</a> commands that the <a href="postmulti.1.html">postmulti(1)</a> instance manager treats
+as "start" commands. For these commands, disabled instances are "checked"
+rather than "started", and failure to "start" a member instance of an
+instance group will abort the start-up of later instances. </p>
+
+<p> This feature is available in Postfix 2.6 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="postmulti_stop_commands">postmulti_stop_commands</a>
+(default: see "postconf -d" output)</b></DT><DD>
+
+<p> The <a href="postfix.1.html">postfix(1)</a> commands that the <a href="postmulti.1.html">postmulti(1)</a> instance manager treats
+as "stop" commands. For these commands, disabled instances are skipped,
+and enabled instances are processed in reverse order. </p>
+
+<p> This feature is available in Postfix 2.6 and later. </p>
+
+
 </DD>
 
 <DT><b><a name="prepend_delivered_header">prepend_delivered_header</a>
index b1c5efcf79642e6a0f52acfe16c66c7c43b1d7f8..92fc12202d669fdc2cb4c3fcd4684eac1d429117 100644 (file)
@@ -94,7 +94,7 @@ the following convention:  </p>
 
 <li> <a href="postmap.1.html">postmap(1)</a>, Postfix lookup table manager 
 
-<li> postmulti(1), Postfix multi-instance manager 
+<li> <a href="postmulti.1.html">postmulti(1)</a>, Postfix multi-instance manager 
 
 <li> <a href="postqueue.1.html">postqueue(1)</a>, Postfix mail queue control 
 
index 8f829f3dac8e02e42d6b7c8981cb4d06ee9dc21b..645ab28ca3264de7e020edcb9172ad83e522117f 100644 (file)
@@ -17,36 +17,31 @@ POSTFIX-WRAPPER(5)                                          POSTFIX-WRAPPER(5)
 
        This document describes how the familiar  "postfix  start"
        etc.  user interface can be used to manage one or multiple
-       Postfix instances, and gives details of an API that allows
-       the  <a href="postfix.1.html">postfix(1)</a>  command  to  coordinate activities with a
+       Postfix instances, and gives details of an API to  coordi-
+       nate  activities  between  the  <a href="postfix.1.html">postfix(1)</a>  command  and a
        multi-instance manager program.
 
-       A trivial but useful multi-instance manager implementation
-       is  described  below,  and  can be found in the file $<a href="postconf.5.html#daemon_directory">dae</a>-
-       <a href="postconf.5.html#daemon_directory">mon_directory</a>/postfix-wrapper. The latter file  also  con-
-       tains instructions for setting up multiple instances.
-
-       With  multi-instance support, the default Postfix instance
-       is required. The location of its  configuration  files  is
-       specified  by  the  built-in  default  value  for the con-
-       fig_directory parameter.
+       With multi-instance support, the default Postfix  instance
+       is   always  required.  The  <a href="postconf.5.html#config_directory">config_directory</a>  parameter's
+       default value specifies that instance's configuration file
+       location.
 
 <b>GENERAL OPERATION</b>
-       Multi-instance support is backwards compatible: when there
-       is  only  one  Postfix instance, commands such as "postfix
-       start" keep doing what they have always done.
+       Multi-instance  support  is backwards compatible: when you
+       run only one Postfix instance, commands such  as  "postfix
+       start" will not change behavior at all.
 
-       Even after multi-instance support has been set up  through
-       the  mechanisms discussed later, sites can continue to use
-       the familiar postfix commands  in  boot  scripts,  upgrade
-       procedures, and other places.
+       Even  with  multiple Postfix instances, you can keep using
+       the same postfix commands in boot scripts, upgrade  proce-
+       dures,  and  other  places. The commands do more work, but
+       humans are not forced to learn new tricks.
 
-       To start all applicable Postfix instances, use:
+       For example, to start all Postfix instances, use:
 
               # postfix start
 
        Other <a href="postfix.1.html">postfix(1)</a> commands also work as expected. For exam-
-       ple, to find out what Postfix instances exist in a  multi-
+       ple,  to find out what Postfix instances exist in a multi-
        instance configuration, use:
 
               # postfix status
@@ -55,51 +50,64 @@ POSTFIX-WRAPPER(5)                                          POSTFIX-WRAPPER(5)
        a multi-instance configuration.
 
 <b>MANAGING AN INDIVIDUAL POSTFIX INSTANCE</b>
-       To operate on a specific  Postfix  instance,  specify  its
-       configuration directory on the <a href="postfix.1.html">postfix(1)</a> command line:
+       To manage a specific Postfix instance, specify its config-
+       uration directory on the <a href="postfix.1.html">postfix(1)</a> command line:
 
               # postfix -c <i>/path/to/config</i><b>_</b><i>directory command</i>
 
-       Alternatively,   the   <a href="postfix.1.html">postfix(1)</a>   command   accepts  the
-       instance's configuration  directory  via  the  MAIL_CONFIG
+       Alternatively,  the   <a href="postfix.1.html">postfix(1)</a>   command   accepts   the
+       instance's  configuration  directory  via  the MAIL_CONFIG
        environment  variable  (the  -c  command-line  option  has
        higher precedence).
 
-       When no Postfix instance  information  is  specified,  the
-       <a href="postfix.1.html">postfix(1)</a>  command will operate on all applicable Postfix
-       instances.
-
-<b>MULTI-INSTANCE MANAGER IMPLEMENTATION</b>
-       Historically, the <a href="postfix.1.html">postfix(1)</a> command invokes the  postfix-
-       script file (currently installed in the daemon directory).
-       This file contains the commands that start or  stop  Post-
-       fix, upgrade the configuration and so on.
-
-       When  multi-instance  support is turned on, the <a href="postfix.1.html">postfix(1)</a>
-       command needs to execute these commands for each  applica-
-       ble  Postfix  instance. This multiplication of commands is
-       handled by a multi-instance manager program.
-
-       Turning on multi-instance support goes as follows:  update
-       the  default Postfix instance's <a href="postconf.5.html">main.cf</a> file, and populate
-       the <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter with the configu-
-       ration   directory   pathnames   of   additional   Postfix
-       instances.
-
-       With multi-instance support turned on, the <a href="postfix.1.html">postfix(1)</a> com-
-       mand  invokes  a multi-instance manager command instead of
-       the postfix-script file. The multi-instance  manager  exe-
-       cutes  the  <a href="postfix.1.html">postfix(1)</a> command for each applicable Postfix
-       instance.  The pathname of the multi-instance  manager  is
-       specified   in   the   default   <a href="postconf.5.html">main.cf</a>   file  with  the
-       <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> parameter.
+       When  no  Postfix  instance  information is specified, the
+       <a href="postfix.1.html">postfix(1)</a> command will operate on all Postfix  instances.
+
+<b>ENABLING POSTFIX(1) MULTI-INSTANCE MODE</b>
+       By  default,  the  <a href="postfix.1.html">postfix(1)</a>  command operates in single-
+       instance mode. In this mode the command invokes the  post-
+       fix-script  file directly (currently installed in the dae-
+       mon directory).  This  file  contains  the  commands  that
+       start  or stop one Postfix instance, that upgrade the con-
+       figuration of one Postfix instance, and so on.
+
+       When the <a href="postfix.1.html">postfix(1)</a>  command  operates  in  multi-instance
+       mode  as  discussed  below,  the  command needs to execute
+       start, stop, etc.  commands  for  each  Postfix  instance.
+       This  multiplication  of  commands  is handled by a multi-
+       instance manager program.
+
+       Turning on <a href="postfix.1.html">postfix(1)</a> multi-instance mode goes as follows:
+       in the default Postfix instance's <a href="postconf.5.html">main.cf</a> file, 1) specify
+       the pathname of a multi-instance manager program with  the
+       <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a>    parameter;   2)   populate   the
+       <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter with  the  configura-
+       tion  directory pathnames of additional Postfix instances.
+       For example:
+
+              /etc/postfix/<a href="postconf.5.html">main.cf</a>:
+                  <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> = $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/postfix-wrapper
+                  <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> = /etc/postfix-test
+
+       The $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/postfix-wrapper  file  implements  a
+       simple  manager  and  contains  instructions  for creating
+       Postfix instances by hand.  The <a href="postmulti.1.html">postmulti(1)</a> command  pro-
+       vides  a  more  extensive implementation including support
+       for life-cycle management.
 
        The <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> and other  <a href="postconf.5.html">main.cf</a>  parame-
        ters are listed below in the CONFIGURATION PARAMETERS sec-
        tion.
 
-       A useful multi-instance manager implementation can  be  as
-       simple as:
+       In multi-instance mode, the <a href="postfix.1.html">postfix(1)</a> command invokes the
+       $<a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a>  command  instead  of the postfix-
+       script file. This multi-instance manager in turn  executes
+       the  <a href="postfix.1.html">postfix(1)</a>  command  in single-instance mode for each
+       Postfix instance.
+
+       To illustrate the main ideas behind multi-instance  opera-
+       tion,  below  is  an example of a simple but useful multi-
+       instance manager implementation:
 
               #!/bin/sh
 
@@ -129,47 +137,43 @@ POSTFIX-WRAPPER(5)                                          POSTFIX-WRAPPER(5)
 
               exit $err
 
-       A  sample  implementation, with instructions, can be found
-       in $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/postfix-wrapper.
-
-       The postmulti(1) command implements a  more  sophisticated
-       approach,  based on a combination of C code and scripting.
-
-<b>ENABLING A SPECIFIC INSTANCE FOR MULTI-INSTANCE OPERATION</b>
+<b>PER-INSTANCE MULTI-INSTANCE MANAGER CONTROLS</b>
        Each Postfix instance has its own <a href="postconf.5.html">main.cf</a> file with param-
-       eters  that  control  multi-instance  operation.  The most
-       important settings are discussed here.
+       eters that control how the multi-instance manager operates
+       on that instance.  This section discusses the most  impor-
+       tant settings.
 
        The  setting  "<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a>  =  yes"  allows  the
-       multi-instance manager to start (and stop) the correspond-
-       ing Postfix instance. For safety reasons, this setting  is
-       not the default.
-
-       The  setting  "<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a>  =  no" is useful for
-       manual testing.  With  this,  the  multi-instance  manager
-       will not start the Postfix instance, and it will skip com-
-       mands such as "stop" or "flush"  that  require  a  running
-       Postfix instance.  The multi-instance manager will execute
-       commands such as "check", "set-permissions"  or  "upgrade-
-       configuration",  and it will replace "start" by "check" so
-       that problems will be reported even when the  instance  is
-       disabled.
-
-<b>SHARED VERSUS NON-SHARED FILES</b>
-       Some  files  are shared between Postfix instances, such as
+       multi-instance manager to start (stop,  etc.)  the  corre-
+       sponding  Postfix  instance. For safety reasons, this set-
+       ting is not the default.
+
+       The default setting "<a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = no" is useful
+       for manual testing with "postfix -c <i>/path/name</i> start" etc.
+       The  multi-instance  manager  will  not  start   such   an
+       instance,  and  it  will  skip  commands such as "stop" or
+       "flush" that require  a  running  Postfix  instance.   The
+       multi-instance  manager  will  execute  commands  such  as
+       "check", "set-permissions" or "upgrade-configuration", and
+       it  will  replace "start" by "check" so that problems will
+       be reported even when the instance is disabled.
+
+<b>MAINTAINING SHARED AND NON-SHARED FILES</b>
+       Some files are shared between Postfix instances,  such  as
        executables and manpages, and some files are per-instance,
-       such  as  the  queue  directory.  See the NON-SHARED FILES
-       section below for a list of per-instance files.
+       such as configuration files, mail queue  files,  and  data
+       files.   See the NON-SHARED FILES section below for a list
+       of per-instance files.
 
        Before Postfix multi-instance support was implemented, the
-       executables,  manpages,  etc., have always been checked or
-       updated as part of  the  default  Postfix  instance.  With
-       multi-instance support, we simply continue to do this.
+       executables,  manpages,  etc., have always been maintained
+       as part of the default Postfix instance.
 
-       Specifically,  Postfix  instances will not check or update
-       shared files when their <a href="postconf.5.html#config_directory">config_directory</a> value  is  listed
-       with   the  default  <a href="postconf.5.html">main.cf</a>'s  <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a>
-       parameter.
+       With multi-instance support,  we  simply  continue  to  do
+       this.   Specifically, a Postfix instance will not check or
+       update shared files when that instance's  <a href="postconf.5.html#config_directory">config_directory</a>
+       value   is   listed   with   the  default  <a href="postconf.5.html">main.cf</a>  file's
+       <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter.
 
        The consequence of this approach is that the default Post-
        fix  instance  should  be  checked  and updated before any
@@ -275,7 +279,7 @@ POSTFIX-WRAPPER(5)                                          POSTFIX-WRAPPER(5)
 
 <b>SEE ALSO</b>
        <a href="postfix.1.html">postfix(1)</a> Postfix control program
-       postmulti(1) full-blown multi-instance manager
+       <a href="postmulti.1.html">postmulti(1)</a> full-blown multi-instance manager
        $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/postfix-wrapper simple multi-instance manager
 
 <b>LICENSE</b>
index ccef49f0c3aa6b72593ffbadbe93ff4b5404d83b..2339142f096dce9619774c1636a336826ff50975 100644 (file)
@@ -270,7 +270,7 @@ POSTFIX(1)                                                          POSTFIX(1)
        <a href="postlock.1.html">postlock(1)</a>, Postfix-compatible locking
        <a href="postlog.1.html">postlog(1)</a>, Postfix-compatible logging
        <a href="postmap.1.html">postmap(1)</a>, Postfix lookup table manager
-       postmulti(1), Postfix multi-instance manager
+       <a href="postmulti.1.html">postmulti(1)</a>, Postfix multi-instance manager
        <a href="postqueue.1.html">postqueue(1)</a>, Postfix mail queue control
        <a href="postsuper.1.html">postsuper(1)</a>, Postfix housekeeping
        <a href="mailq.1.html">mailq(1)</a>, Sendmail compatibility interface
diff --git a/postfix/html/postmulti.1.html b/postfix/html/postmulti.1.html
new file mode 100644 (file)
index 0000000..896106e
--- /dev/null
@@ -0,0 +1,437 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+<title> Postfix manual - postmulti(1) </title>
+</head> <body> <pre>
+POSTMULTI(1)                                                      POSTMULTI(1)
+
+<b>NAME</b>
+       postmulti - Postfix multi-instance manager
+
+<b>SYNOPSIS</b>
+       <b>postmulti -l</b> [<b>-aRv</b>] [<b>-g</b> <i>group</i>] [<b>-i</b> <i>name</i>]
+
+       <b>postmulti -p</b> [<b>-av</b>] [<b>-g</b> <i>group</i>] [<b>-i</b> <i>name</i>] <i>command...</i>
+
+       <b>postmulti -x</b> [<b>-aRv</b>] [<b>-g</b> <i>group</i>] [<b>-i</b> <i>name</i>] <i>command...</i>
+
+       <b>postmulti -e init</b> [<b>-v</b>]
+
+       <b>postmulti -e create</b> [<b>-av</b>] [<b>-g</b> <i>group</i>] [<b>-i</b> <i>name</i>] [<b>-G</b> <i>group</i>]
+       [<b>-I</b> <i>name</i>] [<i>param=value</i> ...]
+
+       <b>postmulti -e import</b> [<b>-av</b>] [<b>-g</b> <i>group</i>] [<b>-i</b> <i>name</i>] [<b>-G</b> <i>group</i>]
+       [<b>-I</b> <i>name</i>] [<b><a href="postconf.5.html#config_directory">config_directory</a>=</b><i>/path</i>]
+
+       <b>postmulti -e destroy</b> [<b>-v</b>] <b>-i</b> <i>name</i>
+
+       <b>postmulti -e deport</b> [<b>-v</b>] <b>-i</b> <i>name</i>
+
+       <b>postmulti -e enable</b> [<b>-v</b>] <b>-i</b> <i>name</i>
+
+       <b>postmulti -e disable</b> [<b>-v</b>] <b>-i</b> <i>name</i>
+
+       <b>postmulti -e assign</b> [<b>-v</b>] <b>-i</b> <i>name</i> [<b>-I</b> <i>name</i>] [-G <i>group</i>]
+
+<b>DESCRIPTION</b>
+       The <a href="postmulti.1.html"><b>postmulti</b>(1)</a> command allows a Postfix administrator to
+       manage multiple Postfix instances on a single host.
+
+       <a href="postmulti.1.html"><b>postmulti</b>(1)</a> implements two fundamental  modes  of  opera-
+       tion.   In <b>iterator</b> mode, it executes the same command for
+       multiple  Postfix  instances.   In  <b>life-cycle  management</b>
+       mode,  it  adds  or  deletes  one instance, or changes the
+       multi-instance status of one instance.
+
+       Each mode of operation has its  own  command  syntax.  For
+       this  reason, each mode is documented in separate sections
+       below.
+
+<b>BACKGROUND</b>
+       A multi-instance configuration  consists  of  one  primary
+       Postfix  instance,  and  one  or  more secondary instances
+       whose configuration directory pathnames  are  recorded  in
+       the  primary  instance's  <a href="postconf.5.html">main.cf</a>  file. Postfix instances
+       share program files and documentation, but have their  own
+       configuration, queue and data directories.
+
+       Currently,  only  the default Postfix instance can be used
+       as primary instance in a multi-instance configuration. The
+       <a href="postmulti.1.html"><b>postmulti</b>(1)</a>  command  does  not  currently  support  a <b>-c</b>
+       option to select  an  alternative  primary  instance,  and
+       exits  with  a  fatal error if the <b>MAIL_CONFIG</b> environment
+       variable is set to a non-default configuration  directory.
+
+       See the <a href="MULTI_INSTANCE_README.html">MULTI_INSTANCE_README</a> tutorial for a more detailed
+       discussion of multi-instance management with <a href="postmulti.1.html"><b>postmulti</b>(1)</a>.
+
+<b>ITERATOR MODE</b>
+       In iterator mode, <b>postmulti</b> performs the same operation on
+       all Postfix instances in turn.
+
+       If multi-instance support is not  enabled,  the  requested
+       command is performed just for the primary instance.
+
+       Iterator mode implements the following command options:
+
+<b>Instance selection</b>
+       <b>-a</b>     Perform the operation on all instances. This is the
+              default.
+
+       <b>-g</b> <i>group</i>
+              Perform the operation only for members of the named
+              <i>group</i>.
+
+       <b>-i</b> <i>name</i>
+              Perform  the  operation  only for the instance with
+              the specified <i>name</i>.  You  can  specify  either  the
+              instance  name  or  the  absolute  pathname  of the
+              instance's configuration directory.  Specify "-" to
+              select the primary Postfix instance.
+
+       <b>-R</b>     Reverse  the iteration order. This may be appropri-
+              ate when updating a  multi-instance  system,  where
+              "sink"   instances   are  started  before  "source"
+              instances.
+
+              This option cannot be used with <b>-p</b>.
+
+<b>List mode</b>
+       <b>-l</b>     List Postfix instances with  their  instance  name,
+              instance group name, enable/disable status and con-
+              figuration directory.
+
+<b>Postfix-wrapper mode</b>
+       <b>-p</b>     Invoke <a href="postfix.1.html"><b>postfix(1)</a></b> to execute the specified <i>command</i>.
+              This   option   implements  the  <a href="postfix-wrapper.5.html"><b>postfix-wrapper</b>(5)</a>
+              interface.
+
+              <b>o</b>      With "start"-like commands, "postfix  check"
+                     is  executed  for  instances  that  are  not
+                     enabled. The full list of commands is speci-
+                     fied   with   the   <a href="postconf.5.html#postmulti_start_commands">postmulti_start_commands</a>
+                     parameter.
+
+              <b>o</b>      With  "stop"-like  commands,  the  iteration
+                     order  is  reversed,  and disabled instances
+                     are skipped. The full list  of  commands  is
+                     specified  with  the <a href="postconf.5.html#postmulti_stop_commands">postmulti_stop_commands</a>
+                     parameter.
+
+              <b>o</b>      With  "reload"  and  other   commands   that
+                     require   a   started   instance,   disabled
+                     instances are skipped. The full list of com-
+                     mands  is  specified with the <a href="postconf.5.html#postmulti_control_commands">postmulti_con</a>-
+                     <a href="postconf.5.html#postmulti_control_commands">trol_commands</a> parameter.
+
+              <b>o</b>      With "status" and other commands that  don't
+                     require  a  started instance, the command is
+                     executed for all instances.
+
+              The <b>-p</b> option can also  be  used  interactively  to
+              start/stop/etc.    a  named  instance  or  instance
+              group. For example, to start just the instances  in
+              the group "msa", invoke <a href="postmulti.1.html"><b>postmulti</b>(1)</a> as follows:
+
+                     # postmulti -g msa -p start
+
+<b>Command mode</b>
+       <b>-x</b>     Execute  the  specified  <i>command</i>  for  all  Postfix
+              instances.  The command runs with appropriate envi-
+              ronment  settings  for  MAIL_CONFIG, <a href="postconf.5.html#command_directory">command_direc</a>-
+              <a href="postconf.5.html#command_directory">tory</a>,      <a href="postconf.5.html#daemon_directory">daemon_directory</a>,      <a href="postconf.5.html#config_directory">config_directory</a>,
+              <a href="postconf.5.html#queue_directory">queue_directory</a>,                    <a href="postconf.5.html#data_directory">data_directory</a>,
+              <a href="postconf.5.html#multi_instance_name">multi_instance_name</a>,    <a href="postconf.5.html#multi_instance_group">multi_instance_group</a>    and
+              <a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a>.
+
+<b>Other options</b>
+       <b>-v</b>     Enable verbose logging for debugging purposes. Mul-
+              tiple <b>-v</b> options  make  the  software  increasingly
+              verbose.
+
+<b>LIFE-CYCLE MANAGEMENT MODE</b>
+       With  the  <b>-e</b>  option  <a href="postmulti.1.html"><b>postmulti</b>(1)</a>  can be used to add or
+       delete a  Postfix  instance,  and  to  manage  the  multi-
+       instance status of an existing instance.
+
+       The following options are implemented:
+
+<b>Existing instance selection</b>
+       <b>-a</b>     When  creating  or importing an instance, place the
+              new instance at the front of the secondary instance
+              list.
+
+       <b>-g</b> <i>group</i>
+              When  creating  or importing an instance, place the
+              new instance before the  first  secondary  instance
+              that is a member of the specified group.
+
+       <b>-i</b> <i>name</i>
+              When  creating  or importing an instance, place the
+              new  instance   before   the   matching   secondary
+              instance.
+
+              With  other life-cycle operations, apply the opera-
+              tion to the named existing instance.   Specify  "-"
+              to select the primary Postfix instance.
+
+<b>New or existing instance name assignment</b>
+       <b>-I</b> <i>name</i>
+              Assign  the  specified instance <i>name</i> to an existing
+              instance  or  to  a  newly  created   or   imported
+              instance.   Instance names other than "-"    (which
+              makes the  instance  "nameless")  must  start  with
+              "postfix-".   This  restriction reduces the likeli-
+              hood of name collisions with system files.
+
+       <b>-G</b> <i>group</i>
+              Assign the specified  <i>group</i>  name  to  an  existing
+              instance   or   to  a  newly  created  or  imported
+              instance.
+
+<b>Instance creation/deletion/status change</b>
+       <b>-e</b> <i>action</i>
+              "Edit" managed instances. The following actions are
+              supported:
+
+              <b>init</b>   This command is required before <a href="postmulti.1.html"><b>postmulti</b>(1)</a>
+                     can be used  to  manage  Postfix  instances.
+                     The  "postmulti -e init" command updates the
+                     primary instance's <a href="postconf.5.html">main.cf</a> file by setting:
+
+                            <a href="postconf.5.html#multi_instance_wrapper">multi_instance_wrapper</a> =
+                                    ${<a href="postconf.5.html#command_directory">command_directory</a>}/postmulti -p --
+                            <a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> = yes
+
+                     You can set these by other means if you pre-
+                     fer.
+
+              <b>create</b> Create  a new Postfix instance and add it to
+                     the <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> parameter  of
+                     the  primary instance.  The "<b>-I</b> <i>name</i>" option
+                     is recommended to give the instance a  short
+                     name  that is used to construct default val-
+                     ues for the private directories of  the  new
+                     instance. The "<b>-G</b> <i>group</i>" option may be spec-
+                     ified to assign the  instance  to  a  group,
+                     otherwise,  the new instance is not a member
+                     of any groups.
+
+                     The  new  instance  <a href="postconf.5.html">main.cf</a>  is  the   stock
+                     <a href="postconf.5.html">main.cf</a> with the parameters that specify the
+                     locations of shared files  cloned  from  the
+                     primary instance.  For "nameless" instances,
+                     you should manually adjust "<a href="postconf.5.html#syslog_name">syslog_name</a>"  to
+                     yield a unique "logtag" starting with "post-
+                     fix-"  that  will  uniquely   identify   the
+                     instance  in the mail logs. It is simpler to
+                     assign the instance a short  name  with  the
+                     "<b>-I</b> <i>name</i>" option.
+
+                     Optional  "name=value" arguments specify the
+                     instance  <a href="postconf.5.html#config_directory">config_directory</a>,  <a href="postconf.5.html#queue_directory">queue_directory</a>
+                     and <a href="postconf.5.html#data_directory">data_directory</a>.  For example:
+
+                            # postmulti -I postfix-mumble \
+                                    -G mygroup -e create \
+                                    <a href="postconf.5.html#config_directory">config_directory</a>=/my/config/dir \
+                                    <a href="postconf.5.html#queue_directory">queue_directory</a>=/my/queue/dir \
+                                    <a href="postconf.5.html#data_directory">data_directory</a>=/my/data/dir
+
+                     If  any  of these pathnames is not supplied,
+                     the program attempts to generate  the  path-
+                     name  by  taking  the  corresponding primary
+                     instance pathname, and by replacing the last
+                     pathname  component  by  the value of the <b>-I</b>
+                     option.
+
+                     If  the  instance  configuration   directory
+                     already  exists, and contains both a <a href="postconf.5.html">main.cf</a>
+                     and <a href="master.5.html">master.cf</a> file, <b>create</b> will "import" the
+                     instance as-is. For existing instances, <b>cre-</b>
+                     <b>ate</b> and <b>import</b> are identical.
+
+              <b>import</b> Import an existing instance into the list of
+                     instances managed by the <a href="postmulti.1.html"><b>postmulti</b>(1)</a> multi-
+                     instance manager.  This adds the instance to
+                     the  <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a>  list of the
+                     primary instance.  If the "<b>-I</b>  <i>name</i>"  option
+                     is  provided  it  specifies the new name for
+                     the instance and is used to define a default
+                     location   for  the  instance  configuration
+                     directory (as with <b>create</b> above).   The  "<b>-G</b>
+                     <i>group</i>"  option  may  be  used  to assign the
+                     instance to a group.  Add  a  "<b><a href="postconf.5.html#config_directory">config_direc</a>-</b>
+                     <b><a href="postconf.5.html#config_directory">tory</a>=</b><i>/path</i>"  argument  to override a default
+                     pathname based on "<b>-I</b> <i>name</i>".
+
+              <b>destroy</b>
+                     Destroy a secondary Postfix instance. To  be
+                     a candidate for destruction an instance must
+                     be disabled, stopped and its queue must  not
+                     contain  any  messages.  Attempts to destroy
+                     the primary Postfix instance trigger a fatal
+                     error, without destroying the instance.
+
+                     The  instance  is  removed  from the primary
+                     instance   <a href="postconf.5.html">main.cf</a>   file's   <a href="postconf.5.html#alternate_config_directories">alternate_con</a>-
+                     <a href="postconf.5.html#alternate_config_directories">fig_directories</a>   parameter  and  its  data,
+                     queue  and  configuration  directories   are
+                     cleaned  of files and directories created by
+                     the Postfix system.  The  <a href="postconf.5.html">main.cf</a>  and  mas-
+                     ter.cf files are removed from the configura-
+                     tion directory even if they have been  modi-
+                     fied  since  initial  creation. Finally, the
+                     instance is "deported" from the list of man-
+                     aged instances.
+
+                     If  other files are present in instance pri-
+                     vate directories, the directories may not be
+                     fully  removed, a warning is logged to alert
+                     the administrator. It is  expected  that  an
+                     instance built using "fresh" directories via
+                     the <b>create</b> action will be fully  removed  by
+                     the  <b>destroy</b>  action (if first disabled). If
+                     the instance configuration and queue  direc-
+                     tories  are  populated with additional files
+                     (access and rewriting  tables,  chroot  jail
+                     content, etc.) the instance directories will
+                     not be fully removed.
+
+                     The <b>destroy</b> action triggers potentially dan-
+                     gerous  file  removal  operations. Make sure
+                     the instance's data, queue and configuration
+                     directories  are  set  correctly  and do not
+                     contain any valuable files.
+
+              <b>deport</b> Deport a secondary instance from the list of
+                     managed instances. This deletes the instance
+                     configuration  directory  from  the  primary
+                     instance's  <a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> list,
+                     but does not remove any  files  or  directo-
+                     ries.
+
+              <b>assign</b> Assign  a  new  instance name or a new group
+                     name to the selected instance.  Use  "<b>-G  -</b>"
+                     to  specify "no group" and "<b>-I -</b>" to specify
+                     "no  name".   If  you  choose  to  make   an
+                     instance  "nameless",  set  a  suitable sys-
+                     log_name in the corresponding <a href="postconf.5.html">main.cf</a>  file.
+
+              <b>enable</b> Mark  the selected instance as enabled. This
+                     just sets the <a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a>  parame-
+                     ter to "yes" in the instance's <a href="postconf.5.html">main.cf</a> file.
+
+              <b>disable</b>
+                     Mark the selected instance as disabled. This
+                     means  that the instance will not be started
+                     etc. with  "postfix  start",  "postmulti  -p
+                     start"  and so on. The instance can still be
+                     started etc. with "postfix -c  config-direc-
+                     tory start".
+
+<b>Other options</b>
+       <b>-v</b>     Enable verbose logging for debugging purposes. Mul-
+              tiple <b>-v</b> options  make  the  software  increasingly
+              verbose.
+
+<b>ENVIRONMENT</b>
+       The <a href="postmulti.1.html"><b>postmulti</b>(1)</a> command exports the following environment
+       variables before executing the  requested  <i>command</i>  for  a
+       given instance:
+
+       <b>MAIL_VERBOSE</b>
+              This  is  set  when  the  -v command-line option is
+              present.
+
+       <b>MAIL_CONFIG</b>
+              The location of the configuration directory of  the
+              instance.
+
+<b>CONFIGURATION PARAMETERS</b>
+       <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
+              The  default  location  of  the Postfix <a href="postconf.5.html">main.cf</a> and
+              <a href="master.5.html">master.cf</a> configuration files.
+
+       <b><a href="postconf.5.html#daemon_directory">daemon_directory</a> (see 'postconf -d' output)</b>
+              The directory with  Postfix  support  programs  and
+              daemon programs.
+
+       <b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
+              The  list  of environment parameters that a Postfix
+              process  will  import  from  a  non-Postfix  parent
+              process.
+
+       <b><a href="postconf.5.html#multi_instance_directories">multi_instance_directories</a> (empty)</b>
+              An  optional list of non-default Postfix configura-
+              tion directories; these directories belong to addi-
+              tional  Postfix  instances  that  share the Postfix
+              executable files and documentation with the default
+              Postfix  instance,  and  that are started, stopped,
+              etc., together with the default Postfix instance.
+
+       <b><a href="postconf.5.html#multi_instance_group">multi_instance_group</a> (empty)</b>
+              The optional instance group name  of  this  Postfix
+              instance.
+
+       <b><a href="postconf.5.html#multi_instance_name">multi_instance_name</a> (empty)</b>
+              The   optional   instance   name  of  this  Postfix
+              instance.
+
+       <b><a href="postconf.5.html#multi_instance_enable">multi_instance_enable</a> (no)</b>
+              Allow this Postfix instance to be started, stopped,
+              etc., by a multi-instance manager.
+
+       <b><a href="postconf.5.html#postmulti_start_commands">postmulti_start_commands</a> (start)</b>
+              The   <a href="postfix.1.html"><b>postfix</b>(1)</a>  commands  that  the  <a href="postmulti.1.html"><b>postmulti</b>(1)</a>
+              instance manager treats as "start" commands.
+
+       <b><a href="postconf.5.html#postmulti_stop_commands">postmulti_stop_commands</a> (see 'postconf -d' output)</b>
+              The  <a href="postfix.1.html"><b>postfix</b>(1)</a>  commands  that  the   <a href="postmulti.1.html"><b>postmulti</b>(1)</a>
+              instance manager treats as "stop" commands.
+
+       <b><a href="postconf.5.html#postmulti_control_commands">postmulti_control_commands</a> (reload flush)</b>
+              The   <a href="postfix.1.html"><b>postfix</b>(1)</a>  commands  that  the  <a href="postmulti.1.html"><b>postmulti</b>(1)</a>
+              instance manager treats as "control" commands, that
+              operate on running instances.
+
+       <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
+              The syslog facility of Postfix logging.
+
+       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
+              The  mail  system  name  that  is  prepended to the
+              process name in syslog  records,  so  that  "smtpd"
+              becomes, for example, "postfix/smtpd".
+
+<b>FILES</b>
+       $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/<a href="postconf.5.html">main.cf</a>, stock configuration file
+       $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/<a href="master.5.html">master.cf</a>, stock configuration file
+       $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/postmulti-script, life-cycle helper program
+
+<b>SEE ALSO</b>
+       <a href="postfix.1.html">postfix(1)</a>, Postfix control program
+       <a href="postfix-wrapper.5.html">postfix-wrapper(5)</a>, Postfix multi-instance API
+
+<b>README FILES</b>
+       <a href="MULTI_INSTANCE_README.html">MULTI_INSTANCE_README</a>, Postfix multi-instance management
+
+<b>HISTORY</b>
+       The  <a href="postmulti.1.html"><b>postmulti</b>(1)</a> command was introduced with Postfix ver-
+       sion 2.6.
+
+<b>LICENSE</b>
+       The Secure Mailer license must be  distributed  with  this
+       software.
+
+<b>AUTHOR(S)</b>
+       Victor Duchovni
+       Morgan Stanley
+
+       Wietse Venema
+       IBM T.J. Watson Research
+       P.O. Box 704
+       Yorktown Heights, NY 10598, USA
+
+                                                                  POSTMULTI(1)
+</pre> </body> </html>
index ce6de4e40ee4d717f266052afa85ee4e6314e717..c4efe7302a1e96ad3e295cbae143231adcc2ec23 100644 (file)
@@ -450,7 +450,7 @@ SENDMAIL(1)                                                        SENDMAIL(1)
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
-       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
+       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
               The  mail  system  name  that  is  prepended to the
               process name in syslog  records,  so  that  "smtpd"
               becomes, for example, "postfix/smtpd".
@@ -477,7 +477,7 @@ SENDMAIL(1)                                                        SENDMAIL(1)
        <a href="VERP_README.html">VERP_README</a>, Postfix VERP howto
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index 77d0625202a3337f8f4e889c86e664b7c5313567..1588febfa98ad977e9f7aa9bba2a2e4a05976f1c 100644 (file)
@@ -730,76 +730,82 @@ SMTP(8)                                                                SMTP(8)
               The time limit for sending or receiving information
               over an internal communication channel.
 
+       <b><a href="postconf.5.html#lmtp_assume_final">lmtp_assume_final</a> (no)</b>
+              When  an  LMTP  server  announces  no  DSN support,
+              assume that the server performs final delivery, and
+              send   "delivered"  delivery  status  notifications
+              instead of "relayed".
+
        <b><a href="postconf.5.html#lmtp_tcp_port">lmtp_tcp_port</a> (24)</b>
-              The  default  TCP port that the Postfix LMTP client
+              The default TCP port that the Postfix  LMTP  client
               connects to.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The maximum amount of time  that  an  idle  Postfix
-              daemon  process  waits  for  an incoming connection
+              The  maximum  amount  of  time that an idle Postfix
+              daemon process waits  for  an  incoming  connection
               before terminating voluntarily.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The maximal number of incoming connections  that  a
-              Postfix  daemon  process will service before termi-
+              The  maximal  number of incoming connections that a
+              Postfix daemon process will service  before  termi-
               nating voluntarily.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The process ID  of  a  Postfix  command  or  daemon
+              The  process  ID  of  a  Postfix  command or daemon
               process.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The  process  name  of  a Postfix command or daemon
+              The process name of a  Postfix  command  or  daemon
               process.
 
        <b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
               The network interface addresses that this mail sys-
-              tem  receives  mail on by way of a proxy or network
+              tem receives mail on by way of a proxy  or  network
               address translation unit.
 
        <b><a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> (empty)</b>
-              An optional  numerical  network  address  that  the
-              Postfix  SMTP  client should bind to when making an
+              An  optional  numerical  network  address  that the
+              Postfix SMTP client should bind to when  making  an
               IPv4 connection.
 
        <b><a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> (empty)</b>
-              An optional  numerical  network  address  that  the
-              Postfix  SMTP  client should bind to when making an
+              An  optional  numerical  network  address  that the
+              Postfix SMTP client should bind to when  making  an
               IPv6 connection.
 
        <b><a href="postconf.5.html#smtp_helo_name">smtp_helo_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
-              The hostname to send in the SMTP EHLO or HELO  com-
+              The  hostname to send in the SMTP EHLO or HELO com-
               mand.
 
        <b><a href="postconf.5.html#lmtp_lhloname">lmtp_lhlo_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
               The hostname to send in the LMTP LHLO command.
 
        <b><a href="postconf.5.html#smtp_host_lookup">smtp_host_lookup</a> (dns)</b>
-              What  mechanisms  when the Postfix SMTP client uses
+              What mechanisms when the Postfix SMTP  client  uses
               to look up a host's IP address.
 
        <b><a href="postconf.5.html#smtp_randomize_addresses">smtp_randomize_addresses</a> (yes)</b>
-              Randomize the order  of  equal-preference  MX  host
+              Randomize  the  order  of  equal-preference MX host
               addresses.
 
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
-       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
-              The  mail  system  name  that  is  prepended to the
-              process name in syslog  records,  so  that  "smtpd"
+       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
+              The mail system  name  that  is  prepended  to  the
+              process  name  in  syslog  records, so that "smtpd"
               becomes, for example, "postfix/smtpd".
 
        Available with Postfix 2.2 and earlier:
 
        <b><a href="postconf.5.html#fallback_relay">fallback_relay</a> (empty)</b>
-              Optional  list of relay hosts for SMTP destinations
+              Optional list of relay hosts for SMTP  destinations
               that can't be found or that are unreachable.
 
        Available with Postfix 2.3 and later:
 
        <b><a href="postconf.5.html#smtp_fallback_relay">smtp_fallback_relay</a> ($<a href="postconf.5.html#fallback_relay">fallback_relay</a>)</b>
-              Optional list of relay hosts for SMTP  destinations
+              Optional  list of relay hosts for SMTP destinations
               that can't be found or that are unreachable.
 
 <b>SEE ALSO</b>
@@ -820,7 +826,7 @@ SMTP(8)                                                                SMTP(8)
        <a href="TLS_README.html">TLS_README</a>, Postfix STARTTLS howto
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
index 744a5bb7185012ff974ae758546a1cd421d38674..38db746f5baa8b94d48da28fe1a631555b7d687e 100644 (file)
@@ -173,7 +173,7 @@ VERIFY(8)                                                            VERIFY(8)
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
-       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
+       <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
               The mail system  name  that  is  prepended  to  the
               process  name  in  syslog  records, so that "smtpd"
               becomes, for example, "postfix/smtpd".
index 9ec17877cc1db6b763b4ca47f17dbd9c005f4b7a..ee464361053d9559eefda88cd94e7990d293c273 100644 (file)
@@ -180,6 +180,8 @@ case "$SYSTEM.$RELEASE" in
     SunOS.5*)  SYSTYPE=SUNOS5
                RANLIB=echo
                SYSLIBS="-lresolv -lsocket -lnsl"
+               # Stock awk breaks with >10 files.
+               test -x /usr/xpg4/bin/awk && AWK=/usr/xpg4/bin/awk
                # Solaris 2.5 added usleep() and POSIX regular expressions
                case $RELEASE in
                    5.[0-4]) CCARGS="$CCARGS -DMISSING_USLEEP -DNO_POSIX_REGEXP";;
index 094ed3e2abeedddf7b74c879d01303babc0c5564..c9753a2860da970f88436e1c9f59942e2daae6a5 100644 (file)
@@ -10,8 +10,8 @@ DAEMONS       = man8/bounce.8 man8/defer.8 man8/cleanup.8 man8/error.8 man8/local.8 \
        man8/scache.8 man8/discard.8 man8/tlsmgr.8
 COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
        man1/postkick.1 man1/postlock.1 man1/postlog.1 man1/postdrop.1 \
-       man1/postmap.1 man1/sendmail.1 man1/mailq.1 man1/newaliases.1 \
-       man1/postqueue.1 man1/postsuper.1
+       man1/postmap.1 man1/postmulti.1 man1/postqueue.1 man1/postsuper.1 \
+       man1/sendmail.1 man1/mailq.1 man1/newaliases.1
 CONFIG = man5/access.5 man5/aliases.5 man5/canonical.5 man5/relocated.5 \
        man5/transport.5 man5/virtual.5 man5/pcre_table.5 man5/regexp_table.5 \
        man5/cidr_table.5 man5/tcp_table.5 man5/header_checks.5 \
@@ -203,6 +203,11 @@ man1/postmap.1: ../src/postmap/postmap.c
            (cmp -s junk $? || mv junk $?) && rm -f junk
        ../mantools/srctoman $? >$@
 
+man1/postmulti.1: ../src/postmulti/postmulti.c
+       ../mantools/fixman ../proto/postconf.proto $? >junk && \
+           (cmp -s junk $? || mv junk $?) && rm -f junk
+       ../mantools/srctoman $? >$@
+
 man1/postqueue.1: ../src/postqueue/postqueue.c
        ../mantools/fixman ../proto/postconf.proto $? >junk && \
            (cmp -s junk $? || mv junk $?) && rm -f junk
diff --git a/postfix/man/man1/postmulti.1 b/postfix/man/man1/postmulti.1
new file mode 100644 (file)
index 0000000..3643972
--- /dev/null
@@ -0,0 +1,403 @@
+.TH POSTMULTI 1 
+.ad
+.fi
+.SH NAME
+postmulti
+\-
+Postfix multi-instance manager
+.SH "SYNOPSIS"
+.na
+.nf
+.fi
+\fBpostmulti\fR \fB-l\fR [\fB-aRv\fR] [\fB-g \fIgroup\fR]
+[\fB-i \fIname\fR]
+
+\fBpostmulti\fR \fB-p\fR [\fB-av\fR] [\fB-g \fIgroup\fR]
+[\fB-i \fIname\fR] \fIcommand...\fR
+
+\fBpostmulti\fR \fB-x\fR [\fB-aRv\fR] [\fB-g \fIgroup\fR]
+[\fB-i \fIname\fR] \fIcommand...\fR
+
+\fBpostmulti\fR \fB-e init\fR [\fB-v\fR]
+
+\fBpostmulti\fR \fB-e create\fR [\fB-av\fR]
+[\fB-g \fIgroup\fR] [\fB-i \fIname\fR] [\fB-G \fIgroup\fR]
+[\fB-I \fIname\fR] [\fIparam=value\fR ...]
+
+\fBpostmulti\fR \fB-e import\fR [\fB-av\fR]
+[\fB-g \fIgroup\fR] [\fB-i \fIname\fR] [\fB-G \fIgroup\fR]
+[\fB-I \fIname\fR] [\fBconfig_directory=\fI/path\fR]
+
+\fBpostmulti\fR \fB-e destroy\fR [\fB-v\fR] \fB-i \fIname\fR
+
+\fBpostmulti\fR \fB-e deport\fR [\fB-v\fR] \fB-i \fIname\fR
+
+\fBpostmulti\fR \fB-e enable\fR [\fB-v\fR] \fB-i \fIname\fR
+
+\fBpostmulti\fR \fB-e disable\fR [\fB-v\fR] \fB-i \fIname\fR
+
+\fBpostmulti\fR \fB-e assign\fR [\fB-v\fR] \fB-i \fIname\fR
+[\fB-I \fIname\fR] [-G \fIgroup\fR]
+.SH DESCRIPTION
+.ad
+.fi
+The \fBpostmulti\fR(1) command allows a Postfix administrator
+to manage multiple Postfix instances on a single host.
+
+\fBpostmulti\fR(1) implements two fundamental modes of
+operation.  In \fBiterator\fR mode, it executes the same
+command for multiple Postfix instances.  In \fBlife-cycle
+management\fR mode, it adds or deletes one instance, or
+changes the multi-instance status of one instance.
+
+Each mode of operation has its own command syntax. For this
+reason, each mode is documented in separate sections below.
+.SH "BACKGROUND"
+.na
+.nf
+.ad
+.fi
+A multi-instance configuration consists of one primary
+Postfix instance, and one or more secondary instances whose
+configuration directory pathnames are recorded in the primary
+instance's main.cf file. Postfix instances share program
+files and documentation, but have their own configuration,
+queue and data directories.
+
+Currently, only the default Postfix instance can be used
+as primary instance in a multi-instance configuration. The
+\fBpostmulti\fR(1) command does not currently support a \fB-c\fR
+option to select an alternative primary instance, and exits
+with a fatal error if the \fBMAIL_CONFIG\fR environment
+variable is set to a non-default configuration directory.
+
+See the MULTI_INSTANCE_README tutorial for a more detailed
+discussion of multi-instance management with \fBpostmulti\fR(1).
+.SH "ITERATOR MODE"
+.na
+.nf
+.ad
+.fi
+In iterator mode, \fBpostmulti\fR performs the same operation
+on all Postfix instances in turn.
+
+If multi-instance support is not enabled, the requested
+command is performed just for the primary instance.
+.PP
+Iterator mode implements the following command options:
+.SH "Instance selection"
+.IP \fB-a\fR
+Perform the operation on all instances. This is the default.
+.IP "\fB-g \fIgroup\fR"
+Perform the operation only for members of the named \fIgroup\fR.
+.IP "\fB-i \fIname\fR"
+Perform the operation only for the instance with the specified
+\fIname\fR.  You can specify either the instance name
+or the absolute pathname of the instance's configuration
+directory.  Specify "-" to select the primary Postfix instance.
+.IP \fB-R\fR
+Reverse the iteration order. This may be appropriate when
+updating a multi-instance system, where "sink" instances
+are started before "source" instances.
+.sp
+This option cannot be used with \fB-p\fR.
+.SH "List mode"
+.IP \fB-l\fR
+List Postfix instances with their instance name, instance
+group name, enable/disable status and configuration directory.
+.SH "Postfix-wrapper mode"
+.IP \fB-p\fR
+Invoke \fBpostfix(1)\fR to execute the specified \fIcommand\fR.
+This option implements the \fBpostfix-wrapper\fR(5) interface.
+.RS
+.IP \(bu
+With "start"-like commands, "postfix check" is executed for
+instances that are not enabled. The full list of commands
+is specified with the postmulti_start_commands parameter.
+.IP \(bu
+With "stop"-like commands, the iteration order is reversed,
+and disabled instances are skipped. The full list of commands
+is specified with the postmulti_stop_commands parameter.
+.IP \(bu
+With "reload" and other commands that require a started
+instance, disabled instances are skipped. The full list of
+commands is specified with the postmulti_control_commands
+parameter.
+.IP \(bu
+With "status" and other commands that don't require a started
+instance, the command is executed for all instances.
+.RE
+.IP
+The \fB-p\fR option can also be used interactively to
+start/stop/etc.  a named instance or instance group. For
+example, to start just the instances in the group "msa",
+invoke \fBpostmulti\fR(1) as follows:
+.RS
+.IP
+# postmulti -g msa -p start
+.RE
+.SH "Command mode"
+.IP \fB-x\fR
+Execute the specified \fIcommand\fR for all Postfix instances.
+The command runs with appropriate environment settings for
+MAIL_CONFIG, command_directory, daemon_directory,
+config_directory, queue_directory, data_directory,
+multi_instance_name, multi_instance_group and
+multi_instance_enable.
+.SH "Other options"
+.IP \fB-v\fR
+Enable verbose logging for debugging purposes. Multiple
+\fB-v\fR options make the software increasingly verbose.
+.SH "LIFE-CYCLE MANAGEMENT MODE"
+.na
+.nf
+.ad
+.fi
+With the \fB-e\fR option \fBpostmulti\fR(1) can be used to
+add or delete a Postfix instance, and to manage the
+multi-instance status of an existing instance.
+.PP
+The following options are implemented:
+.SH "Existing instance selection"
+.IP \fB-a\fR
+When creating or importing an instance, place the new
+instance at the front of the secondary instance list.
+.IP "\fB-g \fIgroup\fR"
+When creating or importing an instance, place the new
+instance before the first secondary instance that is a
+member of the specified group.
+.IP "\fB-i \fIname\fR"
+When creating or importing an instance, place the new
+instance before the matching secondary instance.
+.sp
+With other life-cycle operations, apply the operation to
+the named existing instance.  Specify "-" to select the
+primary Postfix instance.
+.SH "New or existing instance name assignment"
+.IP "\fB-I \fIname\fR"
+Assign the specified instance \fIname\fR to an existing
+instance or to a newly created or imported instance.  Instance
+names other than "-"    (which makes the instance "nameless")
+must start with "postfix-".  This restriction reduces the
+likelihood of name collisions with system files.
+.IP "\fB-G \fIgroup\fR"
+Assign the specified \fIgroup\fR name to an existing instance
+or to a newly created or imported instance.
+.SH "Instance creation/deletion/status change"
+.IP "\fB-e \fIaction\fR"
+"Edit" managed instances. The following actions are supported:
+.RS
+.IP \fBinit\fR
+This command is required before \fBpostmulti\fR(1) can be
+used to manage Postfix instances.  The "postmulti -e init"
+command updates the primary instance's main.cf file by
+setting:
+.RS
+.IP
+.nf
+multi_instance_wrapper =
+        ${command_directory}/postmulti -p --
+multi_instance_enable = yes
+.fi
+.RE
+.IP
+You can set these by other means if you prefer.
+.IP \fBcreate\fR
+Create a new Postfix instance and add it to the
+multi_instance_directories parameter of the primary instance.
+The "\fB-I \fIname\fR" option is recommended to give the
+instance a short name that is used to construct default
+values for the private directories of the new instance. The
+"\fB-G \fIgroup\fR" option may be specified to assign the
+instance to a group, otherwise, the new instance is not a
+member of any groups.
+.sp
+The new instance main.cf is the stock main.cf with the
+parameters that specify the locations of shared files cloned
+from the primary instance.  For "nameless" instances, you
+should manually adjust "syslog_name" to yield a unique
+"logtag" starting with "postfix-" that will uniquely identify
+the instance in the mail logs. It is simpler to assign the
+instance a short name with the "\fB-I \fIname\fR" option.
+.sp
+Optional "name=value" arguments specify the instance
+config_directory, queue_directory and data_directory.
+For example:
+.RS
+.IP
+.nf
+# postmulti -I postfix-mumble \e
+        -G mygroup -e create \e
+        config_directory=/my/config/dir \e
+        queue_directory=/my/queue/dir \e
+        data_directory=/my/data/dir
+.fi
+.RE
+.IP
+If any of these pathnames is not supplied, the program
+attempts to generate the pathname by taking the corresponding
+primary instance pathname, and by replacing the last pathname
+component by the value of the \fB-I\fR option.
+.sp
+If the instance configuration directory already exists, and
+contains both a main.cf and master.cf file, \fBcreate\fR
+will "import" the instance as-is. For existing instances,
+\fBcreate\fR and \fBimport\fR are identical.
+.IP \fBimport\fR
+Import an existing instance into the list of instances
+managed by the \fBpostmulti\fR(1) multi-instance manager.
+This adds the instance to the multi_instance_directories
+list of the primary instance.  If the "\fB-I \fIname\fR"
+option is provided it specifies the new name for the instance
+and is used to define a default location for the instance
+configuration directory (as with \fBcreate\fR above).  The
+"\fB-G \fIgroup\fR" option may be used to assign the instance
+to a group. Add a "\fBconfig_directory=\fI/path\fR" argument
+to override a default pathname based on "\fB-I \fIname\fR".
+.IP \fBdestroy\fR
+Destroy a secondary Postfix instance. To be a candidate for
+destruction an instance must be disabled, stopped and its
+queue must not contain any messages. Attempts to destroy
+the primary Postfix instance trigger a fatal error, without
+destroying the instance.
+.sp
+The instance is removed from the primary instance main.cf
+file's alternate_config_directories parameter and its data,
+queue and configuration directories are cleaned of files
+and directories created by the Postfix system. The main.cf
+and master.cf files are removed from the configuration
+directory even if they have been modified since initial
+creation. Finally, the instance is "deported" from the list
+of managed instances.
+.sp
+If other files are present in instance private directories,
+the directories may not be fully removed, a warning is
+logged to alert the administrator. It is expected that an
+instance built using "fresh" directories via the \fBcreate\fR
+action will be fully removed by the \fBdestroy\fR action
+(if first disabled). If the instance configuration and queue
+directories are populated with additional files (access and
+rewriting tables, chroot jail content, etc.) the instance
+directories will not be fully removed.
+.sp
+The \fBdestroy\fR action triggers potentially dangerous
+file removal operations. Make sure the instance's data,
+queue and configuration directories are set correctly and
+do not contain any valuable files.
+.IP \fBdeport\fR
+Deport a secondary instance from the list of managed
+instances. This deletes the instance configuration directory
+from the primary instance's multi_instance_directories list,
+but does not remove any files or directories.
+.IP \fBassign\fR
+Assign a new instance name or a new group name to the
+selected instance.  Use "\fB-G -\fR" to specify "no group"
+and "\fB-I -\fR" to specify "no name".  If you choose to
+make an instance "nameless", set a suitable syslog_name in
+the corresponding main.cf file.
+.IP \fBenable\fR
+Mark the selected instance as enabled. This just sets the
+multi_instance_enable parameter to "yes" in the instance's
+main.cf file.
+.IP \fBdisable\fR
+Mark the selected instance as disabled. This means that
+the instance will not be started etc. with "postfix start",
+"postmulti -p start" and so on. The instance can still be
+started etc. with "postfix -c config-directory start".
+.SH "Other options"
+.IP \fB-v\fR
+Enable verbose logging for debugging purposes. Multiple
+\fB-v\fR options make the software increasingly verbose.
+.RE
+.SH "ENVIRONMENT"
+.na
+.nf
+.ad
+.fi
+The \fBpostmulti\fR(1) command exports the following environment
+variables before executing the requested \fIcommand\fR for a given
+instance:
+.IP \fBMAIL_VERBOSE\fR
+This is set when the -v command-line option is present.
+.IP \fBMAIL_CONFIG\fR
+The location of the configuration directory of the instance.
+.SH "CONFIGURATION PARAMETERS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+The default location of the Postfix main.cf and master.cf
+configuration files.
+.IP "\fBdaemon_directory (see 'postconf -d' output)\fR"
+The directory with Postfix support programs and daemon programs.
+.IP "\fBimport_environment (see 'postconf -d' output)\fR"
+The list of environment parameters that a Postfix process will
+import from a non-Postfix parent process.
+.IP "\fBmulti_instance_directories (empty)\fR"
+An optional list of non-default Postfix configuration directories;
+these directories belong to additional Postfix instances that share
+the Postfix executable files and documentation with the default
+Postfix instance, and that are started, stopped, etc., together
+with the default Postfix instance.
+.IP "\fBmulti_instance_group (empty)\fR"
+The optional instance group name of this Postfix instance.
+.IP "\fBmulti_instance_name (empty)\fR"
+The optional instance name of this Postfix instance.
+.IP "\fBmulti_instance_enable (no)\fR"
+Allow this Postfix instance to be started, stopped, etc., by a
+multi-instance manager.
+.IP "\fBpostmulti_start_commands (start)\fR"
+The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager treats
+as "start" commands.
+.IP "\fBpostmulti_stop_commands (see 'postconf -d' output)\fR"
+The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager treats
+as "stop" commands.
+.IP "\fBpostmulti_control_commands (reload flush)\fR"
+The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager
+treats as "control" commands, that operate on running instances.
+.IP "\fBsyslog_facility (mail)\fR"
+The syslog facility of Postfix logging.
+.IP "\fBsyslog_name (see 'postconf -d' output)\fR"
+The mail system name that is prepended to the process name in syslog
+records, so that "smtpd" becomes, for example, "postfix/smtpd".
+.SH "FILES"
+.na
+.nf
+$daemon_directory/main.cf, stock configuration file
+$daemon_directory/master.cf, stock configuration file
+$daemon_directory/postmulti-script, life-cycle helper program
+.SH "SEE ALSO"
+.na
+.nf
+postfix(1), Postfix control program
+postfix-wrapper(5), Postfix multi-instance API
+.SH "README FILES"
+.na
+.nf
+Use "\fBpostconf readme_directory\fR" or "\fBpostconf
+html_directory\fR" to locate this information.
+MULTI_INSTANCE_README, Postfix multi-instance management
+.SH "HISTORY"
+.na
+.nf
+.ad
+.fi
+The \fBpostmulti\fR(1) command was introduced with Postfix
+version 2.6.
+.SH "LICENSE"
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH "AUTHOR(S)"
+.na
+.nf
+Victor Duchovni
+Morgan Stanley
+
+Wietse Venema
+IBM T.J. Watson Research
+P.O. Box 704
+Yorktown Heights, NY 10598, USA
index ed7bc5acad80014a38727553cb4a3c410cce53cc..b7abb31a04cb9118516a51e653670efd0c5cc7ec 100644 (file)
@@ -383,7 +383,7 @@ this parameter is empty; otherwise, rewrite message headers and
 append the specified domain name to incomplete addresses.
 .IP "\fBsyslog_facility (mail)\fR"
 The syslog facility of Postfix logging.
-.IP "\fBsyslog_name (postfix)\fR"
+.IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 The mail system name that is prepended to the process name in syslog
 records, so that "smtpd" becomes, for example, "postfix/smtpd".
 .SH "FILES"
@@ -407,8 +407,12 @@ syslogd(8), system logging
 .SH "README_FILES"
 .na
 .nf
+.ad
+.fi
 Use "\fBpostconf readme_directory\fR" or
 "\fBpostconf html_directory\fR" to locate this information.
+.na
+.nf
 DEBUG_README, Postfix debugging howto
 ETRN_README, Postfix ETRN howto
 VERP_README, Postfix VERP howto
index 36690a5b7ecd0d69bf17cfda3ed8e8ea021f815c..00d3942802c7c179115339fc7c9be1bfe34a56a2 100644 (file)
@@ -376,6 +376,12 @@ via the MAIL_CONFIG environment parameter.
 This list must be specified in the default Postfix configuration
 directory, and is used by set-gid Postfix commands such as \fBpostqueue\fR(1)
 and \fBpostdrop\fR(1).
+.SH always_add_missing_headers (default: no)
+Always add (Resent-) From:, To:, Date: or Message-ID: headers
+when not present.  Postfix 2.6 and later add these headers only
+when clients match the local_header_rewrite_clients parameter
+setting.  Earlier Postfix versions always add these headers; this
+may break DKIM signatures that cover non-existent headers.
 .SH always_bcc (default: empty)
 Optional address that receives a "blind carbon copy" of each message
 that is received by the Postfix mail system.
@@ -1906,6 +1912,12 @@ This feature is available in Postfix 2.1 and later.
 .SH line_length_limit (default: 2048)
 Upon input, long lines are chopped up into pieces of at most
 this length; upon delivery, long lines are reconstructed.
+.SH lmtp_assume_final (default: no)
+When an LMTP server announces no DSN support, assume that the
+server performs final delivery, and send "delivered" delivery status
+notifications instead of "relayed". The default setting is backwards
+compatible to avoid the infinetisimal possibility of breaking
+existing LMTP-based content filters.
 .SH lmtp_bind_address (default: empty)
 The LMTP-specific version of the smtp_bind_address configuration
 parameter.  See there for details.
@@ -3219,11 +3231,16 @@ Postfix instance, and that are started, stopped, etc., together
 with the default Postfix instance.  Specify a list of pathnames
 separated by comma or whitespace.
 .PP
-When the list of non-default Postfix configuration directories
-is non-empty, the \fBpostfix\fR(1) command will invoke the multi-instance
-manager specified with the multi_instance_wrapper parameter to
-execute commands on the default instance and on all additional
-Postfix instances.
+When $multi_instance_directories is empty, the \fBpostfix\fR(1) command
+runs in single-instance mode and operates on a single Postfix
+instance only. Otherwise, the \fBpostfix\fR(1) command runs in multi-instance
+mode and invokes the multi-instance manager specified with the
+multi_instance_wrapper parameter. The multi-instance manager in
+turn executes \fBpostfix\fR(1) commands for the default instance and for
+all Postfix instances in $multi_instance_directories.
+.PP
+Currently, this parameter setting is ignored except for the
+default main.cf file.
 .PP
 This feature is available in Postfix 2.6 and later.
 .SH multi_instance_enable (default: no)
@@ -3532,6 +3549,25 @@ The numerical Postfix SMTP server response code when a request
 is rejected by the \fBreject_plaintext_session\fR restriction.
 .PP
 This feature is available in Postfix 2.3 and later.
+.SH postmulti_control_commands (default: reload flush)
+The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager
+treats as "control" commands, that operate on running instances. For
+these commands, disabled instances are skipped.
+.PP
+This feature is available in Postfix 2.6 and later.
+.SH postmulti_start_commands (default: start)
+The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager treats
+as "start" commands. For these commands, disabled instances are "checked"
+rather than "started", and failure to "start" a member instance of an
+instance group will abort the start-up of later instances.
+.PP
+This feature is available in Postfix 2.6 and later.
+.SH postmulti_stop_commands (default: see "postconf -d" output)
+The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager treats
+as "stop" commands. For these commands, disabled instances are skipped,
+and enabled instances are processed in reverse order.
+.PP
+This feature is available in Postfix 2.6 and later.
 .SH prepend_delivered_header (default: command, file, forward)
 The message delivery contexts where the Postfix \fBlocal\fR(8) delivery
 agent prepends a Delivered-To:  message header with the address
index 0e18e4a91aca8292f45d9d85cbe8a8f95cf174ee..f2a1a71a8f799d7343c344ffc07d4387e665a9a0 100644 (file)
@@ -15,34 +15,28 @@ queue and data files.
 
 This document describes how the familiar "postfix start"
 etc. user interface can be used to manage one or multiple
-Postfix instances, and gives details of an API that allows
-the postfix(1) command to coordinate activities with a
-multi-instance manager program.
-
-A trivial but useful multi-instance manager implementation
-is described below, and can be found in the file
-$daemon_directory/postfix-wrapper. The latter file also
-contains instructions for setting up multiple instances.
+Postfix instances, and gives details of an API to coordinate
+activities between the postfix(1) command and a multi-instance
+manager program.
 
 With multi-instance support, the default Postfix instance
-is required. The location of its configuration files is
-specified by the built-in default value for the config_directory
-parameter.
+is always required. The config_directory parameter's default
+value specifies that instance's configuration file location.
 .SH "GENERAL OPERATION"
 .na
 .nf
 .ad
 .fi
-Multi-instance support is backwards compatible: when there
-is only one Postfix instance, commands such as "postfix
-start" keep doing what they have always done.
+Multi-instance support is backwards compatible: when you
+run only one Postfix instance, commands such as "postfix
+start" will not change behavior at all.
 
-Even after multi-instance support has been set up through
-the mechanisms discussed later, sites can continue to use
-the familiar postfix commands in boot scripts, upgrade
-procedures, and other places.
+Even with multiple Postfix instances, you can keep using
+the same postfix commands in boot scripts, upgrade procedures,
+and other places. The commands do more work, but humans are
+not forced to learn new tricks.
 
-To start all applicable Postfix instances, use:
+For example, to start all Postfix instances, use:
 .IP
 # postfix start
 .PP
@@ -59,8 +53,8 @@ a multi-instance configuration.
 .nf
 .ad
 .fi
-To operate on a specific Postfix instance, specify its
-configuration directory on the postfix(1) command line:
+To manage a specific Postfix instance, specify its configuration
+directory on the postfix(1) command line:
 .IP
 # postfix -c \fI/path/to/config_directory command\fR
 .PP
@@ -69,41 +63,57 @@ configuration directory via the MAIL_CONFIG environment
 variable (the -c command-line option has higher precedence).
 
 When no Postfix instance information is specified, the
-postfix(1) command will operate on all applicable Postfix
-instances.
-.SH "MULTI-INSTANCE MANAGER IMPLEMENTATION"
+postfix(1) command will operate on all Postfix instances.
+.SH "ENABLING POSTFIX(1) MULTI-INSTANCE MODE"
 .na
 .nf
 .ad
 .fi
-Historically, the postfix(1) command invokes the postfix-script
-file (currently installed in the daemon directory). This
-file contains the commands that start or stop Postfix,
-upgrade the configuration and so on.
+By default, the postfix(1) command operates in single-instance
+mode. In this mode the command invokes the postfix-script
+file directly (currently installed in the daemon directory).
+This file contains the commands that start or stop one
+Postfix instance, that upgrade the configuration of one
+Postfix instance, and so on.
 
-When multi-instance support is turned on, the postfix(1)
-command needs to execute these commands for each applicable
-Postfix instance. This multiplication of commands is handled
-by a multi-instance manager program.
+When the postfix(1) command operates in multi-instance mode
+as discussed below, the command needs to execute start,
+stop, etc.  commands for each Postfix instance.  This
+multiplication of commands is handled by a multi-instance
+manager program.
 
-Turning on multi-instance support goes as follows: update
-the default Postfix instance's main.cf file, and populate
-the multi_instance_directories parameter with the configuration
-directory pathnames of additional Postfix instances.
-
-With multi-instance support turned on, the postfix(1) command
-invokes a multi-instance manager command instead of the
-postfix-script file. The multi-instance manager executes
-the postfix(1) command for each applicable Postfix instance.
-The pathname of the multi-instance manager is specified in
-the default main.cf file with the multi_instance_wrapper
-parameter.
+Turning on postfix(1) multi-instance mode goes as follows:
+in the default Postfix instance's main.cf file, 1) specify
+the pathname of a multi-instance manager program with the
+multi_instance_wrapper parameter; 2) populate the
+multi_instance_directories parameter with the configuration
+directory pathnames of additional Postfix instances.  For
+example:
+.IP
+.nf
+/etc/postfix/main.cf:
+    multi_instance_wrapper = $daemon_directory/postfix-wrapper
+    multi_instance_directories = /etc/postfix-test
+.fi
+.PP
+The $daemon_directory/postfix-wrapper file implements a
+simple manager and contains instructions for creating Postfix
+instances by hand.  The postmulti(1) command provides a
+more extensive implementation including support for life-cycle
+management.
 
 The multi_instance_directories and other main.cf parameters
 are listed below in the CONFIGURATION PARAMETERS section.
 
-A useful multi-instance manager implementation can be as
-simple as:
+In multi-instance mode, the postfix(1) command invokes the
+$multi_instance_wrapper command instead of the postfix-script
+file. This multi-instance manager in turn executes the
+postfix(1) command in single-instance mode for each Postfix
+instance.
+
+To illustrate the main ideas behind multi-instance operation,
+below is an example of a simple but useful multi-instance
+manager implementation:
 .IP
 .nf
 #!/bin/sh
@@ -134,52 +144,49 @@ done
 
 exit $err
 .fi
-.PP
-A sample implementation, with instructions, can be found
-in $daemon_directory/postfix-wrapper.
-
-The postmulti(1) command implements a more sophisticated
-approach, based on a combination of C code and scripting.
-.SH "ENABLING A SPECIFIC INSTANCE FOR MULTI-INSTANCE OPERATION"
+.SH "PER-INSTANCE MULTI-INSTANCE MANAGER CONTROLS"
 .na
 .nf
 .ad
 .fi
 Each Postfix instance has its own main.cf file with parameters
-that control multi-instance operation. The most important
-settings are discussed here.
+that control how the multi-instance manager operates on
+that instance.  This section discusses the most important
+settings.
 
 The setting "multi_instance_enable = yes" allows the
-multi-instance manager to start (and stop) the corresponding
+multi-instance manager to start (stop, etc.) the corresponding
 Postfix instance. For safety reasons, this setting is not
 the default.
 
-The setting "multi_instance_enable = no" is useful for
-manual testing.  With this, the multi-instance manager will
-not start the Postfix instance, and it will skip commands
-such as "stop" or "flush" that require a running Postfix
-instance.  The multi-instance manager will execute commands
-such as "check", "set-permissions" or "upgrade-configuration",
-and it will replace "start" by "check" so that problems
-will be reported even when the instance is disabled.
-.SH "SHARED VERSUS NON-SHARED FILES"
+The default setting "multi_instance_enable = no" is useful
+for manual testing with "postfix -c \fI/path/name\fR start"
+etc.  The multi-instance manager will not start such an
+instance, and it will skip commands such as "stop" or "flush"
+that require a running Postfix instance.  The multi-instance
+manager will execute commands such as "check", "set-permissions"
+or "upgrade-configuration", and it will replace "start" by
+"check" so that problems will be reported even when the
+instance is disabled.
+.SH "MAINTAINING SHARED AND NON-SHARED FILES"
 .na
 .nf
 .ad
 .fi
 Some files are shared between Postfix instances, such as
 executables and manpages, and some files are per-instance,
-such as the queue directory.  See the NON-SHARED FILES
-section below for a list of per-instance files.
+such as configuration files, mail queue files, and data
+files.  See the NON-SHARED FILES section below for a list
+of per-instance files.
 
 Before Postfix multi-instance support was implemented, the
-executables, manpages, etc., have always been checked or
-updated as part of the default Postfix instance. With
-multi-instance support, we simply continue to do this.
+executables, manpages, etc., have always been maintained
+as part of the default Postfix instance.
 
-Specifically, Postfix instances will not check or update
-shared files when their config_directory value is listed
-with the default main.cf's multi_instance_directories
+With multi-instance support, we simply continue to do this.
+Specifically, a Postfix instance will not check or update
+shared files when that instance's config_directory value is
+listed with the default main.cf file's multi_instance_directories
 parameter.
 
 The consequence of this approach is that the default Postfix
index 412c3e1eb0354b6e39e8f91cd93d2ce76cdc342b..cb6a47b61ac7acad17807da3c6cf79dc6eb89200 100644 (file)
@@ -93,6 +93,11 @@ non-standard Errors-To: message header, instead of the envelope
 sender address (this feature is removed with Postfix version 2.2, is
 turned off by default with Postfix version 2.1, and is always turned on
 with older Postfix versions).
+.PP
+Available in Postfix version 2.6 and later:
+.IP "\fBalways_add_missing_headers (no)\fR"
+Always add (Resent-) From:, To:, Date: or Message-ID headers
+when not present.
 .SH "BUILT-IN CONTENT FILTERING CONTROLS"
 .na
 .nf
@@ -158,30 +163,30 @@ filter) application, and for receiving the response.
 .IP "\fBmilter_content_timeout (300s)\fR"
 The time limit for sending message content to a Milter (mail
 filter) application, and for receiving the response.
-.IP "\fBmilter_connect_macros (see postconf -n output)\fR"
+.IP "\fBmilter_connect_macros (see 'postconf -d' output)\fR"
 The macros that are sent to Milter (mail filter) applications
 after completion of an SMTP connection.
-.IP "\fBmilter_helo_macros (see postconf -n output)\fR"
+.IP "\fBmilter_helo_macros (see 'postconf -d' output)\fR"
 The macros that are sent to Milter (mail filter) applications
 after the SMTP HELO or EHLO command.
-.IP "\fBmilter_mail_macros (see postconf -n output)\fR"
+.IP "\fBmilter_mail_macros (see 'postconf -d' output)\fR"
 The macros that are sent to Milter (mail filter) applications
 after the SMTP MAIL FROM command.
-.IP "\fBmilter_rcpt_macros (see postconf -n output)\fR"
+.IP "\fBmilter_rcpt_macros (see 'postconf -d' output)\fR"
 The macros that are sent to Milter (mail filter) applications
 after the SMTP RCPT TO command.
-.IP "\fBmilter_data_macros (see postconf -n output)\fR"
+.IP "\fBmilter_data_macros (see 'postconf -d' output)\fR"
 The macros that are sent to version 4 or higher Milter (mail
 filter) applications after the SMTP DATA command.
-.IP "\fBmilter_unknown_command_macros (see postconf -n output)\fR"
+.IP "\fBmilter_unknown_command_macros (see 'postconf -d' output)\fR"
 The macros that are sent to version 3 or higher Milter (mail
 filter) applications after an unknown SMTP command.
-.IP "\fBmilter_end_of_data_macros (see postconf -n output)\fR"
+.IP "\fBmilter_end_of_data_macros (see 'postconf -d' output)\fR"
 The macros that are sent to Milter (mail filter) applications
 after the message end-of-data.
 .PP
 Available in Postfix version 2.5 and later:
-.IP "\fBmilter_end_of_header_macros (see postconf -n output)\fR"
+.IP "\fBmilter_end_of_header_macros (see 'postconf -d' output)\fR"
 The macros that are sent to Milter (mail filter) applications
 after the end of the message header.
 .SH "MIME PROCESSING CONTROLS"
@@ -365,7 +370,7 @@ Safety net to keep mail queued that would otherwise be returned to
 the sender.
 .IP "\fBsyslog_facility (mail)\fR"
 The syslog facility of Postfix logging.
-.IP "\fBsyslog_name (postfix)\fR"
+.IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 The mail system name that is prepended to the process name in syslog
 records, so that "smtpd" becomes, for example, "postfix/smtpd".
 .PP
index 720f55859533ff8cde2366d74b89e27d601bb151..b15d3aacd9c5ad88a2da0336c59fa19b3957d898 100644 (file)
@@ -580,6 +580,10 @@ or accepting connections.
 .IP "\fBipc_timeout (3600s)\fR"
 The time limit for sending or receiving information over an internal
 communication channel.
+.IP "\fBlmtp_assume_final (no)\fR"
+When an LMTP server announces no DSN support, assume that the
+server performs final delivery, and send "delivered" delivery status
+notifications instead of "relayed".
 .IP "\fBlmtp_tcp_port (24)\fR"
 The default TCP port that the Postfix LMTP client connects to.
 .IP "\fBmax_idle (100s)\fR"
@@ -612,7 +616,7 @@ address.
 Randomize the order of equal-preference MX host addresses.
 .IP "\fBsyslog_facility (mail)\fR"
 The syslog facility of Postfix logging.
-.IP "\fBsyslog_name (postfix)\fR"
+.IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 The mail system name that is prepended to the process name in syslog
 records, so that "smtpd" becomes, for example, "postfix/smtpd".
 .PP
index fa8c05ec9d0b384ca5ebdfa4c828f91fb5435c4a..0d9a852d750a44837f09c511af651ffb4e8dbc84 100644 (file)
@@ -161,7 +161,7 @@ The process name of a Postfix command or daemon process.
 The location of the Postfix top-level queue directory.
 .IP "\fBsyslog_facility (mail)\fR"
 The syslog facility of Postfix logging.
-.IP "\fBsyslog_name (postfix)\fR"
+.IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 The mail system name that is prepended to the process name in syslog
 records, so that "smtpd" becomes, for example, "postfix/smtpd".
 .SH "SEE ALSO"
index 20b3db5a32a968a2e9f099fb62e8e3d1e5ef0c86..5fea129b39a9c2568cafc4e120c04921f4d27c42 100755 (executable)
@@ -93,7 +93,8 @@ while (<>) {
     s;\ballow_min_user\b;<a href="postconf.5.html#allow_min_user">$&</a>;g;
     s;\ballow_percent_hack\b;<a href="postconf.5.html#allow_percent_hack">$&</a>;g;
     s;\ballow_untrusted_routing\b;<a href="postconf.5.html#allow_untrusted_routing">$&</a>;g;
-    s;\balternate_config_direc[-</bB>]*\n*[ <bB>]*tories\b;<a href="postconf.5.html#alternate_config_directories">$&</a>;g;
+    s;\balternate_con[-</bB>]*\n*[ <bB>]*fig_direc[-</bB>]*\n*[ <bB>]*tories\b;<a href="postconf.5.html#alternate_config_directories">$&</a>;g;
+    s;\balways_add_missing_headers\b;<a href="postconf.5.html#always_add_missing_headers">$&</a>;g;
     s;\balways_bcc\b;<a href="postconf.5.html#always_bcc">$&</a>;g;
     s;\banvil_rate_time_unit\b;<a href="postconf.5.html#anvil_rate_time_unit">$&</a>;g;
     s;\bappend_at_myorigin\b;<a href="postconf.5.html#append_at_myorigin">$&</a>;g;
@@ -119,7 +120,7 @@ while (<>) {
     s;\bcommand_execu[-</bB>]*\n* *[<bB>]*tion_direc[-</bB>]*\n* *[<bB>]*tory\b;<a href="postconf.5.html#command_execution_directory">$&</a>;g;
     s;\bexecu[-</bB>]*\n* *[<bB>]*tion_directory_expansion_filter\b;<a href="postconf.5.html#execution_directory_expansion_filter">$&</a>;g;
     s;\banvil_status_update_time\b;<a href="postconf.5.html#anvil_status_update_time">$&</a>;g;
-    s;\bcommand_directory\b;<a href="postconf.5.html#command_directory">$&</a>;g;
+    s;\bcommand_direc[-</bB>]*\n* *[<bB>]*tory\b;<a href="postconf.5.html#command_directory">$&</a>;g;
     s;\bcommand_expan[-</bB>]*\n* *[<bB>]*sion_filter\b;<a href="postconf.5.html#command_expansion_filter">$&</a>;g;
     s;\bcommand_time_limit\b;<a href="postconf.5.html#command_time_limit">$&</a>;g;
     s;\bconfig_direc[-</bB>]*\n*[ <bB>]*tory\b;<a href="postconf.5.html#config_directory">$&</a>;g;
@@ -333,6 +334,9 @@ while (<>) {
     s;\bpermit_mx_backup_networks\b;<a href="postconf.5.html#permit_mx_backup_networks">$&</a>;g;
     s;\bpickup_service_name\b;<a href="postconf.5.html#pickup_service_name">$&</a>;g;
     s;\bplaintext_reject_code\b;<a href="postconf.5.html#plaintext_reject_code">$&</a>;g;
+    s;\bpostmulti_start_commands\b;<a href="postconf.5.html#postmulti_start_commands">$&</a>;g;
+    s;\bpostmulti_stop_commands\b;<a href="postconf.5.html#postmulti_stop_commands">$&</a>;g;
+    s;\bpostmulti_con[-</bB>]*\n* *[<bB>]*trol_commands\b;<a href="postconf.5.html#postmulti_control_commands">$&</a>;g;
     s;\bprepend_delivered_header\b;<a href="postconf.5.html#prepend_delivered_header">$&</a>;g;
     s;\bprocess_id\b;<a href="postconf.5.html#process_id">$&</a>;g;
     s;\bprocess_id_directory\b;<a href="postconf.5.html#process_id_directory">$&</a>;g;
@@ -725,6 +729,7 @@ while (<>) {
     s/[<bB>]*postlock[<\/bB>]*\(1\)/<a href="postlock.1.html">$&<\/a>/g;
     s/[<bB>]*postlog[<\/bB>]*\(1\)/<a href="postlog.1.html">$&<\/a>/g;
     s/[<bB>]*postmap[<\/bB>]*\(1\)/<a href="postmap.1.html">$&<\/a>/g;
+    s/[<bB>]*postmulti[<\/bB>]*\(1\)/<a href="postmulti.1.html">$&<\/a>/g;
     s/[<bB>]*postqueue[<\/bB>]*\(1\)/<a href="postqueue.1.html">$&<\/a>/g;
     s/[<bB>]*postsuper[<\/bB>]*\(1\)/<a href="postsuper.1.html">$&<\/a>/g;
     s/[<bB>]*send[-<\/bB>]*\n*[ <bB>]*mail[<\/bB>]*\(1\)/<a href="sendmail.1.html">$&<\/a>/g;
index dbda9519cefa347214d88554d8121e47f594fae2..af959d298d851d9978525e48b28b43de9ebef514 100644 (file)
@@ -348,7 +348,8 @@ Such rules slow down all mail and complicate Postfix maintenance.
 
 <h2><a name="remote_only">Configuring header/body checks for mail from outside users only</a></h2>
 
-<p> The following information applies to Postfix 2.1. Earlier
+<p> The following information applies to Postfix 2.1 and later.
+Earlier
 Postfix versions do not support the receive_override_options feature.
 </p>
 
@@ -375,6 +376,9 @@ service with header/body filtering turned off.  </p>
         -o receive_override_options=no_header_body_checks
 </pre>
 
+<li> <p> Add some firewall rule to prevent access to 1.2.3.4:smtp
+from the outside world. </p>
+
 <li> <p> One SMTP server address for mail from outside users with
 header/body filtering turned on via main.cf. </p>
 
diff --git a/postfix/proto/MULTI_INSTANCE_README.html b/postfix/proto/MULTI_INSTANCE_README.html
new file mode 100644 (file)
index 0000000..1e5196a
--- /dev/null
@@ -0,0 +1,1272 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Managing multiple Postfix instances on a single host</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Managing
+multiple Postfix instances on a single host</h1>
+
+<hr>
+
+<h2>Overview </h2>
+
+<p> This document is a guide to managing multiple Postfix instances
+on a single host using the postmulti(1) instance manager. Multi-instance
+support is available with Postfix version 2.6 and later.  See the
+postfix-wrapper(5) manual page for background on the instance
+management framework, and on how to deploy a custom instance manager.
+</p>
+
+<p> Topics covered in this document: </p>
+
+<ul>
+
+<li><a href="#why"> Why multiple Postfix instances </a> 
+
+<li><a href="#split"> Null-client instances versus service instances </a>
+
+<li><a href="#quick"> Multi-instance walk-through  </a> 
+
+<li><a href="#parts"> Components of a Postfix system </a> 
+
+<li><a href="#default"> The default Postfix instance </a> 
+
+<li><a href="#group"> Instance groups </a>
+
+<li><a href="#params"> Multi-instance configuration parameters </a>
+
+<li><a href="#how"> Using the postmulti(1) command </a>
+
+<li><a href="#credits"> Credits </a>
+
+</ul>
+
+<h2><a name="why"> Why multiple Postfix instances </a></h2>
+
+<p> Postfix is a general-purpose mail system that can be configured
+to serve a variety of needs. Examples of Postfix applications are: </p>
+
+<ul>
+
+<li><p> Local mail submission for shell users and system processes. </p>
+
+<li><p> Incoming (MX host) email from the Internet. </p>
+
+<li><p> Outbound mail relay for a corporate network. </p>
+
+<li><p> Authenticated submission for roaming users. </p>
+
+<li><p> Before/after content-filter mail. </p>
+
+</ul>
+
+<p> A single Postfix configuration can provide many or all of these
+services, but a complex interplay of settings may be required, for
+example with master.cf options overriding main.cf settings. In this
+document we take the view that multiple Postfix instances may be a
+simpler way to configure a multi-function Postfix system.  With
+multiple Postfix instances, each instance has its own directories
+for configuration, queue and data files, but it shares all Postfix
+program and documentation files with other instances. </p>
+
+<p> Since there is no single right way to configure your system,
+we recommend that you choose what makes you most comfortable. If
+different Postfix services don't involve incompatible main.cf or
+master.cf settings, and if they can be combined together without
+complex tricks, then a single monolithic configuration may be the
+simplest approach. </p>
+
+<p> The purpose of multi-instance support in Postfix is not to force
+you to create multiple Postfix instances, but rather to give you a
+choice. Multiple instances give you the freedom to tune each Postfix
+instance to a single task that it does well and to combine instances
+into complete systems. </p>
+
+<p> With the introduction of the postmulti(1) utility and the reduction
+of the per-instance configuration footprint of a secondary Postfix
+instance to just a main.cf and master.cf file (other files are now in
+shared locations), we hope that multiple instances will be easier to
+use than ever before. </p>
+
+<h2><a name="split"> Null-client instances versus service instances </a></h2>
+
+<p> In the multi-instance approach to configuring Postfix, the first
+simplification is with the default local-submission Postfix instance.
+</p>
+
+<p> Most UNIX systems require support for email submission with the
+sendmail(1) command so that system processes such as cron jobs can
+send status reports, and so that system users can send email with
+command-line utilities.  Such email can be handled with a <a
+href="STANDARD_CONFIGURATION_README.html#null_client">null-client</a>
+Postfix configuration that forwards all mail to a central mail hub.
+The null client will typically either not run an SMTP listener at
+all (master_service_disable = inet), or it will listen only on the
+loopback interface (inet_interfaces = loopback-only). </p>
+
+<p> When implementing specialized servers for inbound Internet
+email, outbound MTAs, internal mail hubs, and so on, we recommend
+using a null client for local submission and creating single-function
+secondary Postfix instances to serve the specialized needs. </p>
+
+<blockquote>
+
+<p> Note: usually, you need to use different "myhostname" settings
+when you run multiple instances on the same host. Otherwise, there
+will be false "mail loops back to myself" alarms when one instance
+tries to send mail into another instance.  Typically, the null-client
+instance will use the system's hostname, and other instances will
+use their own dedicated "myhostname" settings. Different names are
+not needed when instances send mail to each other with a protocol
+other than SMTP, or with SMTP over a TCP port other than 25 as is
+usual with SMTP-based content filters.  </p>
+
+</blockquote>
+
+<h2><a name="quick"> Multi-instance walk-through </a></h2>
+
+<p> Before discussing the fine details of multi-instance operation
+we first show the steps for creating a border mail server. This
+server has with a null-client Postfix instance for local submission,
+an input Postfix instance to receive mail from the Internet, plus
+an <a href="FILTER_README.html#advanced_filter">advanced</a> SMTP
+content-filter and an output Postfix instance to deliver filtered
+email to its internal destination. </p>
+
+<h3>Setting up the null-client Postfix instance </h3>
+
+<p> On a border mail hub, while mail from the Internet requires a
+great deal of scrutiny, locally submitted messages are typically
+limited to mail from cron jobs and other system services. In this
+regard the border MTA is not different from other Unix hosts in
+your environment. For this reason, it will submit locally-generated
+email to the internal mail hub. We start the construction of the
+border mail server with the <a href="#default_instance">default</a>
+instance, which will be a local-submission <a
+href="STANDARD_CONFIGURATION_README.html#null_client">null client</a>:
+</p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    # We are mta1.example.com
+    #
+    myhostname = mta1.example.com
+    mydomain = example.com
+
+    # Flat user-account namespace in example.com:
+    #
+    #   user@example.com not user@host.example.com
+    #
+    myorigin = $mydomain
+
+    # Postfix 2.6+, disable inet services, specifically disable smtpd(8)
+    #
+    master_service_disable = inet
+
+    # No local delivery:
+    #
+    mydestination =
+    local_transport = error:5.1.1 Mailbox unavailable
+    alias_database =
+    alias_maps =
+    local_recipient_maps =
+
+    # Send everything to the internal mailhub
+    #
+    relayhost = [mailhub.example.com]
+
+    # Indexed table macro:
+    # (use "hash", ... when <a href="CDB_README.html">cdb</a> is not available)
+    #
+    default_database_type = cdb
+    indexed = ${default_database_type}:${config_directory}/
+
+    # Expose origin host of mail from "root", ...
+    #
+    smtp_generic_maps = ${indexed}generic
+
+    # Send messages addressed to "root", ... to the MTA support team
+    #
+    virtual_alias_maps = ${indexed}virtual
+
+/etc/postfix/generic:
+    # The smarthost supports "+" addressing (recipient_delimiter = +).
+    # Mail from "root" exposes the origin host, without replies
+    # and bounces going back to the same host.
+    #
+    # On clustered MTAs this file is typically machine-built from
+    # a template file. The build process expands the template into
+    # "mtaadmin+root=mta1"
+    #
+    root       mtaadmin+root=mta1
+
+/etc/postfix/virtual:
+    # Caretaker aliases:
+    #
+    root       mtaadmin
+    postmaster root
+</pre>
+</blockquote>
+
+<p> You would typically also add a Makefile, to automatically run
+postmap(1) commands when source files change. This Makefile also
+creates a "generic" database when none exists. </p>
+
+<blockquote>
+<pre>
+/etc/postfix/Makefile:
+    MTAADMIN=mtaadmin
+
+    all: virtual.cdb generic.cdb
+
+    generic: Makefile
+           @echo Creating $@
+           @rm -f $@.tmp
+           @printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` &gt; $@.tmp
+           @mv $@.tmp generic
+
+    %.cdb: %
+           postmap cdb:$&lt;
+</pre>
+</blockquote>
+
+<p> Construct the "virtual" and "generic" databases (the latter is
+created by running "make"), then start and test the null-client:
+</p>
+
+<blockquote>
+<pre>
+# cd /etc/postfix; make
+# postfix start
+# sendmail -i -f root -t &lt;&lt;EOF
+From: root
+To: root
+Subject: test
+
+testing
+EOF
+</pre>
+</blockquote>
+
+<p> The test message should be delivered the members of the "mtaadmin"
+address group (or whatever address group you choose) with the
+following headers: </p>
+
+<blockquote>
+<pre>
+From: mtaadmin+root=mta1@example.com
+To: mtadmin+root=mta1@example.com
+Subject: test
+</pre>
+</blockquote>
+
+<h3>Setting up the "output" Postfix instance </h3>
+
+<p> With the null-client instance out of the way, we can create the
+MTA "output" instance that will deliver filtered mail to the inside
+network. We add the "output" instance first, because the output
+instance needs to be up and running before the input instance can
+be fully tested, and when the system boots, the "output" instance
+must start before the input instance. We will put the output and
+input instances into a single instance group named "mta".  </p>
+
+<p> Just once, when adding the first secondary instance, enable
+multi-instance support in the default (null-client) instance: </p>
+
+<blockquote>
+<pre>
+# postmulti -e init
+</pre>
+</blockquote>
+
+<p> Then create the output instance: <p>
+
+<blockquote>
+<pre>
+# postmulti -I postfix-out -G mta -e create
+</pre>
+</blockquote>
+
+<p> The instance configuration directory defaults to /etc/postfix-out,
+more precisely, the "postfix-out" subdirectory of the parent directory
+of the default-instance configuration directory. The new instance will
+be created in a "disabled" state: </p>
+
+<blockquote>
+<pre>
+/etc/postfix-out/main.cf
+    #
+    # ... "stock" main.cf settings ...
+    #
+    multi_instance_name = postfix-out
+    queue_directory = /var/spool/postfix-out
+    data_directory = /var/lib/postfix-out
+    #
+    multi_instance_enable = no
+    master_service_disable = inet
+    authorized_submit_users =
+</pre>
+</blockquote>
+
+<p> This instance has a "stock" master.cf file, and its queue and
+data directories, also named "postfix-out", will be located in the
+same parent directories as the corresponding directories of the
+default instance (e.g., /var/spool/postfix-out and /var/lib/postfix-out).
+</p>
+
+<p> While this instance is immediately safe to start, it is not yet
+usefully configured. It needs to be customized to fit the role of a
+post-filter re-injection SMTP service. Typical additions include: </p>
+
+<blockquote>
+<pre>
+/etc/postfix-out/master.cf:
+    # Replace default "smtp inet" entry with one listening on port 10026.
+    127.0.0.1:10026     inet  n       -       n       -       -       smtpd
+
+/etc/postfix-out/main.cf
+    # ...
+
+    # Comment out if you don't use IPv6 internally
+    # inet_protocols = ipv4
+    inet_interfaces = loopback-only
+    mynetworks_style = host
+    smtpd_authorized_xforward_hosts = $mynetworks
+
+    # Don't anvil(8) control the re-injection port.
+    #
+    smtpd_client_connection_count_limit = 0
+    smtpd_client_event_limit_exceptions = $mynetworks
+
+    # Best practice when inet_interfaces is set, as this is not a
+    # "secondary IP personality" configuration.
+    #
+    smtp_bind_address = 0.0.0.0
+
+    # All header rewriting happens upstream
+    #
+    local_header_rewrite_clients =
+
+    # No local delivery on border gateway
+    #
+    mydestination =
+    alias_maps =
+    alias_database =
+    local_recipient_maps =
+    local_transport = error:5.1.1 Mailbox unavailable
+
+    # May need a recipient_delimiter for per-user transport lookups:
+    #
+    recipient_delimiter = +
+
+    # Only one (unrestricted client)
+    # With multiple instances, rarely need "-o param=value" overrides
+    # in master.cf, each instance gets its own main.cf file.
+    #
+    smtpd_recipient_restrictions = permit_mynetworks, reject
+
+    # Tolerate occasional high latency in the  content filter.
+    #
+    smtpd_timeout = 1200s
+
+    # Best when empty, with all parent domain matches explicit.
+    #
+    parent_domain_matches_subdomains =
+
+    # Use the "relay" transport for inbound mail, and the default
+    # "smtp" transport for outbound mail (bounces, ...). The latter
+    # won't starve the former of delivery agent slots.
+    #
+    relay_domains = example.com, .example.com
+
+    # With xforward, match the input instance setting, if you
+    # want "yes", set both to "yes".
+    #
+    smtpd_client_port_logging = no
+
+    # Transport settings ...
+    # Message size limit
+    # Concurrency tuning for "relay" and "smtp" transport
+    # ...
+</pre>
+</blockquote>
+
+<p> With the "output" configuration in place, enable and start the
+instance: </p>
+
+<blockquote>
+<pre>
+1 # postmulti -i postfix-out -x postconf -e \
+2     "master_service_disable =" "authorized_submit_users = root"
+3 # postmulti -i postfix-out -e enable
+4 # postmulti -i postfix-out -p start
+</pre>
+</blockquote>
+
+<p> This uses the postmulti(1) command to invoke postconf(1) in the
+context (MAIL_CONFIG=/etc/postfix-out) of the output instance.  </p>
+
+<ul>
+
+<li> <p> Lines 1-2: With "authorized_submit_users = root", the
+superuser can test the postix-out instance with "postmulti -i
+postfix-out -x sendmail -bv recipient...", but otherwise local
+submission remains disabled.  </p>
+
+<li> <p> Lines 1-2: With "master_service_disable =", the "inet"
+listeners are re-enabled. </p>
+
+<li> <p> Line 3: The output instance is enabled for multi-instance
+start/stop. </p>
+
+<li> <p> Line 4: The output instance is started. </p>
+
+</ul>
+
+<p> Test the output instance by submitting probe messages via "sendmail
+-bv" and "telnet". For production systems, in-depth configuration tests
+should be done on a lab system. The simple tests just suggested will only
+confirm successful deployment of a configuration that should already be
+known good. </p>
+
+<h3> Setting up the content-filter proxy </h3>
+
+<p> With the output instance ready, deploy your content-filter
+proxy.  Most proxies will need their own /etc/rc* start/stop script.
+Some proxies, however, are started on demand by the Postfix spawn(8)
+service, in which case you need to add the relevant spawn(8) entry
+to the output instance master.cf file.  </p>
+
+<p> Configure the proxy to listen on 127.0.0.1:10025 and to re-inject
+filtered email to 127.0.0.1:10026.  Start the proxy service if
+necessary, then test the proxy via "telnet" or automated SMTP
+injectors. The proxy should support the following ESMTP features:
+DSN, 8BITMIME, and XFORWARD. In addition, the proxy should support
+multiple mail deliveries within an SMTP session. </p>
+
+<h3> Setting up the input Postfix instance </h3>
+
+<p> The input Postfix instance receives mail from the network and
+sends it through the content filter. Now we create the input instance,
+also part of the "mta" instance group: </p>
+
+<blockquote>
+<pre>
+# postmulti -I postfix-in -G mta -e create
+</pre>
+</blockquote>
+
+<p> The new instance configuration directory defaults to /etc/postfix-in,
+more precisely, the "postfix-in" subdirectory of the parent directory
+of the default-instance configuration directory. The new instance will
+be created in a "disabled" state: </p>
+
+<blockquote>
+<pre>
+/etc/postfix-in/main.cf
+    #
+    # ... "stock" main.cf settings ...
+    #
+    multi_instance_name = postfix-in
+    queue_directory = /var/spool/postfix-in
+    data_directory = /var/lib/postfix-in
+    #
+    multi_instance_enable = no
+    master_service_disable = inet
+    authorized_submit_users =
+</pre>
+</blockquote>
+
+<p> As before, make appropriate changes to main.cf and master.cf to
+make the instance production ready. Consider setting "soft_bounce = yes"
+during the first few hours of deployment, so you can iron-out any unexpected
+"kinks". </p>
+
+<p> Manual testing can start with:
+
+<blockquote>
+<pre>
+/etc/postfix-in/main.cf
+    # Accept only local traffic, but allow impersonation:
+    inet_interfaces = 127.0.0.1
+    smtpd_authorized_xclient_hosts = 127.0.0.1
+</pre>
+</blockquote>
+
+<p> This allows you to use the Postfix-specific <a
+href="XCLIENT_README.html">XCLIENT</a> SMTP command to safely
+simulate connections from remote systems before any remote systems
+are able to connect. If the test results look good, revert the above
+settings to the required production values. Typical settings in the
+pre-filter input instance include: </p>
+
+<blockquote>
+<pre>
+/etc/postfix-in/main.cf
+    #
+    # ... 
+    #
+
+    # No local delivery on border gateway
+    #
+    mydestination =
+    alias_maps =
+    alias_database =
+    local_recipient_maps =
+    local_transport = error:5.1.1 Mailbox unavailable
+
+    # Don't rewrite remote headers
+    #
+    local_header_rewrite_clients =
+
+    # All recipients of not yet filtered email go to the same filter together.
+    #
+    # With multiple instances, the content-filter is specified
+    # via transport settings not the "content_filter" transport
+    # switch override! Here the filter listens on local port 10025.
+    #
+    # If you need to route some users or recipient domains directly to the
+    # output instance bypassing the filter, just define a transport table
+    # with suitable entries.
+    #
+    default_transport = smtp:[127.0.0.1]:10025
+    relay_transport = $default_transport
+    virtual_transport = $default_transport
+    transport_maps =
+
+    # Pass original client log information through the filter.
+    #
+    smtp_send_xforward_command = yes
+
+    # Avoid splitting the envelope and scanning messages multiple times.
+    # Match the re-injection server's recipient limit.
+    #
+       smtp_destination_recipient_limit = 1000
+
+    # Tolerate occasional high latency in the content filter.
+    #
+    smtp_data_done_timeout = 1200s
+
+    # With xforward, match the output instance setting, if you
+    # want "yes", set both to "yes".
+    #
+    smtpd_client_port_logging = no
+
+    # ... Lots of settings for inbound MX host ...
+</pre>
+</blockquote>
+
+<p> With the "input" instance configured, enable and start it: </p>
+
+<blockquote>
+<pre>
+# postmulti -i postfix-in -x postconf -e \
+    "master_service_disable =" "authorized_submit_users = root"
+# postmulti -i postfix-in -e enable
+# postmulti -i postfix-in -p start
+</pre>
+</blockquote>
+
+<p> That's it. You now have a 3-instance configuration. A null-client
+sending all locally submitted mail to the internal mail hub and a pair of
+"mta" instances that receive mail from the Internet, pass it through a
+content-filter, and then deliver it to the internal destination. </p>
+
+<p> Running "postfix start" or "postfix stop" will now start/stop all
+three Postfix instances. You can use "postfix -c /config/path start"
+to start just one instance, or use the instance name (or instance
+group name) via postmulti(1): </p>
+
+<blockquote>
+<pre>
+# postmulti -i - -p stop
+# postmulti -g mta -p status
+# postmulti -i postfix-out -p flush
+# postmulti -i postfix-in -p reload
+# ...
+</pre>
+</blockquote>
+
+<p> This example ends the multi-instance "walk through". The remainder
+of this document provides background information on Postfix
+multi-instance support features and options. </p>
+
+<h2><a name="parts"> Components of a Postfix system </a></h2>
+
+<p> A Postfix system consists of the following components: </p>
+
+<p> Shared among all instances: </p>
+
+<ul>
+
+<li><p> Command-line utilities for administrators and users installed in
+$command_directory, $sendmail_path, $mailq_path and $newaliases_path. </p>
+
+<li><p> Daemon executables, and run-time support files installed in
+$daemon_directory. </p>
+
+<li><p> Bundled documentation, installed in $html_directory,
+$manpage_directory and $readme_directory. </p>
+
+<li><p> Entries in /etc/passwd and /etc/group for the $mail_owner user and
+$setgid_group group. The the $mail_owner user provides the mail system
+with a protected (non-root) execution context. The $setgid_group group
+is used exclusively to support the setgid postdrop(1) and postqueue(1)
+utilities (it <b>must not</b> be the primary group or secondary group
+of any users, including the $mail_owner user). </p>
+
+</ul>
+
+<p> Private to each instance: </p>
+
+<ul>
+
+<li><p> The main.cf, master.cf (and other optional) configuration
+files in $config_directory. </p>
+
+<li> <p> The maildrop, incoming, active, deferred and hold queues
+in $queue_directory (which contains additional directories needed
+by Postfix, and which optionally doubles as a chroot jail for Postfix
+daemon processes). </p>
+
+<li> <p> Various caches (TLS session, address verification, ...)
+in $data_directory. </p>
+
+</ul>
+
+<p> The Postfix configuration parameters mentioned above are
+collectively referred to as "installation parameters". Their default
+values are set when the Postfix software is built from source, and
+all but one may be optionally set to a non-default value via the
+main.cf file.  The one parameter that (catch-22) cannot be set in
+main.cf is $config_directory, as this defines the location of the
+main.cf file itself. </p>
+
+<p> Though config_directory cannot be set in main.cf, postfix(1) and
+most of the other command-line Postfix utilities allow you to specify a
+non-default configuration directory via a command line option (typically
+<b>-c</b>) or via the MAIL_CONFIG environment variable. In this way,
+it is possible to have multiple configuration directories on the same
+machine, and to have multiple running master(8) daemons each with its
+own configuration files, queue directory and data directory. </p>
+
+<p> These multiple running copies of master(8) share the base Postfix
+software. They do not (and cannot) share their configuration
+directories, queue directories or data directories. </p>
+
+<p> Each combination of configuration directory, together with the queue
+directory and data directory (specified in the corresponding main.cf file)
+make up a Postfix <b>instance</b>. </p>
+
+<h2><a name="default"> The default Postfix instance </a></h2>
+
+<p> One Postfix instance is special: this is the instance whose
+configuration directory is the default one compiled into the Postfix
+utilities. The location of the default configuration directory is
+typically /etc/postfix, and can be queried via the "postconf -d
+config_directory" command.  We call the instance with this configuration
+directory the "default instance". </p>
+
+<p> The default instance is responsible for local mail submission. The
+setgid postdrop(1) utility is used by the sendmail(1) local submission
+program to spool messages into the <b>maildrop</b> sub-directory of the
+queue directory of the default instance. </p>
+
+<p> Even in the rare case when "sendmail -C" is used to submit local mail
+into a non-default Postfix instance, for security reasons, postdrop(1)
+will consult the default main.cf file to check the validity of the
+requested non-default configuration directory. </p>
+
+<p> So, while in most other respects, all instances are equal, the
+default instance is "more equal than others". You may choose to create
+additional instances, but you must have at least the default instance,
+with its configuration directory in the default compiled-in location. </p>
+
+<h2><a name="group"> Instance groups </a></h2>
+
+<p> The postmulti(1) multi-instance manager supports the notion of an
+instance "group". Typically, the member instances of an instance group
+constitute a logical service, and are expected to all be running or all
+be stopped. </p>
+
+<p> In many cases a single Postfix instance will be a complete logical
+"service". You should define such instances as stand-alone instances
+that are not members of any instance "group". The null-client
+instance is an example of a non-group instance. </p>
+
+<p> When a logical service consists of multiple Postfix instances,
+often a pair of pre-filter and post-filter instances with a content
+filter proxy between them, the related instances should be members
+of a single instance group (however, the content filter usually has
+its own start/stop procedure that is separate from any Postfix
+instance).  </p>
+
+<p> The default instance main.cf file's $multi_instance_directories
+configuration parameter lists the configuration directories of all
+secondary (non-default) instances. Together with the default instance,
+these secondary instances are managed by the multi-instance manager.
+Instances are started in the order listed, and stopped in the
+opposite order. For instances that are members of a service "group",
+you should arrange to start the service back-to-front, with the
+output stages started and ready to receive mail before the input
+stages are started. </p>
+
+<h2><a name="params"> Multi-instance configuration parameters </a></h2>
+
+<dl>
+
+<dt> multi_instance_wrapper </dt> 
+
+<dd> <p> This default-instance configuration parameter must be set
+to a suitable multi-instance manager's "wrapper" program that
+controls the starting, stopping, etc. of a multi-instance Postfix
+system. To use the postmulti(1) manager described in this document,
+this parameter should be set with the "<a href="#init">postmulti
+-e init</a>" command.  </p> </dd>
+
+<dt> multi_instance_directories </dt>
+
+<dd> <p> This default-instance configuration parameter specifies
+an optional list of the secondary instances controlled via the
+multi-instance manager. Instances are listed in their "start" order,
+with the default instance always started first (if enabled). If
+$multi_instance_directories is left empty, the postfix(1) command
+runs with multi-instance support turned off, and none of the
+multi_instance_ configuration parameters will have any effect. </p>
+
+<p> Do not assign a non-empty list of secondary instance configuration
+directories to multi_instance_directories until you have configured a
+suitable multi_instance_wrapper setting! This is best accomplished via
+the "<a href="#init">postmulti -e init</a>" command.
+</p> </dd>
+
+<dt> multi_instance_name </dt>
+
+<dd> <p> Each Postfix instance may be assigned a distinct name (with
+"postfix -e create/import/assign -I <i>name</i>..."). This name can
+be used with the postmulti(1) command-line utility to perform tasks
+on the instance by name (rather than the full pathname of its
+configuration directory). Choose a name that concisely captures the
+role of the instance (it must start with "postfix-").  It is an
+error for two instances to have the same $multi_instance_name.  You
+can leave an instance "nameless" by leaving this parameter at the
+default empty setting. </p>
+
+<p> To avoid confusion in your logs, if you don't assign each
+secondary instance a non-empty (distinct) $multi_instance_name, you
+should make sure that the $syslog_name setting is different for
+each instance. The $syslog_name parameter defaults to $multi_instance_name
+when the latter is non-empty. If at all possible, the syslog_name
+should start with "postfix-", this helps log parsers to identify
+log entries from secondary Postfix instances.  </p> </dd>
+
+<dt> multi_instance_group </dt>
+
+<dd> <p> Each Postfix instance may be assigned an "instance group"
+name (with "postfix -e create/import/assign -G <i>name</i>...").
+The default (empty) value of multi_instance_group parameter indicates
+a stand-alone instance that is not part of any group. The group
+name can be used with the postmulti(1) command-line utility to
+perform a task on the members of a group by name. Choose a single-word
+group name that concisely captures the role of the group.  </p>
+</dd>
+
+<dt> multi_instance_enable </dt>
+
+<dd> <p> This parameter controls whether a Postfix instance will
+be started by a Postfix multi-instance manager.  The default value
+is "no". The instance can be started explicitly with "postfix -c
+/path/to/config/directory"; this is useful for testing.  </p>
+
+<p> When an instance is disabled, the postfix(1) "start" command
+is replaced by "check". </p>
+
+<p> Some postfix(1) commands (such as "stop", "flush", ...) require
+a running Postfix instance, and skip instances that are disabled.
+</p>
+
+<p> Other postfix(1) commands (such as "status", "set-permissions",
+"upgrade-configuration", ...) do not require a running Postfix
+system, and apply to all instances whether enabled or not.  </p>
+</dd>
+
+</dl>
+
+<p> The postmulti(1) utility can be used to create (or destroy) instances.
+It can also be used to "import" or "deport" existing instances into or
+from the list of managed instances. When using postmulti(1) to manage
+instances, the above configuration parameters are managed for you
+automatically. See below. </p>
+
+<h2><a name="how"> Using the postmulti(1) command </a></h2>
+
+<ul>
+
+<li><a href="#init"> Initializing the multi-instance manager </a>
+
+<li><a href="#list"> Listing managed instances </a>
+
+<li><a href="#start"> Starting or stopping a multi-instance system </a>
+
+<li><a href="#adhoc"> Ad-hoc multi-instance operations </a>
+
+<li><a href="#create"> Creating a new Postfix instance </a>
+
+<li><a href="#destroy"> Destroying a Postfix instance </a>
+
+<li><a href="#import"> Importing an existing Postfix instance </a>
+
+<li><a href="#deport"> Deporting a managed Postfix instance </a>
+
+<li><a href="#assign"> Assigning a new name or group name </a>
+
+<li><a href="#enable"> Enabling/disabling managed instances </a>
+
+</ul>
+
+<h3><a name="init"> Initializing the multi-instance manager </a></h3>
+
+<p> Before postmulti(1) is used for the first time, you must install
+it as the multi_instance_wrapper for your Postfix system and enable
+multi-instance operation of the default Postfix instance. You can then
+proceed to add <a href="#create">new</a> or <a href="#import">existing</a>
+instances to the multi-instance configuration. This initial installation
+is accomplished as follows: </p>
+
+<blockquote>
+<pre>
+    # postmulti -e init
+</pre>
+</blockquote>
+
+<p> This updates the default instance main.cf file as follows: </p>
+
+<blockquote>
+<pre>
+    # Use postmulti(1) as a postfix-wrapper(5)
+    #
+    multi_instance_wrapper = ${command_directory}/postmulti -p --
+
+    # Configure the default instance to start when in multi-instance mode
+    #
+    multi_instance_enable = yes
+</pre>
+</blockquote>
+
+<p> If you prefer, you can make these changes by editing the default
+main.cf directly, or by using "postconf -e". </p>
+
+<h3><a name="list"> Listing managed instances </a></h3>
+
+<p> The list of managed instances consists of the default instance and
+the additional instances whose configuration directories are listed
+(in start order) under the multi_instance_directories parameter of the
+default main.cf configuration file.  </p>
+
+<p> You can list selected instances, groups of instances or all
+instances by specifying only the instance matching options with the
+"-l" option.  The "-a" option is assumed if no other instance
+selection options are specified (this behavior changes with the
+"-e" option).  As a special case, even if it has an explicit name,
+the default instance can always be selected via "-i -". </p>
+
+<blockquote>
+<pre>
+# postmulti -l -a
+# postmulti -l -g a_group
+# postmulti -l -i an_instance
+</pre>
+</blockquote>
+
+<p> The output is one line per instance (in "postfix start" order):
+</p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th align="left">name</th> <th align="left">group</th> <th
+align="left">enabled</th> <th align="left">config_directory</th>
+</tr>
+
+<tr> <td>-</td> <td>-</td> <td>yes</td> <td>/etc/postfix
+
+<tr> <td>mta-out</td> <td>mta</td> <td>yes</td> <td>/etc/postfix/mta-out
+
+<tr> <td>mta-in</td> <td>mta</td> <td>yes</td> <td>/etc/postfix-mta-in
+
+<tr> <td>msa-out</td> <td>msa</td> <td>yes</td> <td>/etc/postfix-msa-out
+
+<tr> <td>msa-in</td> <td>msa</td> <td>yes</td> <td>/etc/postfix-msa-in
+
+<tr> <td>test</td> <td>-</td> <td>no</td> <td>/etc/postfix-test
+
+</table>
+
+</blockquote>
+
+<p> The first line showing the column headings is not part of the
+output. When either the instance name or the instance group is not
+set, it is shown as a "-". </p>
+
+<p> When selecting an existing instance via the "-i" option, you
+can always use the full pathname of its configuration directory
+instead of the instance (short) name. This is the only way to select
+a non-default nameless instance. The default instance can be selected
+via "-i -", whether it has a name or not. </p>
+
+<p> To list instances in reverse start order, include the "-R"
+option together with the instance selection options. </p>
+
+<h3><a name="start"> Starting or stopping a multi-instance system
+</a></h3>
+
+<p> To start, stop, reload, etc. the complete (already configured as
+above) multi-instance system just use postfix(1) as you would with a
+single-instance system. The Postfix multi-instance wrapper framework
+insulates Postfix init.d start and package upgrade scripts from the
+details of multi-instance management! </p>
+
+<p> The <b>-p</b> option of postmulti(1) turns on postfix(1) compatibility
+mode. With this option the remaining arguments are exactly those supported
+by postfix(1), but commands are applied to all instances or all enabled
+instances as appropriate. As described above, this switch is required
+when using postmulti(1) as the multi_instance_wrapper. </p>
+
+<p> If you want to specify a subset of instances by name, or group name,
+or run arbitrary commands (not just "postfix stop/start/etc. in the
+context (MAIL_CONFIG environment variable setting) of a particular
+instance or group of instances, then you can use the instance-aware
+postmulti(1) utility directly. </p>
+
+<h3><a name="adhoc"> Ad-hoc multi-instance operations </a></h3>
+
+<p> The postmulti(1) command can be used by the administrator to run arbitrary
+commands in the context of one or more Postfix instances. The most common
+use-case is stopping or starting a group of Postfix instances: </p>
+
+<blockquote>
+<pre>
+# postmulti -g mygroup -p start
+# postmulti -g mygroup -p flush
+# postmulti -g mygroup -p reload
+# postmulti -g mygroup -p status
+# postmulti -g mygroup -p stop
+# postmulti -g mygroup -p upgrade-configuration
+</pre>
+</blockquote>
+
+<p> The <b>-p</b> option is essentially a short-hand for a leading
+<b>postfix</b> command argument, but with appropriate additional options
+turned on depending on the first argument. In the case of "start",
+disabled instances are "checked" (postfix check) rather than simply
+skipped. </p>
+
+<p> The resulting command is executed for each candidate instance with
+the <b>MAIL_CONFIG</b> environment variable set to the configuration
+directory of the corresponding Postfix instance. </p>
+
+<p> The postmulti(1) utility is able to launch commands other than
+postfix(1), Use the <b>-x</b> option to ask postmulti to execute an
+ad-hoc command for all instances, a group of instances, or just one
+instance. With ad-hoc commands the multi_instance_enable parameter
+is ignored: the command is unconditionally executed for the instances
+selected via -a, -g or -i. In addition to MAIL_CONFIG, the following
+instance parameters are exported into the command environment: </p>
+
+<blockquote>
+<pre>
+command_directory=$command_directory
+daemon_directory=$daemon_directory
+config_directory=$config_directory
+queue_directory=$queue_directory
+data_directory=$data_directory
+multi_instance_name=$multi_instance_name
+multi_instance_group=$multi_instance_group
+multi_instance_enable=$multi_instance_enable
+</pre>
+</blockquote>
+
+<p> The config_directory setting is of course the same as MAIL_CONFIG,
+and is arguably redundant, but leaving it in is less surprising. If
+you want to skip disabled instances, just check multi_instance_enable
+environment variable and exit if it is set to "no". </p>
+
+<p> The ability to run ad-hoc commands opens up a wealth of additional
+possibilities: </p>
+
+<ul>
+
+<li><p> Specify an instance by name rather than configuration directory
+when using sendmail(1) to send a verification probe: </p>
+
+<blockquote>
+<pre>
+$ postmulti -i postfix-myinst -x sendmail -bv test@example.net
+</pre>
+</blockquote>
+
+<li><p> Display non-default main.cf settings of all Postfix instances.
+This uses an inline shell script to package together multiple shell
+commands to execute for each instance: </p>
+
+<blockquote>
+<pre>
+$ postmulti -x sh -c 'echo "-- $MAIL_CONFIG"; postconf -n'
+</pre>
+</blockquote>
+
+<li><p> Put all mail in enabled member instances of a group on hold: </p>
+
+<blockquote>
+<pre>
+# postmulti -g group_name -x \
+    sh -c 'test $multi_instance_enable = yes &amp;&amp; postsuper -h ALL'
+</pre>
+</blockquote>
+
+<li><p> Show top 10 domains in the deferred queue of all instances:
+</p>
+
+<blockquote>
+<pre>
+# postmulti -x sh -c 'echo "-- $MAIL_CONFIG"; qshape deferred | head -12'
+</pre>
+</blockquote>
+
+</ul>
+
+<h3><a name="create"> Creating a new Postfix instance </a></h3>
+
+<p> The postmulti(1) command can be used to create additional Postfix
+instances. New instances are created with local submission and all "inet"
+services disabled via the following non-default parameter settings in
+the main.cf file: </p>
+
+<blockquote>
+<pre>
+authorized_submit_users =
+master_service_disable = inet
+</pre>
+</blockquote>
+
+<p> The above settings ensure that new instances are safe to start
+immediately: they will not conflict with inet listeners in existing
+Postfix instances.  They will also not accept any mail until they are
+fully configured, at which point you can do away with one or both of
+the above safety measures. </p>
+
+<p> The postmulti(1) command encourages a preferred way of organizing
+the configuration directories, queue directories and data directories
+of non-default instances. If the default instance settings are: </p>
+
+<blockquote>
+<pre>
+config_directory = /conf-path/postfix
+queue_directory = /queue-path/postfix
+data_directory = /data-path/postfix
+</pre>
+</blockquote>
+
+<p> A newly-created instance named <i>postfix-myinst</i> will by default
+have: </p>
+
+<blockquote>
+<pre>
+multi_instance_enable = no
+multi_instance_name = postfix-myinst
+config_directory = /conf-path/postfix-myinst
+queue_directory = /queue-path/postfix-myinst
+data_directory = /data-path/postfix-myinst
+</pre>
+</blockquote>
+
+<p> You can override any of these defaults when creating the instance,
+but unless you want to spread instance queue directories over multiple
+file-systems, use the default naming strategy. It keeps the multiple
+instances organized in a uniform, predictable fashion. </p>
+
+<p> When specifying the instance name later, you can refer to it
+either as "postfix-myinst", or via the full path of the configuration
+directory. </p>
+
+<p> To create a new instance just use the <b>-e create</b> option: </p>
+
+<blockquote>
+<pre>
+# postmulti -I postfix-myinst -e create
+</pre>
+</blockquote>
+
+<p> If the new instance is to belong to a group of related instances that
+implement a single logical service, assign it to a group: </p>
+
+<blockquote>
+<pre>
+# postmulti -I postfix-myinst -G mygroup -e create
+</pre>
+</blockquote>
+
+<p> If you want to override the conventional values of the instance
+installation parameters, specify their values on the command-line: </p>
+
+<blockquote>
+<pre>
+# postmulti [-I postfix-myinst] [-G mygroup] -e create \
+       "config_directory = /path/to/config_directory" \
+       "queue_directory = /path/to/queue_directory" \
+       "data_directory = /path/to/data_directory"
+</pre>
+</blockquote>
+
+<p> A note on the <b>-I</b> and <b>-G</b> options above. These are always
+used to assign a name or group name to an instance, while the <b>-i</b>
+and <b>-g</b> options always select existing instances.  By default,
+the configuration directories of newly managed instances are appended
+to the instance list. You can use the "-i" or "-g" or "-a" options to
+insert the new instance before the specified instance or group, or at
+the beginning of the instance list (multi_instance_directories parameter
+of the default instance). </p>
+
+<p> If you do specify a name (use "-I" with a name that is not "-")
+for the new instance, you may omit any of the 3 instance installation
+parameters whose instance-name based value is acceptable. Otherwise, all
+three instance installation parameters are required. You should set the
+"syslog_name" explicitly in the main.cf file of a "nameless" instance,
+in order to avoid confusion in the mail logs when multiple instances
+are in use. </p>
+
+<h3><a name="destroy"> Destroying a Postfix instance </a></h3>
+
+<p> If you no longer need an instance, you can destroy it via: </p>
+
+<blockquote>
+<pre>
+# postmulti -i postfix-myinst -p stop
+# postmulti -i postfix-myinst -e disable
+# postmulti -i postfix-myinst -e destroy
+</pre>
+</blockquote>
+
+<p> The instance must be stopped, disabled and have no queued messages.
+This is expected to fully delete a just created instance that has never
+been used. If the instance is not freshly created, files added after
+the instance was created will remain in the configuration, queue or
+data directories, in which case the corresponding directory may not
+be fully removed and a warning to that effect will be displayed. You
+can complete the destruction of the instance manually by removing any
+unwanted remnants of the instance-specific "private" directories. </p>
+
+<h3><a name="import"> Importing an existing Postfix instance </a></h3>
+
+<p> If you already have an existing secondary Postfix instance that is
+not yet managed via postmulti(1), you can "import" it into the list
+of managed instances. If your instance is already using the default
+configuration directory naming scheme, just specify the corresponding
+instance name (the multi_instance_name parameter in its configuration
+file will be adjusted to match this name if necessary): </p>
+
+<blockquote>
+<pre>
+# postmulti -I postfix-myinst [-G mygroup] -e import
+</pre>
+</blockquote>
+
+<p> Otherwise, you must specify the location of its configuration
+directory: </p>
+
+<blockquote>
+<pre>
+# postmulti [-I postfix-myinst] [-G mygroup] -e import \
+       "config_directory = /path/of/config_directory"
+</pre>
+</blockquote>
+
+<p> When the instance is imported, you can assign a name or a group. As
+with <a href="#create">"create"</a>, you can control the placement of the
+new instance in the start order by using "-i", "-g" or "-a" to prepend
+before the selected instance or instances. </p>
+
+<p> An imported instance is usually not multi-instance "enabled",
+unless it was part of a multi-instance configuration at an earlier
+time.  If it is fully configured and ready to run, don't forget
+to <a href="#enable">enable</a> it and if necessary start it. When
+other enabled instances are already running, new instances need to
+be started individually when they are first created or imported.
+</p>
+
+<p> To find out what instances are running, use: </p>
+
+<blockquote>
+<pre>
+# postfix status
+</pre>
+</blockquote>
+
+<h3><a name="deport"> Deporting a managed Postfix instance </a></h3>
+
+<p> You can "deport" an existing instance from the list of managed
+instances.  This does not destroy the instance, rather the instance
+just becomes a stand-alone Postfix instance not registered with the
+multi-instance manager. postmulti(1) will refuse to "deport" an
+instance that is not stopped and disabled. </p>
+
+<blockquote>
+<pre>
+# postmulti -i postfix-myinst -p stop
+# postmulti -i postfix-myinst -e disable
+# postmulti -i postfix-myinst -e deport
+</pre>
+</blockquote>
+
+<h3><a name="assign"> Assigning a new name or group name </a></h3>
+
+<p> You can assign a new name or new group to a managed instance.
+Use "-" as the new value to assign the instance to no group or make it
+nameless. To specify a nameless secondary instance use the configuration
+directory path instead of the old name: </p>
+
+<blockquote>
+<pre>
+# postmulti -i postfix-old [-I postfix-new] [-G newgroup] -e assign
+</pre>
+</blockquote>
+
+<h3><a name="enable"> Enabling/disabling managed instances </a></h3>
+
+<p> You can enable or disable a managed instance. As documented in
+postfix-wrapper(5), disabled instances are skipped with actions
+that <a href="postconf.5.html#postmulti_start_commands">start</a>,
+<a href="postconf.5.html#postmulti_start_commands">stop</a> or <a
+href="postconf.5.html#postmulti_control_commands">control</a> running
+Postfix instances. </p>
+
+<blockquote>
+<pre>
+# postmulti -i postfix-myinst -e enable
+# postmulti -i postfix-myinst -e disable
+</pre>
+</blockquote>
+
+<h2><a name="credits"> Credits </a></h2>
+
+<p> Wietse Venema created Postfix, designed and implemented the
+multi-instance wrapper framework and provided design feedback that made
+the postmulti(1) utility much more general and useful than originally
+envisioned. </p>
+
+<p> The postmulti(1) utility was developed by Victor Duchovni of Morgan
+Stanley, who also wrote the initial version of this document. </p>
+
+</body> </html>
index 9b1398ce61a0acd84a4485234b46a97a297f811f..886e7fc8b51bcd1dcaa7b8e41eae1489806c2324 100644 (file)
@@ -24,6 +24,7 @@ HTML  = ../html/ADDRESS_CLASS_README.html \
        ../html/LINUX_README.html \
        ../html/LOCAL_RECIPIENT_README.html ../html/MAILDROP_README.html \
        ../html/MILTER_README.html \
+       ../html/MULTI_INSTANCE_README.html \
        ../html/MYSQL_README.html ../html/NFS_README.html \
        ../html/OVERVIEW.html \
        ../html/PACKAGE_README.html ../html/PCRE_README.html \
@@ -61,6 +62,7 @@ README        = ../README_FILES/ADDRESS_CLASS_README \
        ../README_FILES/LINUX_README \
        ../README_FILES/LOCAL_RECIPIENT_README ../README_FILES/MAILDROP_README \
        ../README_FILES/MILTER_README \
+       ../README_FILES/MULTI_INSTANCE_README \
        ../README_FILES/MYSQL_README ../README_FILES/NFS_README \
        ../README_FILES/OVERVIEW \
        ../README_FILES/PACKAGE_README ../README_FILES/PCRE_README \
@@ -196,6 +198,9 @@ clobber:
 ../html/MILTER_README.html: MILTER_README.html
        $(POSTLINK) $? >$@
 
+../html/MULTI_INSTANCE_README.html: MULTI_INSTANCE_README.html
+       $(POSTLINK) $? >$@
+
 ../html/MYSQL_README.html: MYSQL_README.html
        $(POSTLINK) $? >$@
 
@@ -343,6 +348,9 @@ clobber:
 ../README_FILES/MILTER_README: MILTER_README.html
        $(HT2READ) $? >$@
 
+../README_FILES/MULTI_INSTANCE_README: MULTI_INSTANCE_README.html
+       $(HT2READ) $? >$@
+
 ../README_FILES/MYSQL_README: MYSQL_README.html
        $(HT2READ) $? >$@
 
index 6e25b064d23671c93b75d98a17c4a861ce21afcd..ac8bbd47615c23afbdc89910d5f33bbd3251c170 100644 (file)
@@ -728,6 +728,11 @@ for shell scripts. </p>
 such as canonical(5), virtual(5) and others. It is a cousin of the
 UNIX makemap command. </p>
 
+<li> <p> The postmulti(1) command repeats the "postfix start" etc.
+command for each Postfix instance, and supports creation, deletion
+etc. of Postfix instances. For a tutorial, see MULTI_INSTANCE_README.
+</p>
+
 <li> <p> The postqueue(1) command is the privileged command that
 is run by Postfix sendmail(1) and mailq(1) in order to flush or
 list the
index ff5b64f56db79b6803f466f62d802e8924300562..4edc339f18c344117b68414edfed712e43d14c22 100644 (file)
@@ -111,7 +111,7 @@ their default settings. </p>
 1 /etc/postfix/main.cf:
 2     myorigin = $mydomain
 3     relayhost = $mydomain
-4     inet_interfaces = 127.0.0.1
+4     inet_interfaces = loopback-only
 5     local_transport = error:local delivery is disabled
 6 
 7 /etc/postfix/master.cf:
index 32744ffd2cc046524aa0f24ffc3630b68bb07d2d..6df8cb6623ddb1ca9ad9d59c723a5377a24dac2b 100644 (file)
@@ -226,10 +226,11 @@ clients get a chance to talk to Postfix.  </p>
 
 <ul>
 
-<li> <p> Use "421" reply codes for botnet-related RBLs or for
-selected non-RBL restrictions. This causes Postfix 2.3 and later
-to disconnect immediately without waiting for the remote SMTP
-client to send a QUIT command. </p>
+<li> <p> Use "521" reply codes (Postfix 2.6 and later) for
+botnet-related RBLs or for selected non-RBL restrictions. With
+Postfix 2.3-2.5 use "421" for a similar result. The Postfix SMTP
+server will disconnect immediately without waiting for the remote
+SMTP client to send a QUIT command. </p>
 
 <p> You can set individual reject codes for RBLs, and for individual
 responses from a specific RBL. We'll use zen.spamhaus.org as an
@@ -237,7 +238,7 @@ example; by the time you read this document, details may have
 changed.  Right now, their documents say that a response of 127.0.0.10
 or 127.0.0.11 indicates a dynamic client IP address, which means
 that the machine is probably running a bot of some kind.  To give
-a 421 response instead of the default 554 response, use something
+a 521 response instead of the default 554 response, use something
 like: </p>
 
 <pre>
@@ -251,11 +252,11 @@ like: </p>
  8      rbl_reply_maps = hash:/etc/postfix/rbl_reply_maps
  9  
 10  /etc/postfix/rbl_reply_maps:
-11      zen.spamhaus.org=127.0.0.10 421 4.7.1 Service unavailable;
+11      zen.spamhaus.org=127.0.0.10 521 4.7.1 Service unavailable;
 12       $rbl_class [$rbl_what] blocked using
 13       $rbl_domain${rbl_reason?; $rbl_reason}
 14  
-15      zen.spamhaus.org=127.0.0.11 421 4.7.1 Service unavailable;
+15      zen.spamhaus.org=127.0.0.11 521 4.7.1 Service unavailable;
 16       $rbl_class [$rbl_what] blocked using
 17       $rbl_domain${rbl_reason?; $rbl_reason}
 </pre>
@@ -264,7 +265,8 @@ like: </p>
 will still only do a single DNS query, so the performance difference
 is negligible. </p>
 
-<p> The down-side of sending 421 instead of the default 554 is that
+<p> With Postfix 2.3-2.5, use 421 (reply code 521 will not cause
+Postfix to disconnect). The down-side of sending 421 is that
 it works only for zombies and other malware. If the client is running
 a real MTA, then it may connect again several times until the mail
 expires in its queue. When this is a problem, stick with the default
index 628e4e61838e36dae09ec981a1cda2ded502e93d..5c55409e30cafb4c28afca86e81117497add70c8 100644 (file)
@@ -12065,11 +12065,16 @@ Postfix instance, and that are started, stopped, etc., together
 with the default Postfix instance.  Specify a list of pathnames
 separated by comma or whitespace.  </p>
 
-<p> When the list of non-default Postfix configuration directories
-is non-empty, the postfix(1) command will invoke the multi-instance
-manager specified with the multi_instance_wrapper parameter to
-execute commands on the default instance and on all additional
-Postfix instances.  </p>
+<p> When $multi_instance_directories is empty, the postfix(1) command
+runs in single-instance mode and operates on a single Postfix
+instance only. Otherwise, the postfix(1) command runs in multi-instance
+mode and invokes the multi-instance manager specified with the
+multi_instance_wrapper parameter. The multi-instance manager in
+turn executes postfix(1) commands for the default instance and for
+all Postfix instances in $multi_instance_directories.  </p>
+
+<p> Currently, this parameter setting is ignored except for the
+default main.cf file. </p>
 
 <p> This feature is available in Postfix 2.6 and later. </p>
 
@@ -12175,3 +12180,44 @@ for opportunities to reject mail, and defers the client request
 only if it would otherwise be accepted. </p>
 
 <p> This feature is available in Postfix 2.6 and later. </p>
+
+%PARAM postmulti_start_commands start
+
+<p> The postfix(1) commands that the postmulti(1) instance manager treats
+as "start" commands. For these commands, disabled instances are "checked"
+rather than "started", and failure to "start" a member instance of an
+instance group will abort the start-up of later instances. </p>
+
+<p> This feature is available in Postfix 2.6 and later. </p>
+
+%PARAM postmulti_stop_commands see "postconf -d" output
+
+<p> The postfix(1) commands that the postmulti(1) instance manager treats
+as "stop" commands. For these commands, disabled instances are skipped,
+and enabled instances are processed in reverse order. </p>
+
+<p> This feature is available in Postfix 2.6 and later. </p>
+
+%PARAM postmulti_control_commands reload flush
+
+<p> The postfix(1) commands that the postmulti(1) instance manager
+treats as "control" commands, that operate on running instances. For
+these commands, disabled instances are skipped. </p>
+
+<p> This feature is available in Postfix 2.6 and later. </p>
+
+%PARAM lmtp_assume_final no
+
+<p> When an LMTP server announces no DSN support, assume that the
+server performs final delivery, and send "delivered" delivery status
+notifications instead of "relayed". The default setting is backwards
+compatible to avoid the infinetisimal possibility of breaking
+existing LMTP-based content filters. </p>
+
+%PARAM always_add_missing_headers no
+
+<p> Always add (Resent-) From:, To:, Date: or Message-ID: headers
+when not present.  Postfix 2.6 and later add these headers only
+when clients match the local_header_rewrite_clients parameter
+setting.  Earlier Postfix versions always add these headers; this
+may break DKIM signatures that cover non-existent headers. </p>
index 982daafbbcc65b9ca96a9252bfe5cd92326b3ba4..8856448fca13697ae235263b4e884494f73d8f50 100644 (file)
 #
 #      This document describes how the familiar "postfix start"
 #      etc. user interface can be used to manage one or multiple
-#      Postfix instances, and gives details of an API that allows
-#      the postfix(1) command to coordinate activities with a
-#      multi-instance manager program.
-#
-#      A trivial but useful multi-instance manager implementation
-#      is described below, and can be found in the file
-#      $daemon_directory/postfix-wrapper. The latter file also
-#      contains instructions for setting up multiple instances.
+#      Postfix instances, and gives details of an API to coordinate
+#      activities between the postfix(1) command and a multi-instance
+#      manager program.
 #
 #      With multi-instance support, the default Postfix instance
-#      is required. The location of its configuration files is
-#      specified by the built-in default value for the config_directory
-#      parameter.
+#      is always required. The config_directory parameter's default
+#      value specifies that instance's configuration file location.
 # GENERAL OPERATION
 # .ad
 # .fi
-#      Multi-instance support is backwards compatible: when there
-#      is only one Postfix instance, commands such as "postfix
-#      start" keep doing what they have always done.
+#      Multi-instance support is backwards compatible: when you
+#      run only one Postfix instance, commands such as "postfix
+#      start" will not change behavior at all.
 #
-#      Even after multi-instance support has been set up through
-#      the mechanisms discussed later, sites can continue to use
-#      the familiar postfix commands in boot scripts, upgrade
-#      procedures, and other places.
+#      Even with multiple Postfix instances, you can keep using
+#      the same postfix commands in boot scripts, upgrade procedures,
+#      and other places. The commands do more work, but humans are
+#      not forced to learn new tricks.
 #
-#      To start all applicable Postfix instances, use:
+#      For example, to start all Postfix instances, use:
 # .IP
 #      # postfix start
 # .PP
@@ -51,8 +45,8 @@
 # MANAGING AN INDIVIDUAL POSTFIX INSTANCE
 # .ad
 # .fi
-#      To operate on a specific Postfix instance, specify its
-#      configuration directory on the postfix(1) command line:
+#      To manage a specific Postfix instance, specify its configuration
+#      directory on the postfix(1) command line:
 # .IP
 #      # postfix -c \fI/path/to/config_directory command\fR
 # .PP
 #      variable (the -c command-line option has higher precedence).
 #
 #      When no Postfix instance information is specified, the
-#      postfix(1) command will operate on all applicable Postfix
-#      instances.
-# MULTI-INSTANCE MANAGER IMPLEMENTATION
+#      postfix(1) command will operate on all Postfix instances.
+# ENABLING POSTFIX(1) MULTI-INSTANCE MODE
 # .ad
 # .fi
-#      Historically, the postfix(1) command invokes the postfix-script
-#      file (currently installed in the daemon directory). This
-#      file contains the commands that start or stop Postfix,
-#      upgrade the configuration and so on.
+#      By default, the postfix(1) command operates in single-instance
+#      mode. In this mode the command invokes the postfix-script
+#      file directly (currently installed in the daemon directory).
+#      This file contains the commands that start or stop one
+#      Postfix instance, that upgrade the configuration of one
+#      Postfix instance, and so on.
 #
-#      When multi-instance support is turned on, the postfix(1)
-#      command needs to execute these commands for each applicable
-#      Postfix instance. This multiplication of commands is handled
-#      by a multi-instance manager program.
+#      When the postfix(1) command operates in multi-instance mode
+#      as discussed below, the command needs to execute start,
+#      stop, etc.  commands for each Postfix instance.  This
+#      multiplication of commands is handled by a multi-instance
+#      manager program.
 #
-#      Turning on multi-instance support goes as follows: update
-#      the default Postfix instance's main.cf file, and populate
-#      the multi_instance_directories parameter with the configuration
-#      directory pathnames of additional Postfix instances.
-#
-#      With multi-instance support turned on, the postfix(1) command
-#      invokes a multi-instance manager command instead of the
-#      postfix-script file. The multi-instance manager executes
-#      the postfix(1) command for each applicable Postfix instance.
-#      The pathname of the multi-instance manager is specified in
-#      the default main.cf file with the multi_instance_wrapper
-#      parameter.
+#      Turning on postfix(1) multi-instance mode goes as follows:
+#      in the default Postfix instance's main.cf file, 1) specify
+#      the pathname of a multi-instance manager program with the
+#      multi_instance_wrapper parameter; 2) populate the
+#      multi_instance_directories parameter with the configuration
+#      directory pathnames of additional Postfix instances.  For
+#      example:
+# .IP
+# .nf
+#      /etc/postfix/main.cf:
+#          multi_instance_wrapper = $daemon_directory/postfix-wrapper
+#          multi_instance_directories = /etc/postfix-test
+# .fi
+# .PP
+#      The $daemon_directory/postfix-wrapper file implements a
+#      simple manager and contains instructions for creating Postfix
+#      instances by hand.  The postmulti(1) command provides a
+#      more extensive implementation including support for life-cycle
+#      management.
 #
 #      The multi_instance_directories and other main.cf parameters
 #      are listed below in the CONFIGURATION PARAMETERS section.
 #
-#      A useful multi-instance manager implementation can be as
-#      simple as:
+#      In multi-instance mode, the postfix(1) command invokes the
+#      $multi_instance_wrapper command instead of the postfix-script
+#      file. This multi-instance manager in turn executes the
+#      postfix(1) command in single-instance mode for each Postfix
+#      instance.
+#
+#      To illustrate the main ideas behind multi-instance operation,
+#      below is an example of a simple but useful multi-instance
+#      manager implementation:
 # .IP
 # .nf
 #      #!/bin/sh
 #
 #      exit $err
 # .fi
-# .PP
-#      A sample implementation, with instructions, can be found
-#      in $daemon_directory/postfix-wrapper.
-#
-#      The postmulti(1) command implements a more sophisticated
-#      approach, based on a combination of C code and scripting.
-# ENABLING A SPECIFIC INSTANCE FOR MULTI-INSTANCE OPERATION
+# PER-INSTANCE MULTI-INSTANCE MANAGER CONTROLS
 # .ad
 # .fi
 #      Each Postfix instance has its own main.cf file with parameters
-#      that control multi-instance operation. The most important
-#      settings are discussed here.
+#      that control how the multi-instance manager operates on
+#      that instance.  This section discusses the most important
+#      settings.
 #
 #      The setting "multi_instance_enable = yes" allows the
-#      multi-instance manager to start (and stop) the corresponding
+#      multi-instance manager to start (stop, etc.) the corresponding
 #      Postfix instance. For safety reasons, this setting is not
 #      the default.
 #
-#      The setting "multi_instance_enable = no" is useful for
-#      manual testing.  With this, the multi-instance manager will
-#      not start the Postfix instance, and it will skip commands
-#      such as "stop" or "flush" that require a running Postfix
-#      instance.  The multi-instance manager will execute commands
-#      such as "check", "set-permissions" or "upgrade-configuration",
-#      and it will replace "start" by "check" so that problems
-#      will be reported even when the instance is disabled.
-# SHARED VERSUS NON-SHARED FILES
+#      The default setting "multi_instance_enable = no" is useful
+#      for manual testing with "postfix -c \fI/path/name\fR start"
+#      etc.  The multi-instance manager will not start such an
+#      instance, and it will skip commands such as "stop" or "flush"
+#      that require a running Postfix instance.  The multi-instance
+#      manager will execute commands such as "check", "set-permissions"
+#      or "upgrade-configuration", and it will replace "start" by
+#      "check" so that problems will be reported even when the
+#      instance is disabled.
+# MAINTAINING SHARED AND NON-SHARED FILES
 # .ad
 # .fi
 #      Some files are shared between Postfix instances, such as
 #      executables and manpages, and some files are per-instance,
-#      such as the queue directory.  See the NON-SHARED FILES
-#      section below for a list of per-instance files.
+#      such as configuration files, mail queue files, and data
+#      files.  See the NON-SHARED FILES section below for a list
+#      of per-instance files.
 #
 #      Before Postfix multi-instance support was implemented, the
-#      executables, manpages, etc., have always been checked or
-#      updated as part of the default Postfix instance. With
-#      multi-instance support, we simply continue to do this.
+#      executables, manpages, etc., have always been maintained
+#      as part of the default Postfix instance. 
 #
-#      Specifically, Postfix instances will not check or update
-#      shared files when their config_directory value is listed
-#      with the default main.cf's multi_instance_directories
+#      With multi-instance support, we simply continue to do this.
+#      Specifically, a Postfix instance will not check or update
+#      shared files when that instance's config_directory value is
+#      listed with the default main.cf file's multi_instance_directories
 #      parameter.
 #
 #      The consequence of this approach is that the default Postfix
index a281ed553a47148f441332de60d75507a801ce94..688b6860d28b5fe2b9a5b20a77233eeb30694965 100644 (file)
 /*     sender address (this feature is removed with Postfix version 2.2, is
 /*     turned off by default with Postfix version 2.1, and is always turned on
 /*     with older Postfix versions).
+/* .PP
+/*     Available in Postfix version 2.6 and later:
+/* .IP "\fBalways_add_missing_headers (no)\fR"
+/*     Always add (Resent-) From:, To:, Date: or Message-ID headers
+/*     when not present.
 /* BUILT-IN CONTENT FILTERING CONTROLS
 /* .ad
 /* .fi
 /* .IP "\fBmilter_content_timeout (300s)\fR"
 /*     The time limit for sending message content to a Milter (mail
 /*     filter) application, and for receiving the response.
-/* .IP "\fBmilter_connect_macros (see postconf -n output)\fR"
+/* .IP "\fBmilter_connect_macros (see 'postconf -d' output)\fR"
 /*     The macros that are sent to Milter (mail filter) applications
 /*     after completion of an SMTP connection.
-/* .IP "\fBmilter_helo_macros (see postconf -n output)\fR"
+/* .IP "\fBmilter_helo_macros (see 'postconf -d' output)\fR"
 /*     The macros that are sent to Milter (mail filter) applications
 /*     after the SMTP HELO or EHLO command.
-/* .IP "\fBmilter_mail_macros (see postconf -n output)\fR"
+/* .IP "\fBmilter_mail_macros (see 'postconf -d' output)\fR"
 /*     The macros that are sent to Milter (mail filter) applications
 /*     after the SMTP MAIL FROM command.
-/* .IP "\fBmilter_rcpt_macros (see postconf -n output)\fR"
+/* .IP "\fBmilter_rcpt_macros (see 'postconf -d' output)\fR"
 /*     The macros that are sent to Milter (mail filter) applications
 /*     after the SMTP RCPT TO command.
-/* .IP "\fBmilter_data_macros (see postconf -n output)\fR"
+/* .IP "\fBmilter_data_macros (see 'postconf -d' output)\fR"
 /*     The macros that are sent to version 4 or higher Milter (mail
 /*     filter) applications after the SMTP DATA command.
-/* .IP "\fBmilter_unknown_command_macros (see postconf -n output)\fR"
+/* .IP "\fBmilter_unknown_command_macros (see 'postconf -d' output)\fR"
 /*     The macros that are sent to version 3 or higher Milter (mail
 /*     filter) applications after an unknown SMTP command.
-/* .IP "\fBmilter_end_of_data_macros (see postconf -n output)\fR"
+/* .IP "\fBmilter_end_of_data_macros (see 'postconf -d' output)\fR"
 /*     The macros that are sent to Milter (mail filter) applications
 /*     after the message end-of-data.
 /* .PP
 /*     Available in Postfix version 2.5 and later:
-/* .IP "\fBmilter_end_of_header_macros (see postconf -n output)\fR"
+/* .IP "\fBmilter_end_of_header_macros (see 'postconf -d' output)\fR"
 /*     The macros that are sent to Milter (mail filter) applications
 /*     after the end of the message header.
 /* MIME PROCESSING CONTROLS
 /*     the sender.
 /* .IP "\fBsyslog_facility (mail)\fR"
 /*     The syslog facility of Postfix logging.
-/* .IP "\fBsyslog_name (postfix)\fR"
+/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 /*     The mail system name that is prepended to the process name in syslog
 /*     records, so that "smtpd" becomes, for example, "postfix/smtpd".
 /* .PP
index bb3983c4df6c39aee76c590119e7cc4470a623e4..67a27a8d96197fcd67a0938ade6e0088a72d91e4 100644 (file)
@@ -162,6 +162,7 @@ char   *var_milt_eod_macros;                /* end-of-data macros */
 char   *var_milt_unk_macros;           /* unknown command macros */
 char   *var_cleanup_milters;           /* non-SMTP mail */
 int     var_auto_8bit_enc_hdr;         /* auto-detect 8bit encoding header */
+int     var_always_add_hdrs;           /* always add missing headers */
 
 CONFIG_INT_TABLE cleanup_int_table[] = {
     VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
@@ -177,6 +178,7 @@ CONFIG_BOOL_TABLE cleanup_bool_table[] = {
     VAR_ENABLE_ORCPT, DEF_ENABLE_ORCPT, &var_enable_orcpt,
     VAR_VERP_BOUNCE_OFF, DEF_VERP_BOUNCE_OFF, &var_verp_bounce_off,
     VAR_AUTO_8BIT_ENC_HDR, DEF_AUTO_8BIT_ENC_HDR, &var_auto_8bit_enc_hdr,
+    VAR_ALWAYS_ADD_HDRS, DEF_ALWAYS_ADD_HDRS, &var_always_add_hdrs,
     0,
 };
 
@@ -318,7 +320,6 @@ void    cleanup_pre_jail(char *unused_name, char **unused_argv)
        CANON_CLASS_HDR_RCPT, CLEANUP_CANON_FLAG_HDR_RCPT,
        0,
     };
-
     static const NAME_MASK masq_class_table[] = {
        MASQ_CLASS_ENV_FROM, CLEANUP_MASQ_FLAG_ENV_FROM,
        MASQ_CLASS_ENV_RCPT, CLEANUP_MASQ_FLAG_ENV_RCPT,
index 4d1273222da713df6ec0cbe4e9a1e6eebb9cdf99..236db5e11a41ddb217c0d0a9938fef7d1686ca68 100644 (file)
@@ -625,7 +625,8 @@ static void cleanup_header_done_callback(void *context)
      * the message ID matches the queue ID creation time, as long as we use
      * the queue ID in the message ID.
      */
-    if ((state->headers_seen & (1 << (state->resent[0] ?
+    if ((state->hdr_rewrite_context || var_always_add_hdrs)
+       && (state->headers_seen & (1 << (state->resent[0] ?
                           HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID))) == 0) {
        tv = state->handle->ctime.tv_sec;
        tp = gmtime(&tv);
@@ -641,8 +642,9 @@ static void cleanup_header_done_callback(void *context)
      * Add a missing (Resent-)Date: header. The date is in local time units,
      * with the GMT offset at the end.
      */
-    if ((state->headers_seen & (1 << (state->resent[0] ?
-                                     HDR_RESENT_DATE : HDR_DATE))) == 0) {
+    if ((state->hdr_rewrite_context || var_always_add_hdrs)
+       && (state->headers_seen & (1 << (state->resent[0] ?
+                                      HDR_RESENT_DATE : HDR_DATE))) == 0) {
        cleanup_out_format(state, REC_TYPE_NORM, "%sDate: %s",
                      state->resent, mail_date(state->arrival_time.tv_sec));
     }
@@ -650,8 +652,9 @@ static void cleanup_header_done_callback(void *context)
     /*
      * Add a missing (Resent-)From: header.
      */
-    if ((state->headers_seen & (1 << (state->resent[0] ?
-                                     HDR_RESENT_FROM : HDR_FROM))) == 0) {
+    if ((state->hdr_rewrite_context || var_always_add_hdrs)
+       && (state->headers_seen & (1 << (state->resent[0] ?
+                                      HDR_RESENT_FROM : HDR_FROM))) == 0) {
        quote_822_local(state->temp1, *state->sender ?
                        state->sender : MAIL_ADDR_MAIL_DAEMON);
        vstring_sprintf(state->temp2, "%sFrom: %s",
@@ -695,7 +698,8 @@ static void cleanup_header_done_callback(void *context)
 #define VISIBLE_RCPT   ((1 << HDR_TO) | (1 << HDR_RESENT_TO) \
                        | (1 << HDR_CC) | (1 << HDR_RESENT_CC))
 
-    if ((state->headers_seen & VISIBLE_RCPT) == 0 && *var_rcpt_witheld) {
+    if ((state->hdr_rewrite_context || var_always_add_hdrs)
+       && (state->headers_seen & VISIBLE_RCPT) == 0 && *var_rcpt_witheld) {
        if (!is_header(var_rcpt_witheld)) {
            msg_warn("bad %s header text \"%s\" -- "
                     "need \"headername: headervalue\"",
index ac61287ace6477480296eee2884ec2dfa080f88d..b34edaeacdf1fc2b11f61e37167c7d9208bd5f95 100644 (file)
@@ -80,7 +80,7 @@ static void print_rr(DNS_RR *rr)
 int     main(int argc, char **argv)
 {
     ARGV   *types_argv;
-    int    *types;
+    unsigned *types;
     char   *name;
     VSTRING *fqdn = vstring_alloc(100);
     VSTRING *why = vstring_alloc(100);
index 4877e863d4587ec9cb68ae4f5dc5800a51e77859..935f194abd81e179238059ba1204adbb9b1f5ef5 100644 (file)
@@ -485,10 +485,19 @@ static int dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
     const char *myname = "dict_ldap_set_tls_options";
     int     rc;
 
+#ifdef LDAP_OPT_X_TLS_NEWCTX
+    int     am_server = 0;
+    LDAP   *ld = dict_ldap->ld;
+
+#else
+    LDAP   *ld = 0;
+
+#endif
+
     if (dict_ldap->start_tls || dict_ldap->ldap_ssl) {
        if (*dict_ldap->tls_random_file) {
-           if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_RANDOM_FILE,
-                              dict_ldap->tls_random_file)) != LDAP_SUCCESS) {
+           if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_RANDOM_FILE,
+                            dict_ldap->tls_random_file)) != LDAP_SUCCESS) {
                msg_warn("%s: Unable to set tls_random_file to %s: %d: %s",
                         myname, dict_ldap->tls_random_file,
                         rc, ldap_err2string(rc));
@@ -496,8 +505,8 @@ static int dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
            }
        }
        if (*dict_ldap->tls_ca_cert_file) {
-           if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
-                             dict_ldap->tls_ca_cert_file)) != LDAP_SUCCESS) {
+           if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_CACERTFILE,
+                           dict_ldap->tls_ca_cert_file)) != LDAP_SUCCESS) {
                msg_warn("%s: Unable to set tls_ca_cert_file to %s: %d: %s",
                         myname, dict_ldap->tls_ca_cert_file,
                         rc, ldap_err2string(rc));
@@ -505,8 +514,8 @@ static int dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
            }
        }
        if (*dict_ldap->tls_ca_cert_dir) {
-           if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR,
-                              dict_ldap->tls_ca_cert_dir)) != LDAP_SUCCESS) {
+           if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_CACERTDIR,
+                            dict_ldap->tls_ca_cert_dir)) != LDAP_SUCCESS) {
                msg_warn("%s: Unable to set tls_ca_cert_dir to %s: %d: %s",
                         myname, dict_ldap->tls_ca_cert_dir,
                         rc, ldap_err2string(rc));
@@ -514,8 +523,8 @@ static int dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
            }
        }
        if (*dict_ldap->tls_cert) {
-           if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CERTFILE,
-                                     dict_ldap->tls_cert)) != LDAP_SUCCESS) {
+           if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_CERTFILE,
+                                   dict_ldap->tls_cert)) != LDAP_SUCCESS) {
                msg_warn("%s: Unable to set tls_cert to %s: %d: %s",
                         myname, dict_ldap->tls_cert,
                         rc, ldap_err2string(rc));
@@ -523,7 +532,7 @@ static int dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
            }
        }
        if (*dict_ldap->tls_key) {
-           if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_KEYFILE,
+           if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_KEYFILE,
                                      dict_ldap->tls_key)) != LDAP_SUCCESS) {
                msg_warn("%s: Unable to set tls_key to %s: %d: %s",
                         myname, dict_ldap->tls_key,
@@ -532,21 +541,29 @@ static int dict_ldap_set_tls_options(DICT_LDAP *dict_ldap)
            }
        }
        if (*dict_ldap->tls_cipher_suite) {
-           if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE,
-                             dict_ldap->tls_cipher_suite)) != LDAP_SUCCESS) {
+           if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_CIPHER_SUITE,
+                           dict_ldap->tls_cipher_suite)) != LDAP_SUCCESS) {
                msg_warn("%s: Unable to set tls_cipher_suite to %s: %d: %s",
                         myname, dict_ldap->tls_cipher_suite,
                         rc, ldap_err2string(rc));
                return (-1);
            }
        }
-       if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
-                      &(dict_ldap->tls_require_cert))) != LDAP_SUCCESS) {
+       if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_REQUIRE_CERT,
+                        &(dict_ldap->tls_require_cert))) != LDAP_SUCCESS) {
            msg_warn("%s: Unable to set tls_require_cert to %d: %d: %s",
                     myname, dict_ldap->tls_require_cert,
                     rc, ldap_err2string(rc));
            return (-1);
        }
+#ifdef LDAP_OPT_X_TLS_NEWCTX
+       if ((rc = ldap_set_option(ld, LDAP_OPT_X_TLS_NEWCTX, &am_server))
+           != LDAP_SUCCESS) {
+           msg_warn("%s: Unable to allocate new TLS context %d: %s",
+                    myname, rc, ldap_err2string(rc));
+           return (-1);
+       }
+#endif
     }
     return (0);
 }
@@ -592,10 +609,6 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
 
 #ifdef LDAP_OPT_NETWORK_TIMEOUT
 #ifdef LDAP_API_FEATURE_X_OPENLDAP
-    if (dict_ldap_set_tls_options(dict_ldap) != 0) {
-       dict_errno = DICT_ERR_RETRY;
-       return (-1);
-    }
     ldap_initialize(&(dict_ldap->ld), dict_ldap->server_host);
 #else
     dict_ldap->ld = ldap_init(dict_ldap->server_host,
@@ -700,6 +713,8 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
 #endif
 
 #ifdef LDAP_API_FEATURE_X_OPENLDAP
+    if (dict_ldap_set_tls_options(dict_ldap) != 0)
+       DICT_LDAP_UNBIND_RETURN(dict_ldap->ld, DICT_ERR_RETRY, -1);
     if (dict_ldap->start_tls) {
        if ((saved_alarm = signal(SIGALRM, dict_ldap_timeout)) == SIG_ERR) {
            msg_warn("%s: Error setting signal handler for STARTTLS timeout: %m",
index 8accd9f160f31e8de8755f9ed566f441f10dd0ba..6884859eeeab5b2797befc6fc3575f17879da899 100644 (file)
 /*     for integer values. The default value can be a macro
 /*     expression ($name, ${name?value} and ${name:value}).
 /*
-/*     get_mail_conf_int() looks up the named entry in the global
+/*     get_mail_conf_nint() looks up the named entry in the global
 /*     configuration dictionary. The default value is returned
 /*     when no value was found.
 /*     \fImin\fR is zero or specifies a lower limit on the integer
 /*     value or string length; \fImax\fR is zero or specifies an
 /*     upper limit on the integer value or string length.
 /*
-/*     get_mail_conf_int_fn() is similar but specifies a function that
+/*     get_mail_conf_nint_fn() is similar but specifies a function that
 /*     provides the default value. The function is called only
 /*     when the default value is needed.
 /*
-/*     set_mail_conf_int() updates the named entry in the global
+/*     set_mail_conf_nint() updates the named entry in the global
 /*     configuration dictionary. This has no effect on values that
 /*     have been looked up earlier via the get_mail_conf_XXX() routines.
 /*
-/*     get_mail_conf_int_table() and get_mail_conf_int_fn_table() initialize
+/*     get_mail_conf_nint_table() and get_mail_conf_nint_fn_table() initialize
 /*     lists of variables, as directed by their table arguments. A table
 /*     must be terminated by a null entry.
 /*
-/*     get_mail_conf_int2() concatenates the two names and is otherwise
-/*     identical to get_mail_conf_int().
+/*     get_mail_conf_nint2() concatenates the two names and is otherwise
+/*     identical to get_mail_conf_nint().
 /* DIAGNOSTICS
 /*     Fatal errors: malformed numerical value.
 /* SEE ALSO
index d952a7ce5d584c51b2a441ebf1afcbc21b2da6e3..516d917359d03094731be42e7ed34e4146a562d6 100644 (file)
@@ -332,6 +332,14 @@ extern char *var_always_bcc;
 #define DEF_RCPT_WITHELD       "To: undisclosed-recipients:;"
 extern char *var_rcpt_witheld;
 
+ /*
+  * Add missing headers. Postfix 2.6 no longer adds headers to remote mail by
+  * default.
+  */
+#define VAR_ALWAYS_ADD_HDRS    "always_add_missing_headers"
+#define DEF_ALWAYS_ADD_HDRS    0
+extern bool var_always_add_hdrs;
+
  /*
   * Standards violation: allow/permit RFC 822-style addresses in SMTP
   * commands.
@@ -1105,7 +1113,7 @@ extern int var_smtpd_tmout;
 extern int var_smtpd_starttls_tmout;
 
 #define VAR_SMTPD_RCPT_LIMIT   "smtpd_recipient_limit"
-#define DEF_SMTPD_RCPT_LIMIT   "1000"
+#define DEF_SMTPD_RCPT_LIMIT   1000
 extern int var_smtpd_rcpt_limit;
 
 #define VAR_SMTPD_SOFT_ERLIM   "smtpd_soft_error_limit"
@@ -1660,6 +1668,10 @@ extern int var_smtp_sasl_auth_cache_time;
 #define DEF_LMTP_TCP_PORT      "24"
 extern char *var_lmtp_tcp_port;
 
+#define VAR_LMTP_ASSUME_FINAL  "lmtp_assume_final"
+#define DEF_LMTP_ASSUME_FINAL  0
+extern bool var_lmtp_assume_final;
+
 #define VAR_LMTP_CACHE_CONN    "lmtp_cache_connection"
 #define DEF_LMTP_CACHE_CONN    1
 extern bool var_lmtp_cache_conn;
@@ -3019,12 +3031,12 @@ extern char *var_smtp_body_chks;
   * Scheduler concurrency feedback algorithms.
   */
 #define VAR_CONC_POS_FDBACK    "default_destination_concurrency_positive_feedback"
-#define _CONC_POS_FDBACK       "_concurrency_positive_feedback"
+#define _CONC_POS_FDBACK       "_destination_concurrency_positive_feedback"
 #define DEF_CONC_POS_FDBACK    "1"
 extern char *var_conc_pos_feedback;
 
 #define VAR_CONC_NEG_FDBACK    "default_destination_concurrency_negative_feedback"
-#define _CONC_NEG_FDBACK       "_concurrency_negative_feedback"
+#define _CONC_NEG_FDBACK       "_destination_concurrency_negative_feedback"
 #define DEF_CONC_NEG_FDBACK    "1"
 extern char *var_conc_neg_feedback;
 
@@ -3032,7 +3044,7 @@ extern char *var_conc_neg_feedback;
 #define CONC_FDBACK_NAME_SQRT_WIN "sqrt_concurrency"
 
 #define VAR_CONC_COHORT_LIM    "default_destination_concurrency_failed_cohort_limit"
-#define _CONC_COHORT_LIM       "_concurrency_failed_cohort_limit"
+#define _CONC_COHORT_LIM       "_destination_concurrency_failed_cohort_limit"
 #define DEF_CONC_COHORT_LIM    1
 extern int var_conc_cohort_limit;
 
@@ -3090,6 +3102,21 @@ extern char *var_multi_group;
 #define DEF_MULTI_ENABLE       0
 extern bool var_multi_enable;
 
+ /*
+  * postmulti(1) instance manager
+  */
+#define VAR_MULTI_START_CMDS   "postmulti_start_commands"
+#define DEF_MULTI_START_CMDS   "start"
+extern char *var_multi_start_cmds;
+
+#define VAR_MULTI_STOP_CMDS    "postmulti_stop_commands"
+#define DEF_MULTI_STOP_CMDS    "stop abort drain quick-stop"
+extern char *var_multi_stop_cmds;
+
+#define VAR_MULTI_CNTRL_CMDS   "postmulti_control_commands"
+#define DEF_MULTI_CNTRL_CMDS   "reload flush"
+extern char *var_multi_cntrl_cmds;
+
 /* LICENSE
 /* .ad
 /* .fi
index dfad21eeedaac0981f1cf3d3cede996460bc7352..00e1c4011cad48c53efb32ab86d29467f87a54af 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20090212"
+#define MAIL_RELEASE_DATE      "20090404"
 #define MAIL_VERSION_NUMBER    "2.6"
 
 #ifdef SNAPSHOT
index 8006873eca6d5c753dd58c48d3755ffcaf54c90e..b117564e1a64bf4521aead3dc686edf47bfc098b 100644 (file)
@@ -286,6 +286,8 @@ QMGR_TRANSPORT *qmgr_transport_select(void)
            continue;
        need = xport->pending + 1;
        for (queue = xport->queue_list.next; queue; queue = queue->peers.next) {
+           if (QMGR_QUEUE_READY(queue) == 0)
+               continue;
            if ((need -= MIN5af51743e4eef(queue->window - queue->busy_refcount,
                                          queue->todo_refcount)) <= 0) {
                QMGR_LIST_ROTATE(qmgr_transport_list, xport);
index 3747e7800a501a9f15743ab9a33993c7eb62bb07..2cdccebe3f2d9fb5b21386154e37eb68488e72f5 100644 (file)
@@ -520,7 +520,8 @@ int     main(int argc, char **argv)
     /*
      * Run the management script.
      */
-    if (force_single_instance || *var_multi_conf_dirs == 0) {
+    if (force_single_instance 
+       || argv_split(var_multi_conf_dirs, "\t\r\n, ")->argc == 0) {
        script = concatenate(var_daemon_dir, "/postfix-script", (char *) 0);
        if (optind < 1)
            msg_panic("bad optind value");
diff --git a/postfix/src/postmulti/.indent.pro b/postfix/src/postmulti/.indent.pro
new file mode 120000 (symlink)
index 0000000..5c837ec
--- /dev/null
@@ -0,0 +1 @@
+../../.indent.pro
\ No newline at end of file
diff --git a/postfix/src/postmulti/Makefile.in b/postfix/src/postmulti/Makefile.in
new file mode 100644 (file)
index 0000000..b071ec9
--- /dev/null
@@ -0,0 +1,83 @@
+SHELL  = /bin/sh
+SRCS   = postmulti.c 
+OBJS   = postmulti.o 
+HDRS   = 
+TESTSRC        = 
+DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+FILES  = Makefile $(SRCS) $(HDRS)
+INC_DIR        = ../../include
+TESTPROG=
+PROG   = postmulti
+LIBS   = ../../lib/libglobal.a ../../lib/libutil.a
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+$(PROG):       $(OBJS) $(LIBS)
+       $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+
+$(OBJS): ../../conf/makedefs.out
+
+Makefile: Makefile.in
+       cat ../../conf/makedefs.out $? >$@
+
+test:  $(TESTPROG)
+
+tests:
+
+root_tests:
+
+update: ../../bin/$(PROG)
+
+../../bin/$(PROG): $(PROG)
+       cp $(PROG) ../../bin
+
+printfck: $(OBJS) $(PROG)
+       rm -rf printfck
+       mkdir printfck
+       sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
+       set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
+       cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
+
+shar:
+       @shar $(FILES)
+
+lint:
+       lint $(SRCS)
+
+clean:
+       rm -f *.o *core $(PROG) $(TESTPROG) junk
+       rm -rf printfck
+
+tidy:  clean
+
+depend: $(MAKES)
+       (sed '1,/^# do not edit/!d' Makefile.in; \
+       set -e; for i in [a-z][a-z0-9]*.c; do \
+           $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+           -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' \
+           -e 's/o: \.\//o: /' -e p -e '}' ; \
+       done | sort -u) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+       @$(EXPORT) make -f Makefile.in Makefile 1>&2
+
+# do not edit below this line - it is generated by 'make depend'
+postmulti.o: ../../include/argv.h
+postmulti.o: ../../include/clean_env.h
+postmulti.o: ../../include/htable.h
+postmulti.o: ../../include/mail_conf.h
+postmulti.o: ../../include/mail_params.h
+postmulti.o: ../../include/mail_version.h
+postmulti.o: ../../include/msg.h
+postmulti.o: ../../include/msg_syslog.h
+postmulti.o: ../../include/msg_vstream.h
+postmulti.o: ../../include/mymalloc.h
+postmulti.o: ../../include/name_code.h
+postmulti.o: ../../include/ring.h
+postmulti.o: ../../include/safe.h
+postmulti.o: ../../include/stringops.h
+postmulti.o: ../../include/sys_defs.h
+postmulti.o: ../../include/vbuf.h
+postmulti.o: ../../include/vstream.h
+postmulti.o: ../../include/vstring.h
+postmulti.o: ../../include/vstring_vstream.h
+postmulti.o: postmulti.c
diff --git a/postfix/src/postmulti/postmulti.c b/postfix/src/postmulti/postmulti.c
new file mode 100644 (file)
index 0000000..353eefd
--- /dev/null
@@ -0,0 +1,1791 @@
+/*++
+/* NAME
+/*     postmulti 1
+/* SUMMARY
+/*     Postfix multi-instance manager
+/* SYNOPSIS
+/* .fi
+/*     \fBpostmulti\fR \fB-l\fR [\fB-aRv\fR] [\fB-g \fIgroup\fR]
+/*     [\fB-i \fIname\fR]
+/*
+/*     \fBpostmulti\fR \fB-p\fR [\fB-av\fR] [\fB-g \fIgroup\fR]
+/*     [\fB-i \fIname\fR] \fIcommand...\fR
+/*
+/*     \fBpostmulti\fR \fB-x\fR [\fB-aRv\fR] [\fB-g \fIgroup\fR]
+/*     [\fB-i \fIname\fR] \fIcommand...\fR
+/*
+/*     \fBpostmulti\fR \fB-e init\fR [\fB-v\fR]
+/*
+/*     \fBpostmulti\fR \fB-e create\fR [\fB-av\fR]
+/*     [\fB-g \fIgroup\fR] [\fB-i \fIname\fR] [\fB-G \fIgroup\fR]
+/*     [\fB-I \fIname\fR] [\fIparam=value\fR ...]
+/*
+/*     \fBpostmulti\fR \fB-e import\fR [\fB-av\fR]
+/*     [\fB-g \fIgroup\fR] [\fB-i \fIname\fR] [\fB-G \fIgroup\fR]
+/*     [\fB-I \fIname\fR] [\fBconfig_directory=\fI/path\fR]
+/*
+/*     \fBpostmulti\fR \fB-e destroy\fR [\fB-v\fR] \fB-i \fIname\fR
+/*
+/*     \fBpostmulti\fR \fB-e deport\fR [\fB-v\fR] \fB-i \fIname\fR
+/*
+/*     \fBpostmulti\fR \fB-e enable\fR [\fB-v\fR] \fB-i \fIname\fR
+/*
+/*     \fBpostmulti\fR \fB-e disable\fR [\fB-v\fR] \fB-i \fIname\fR
+/*
+/*     \fBpostmulti\fR \fB-e assign\fR [\fB-v\fR] \fB-i \fIname\fR
+/*     [\fB-I \fIname\fR] [-G \fIgroup\fR]
+/* DESCRIPTION
+/*     The \fBpostmulti\fR(1) command allows a Postfix administrator
+/*     to manage multiple Postfix instances on a single host.
+/*
+/*     \fBpostmulti\fR(1) implements two fundamental modes of
+/*     operation.  In \fBiterator\fR mode, it executes the same
+/*     command for multiple Postfix instances.  In \fBlife-cycle
+/*     management\fR mode, it adds or deletes one instance, or
+/*     changes the multi-instance status of one instance.
+/*
+/*     Each mode of operation has its own command syntax. For this
+/*     reason, each mode is documented in separate sections below.
+/* BACKGROUND
+/* .ad
+/* .fi
+/*     A multi-instance configuration consists of one primary
+/*     Postfix instance, and one or more secondary instances whose
+/*     configuration directory pathnames are recorded in the primary
+/*     instance's main.cf file. Postfix instances share program
+/*     files and documentation, but have their own configuration,
+/*     queue and data directories.
+/*
+/*     Currently, only the default Postfix instance can be used
+/*     as primary instance in a multi-instance configuration. The
+/*     \fBpostmulti\fR(1) command does not currently support a \fB-c\fR
+/*     option to select an alternative primary instance, and exits
+/*     with a fatal error if the \fBMAIL_CONFIG\fR environment
+/*     variable is set to a non-default configuration directory.
+/*
+/*     See the MULTI_INSTANCE_README tutorial for a more detailed
+/*     discussion of multi-instance management with \fBpostmulti\fR(1).
+/* ITERATOR MODE
+/* .ad
+/* .fi
+/*     In iterator mode, \fBpostmulti\fR performs the same operation
+/*     on all Postfix instances in turn.
+/*
+/*     If multi-instance support is not enabled, the requested
+/*     command is performed just for the primary instance.
+/* .PP
+/*     Iterator mode implements the following command options:
+/* .SH "Instance selection"
+/* .IP \fB-a\fR
+/*     Perform the operation on all instances. This is the default.
+/* .IP "\fB-g \fIgroup\fR"
+/*     Perform the operation only for members of the named \fIgroup\fR.
+/* .IP "\fB-i \fIname\fR"
+/*     Perform the operation only for the instance with the specified
+/*     \fIname\fR.  You can specify either the instance name
+/*     or the absolute pathname of the instance's configuration
+/*     directory.  Specify "-" to select the primary Postfix instance.
+/* .IP \fB-R\fR
+/*     Reverse the iteration order. This may be appropriate when
+/*     updating a multi-instance system, where "sink" instances
+/*     are started before "source" instances.
+/* .sp
+/*     This option cannot be used with \fB-p\fR.
+/* .SH "List mode"
+/* .IP \fB-l\fR
+/*     List Postfix instances with their instance name, instance
+/*     group name, enable/disable status and configuration directory.
+/* .SH "Postfix-wrapper mode"
+/* .IP \fB-p\fR
+/*     Invoke \fBpostfix(1)\fR to execute the specified \fIcommand\fR.
+/*     This option implements the \fBpostfix-wrapper\fR(5) interface.
+/* .RS
+/* .IP \(bu
+/*     With "start"-like commands, "postfix check" is executed for
+/*     instances that are not enabled. The full list of commands
+/*     is specified with the postmulti_start_commands parameter.
+/* .IP \(bu
+/*     With "stop"-like commands, the iteration order is reversed,
+/*     and disabled instances are skipped. The full list of commands
+/*     is specified with the postmulti_stop_commands parameter.
+/* .IP \(bu
+/*     With "reload" and other commands that require a started
+/*     instance, disabled instances are skipped. The full list of
+/*     commands is specified with the postmulti_control_commands
+/*     parameter.
+/* .IP \(bu
+/*     With "status" and other commands that don't require a started
+/*     instance, the command is executed for all instances.
+/* .RE
+/* .IP
+/*     The \fB-p\fR option can also be used interactively to
+/*     start/stop/etc.  a named instance or instance group. For
+/*     example, to start just the instances in the group "msa",
+/*     invoke \fBpostmulti\fR(1) as follows:
+/* .RS
+/* .IP
+/*     # postmulti -g msa -p start
+/* .RE
+/* .SH "Command mode"
+/* .IP \fB-x\fR
+/*     Execute the specified \fIcommand\fR for all Postfix instances.
+/*     The command runs with appropriate environment settings for
+/*     MAIL_CONFIG, command_directory, daemon_directory,
+/*     config_directory, queue_directory, data_directory,
+/*     multi_instance_name, multi_instance_group and
+/*     multi_instance_enable.
+/* .SH "Other options"
+/* .IP \fB-v\fR
+/*     Enable verbose logging for debugging purposes. Multiple
+/*     \fB-v\fR options make the software increasingly verbose.
+/* LIFE-CYCLE MANAGEMENT MODE
+/* .ad
+/* .fi
+/*     With the \fB-e\fR option \fBpostmulti\fR(1) can be used to
+/*     add or delete a Postfix instance, and to manage the
+/*     multi-instance status of an existing instance.
+/* .PP
+/*     The following options are implemented:
+/* .SH "Existing instance selection"
+/* .IP \fB-a\fR
+/*     When creating or importing an instance, place the new
+/*     instance at the front of the secondary instance list.
+/* .IP "\fB-g \fIgroup\fR"
+/*     When creating or importing an instance, place the new
+/*     instance before the first secondary instance that is a
+/*     member of the specified group.
+/* .IP "\fB-i \fIname\fR"
+/*     When creating or importing an instance, place the new
+/*     instance before the matching secondary instance.
+/* .sp
+/*     With other life-cycle operations, apply the operation to
+/*     the named existing instance.  Specify "-" to select the
+/*     primary Postfix instance.
+/* .SH "New or existing instance name assignment"
+/* .IP "\fB-I \fIname\fR"
+/*     Assign the specified instance \fIname\fR to an existing
+/*     instance or to a newly created or imported instance.  Instance
+/*     names other than "-"    (which makes the instance "nameless")
+/*     must start with "postfix-".  This restriction reduces the
+/*     likelihood of name collisions with system files.
+/* .IP "\fB-G \fIgroup\fR"
+/*     Assign the specified \fIgroup\fR name to an existing instance
+/*     or to a newly created or imported instance.
+/* .SH "Instance creation/deletion/status change"
+/* .IP "\fB-e \fIaction\fR"
+/*     "Edit" managed instances. The following actions are supported:
+/* .RS
+/* .IP \fBinit\fR
+/*     This command is required before \fBpostmulti\fR(1) can be
+/*     used to manage Postfix instances.  The "postmulti -e init"
+/*     command updates the primary instance's main.cf file by
+/*     setting:
+/* .RS
+/* .IP
+/* .nf
+/*     multi_instance_wrapper =
+/*             ${command_directory}/postmulti -p --
+/*     multi_instance_enable = yes
+/* .fi
+/* .RE
+/* .IP
+/*     You can set these by other means if you prefer.
+/* .IP \fBcreate\fR
+/*     Create a new Postfix instance and add it to the
+/*     multi_instance_directories parameter of the primary instance.
+/*     The "\fB-I \fIname\fR" option is recommended to give the
+/*     instance a short name that is used to construct default
+/*     values for the private directories of the new instance. The
+/*     "\fB-G \fIgroup\fR" option may be specified to assign the
+/*     instance to a group, otherwise, the new instance is not a
+/*     member of any groups.
+/* .sp
+/*     The new instance main.cf is the stock main.cf with the
+/*     parameters that specify the locations of shared files cloned
+/*     from the primary instance.  For "nameless" instances, you
+/*     should manually adjust "syslog_name" to yield a unique
+/*     "logtag" starting with "postfix-" that will uniquely identify
+/*     the instance in the mail logs. It is simpler to assign the
+/*     instance a short name with the "\fB-I \fIname\fR" option.
+/* .sp
+/*     Optional "name=value" arguments specify the instance
+/*     config_directory, queue_directory and data_directory.
+/*     For example:
+/* .RS
+/* .IP
+/* .nf
+/*     # postmulti -I postfix-mumble \e
+/*             -G mygroup -e create \e
+/*             config_directory=/my/config/dir \e
+/*             queue_directory=/my/queue/dir \e
+/*             data_directory=/my/data/dir
+/* .fi
+/* .RE
+/* .IP
+/*     If any of these pathnames is not supplied, the program
+/*     attempts to generate the pathname by taking the corresponding
+/*     primary instance pathname, and by replacing the last pathname
+/*     component by the value of the \fB-I\fR option.
+/* .sp
+/*     If the instance configuration directory already exists, and
+/*     contains both a main.cf and master.cf file, \fBcreate\fR
+/*     will "import" the instance as-is. For existing instances,
+/*     \fBcreate\fR and \fBimport\fR are identical.
+/* .IP \fBimport\fR
+/*     Import an existing instance into the list of instances
+/*     managed by the \fBpostmulti\fR(1) multi-instance manager.
+/*     This adds the instance to the multi_instance_directories
+/*     list of the primary instance.  If the "\fB-I \fIname\fR"
+/*     option is provided it specifies the new name for the instance
+/*     and is used to define a default location for the instance
+/*     configuration directory (as with \fBcreate\fR above).  The
+/*     "\fB-G \fIgroup\fR" option may be used to assign the instance
+/*     to a group. Add a "\fBconfig_directory=\fI/path\fR" argument
+/*     to override a default pathname based on "\fB-I \fIname\fR".
+/* .IP \fBdestroy\fR
+/*     Destroy a secondary Postfix instance. To be a candidate for
+/*     destruction an instance must be disabled, stopped and its
+/*     queue must not contain any messages. Attempts to destroy
+/*     the primary Postfix instance trigger a fatal error, without
+/*     destroying the instance.
+/* .sp
+/*     The instance is removed from the primary instance main.cf
+/*     file's alternate_config_directories parameter and its data,
+/*     queue and configuration directories are cleaned of files
+/*     and directories created by the Postfix system. The main.cf
+/*     and master.cf files are removed from the configuration
+/*     directory even if they have been modified since initial
+/*     creation. Finally, the instance is "deported" from the list
+/*     of managed instances.
+/* .sp
+/*     If other files are present in instance private directories,
+/*     the directories may not be fully removed, a warning is
+/*     logged to alert the administrator. It is expected that an
+/*     instance built using "fresh" directories via the \fBcreate\fR
+/*     action will be fully removed by the \fBdestroy\fR action
+/*     (if first disabled). If the instance configuration and queue
+/*     directories are populated with additional files (access and
+/*     rewriting tables, chroot jail content, etc.) the instance
+/*     directories will not be fully removed.
+/* .sp
+/*     The \fBdestroy\fR action triggers potentially dangerous
+/*     file removal operations. Make sure the instance's data,
+/*     queue and configuration directories are set correctly and
+/*     do not contain any valuable files.
+/* .IP \fBdeport\fR
+/*     Deport a secondary instance from the list of managed
+/*     instances. This deletes the instance configuration directory
+/*     from the primary instance's multi_instance_directories list,
+/*     but does not remove any files or directories.
+/* .IP \fBassign\fR
+/*     Assign a new instance name or a new group name to the
+/*     selected instance.  Use "\fB-G -\fR" to specify "no group"
+/*     and "\fB-I -\fR" to specify "no name".  If you choose to
+/*     make an instance "nameless", set a suitable syslog_name in
+/*     the corresponding main.cf file.
+/* .IP \fBenable\fR
+/*     Mark the selected instance as enabled. This just sets the
+/*     multi_instance_enable parameter to "yes" in the instance's
+/*     main.cf file.
+/* .IP \fBdisable\fR
+/*     Mark the selected instance as disabled. This means that
+/*     the instance will not be started etc. with "postfix start",
+/*     "postmulti -p start" and so on. The instance can still be
+/*     started etc. with "postfix -c config-directory start".
+/* .SH "Other options"
+/* .IP \fB-v\fR
+/*     Enable verbose logging for debugging purposes. Multiple
+/*     \fB-v\fR options make the software increasingly verbose.
+/* .RE
+/* ENVIRONMENT
+/* .ad
+/* .fi
+/*     The \fBpostmulti\fR(1) command exports the following environment
+/*     variables before executing the requested \fIcommand\fR for a given
+/*     instance:
+/* .IP \fBMAIL_VERBOSE\fR
+/*     This is set when the -v command-line option is present.
+/* .IP \fBMAIL_CONFIG\fR
+/*     The location of the configuration directory of the instance.
+/* CONFIGURATION PARAMETERS
+/* .ad
+/* .fi
+/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+/*     The default location of the Postfix main.cf and master.cf
+/*     configuration files.
+/* .IP "\fBdaemon_directory (see 'postconf -d' output)\fR"
+/*     The directory with Postfix support programs and daemon programs.
+/* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
+/*     The list of environment parameters that a Postfix process will
+/*     import from a non-Postfix parent process.
+/* .IP "\fBmulti_instance_directories (empty)\fR"
+/*     An optional list of non-default Postfix configuration directories;
+/*     these directories belong to additional Postfix instances that share
+/*     the Postfix executable files and documentation with the default
+/*     Postfix instance, and that are started, stopped, etc., together
+/*     with the default Postfix instance.
+/* .IP "\fBmulti_instance_group (empty)\fR"
+/*     The optional instance group name of this Postfix instance.
+/* .IP "\fBmulti_instance_name (empty)\fR"
+/*     The optional instance name of this Postfix instance.
+/* .IP "\fBmulti_instance_enable (no)\fR"
+/*     Allow this Postfix instance to be started, stopped, etc., by a
+/*     multi-instance manager.
+/* .IP "\fBpostmulti_start_commands (start)\fR"
+/*     The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager treats
+/*     as "start" commands.
+/* .IP "\fBpostmulti_stop_commands (see 'postconf -d' output)\fR"
+/*     The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager treats
+/*     as "stop" commands.
+/* .IP "\fBpostmulti_control_commands (reload flush)\fR"
+/*     The \fBpostfix\fR(1) commands that the \fBpostmulti\fR(1) instance manager
+/*     treats as "control" commands, that operate on running instances.
+/* .IP "\fBsyslog_facility (mail)\fR"
+/*     The syslog facility of Postfix logging.
+/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
+/*     The mail system name that is prepended to the process name in syslog
+/*     records, so that "smtpd" becomes, for example, "postfix/smtpd".
+/* FILES
+/*     $daemon_directory/main.cf, stock configuration file
+/*     $daemon_directory/master.cf, stock configuration file
+/*     $daemon_directory/postmulti-script, life-cycle helper program
+/* SEE ALSO
+/*     postfix(1), Postfix control program
+/*     postfix-wrapper(5), Postfix multi-instance API
+/* README FILES
+/*     Use "\fBpostconf readme_directory\fR" or "\fBpostconf
+/*     html_directory\fR" to locate this information.
+/*     MULTI_INSTANCE_README, Postfix multi-instance management
+/* HISTORY
+/* .ad
+/* .fi
+/*     The \fBpostmulti\fR(1) command was introduced with Postfix
+/*     version 2.6.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Victor Duchovni
+/*     Morgan Stanley
+/*
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <vstream.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <errno.h>
+#include <ctype.h>
+#ifdef USE_PATHS_H
+#include <paths.h>
+#endif
+#include <stddef.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <msg_vstream.h>
+#include <msg_syslog.h>
+#include <vstream.h>
+#include <vstring_vstream.h>
+#include <stringops.h>
+#include <clean_env.h>
+#include <argv.h>
+#include <safe.h>
+#include <mymalloc.h>
+#include <htable.h>
+#include <name_code.h>
+#include <ring.h>
+
+/* Global library. */
+
+#include <mail_version.h>
+#include <mail_params.h>
+#include <mail_conf.h>
+
+/* Application-specific. */
+
+ /*
+  * Configuration parameters, specific to postmulti(1).
+  */
+char   *var_multi_start_cmds;
+char   *var_multi_stop_cmds;
+char   *var_multi_cntrl_cmds;
+
+ /*
+  * Shared directory pathnames.
+  */
+typedef struct {
+    const char *param_name;
+    char  **param_value;
+} SHARED_PATH;
+
+static SHARED_PATH shared_dir_table[] = {
+    VAR_COMMAND_DIR, &var_command_dir,
+    VAR_DAEMON_DIR, &var_daemon_dir,
+    0,
+};
+
+ /*
+  * Actions.
+  */
+#define ITER_CMD_POSTFIX       (1<<0)  /* postfix(1) iterator mode */
+#define ITER_CMD_LIST          (1<<1)  /* listing iterator mode */
+#define ITER_CMD_GENERIC       (1<<2)  /* generic command iterator mode */
+
+#define ITER_CMD_MASK_ALL \
+    (ITER_CMD_POSTFIX | ITER_CMD_LIST | ITER_CMD_GENERIC)
+
+#define EDIT_CMD_CREATE                (1<<4)  /* create new instance */
+#define EDIT_CMD_IMPORT                (1<<5)  /* import existing instance */
+#define EDIT_CMD_DESTROY       (1<<6)  /* destroy instance */
+#define EDIT_CMD_DEPORT                (1<<7)  /* export instance */
+#define EDIT_CMD_ENABLE                (1<<8)  /* enable start/stop */
+#define EDIT_CMD_DISABLE       (1<<9)  /* disable start/stop */
+#define EDIT_CMD_ASSIGN                (1<<10) /* assign name/group */
+#define EDIT_CMD_INIT          (1<<11) /* hook into main.cf */
+
+#define EDIT_CMD_MASK_ADD      (EDIT_CMD_CREATE | EDIT_CMD_IMPORT)
+#define EDIT_CMD_MASK_DEL      (EDIT_CMD_DESTROY | EDIT_CMD_DEPORT)
+#define EDIT_CMD_MASK_ASSIGN   (EDIT_CMD_MASK_ADD | EDIT_CMD_ASSIGN)
+#define EDIT_CMD_MASK_ENB      (EDIT_CMD_ENABLE | EDIT_CMD_DISABLE)
+#define EDIT_CMD_MASK_ALL \
+    (EDIT_CMD_MASK_ASSIGN | EDIT_CMD_MASK_DEL | EDIT_CMD_MASK_ENB | \
+       EDIT_CMD_INIT)
+
+ /*
+  * Edit command to number mapping, and vice versa.
+  */
+static NAME_CODE edit_command_table[] = {
+    "create", EDIT_CMD_CREATE,
+    "import", EDIT_CMD_IMPORT,
+    "destroy", EDIT_CMD_DESTROY,
+    "deport", EDIT_CMD_DEPORT,
+    "enable", EDIT_CMD_ENABLE,
+    "disable", EDIT_CMD_DISABLE,
+    "assign", EDIT_CMD_ASSIGN,
+    "init", EDIT_CMD_INIT,
+    0, -1,
+};
+
+#define EDIT_CMD_CODE(str) \
+       name_code(edit_command_table, NAME_CODE_FLAG_STRICT_CASE, (str))
+#define EDIT_CMD_STR(code)     str_name_code(edit_command_table, (code))
+
+ /*
+  * Mandatory prefix for non-empty instance names.
+  */
+#ifndef NAME_PREFIX
+#define NAME_PREFIX "postfix-"
+#endif
+#define HAS_NAME_PREFIX(name) \
+     (strncmp((name), NAME_PREFIX, sizeof(NAME_PREFIX)-1) == 0)
+#define NEED_NAME_PREFIX(name) \
+    ((name) != 0 && strcmp((name), "-") != 0 && !HAS_NAME_PREFIX(name))
+#define NAME_SUFFIX(name) ((name) + sizeof(NAME_PREFIX) - 1)
+
+ /*
+  * In-core instance structure. Only private information is kept here.
+  */
+typedef struct instance {
+    RING    ring;                      /* linkage. */
+    char   *config_dir;                        /* private */
+    char   *queue_dir;                 /* private */
+    char   *data_dir;                  /* private */
+    char   *name;                      /* null or name */
+    char   *gname;                     /* null or group */
+    int     enabled;                   /* start/stop enable */
+    int     primary;                   /* special */
+} INSTANCE;
+
+ /*
+  * Managed instance list (edit mode and iterator mode).
+  */
+static RING instance_hd[1];            /* instance list head */
+
+#define RING_TO_INSTANCE(ring_ptr)     RING_TO_APPL(ring_ptr, INSTANCE, ring)
+#define RING_PTR_OF(x)                 (&((x)->ring))
+
+#define FOREACH_INSTANCE(entry) \
+    for ((entry) = instance_hd; \
+        ((entry) = ring_succ(entry)) != instance_hd;)
+
+#define FOREACH_SECONDARY_INSTANCE(entry) \
+    for ((entry) = ring_succ(instance_hd); \
+        ((entry) = ring_succ(entry)) != instance_hd;)
+
+#define NEXT_ITERATOR_INSTANCE(flags, entry) \
+    (((flags) & ITER_FLAG_REVERSE) ? ring_pred(entry) : ring_succ(entry))
+
+#define FOREACH_ITERATOR_INSTANCE(flags, entry) \
+    for ((entry) = instance_hd; \
+       ((entry) = NEXT_ITERATOR_INSTANCE(flags, (entry))) != instance_hd;)
+
+ /*
+  * Instance selection. One can either select all instances, select by
+  * instance name, or select by instance group.
+  */
+typedef struct {
+    int     type;                      /* see below */
+    char   *name;                      /* undefined or name */
+} INST_SELECTION;
+
+#define INST_SEL_NONE          0       /* default: no selection */
+#define INST_SEL_ALL           1       /* select all instances */
+#define INST_SEL_NAME          2       /* select instance name */
+#define INST_SEL_GROUP         3       /* select instance group */
+
+ /*
+  * Instance name assignment. Each instance may be assigned an instance name
+  * (this must be globally unique within a multi-instance cluster) or an
+  * instance group name (this is intended to be shared). Externally, empty
+  * names may be represented as "-". Internally, we use "" only, to simplify
+  * the code.
+  */
+typedef struct {
+    char   *name;                      /* null or assigned instance name */
+    char   *gname;                     /* null or assigned group name */
+} NAME_ASSIGNMENT;
+
+ /*
+  * Iterator controls for non-edit commands. One can reverse the iteration
+  * order, or give special treatment to disabled instances.
+  */
+#define ITER_FLAG_DEFAULT      0       /* default setting */
+#define ITER_FLAG_REVERSE      (1<<0)  /* reverse iteration order */
+#define ITER_FLAG_CHECK_DISABLED (1<<1)        /* check disabled instances */
+#define ITER_FLAG_SKIP_DISABLED        (1<<2)  /* skip disabled instances */
+
+ /*
+  * Environment export controls for edit commands. postmulti(1) exports only
+  * things that need to be updated.
+  */
+#define EXP_FLAG_MULTI_DIRS    (1<<0)  /* export multi_instance_directories */
+#define EXP_FLAG_MULTI_NAME    (1<<1)  /* export multi_instance_name */
+#define EXP_FLAG_MULTI_GROUP   (1<<2)  /* export multi_instance_group */
+
+ /*
+  * To detect conflicts, each instance name and each shared or private
+  * pathname is registered in one place, with its owner. Everyone must
+  * register their claims when they join, and will be rejected in case of
+  * conlict.
+  * 
+  * Each claim value involves a parameter value (either a directory name or an
+  * instance name). Each claim owner is the config_directory pathname plus
+  * the parameter name.
+  * 
+  * XXX: No multi.cf lock file, so this is not race-free.
+  */
+static HTABLE *claim_table;
+
+#define IS_CLAIMED_BY(name) \
+    (claim_table ? htable_find(claim_table, (name)) : 0)
+
+ /*
+  * Forward references.
+  */
+static int iterate_command(int, int, char **, INST_SELECTION *);
+static int match_instance_selection(INSTANCE *, INST_SELECTION *);
+
+ /*
+  * Convenience.
+  */
+#define INSTANCE_NAME(i) ((i)->name ? (i)->name : (i)->config_dir)
+#define STR(buf)       vstring_str(buf)
+
+/* register_claim - register claim or bust */
+
+static void register_claim(const char *instance_path, const char *param_name,
+                                  const char *param_value)
+{
+    const char *myname = "register_claim";
+    char   *requestor;
+    const char *owner;
+
+    /*
+     * Sanity checks.
+     */
+    if (instance_path == 0 || *instance_path == 0)
+       msg_panic("%s: no or empty instance pathname", myname);
+    if (param_name == 0 || *param_name == 0)
+       msg_panic("%s: no or empty parameter name", myname);
+    if (param_value == 0)
+       msg_panic("%s: no parameter value", myname);
+
+    /*
+     * Make a claim or report a conflict.
+     */
+    if (claim_table == 0)
+       claim_table = htable_create(100);
+    requestor = concatenate(instance_path, ", ", param_name, (char *) 0);
+    if ((owner = htable_find(claim_table, param_value)) == 0) {
+       (void) htable_enter(claim_table, param_value, requestor);
+    } else if (strcmp(owner, requestor) == 0) {
+       myfree(requestor);
+    } else {
+       msg_fatal("instance %s, %s=%s conflicts with instance %s=%s",
+               instance_path, param_name, param_value, owner, param_value);
+    }
+}
+
+/* claim_instance_attributes - claim multiple private instance attributes */
+
+static void claim_instance_attributes(INSTANCE *ip)
+{
+
+    /*
+     * Detect instance name or pathname conflicts between this instance and
+     * other instances. XXX: No multi.cf lock file, so this is not race-free.
+     */
+    if (ip->name)
+       register_claim(ip->config_dir, VAR_MULTI_NAME, ip->name);
+    register_claim(ip->config_dir, VAR_CONFIG_DIR, ip->config_dir);
+    register_claim(ip->config_dir, VAR_QUEUE_DIR, ip->queue_dir);
+    register_claim(ip->config_dir, VAR_DATA_DIR, ip->data_dir);
+}
+
+/* alloc_instance - allocate a single instance object */
+
+static INSTANCE *alloc_instance(const char *config_dir)
+{
+    INSTANCE *ip = (INSTANCE *) mymalloc(sizeof(INSTANCE));
+
+    ring_init(RING_PTR_OF(ip));
+    ip->config_dir = config_dir ? mystrdup(config_dir) : 0;
+    ip->queue_dir = 0;
+    ip->data_dir = 0;
+    ip->name = 0;
+    ip->gname = 0;
+    ip->enabled = 0;
+    ip->primary = 0;
+
+    return (ip);
+}
+
+#if 0
+
+/* free_instance - free a single instance object */
+
+static void free_instance(INSTANCE *ip)
+{
+
+    /*
+     * If we continue after secondary main.cf file read error, we must be
+     * prepared for the case that some parameters may be missing.
+     */
+    if (ip->name)
+       myfree(ip->name);
+    if (ip->gname)
+       myfree(ip->gname);
+    if (ip->config_dir)
+       myfree(ip->config_dir);
+    if (ip->queue_dir)
+       myfree(ip->queue_dir);
+    if (ip->data_dir)
+       myfree(ip->data_dir);
+    myfree((char *) ip);
+}
+
+#endif
+
+/* insert_instance - insert instance before selected location, claim names */
+
+static void insert_instance(INSTANCE *ip, INST_SELECTION *selection)
+{
+    RING   *old;
+
+#define append_instance(ip) insert_instance((ip), (INST_SELECTION *) 0)
+
+    /*
+     * Insert instance before the selected site.
+     */
+    claim_instance_attributes(ip);
+    if (ring_succ(instance_hd) == 0)
+       ring_init(instance_hd);
+    if (selection && selection->type != INST_SEL_NONE) {
+       FOREACH_SECONDARY_INSTANCE(old) {
+           if (match_instance_selection(RING_TO_INSTANCE(old), selection)) {
+               ring_prepend(old, RING_PTR_OF(ip));
+               return;
+           }
+       }
+       if (selection->type != INST_SEL_ALL)
+           msg_fatal("No matching secondary instances");
+    }
+    ring_prepend(instance_hd, RING_PTR_OF(ip));
+}
+
+/* create_primary_instance - synthetic entry for primary instance */
+
+static INSTANCE *create_primary_instance(void)
+{
+    INSTANCE *ip = alloc_instance(var_config_dir);
+
+    /*
+     * There is no need to load primary instance paramater settings from
+     * file. We already have the main.cf parameters of interest in memory.
+     */
+#define SAVE_INSTANCE_NAME(val) (*(val) ? mystrdup(val) : 0)
+
+    ip->name = SAVE_INSTANCE_NAME(var_multi_name);
+    ip->gname = SAVE_INSTANCE_NAME(var_multi_group);
+    ip->enabled = var_multi_enable;
+    ip->queue_dir = mystrdup(var_queue_dir);
+    ip->data_dir = mystrdup(var_data_dir);
+    ip->primary = 1;
+    return (ip);
+}
+
+/* load_instance - read instance parameters from config_dir/main.cf */
+
+static INSTANCE *load_instance(INSTANCE *ip)
+{
+    VSTREAM *pipe;
+    VSTRING *buf;
+    char   *name;
+    char   *value;
+    ARGV   *cmd;
+    int     count = 0;
+    static NAME_CODE bool_code[] = {
+       CONFIG_BOOL_YES, 1,
+       CONFIG_BOOL_NO, 0,
+       0, -1,
+    };
+
+    /*
+     * XXX: We could really use a "postconf -E" to expand values in the
+     * context of the target main.cf!
+     */
+#define REQUEST_PARAM_COUNT 5                  /* # of requested parameters */
+
+    cmd = argv_alloc(REQUEST_PARAM_COUNT + 3);
+    name = concatenate(var_command_dir, "/", "postconf", (char *) 0);
+    argv_add(cmd, name, "-c", ip->config_dir,
+            VAR_QUEUE_DIR, VAR_DATA_DIR,
+            VAR_MULTI_NAME, VAR_MULTI_GROUP, VAR_MULTI_ENABLE,
+            (char *) 0);
+    myfree(name);
+    pipe = vstream_popen(O_RDONLY, VSTREAM_POPEN_ARGV, cmd->argv,
+                        VSTREAM_POPEN_END);
+    argv_free(cmd);
+    if (pipe == 0)
+       msg_fatal("Cannot parse %s/main.cf file: %m", ip->config_dir);
+
+    /*
+     * Read parameter settings from postconf. See also comments below on
+     * whether we should continue or skip groups after error instead of
+     * bailing out immediately.
+     */
+    buf = vstring_alloc(100);
+    while (vstring_get_nonl(buf, pipe) != VSTREAM_EOF) {
+       if (split_nameval(STR(buf), &name, &value))
+           msg_fatal("Invalid %s/main.cf parameter: %s",
+                     ip->config_dir, STR(buf));
+       if (strcmp(name, VAR_QUEUE_DIR) == 0 && ++count)
+           ip->queue_dir = mystrdup(value);
+       else if (strcmp(name, VAR_DATA_DIR) == 0 && ++count)
+           ip->data_dir = mystrdup(value);
+       else if (strcmp(name, VAR_MULTI_NAME) == 0 && ++count)
+           ip->name = SAVE_INSTANCE_NAME(value);
+       else if (strcmp(name, VAR_MULTI_GROUP) == 0 && ++count)
+           ip->gname = SAVE_INSTANCE_NAME(value);
+       else if (strcmp(name, VAR_MULTI_ENABLE) == 0 && ++count) {
+           /* mail_conf_bool(3) is case insensitive! */
+           ip->enabled = name_code(bool_code, NAME_CODE_FLAG_NONE, value);
+           if (ip->enabled < 0)
+               msg_fatal("Unexpected %s/main.cf entry: %s = %s",
+                         ip->config_dir, VAR_MULTI_ENABLE, value);
+       }
+    }
+    vstring_free(buf);
+
+    /*
+     * XXX We should not bail out while reading a bad secondary main.cf file.
+     * When we manage dozens or more instances, the likelihood increases that
+     * some file will be damaged or missing after a system crash. That is not
+     * a good reason to prevent undamaged Postfix instances from starting.
+     */
+    if (count != REQUEST_PARAM_COUNT)
+       msg_fatal("Failed to obtain all required %s/main.cf parameters",
+                 ip->config_dir);
+
+    if (vstream_pclose(pipe))
+       msg_fatal("Cannot parse %s/main.cf file", ip->config_dir);
+    return (ip);
+}
+
+/* load_all_instances - compute list of Postfix instances */
+
+static void load_all_instances(void)
+{
+    INSTANCE *primary_instance;
+    char  **cpp;
+    ARGV   *secondary_names;
+
+    /*
+     * Avoid unexpected behavior when $multi_instance_directories contains
+     * only comma characters. Count the actual number of elements, before we
+     * decide that the list is empty.
+     */
+    secondary_names = argv_split(var_multi_conf_dirs, "\t\n\r, ");
+
+    /*
+     * First, the primary instance.  This is synthesized out of thin air.
+     */
+    primary_instance = create_primary_instance();
+    if (secondary_names->argc == 0)
+       primary_instance->enabled = 1;          /* Single-instance mode */
+    append_instance(primary_instance);
+
+    /*
+     * Next, instances defined in $multi_instance_directories. Note:
+     * load_instance() has side effects on the global config dictionary, but
+     * this does not affect the values that have already been extracted into
+     * C variables.
+     */
+    for (cpp = secondary_names->argv; *cpp != 0; cpp++)
+       append_instance(load_instance(alloc_instance(*cpp)));
+
+    argv_free(secondary_names);
+}
+
+/* match_instance_selection - match all/name/group constraints */
+
+static int match_instance_selection(INSTANCE *ip, INST_SELECTION *selection)
+{
+    char   *iname;
+    char   *name;
+
+    /*
+     * When selecting (rather than assigning names) an instance, we match by
+     * the instance name, config_directory path, or the instance name suffix
+     * (name without mandatory prefix). Selecting "-" selects the primary
+     * instance.
+     */
+    switch (selection->type) {
+    case INST_SEL_NONE:
+       return (0);
+    case INST_SEL_ALL:
+       return (1);
+    case INST_SEL_GROUP:
+       return (ip->gname != 0 && strcmp(selection->name, ip->gname) == 0);
+    case INST_SEL_NAME:
+       name = selection->name;
+       if (*name == '/' || ip->name == 0)
+           iname = ip->config_dir;
+       else if (!HAS_NAME_PREFIX(name) && HAS_NAME_PREFIX(ip->name))
+           iname = NAME_SUFFIX(ip->name);
+       else
+           iname = ip->name;
+       return (strcmp(name, iname) == 0
+               || (ip->primary && strcmp(name, "-") == 0));
+    default:
+       msg_panic("match_instance_selection: unknown selection type: %d",
+                 selection->type);
+    }
+}
+
+/* check_setenv - setenv() with extreme prejudice */
+
+static void check_setenv(const char *name, const char *value)
+{
+#define CLOBBER 1
+    if (setenv(name, value, CLOBBER) < 0)
+       msg_fatal("setenv: %m");
+}
+
+/* prepend_command_path - prepend command_directory to PATH */
+
+static void prepend_command_path(void)
+{
+    char   *cmd_path;
+
+    /*
+     * Carefully prepend "$command_directory:" to PATH. We can free the
+     * buffer after check_setenv(), since the value is copied there.
+     */
+    cmd_path = safe_getenv("PATH");
+    cmd_path = concatenate(var_command_dir, ":", (cmd_path && *cmd_path) ?
+                          cmd_path : ROOT_PATH, (char *) 0);
+    check_setenv("PATH", cmd_path);
+    myfree(cmd_path);
+}
+
+/* check_shared_dir_status - check and claim shared directories */
+
+static void check_shared_dir_status(void)
+{
+    struct stat st;
+    const SHARED_PATH *sp;
+
+    for (sp = shared_dir_table; sp->param_name; ++sp) {
+       if (stat(sp->param_value[0], &st) < 0)
+           msg_fatal("%s = '%s': directory not found: %m",
+                     sp->param_name, sp->param_value[0]);
+       if (!S_ISDIR(st.st_mode))
+           msg_fatal("%s = '%s' is not a directory",
+                     sp->param_name, sp->param_value[0]);
+       register_claim(var_config_dir, sp->param_name, sp->param_value[0]);
+    }
+}
+
+/* check_safe_name - allow instance or group name with only "safe" characters */
+
+static int check_safe_name(const char *s)
+{
+#define SAFE_PUNCT     "!@%-_=+:./"
+    if (*s == 0)
+       return (0);
+    for (; *s; ++s) {
+       if (!ISALNUM(*s) && !strchr(SAFE_PUNCT, *s))
+           return (0);
+    }
+    return (1);
+}
+
+/* check_name_assignments - Check validity of assigned instance or group name */
+
+static void check_name_assignments(NAME_ASSIGNMENT *assignment)
+{
+
+    /*
+     * Syntax check the assigned instance name. This name is also used to
+     * generate directory pathnames, so we must not allow "/" characters.
+     * 
+     * The value "" will clear the name and is always valid. The command-line
+     * parser has already converted "-" into "", to simplify implementation.
+     */
+    if (assignment->name && *assignment->name) {
+       if (!check_safe_name(assignment->name))
+           msg_fatal("Unsafe characters in new instance name: '%s'",
+                     assignment->name);
+       if (strchr(assignment->name, '/'))
+           msg_fatal("Illegal '/' character in new instance name: '%s'",
+                     assignment->name);
+       if (NEED_NAME_PREFIX(assignment->name))
+           msg_fatal("New instance name must start with '%s'",
+                     NAME_PREFIX);
+    }
+
+    /*
+     * Syntax check the assigned group name.
+     */
+    if (assignment->gname && *assignment->gname) {
+       if (!check_safe_name(assignment->gname))
+           msg_fatal("Unsafe characters in '-G %s'", assignment->gname);
+    }
+}
+
+/* do_name_assignments - assign instance/group names */
+
+static int do_name_assignments(INSTANCE *target, NAME_ASSIGNMENT *assignment)
+{
+    int     export_flags = 0;
+
+    /*
+     * The command-line parser has already converted "-" into "", to simplify
+     * implementation.
+     */
+    if (assignment->name
+       && strcmp(assignment->name, target->name ? target->name : "")) {
+       register_claim(target->config_dir, VAR_MULTI_NAME, assignment->name);
+       if (target->name)
+           myfree(target->name);
+       target->name = SAVE_INSTANCE_NAME(assignment->name);
+       export_flags |= EXP_FLAG_MULTI_NAME;
+    }
+    if (assignment->gname
+       && strcmp(assignment->gname, target->gname ? target->gname : "")) {
+       if (target->gname)
+           myfree(target->gname);
+       target->gname = SAVE_INSTANCE_NAME(assignment->gname);
+       export_flags |= EXP_FLAG_MULTI_GROUP;
+    }
+    return (export_flags);
+}
+
+/* make_private_path - generate secondary pathname using primary as template */
+
+static char *make_private_path(const char *param_name,
+                                      const char *primary_value,
+                                      NAME_ASSIGNMENT *assignment)
+{
+    char   *path;
+    char   *base;
+    char   *end;
+
+    /*
+     * The command-line parser has already converted "-" into "", to simplify
+     * implementation.
+     */
+    if (assignment->name == 0 || *assignment->name == 0)
+       msg_fatal("Missing %s parameter value", param_name);
+
+    if (*primary_value != '/')
+       msg_fatal("Invalid default %s parameter value: '%s': "
+                 "specify an absolute pathname",
+                 param_name, primary_value);
+
+    base = mystrdup(primary_value);
+    if ((end = strrchr(base, '/')) != 0) {
+       /* Drop trailing slashes */
+       if (end[1] == '\0') {
+           while (--end > base && *end == '/')
+               *end = '\0';
+           end = strrchr(base, '/');
+       }
+       /* Drop last path component */
+       while (end > base && *end == '/')
+           *end-- = '\0';
+    }
+    path = concatenate(base[1] ? base : "", "/",
+                      assignment->name, (char *) 0);
+    myfree(base);
+    return (path);
+}
+
+/* assign_new_parameter - assign new instance private name=value */
+
+static void assign_new_parameter(INSTANCE *new, int edit_cmd,
+                                        const char *arg)
+{
+    char   *saved_arg;
+    char   *name;
+    char   *value;
+    char   *end;
+    char  **target = 0;
+
+    /*
+     * With "import", only config_directory is specified on the command line
+     * (either explicitly as config_directory=/path/name, or implicitly as
+     * instance name). The other private directory pathnames are taken from
+     * the existing instance's main.cf file.
+     * 
+     * With "create", all private pathname parameters are specified on the
+     * command line, or generated from an instance name.
+     */
+    saved_arg = mystrdup(arg);
+    if (split_nameval(saved_arg, &name, &value))
+       msg_fatal("Malformed parameter setting '%s'", arg);
+
+    if (strcmp(VAR_CONFIG_DIR, name) == 0) {
+       target = &new->config_dir;
+    } else if (edit_cmd != EDIT_CMD_IMPORT) {
+       if (strcmp(VAR_QUEUE_DIR, name) == 0) {
+           target = &new->queue_dir;
+       } else if (strcmp(VAR_DATA_DIR, name) == 0) {
+           target = &new->data_dir;
+       }
+    }
+    if (target == 0)
+       msg_fatal("Parameter '%s' not valid with action %s",
+                 name, EDIT_CMD_STR(edit_cmd));
+
+    /*
+     * Extract and assign the parameter value. We do a limited number of
+     * checks here. Conflicts between instances are checked by the caller.
+     * More checks may be implemented in the helper script if inspired.
+     */
+    if (*value != '/')
+       msg_fatal("Parameter setting '%s' is not an absolute path", name);
+
+    /* Tolerate+trim trailing "/" from readline completion */
+    for (end = value + strlen(value) - 1; end > value && *end == '/'; --end)
+       *end = 0;
+
+    /* No checks here for "/." or other shoot-foot silliness. */
+    if (end == value)
+       msg_fatal("Parameter setting '%s' is the root directory", name);
+
+    if (*target)
+       myfree(*target);
+    *target = mystrdup(value);
+
+    /*
+     * Cleanup.
+     */
+    myfree(saved_arg);
+}
+
+/* assign_new_parameters - initialize new instance private parameters */
+
+static void assign_new_parameters(INSTANCE *new, int edit_cmd,
+                                  char **argv, NAME_ASSIGNMENT *assignment)
+{
+    const char *owner;
+
+    /*
+     * Sanity check the explicit parameter settings. More stringent checks
+     * may take place in the helper script.
+     */
+    while (*argv)
+       assign_new_parameter(new, edit_cmd, *argv++);
+
+    /*
+     * Initialize any missing private directory pathnames, using the primary
+     * configuration directory parameter values as a template, and using the
+     * assigned instance name to fill in the blanks.
+     * 
+     * When importing an existing instance, load private directory pathnames
+     * from its main.cf file.
+     */
+    if (new->config_dir == 0)
+       new->config_dir =
+           make_private_path(VAR_CONFIG_DIR, var_config_dir, assignment);
+    /* Needed for better-quality error message. */
+    if ((owner = IS_CLAIMED_BY(new->config_dir)) != 0)
+       msg_fatal("new %s=%s is already in use by instance %s=%s",
+                 VAR_CONFIG_DIR, new->config_dir, owner, new->config_dir);
+    if (edit_cmd != EDIT_CMD_IMPORT) {
+       if (new->queue_dir == 0)
+           new->queue_dir =
+               make_private_path(VAR_QUEUE_DIR, var_queue_dir, assignment);
+       if (new->data_dir == 0)
+           new->data_dir =
+               make_private_path(VAR_DATA_DIR, var_data_dir, assignment);
+    } else {
+       load_instance(new);
+    }
+}
+
+/* export_helper_environment - update environment settings for helper command */
+
+static void export_helper_environment(INSTANCE *target, int export_flags)
+{
+    ARGV   *import_env;
+    VSTRING *multi_dirs;
+    const SHARED_PATH *sp;
+    RING   *entry;
+
+    /*
+     * Environment import filter, to enforce consistent behavior whether this
+     * command is started by hand, or at system boot time. This is necessary
+     * because some shell scripts use environment settings to override
+     * main.cf settings.
+     */
+    import_env = argv_split(var_import_environ, ", \t\r\n");
+    clean_env(import_env->argv);
+    argv_free(import_env);
+
+    /*
+     * Prepend $command_directory: to PATH. This supposedly ensures that
+     * naive programs will execute commands from the right Postfix version.
+     */
+    prepend_command_path();
+
+    /*
+     * The following ensures that Postfix's own programs will target the
+     * primary instance.
+     */
+    check_setenv(CONF_ENV_PATH, var_config_dir);
+
+    /*
+     * Export the parameter settings that are shared between instances.
+     */
+    for (sp = shared_dir_table; sp->param_name; ++sp)
+       check_setenv(sp->param_name, sp->param_value[0]);
+
+    /*
+     * Export the target instance's private directory locations.
+     */
+    check_setenv(VAR_CONFIG_DIR, target->config_dir);
+    check_setenv(VAR_QUEUE_DIR, target->queue_dir);
+    check_setenv(VAR_DATA_DIR, target->data_dir);
+
+    /*
+     * With operations that add or delete a secondary instance, we export the
+     * modified multi_instance_directories parameter value for the primary
+     * Postfix instance.
+     */
+    if (export_flags & EXP_FLAG_MULTI_DIRS) {
+       multi_dirs = vstring_alloc(100);
+       FOREACH_SECONDARY_INSTANCE(entry) {
+           if (VSTRING_LEN(multi_dirs) > 0)
+               VSTRING_ADDCH(multi_dirs, ' ');
+           vstring_strcat(multi_dirs, RING_TO_INSTANCE(entry)->config_dir);
+       }
+       check_setenv(VAR_MULTI_CONF_DIRS, STR(multi_dirs));
+       vstring_free(multi_dirs);
+    }
+
+    /*
+     * Export updates for the instance name and group. Empty value (or no
+     * export) means don't update, "-" means clear.
+     */
+    if (export_flags & EXP_FLAG_MULTI_NAME)
+       check_setenv(VAR_MULTI_NAME, target->name && *target->name ?
+                    target->name : "-");
+
+    if (export_flags & EXP_FLAG_MULTI_GROUP)
+       check_setenv(VAR_MULTI_GROUP, target->gname && *target->gname ?
+                    target->gname : "-");
+
+    /*
+     * If we would implement enable/disable commands by exporting the updated
+     * parameter value, then we could skip commands that have no effect, just
+     * like we can skip "assign" commands that make no change.
+     */
+}
+
+/* install_new_instance - install and return newly created instance */
+
+static INSTANCE *install_new_instance(int edit_cmd, char **argv,
+                                             INST_SELECTION *selection,
+                                             NAME_ASSIGNMENT *assignment,
+                                             int *export_flags)
+{
+    INSTANCE *new;
+
+    new = alloc_instance((char *) 0);
+    check_name_assignments(assignment);
+    assign_new_parameters(new, edit_cmd, argv, assignment);
+    *export_flags |=
+       (do_name_assignments(new, assignment) | EXP_FLAG_MULTI_DIRS);
+    insert_instance(new, selection);
+    return (new);
+}
+
+/* update_instance - update existing instance, return export flags */
+
+static int update_instance(INSTANCE *target, NAME_ASSIGNMENT *assignment)
+{
+    int     export_flags;
+
+    check_name_assignments(assignment);
+    export_flags = do_name_assignments(target, assignment);
+    return (export_flags);
+}
+
+/* select_existing_instance - return instance selected for management */
+
+static INSTANCE *select_existing_instance(INST_SELECTION *selection,
+                                                 int unlink_flag,
+                                                 int *export_flags)
+{
+    INSTANCE *selected = 0;
+    RING   *entry;
+    INSTANCE *ip;
+
+#define DONT_UNLINK    0
+#define DO_UNLINK      1
+
+    if (selection->type != INST_SEL_NAME)
+       msg_fatal("Select an instance via '-i name'");
+
+    /* Find the selected instance and its predecessor */
+    FOREACH_INSTANCE(entry) {
+       if (match_instance_selection(ip = RING_TO_INSTANCE(entry), selection)) {
+           selected = ip;
+           break;
+       }
+    }
+
+    if (selected == 0)
+       msg_fatal("No instance named %s", selection->name);
+
+    if (unlink_flag) {
+       /* Splice the target instance out of the list */
+       if (ring_pred(entry) == instance_hd)
+           msg_fatal("Cannot remove the primary instance");
+       if (selected->enabled)
+           msg_fatal("Cannot remove enabled instances");
+       ring_detach(entry);
+       if (export_flags == 0)
+           msg_panic("select_existing_instance: no export flags");
+       *export_flags |= EXP_FLAG_MULTI_DIRS;
+    }
+    return (selected);
+}
+
+/* manage - create/destroy/... manage instances */
+
+static NORETURN manage(int edit_cmd, int argc, char **argv,
+                              INST_SELECTION *selection,
+                              NAME_ASSIGNMENT *assignment)
+{
+    char   *cmd;
+    INSTANCE *target;
+    int     export_flags;
+
+    /*
+     * Edit mode is not subject to iterator controls.
+     */
+#define NO_EXPORT_FLAGS                ((int *) 0)
+    export_flags = 0;
+
+    switch (edit_cmd) {
+    case EDIT_CMD_INIT:
+       target = create_primary_instance();
+       break;
+
+    case EDIT_CMD_CREATE:
+    case EDIT_CMD_IMPORT:
+       load_all_instances();
+       target = install_new_instance(edit_cmd, argv, selection,
+                                     assignment, &export_flags);
+       break;
+
+    case EDIT_CMD_ASSIGN:
+       load_all_instances();
+       target =
+           select_existing_instance(selection, DONT_UNLINK, NO_EXPORT_FLAGS);
+       export_flags |= update_instance(target, assignment);
+       if (export_flags == 0)
+           exit(0);
+       break;
+
+    case EDIT_CMD_DESTROY:
+    case EDIT_CMD_DEPORT:
+       load_all_instances();
+       target = select_existing_instance(selection, DO_UNLINK, &export_flags);
+       break;
+
+    default:
+       load_all_instances();
+       target =
+           select_existing_instance(selection, DONT_UNLINK, NO_EXPORT_FLAGS);
+       break;
+    }
+
+    /*
+     * Set up the helper script's process environment, and execute the helper
+     * script.
+     */
+#define HELPER "postmulti-script"
+
+    export_helper_environment(target, export_flags);
+    cmd = concatenate(var_daemon_dir, "/" HELPER, (char *) 0);
+    execl(cmd, cmd, "-e", EDIT_CMD_STR(edit_cmd), (char *) 0);
+    msg_fatal("%s: %m", cmd);
+}
+
+/* run_user_command - execute external command with requested MAIL_CONFIG env */
+
+static int run_user_command(INSTANCE *ip, int iter_cmd, int iter_flags,
+                                   char **argv)
+{
+    WAIT_STATUS_T status;
+    int     pid;
+    int     wpid;
+
+    /*
+     * Set up a process environment. The postfix(1) command needs MAIL_CONFIG
+     * (or the equivalent command-line option); it overrides everything else.
+     * 
+     * postmulti(1) typically runs various Postfix utilities (postsuper, ...) in
+     * the context of one or more instances. It can also run various scripts
+     * on the users PATH. So we can't clobber the user's PATH, but do want to
+     * make sure that the utilities in $command_directory are always found in
+     * the right place (or at all).
+     */
+    switch (pid = fork()) {
+    case -1:
+       msg_warn("fork %s: %m", argv[0]);
+       return -1;
+    case 0:
+       check_setenv(CONF_ENV_PATH, ip->config_dir);
+       if (iter_cmd != ITER_CMD_POSTFIX) {
+           check_setenv(VAR_DAEMON_DIR, var_daemon_dir);
+           check_setenv(VAR_COMMAND_DIR, var_command_dir);
+           check_setenv(VAR_CONFIG_DIR, ip->config_dir);
+           check_setenv(VAR_QUEUE_DIR, ip->queue_dir);
+           check_setenv(VAR_DATA_DIR, ip->data_dir);
+           check_setenv(VAR_MULTI_NAME, ip->name ? ip->name : "");
+           check_setenv(VAR_MULTI_GROUP, ip->gname ? ip->gname : "");
+           check_setenv(VAR_MULTI_ENABLE, ip->enabled ?
+                        CONFIG_BOOL_YES : CONFIG_BOOL_NO);
+           prepend_command_path();
+       }
+
+       /*
+        * Replace: postfix -- start ... With: postfix -- check ...
+        */
+       if (iter_cmd == ITER_CMD_POSTFIX
+           && (iter_flags & ITER_FLAG_CHECK_DISABLED) && !ip->enabled)
+           argv[2] = "check";
+
+       execvp(argv[0], argv);
+       msg_fatal("execvp %s: %m", argv[0]);
+    default:
+       do {
+           wpid = waitpid(pid, &status, 0);
+       } while (wpid == -1 && errno == EINTR);
+       return (wpid == -1 ? -1 :
+               WIFEXITED(status) ? WEXITSTATUS(status) : 1);
+    }
+}
+
+/* word_in_list - look up command in start, stop, or control list */
+
+static int word_in_list(char *cmdlist, const char *cmd)
+{
+    char   *saved;
+    char   *cp;
+    char   *elem;
+
+    cp = saved = mystrdup(cmdlist);
+    while ((elem = mystrtok(&cp, "\t\n\r, ")) != 0 && strcmp(elem, cmd) != 0)
+        /* void */ ;
+    myfree(saved);
+    return (elem != 0);
+}
+
+/* iterate_postfix_command - execute postfix(1) command */
+
+static int iterate_postfix_command(int iter_cmd, int argc, char **argv,
+                                          INST_SELECTION *selection)
+{
+    int     exit_status;
+    char   *cmd;
+    ARGV   *my_argv;
+    int     iter_flags;
+
+    /*
+     * Override the iterator controls.
+     */
+    if (word_in_list(var_multi_start_cmds, argv[0])) {
+       iter_flags = ITER_FLAG_CHECK_DISABLED;
+    } else if (word_in_list(var_multi_stop_cmds, argv[0])) {
+       iter_flags = ITER_FLAG_SKIP_DISABLED | ITER_FLAG_REVERSE;
+    } else if (word_in_list(var_multi_cntrl_cmds, argv[0])) {
+       iter_flags = ITER_FLAG_SKIP_DISABLED;
+    } else {
+       iter_flags = 0;
+    }
+
+    /*
+     * Override the command line in a straightforward manner: prepend
+     * "postfix --" to the command arguments. Other overrides (environment,
+     * start -> check) are implemented below the iterator.
+     */
+#define POSTFIX_CMD    "postfix"
+
+    my_argv = argv_alloc(argc + 2);
+    cmd = concatenate(var_command_dir, "/" POSTFIX_CMD, (char *) 0);
+    argv_add(my_argv, cmd, "--", (char *) 0);
+    myfree(cmd);
+    while (*argv)
+       argv_add(my_argv, *argv++, (char *) 0);
+
+    /*
+     * Execute the command for all applicable Postfix instances.
+     */
+    exit_status =
+       iterate_command(iter_cmd, iter_flags, my_argv->argv, selection);
+
+    argv_free(my_argv);
+    return (exit_status);
+}
+
+/* list_instances - list all selected instances */
+
+static void list_instances(int iter_flags, INST_SELECTION *selection)
+{
+    RING   *entry;
+    INSTANCE *ip;
+
+    /*
+     * Iterate over the selected instances.
+     */
+    FOREACH_ITERATOR_INSTANCE(iter_flags, entry) {
+       ip = RING_TO_INSTANCE(entry);
+       if (match_instance_selection(ip, selection))
+           vstream_printf("%-15s %-15s %-9s %s\n",
+                          ip->name ? ip->name : "-",
+                          ip->gname ? ip->gname : "-",
+                          ip->enabled ? "y" : "n",
+                          ip->config_dir);
+    }
+    if (vstream_fflush(VSTREAM_OUT))
+       msg_fatal("error writing output: %m");
+}
+
+/* iterate_command - execute command for selected instances */
+
+static int iterate_command(int iter_cmd, int iter_flags, char **argv,
+                                  INST_SELECTION *selection)
+{
+    int     exit_status = 0;
+    int     matched = 0;
+    RING   *entry;
+    INSTANCE *ip;
+
+    /*
+     * Iterate over the selected instances.
+     */
+    FOREACH_ITERATOR_INSTANCE(iter_flags, entry) {
+       ip = RING_TO_INSTANCE(entry);
+       if (!match_instance_selection(ip, selection))
+           continue;
+       matched = 1;
+
+       /* Run the requested command */
+       if (run_user_command(ip, iter_cmd, iter_flags, argv) != 0)
+           exit_status = 1;
+    }
+    if (matched == 0)
+       msg_fatal("No matching instances");
+
+    return (exit_status);
+}
+
+/* iterate - Iterate over all or selected instances */
+
+static NORETURN iterate(int iter_cmd, int iter_flags, int argc, char **argv,
+                               INST_SELECTION *selection)
+{
+    int     exit_status;
+
+    /*
+     * In iterator mode, no selection means wild-card selection.
+     */
+    if (selection->type == INST_SEL_NONE)
+       selection->type = INST_SEL_ALL;
+
+    /*
+     * Load the in-memory instance table from main.cf files.
+     */
+    load_all_instances();
+
+    /*
+     * Iterate over the selected instances.
+     */
+    switch (iter_cmd) {
+    case ITER_CMD_POSTFIX:
+       exit_status = iterate_postfix_command(iter_cmd, argc, argv, selection);
+       break;
+    case ITER_CMD_LIST:
+       list_instances(iter_flags, selection);
+       exit_status = 0;
+       break;
+    case ITER_CMD_GENERIC:
+       exit_status = iterate_command(iter_cmd, iter_flags, argv, selection);
+       break;
+    default:
+       msg_panic("iterate: unknown mode: %d", iter_cmd);
+    }
+    exit(exit_status);
+}
+
+static NORETURN usage(const char *progname)
+{
+    msg_fatal("Usage:"
+             "%s -l [-v] [-a] [-g group] [-i instance] | "
+             "%s -p [-v] [-a] [-g group] [-i instance] command... | "
+             "%s -x [-v] [-a] [-i name] [-g group] command... | "
+             "%s -e action [-v] [-a] [-i name] [-g group] [-I name] "
+             "[-G group] [param=value ...]",
+             progname, progname, progname, progname);
+}
+
+MAIL_VERSION_STAMP_DECLARE;
+
+/* main - iterate commands over multiple instance or manage instances */
+
+int     main(int argc, char **argv)
+{
+    int     fd;
+    struct stat st;
+    char   *slash;
+    char   *config_dir;
+    int     ch;
+    static const CONFIG_STR_TABLE str_table[] = {
+       VAR_MULTI_START_CMDS, DEF_MULTI_START_CMDS, &var_multi_start_cmds, 0, 0,
+       VAR_MULTI_STOP_CMDS, DEF_MULTI_STOP_CMDS, &var_multi_stop_cmds, 0, 0,
+       VAR_MULTI_CNTRL_CMDS, DEF_MULTI_CNTRL_CMDS, &var_multi_cntrl_cmds, 0, 0,
+       0,
+    };
+    int     instance_select_count = 0;
+    int     command_mode_count = 0;
+    INST_SELECTION selection;
+    NAME_ASSIGNMENT assignment;
+    int     iter_flags = ITER_FLAG_DEFAULT;
+    int     cmd_mode = 0;
+    int     code;
+
+    selection.type = INST_SEL_NONE;
+    assignment.name = assignment.gname = 0;
+
+    /*
+     * Fingerprint executables and core dumps.
+     */
+    MAIL_VERSION_STAMP_ALLOCATE;
+
+    /*
+     * Be consistent with file permissions.
+     */
+    umask(022);
+
+    /*
+     * To minimize confusion, make sure that the standard file descriptors
+     * are open before opening anything else. XXX Work around for 44BSD where
+     * fstat can return EBADF on an open file descriptor.
+     */
+    for (fd = 0; fd < 3; fd++)
+       if (fstat(fd, &st) == -1
+           && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
+           msg_fatal("open /dev/null: %m");
+
+    /*
+     * Set up diagnostics. XXX What if stdin is the system console during
+     * boot time? It seems a bad idea to log startup errors to the console.
+     * This is UNIX, a system that can run without hand holding.
+     */
+    if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
+       argv[0] = slash + 1;
+    if (isatty(STDERR_FILENO))
+       msg_vstream_init(argv[0], VSTREAM_ERR);
+    msg_syslog_init(argv[0], LOG_PID, LOG_FACILITY);
+
+    if ((config_dir = getenv(CONF_ENV_PATH)) != 0
+       && strcmp(config_dir, DEF_CONFIG_DIR) != 0)
+       msg_fatal("Non-default configuration directory: %s=%s",
+                 CONF_ENV_PATH, config_dir);
+
+    /*
+     * Parse switches.
+     */
+    while ((ch = GETOPT(argc, argv, "ae:g:i:G:I:lpRvx")) > 0) {
+       switch (ch) {
+       default:
+           usage(argv[0]);
+           /* NOTREACHED */
+       case 'a':
+           if (selection.type != INST_SEL_ALL)
+               instance_select_count++;
+           selection.type = INST_SEL_ALL;
+           break;
+       case 'e':
+           if ((code = EDIT_CMD_CODE(optarg)) < 0)
+               msg_fatal("Invalid '-e' edit action '%s'. Specify '%s', "
+                         "'%s', '%s', '%s', '%s', '%s', '%s', '%s' or '%s'",
+                         optarg,
+                         EDIT_CMD_STR(EDIT_CMD_CREATE),
+                         EDIT_CMD_STR(EDIT_CMD_DESTROY),
+                         EDIT_CMD_STR(EDIT_CMD_IMPORT),
+                         EDIT_CMD_STR(EDIT_CMD_DEPORT),
+                         EDIT_CMD_STR(EDIT_CMD_ENABLE),
+                         EDIT_CMD_STR(EDIT_CMD_DISABLE),
+                         EDIT_CMD_STR(EDIT_CMD_ASSIGN),
+                         EDIT_CMD_STR(EDIT_CMD_INIT),
+                         optarg);
+           if (cmd_mode != code)
+               command_mode_count++;
+           cmd_mode = code;
+           break;
+       case 'g':
+           instance_select_count++;
+           selection.type = INST_SEL_GROUP;
+           selection.name = optarg;
+           break;
+       case 'i':
+           instance_select_count++;
+           selection.type = INST_SEL_NAME;
+           selection.name = optarg;
+           break;
+       case 'G':
+           if (assignment.gname != 0)
+               msg_fatal("Specify at most one '-G' option");
+           assignment.gname = strcmp(optarg, "-") == 0 ? "" : optarg;
+           break;
+       case 'I':
+           if (assignment.name != 0)
+               msg_fatal("Specify at most one '-I' option");
+           assignment.name = strcmp(optarg, "-") == 0 ? "" : optarg;
+           break;
+       case 'l':
+           if (cmd_mode != ITER_CMD_LIST)
+               command_mode_count++;
+           cmd_mode = ITER_CMD_LIST;
+           break;
+       case 'p':
+           if (cmd_mode != ITER_CMD_POSTFIX)
+               command_mode_count++;
+           cmd_mode = ITER_CMD_POSTFIX;
+           break;
+       case 'R':
+           iter_flags ^= ITER_FLAG_REVERSE;
+           break;
+       case 'v':
+           msg_verbose++;
+           check_setenv(CONF_ENV_VERB, "");
+           break;
+       case 'x':
+           if (cmd_mode != ITER_CMD_GENERIC)
+               command_mode_count++;
+           cmd_mode = ITER_CMD_GENERIC;
+           break;
+       }
+    }
+
+    /*
+     * Report missing arguments, or wrong arguments in the wrong context.
+     */
+    if (instance_select_count > 1)
+       msg_fatal("Specity no more than one of '-a', '-g', '-i'");
+
+    if (command_mode_count != 1)
+       msg_fatal("Specify exactly one of '-e', '-l', '-p', '-x'");
+
+    if (cmd_mode == ITER_CMD_LIST && argc > optind)
+       msg_fatal("Command not allowed with '-l'");
+
+    if (cmd_mode == ITER_CMD_POSTFIX || cmd_mode == ITER_CMD_GENERIC)
+       if (argc == optind)
+           msg_fatal("Command required with '-p' or '-x' option");
+
+    if (cmd_mode == ITER_CMD_POSTFIX || (cmd_mode & EDIT_CMD_MASK_ALL))
+       if (iter_flags != ITER_FLAG_DEFAULT)
+           msg_fatal("The '-p' and '-e' options preclude the use of '-R'");
+
+    if ((cmd_mode & EDIT_CMD_MASK_ASSIGN) == 0
+       && (assignment.name || assignment.gname)) {
+       if ((cmd_mode & EDIT_CMD_MASK_ALL) == 0)
+           msg_fatal("Cannot assign instance name or group without '-e %s'",
+                     EDIT_CMD_STR(EDIT_CMD_ASSIGN));
+       else
+           msg_fatal("Cannot assign instance name or group with '-e %s'",
+                     EDIT_CMD_STR(cmd_mode));
+    }
+    if (cmd_mode & EDIT_CMD_MASK_ALL) {
+       if (cmd_mode == EDIT_CMD_ASSIGN
+           && (assignment.name == 0 && assignment.gname == 0))
+           msg_fatal("Specify new instance name or group with '-e %s'",
+                     EDIT_CMD_STR(cmd_mode));
+
+       if ((cmd_mode & ~EDIT_CMD_MASK_ADD) != 0 && argc > optind)
+           msg_fatal("Parameter overrides not valid with '-e %s'",
+                     EDIT_CMD_STR(cmd_mode));
+    }
+
+    /*
+     * Proces main.cf parameters.
+     */
+    mail_conf_read();
+    get_mail_conf_str_table(str_table);
+
+    /*
+     * Sanity checks.
+     */
+    check_shared_dir_status();
+
+    /*
+     * Iterate over selected instances, or manipulate one instance.
+     */
+    if (cmd_mode & ITER_CMD_MASK_ALL)
+       iterate(cmd_mode, iter_flags, argc - optind, argv + optind, &selection);
+    else
+       manage(cmd_mode, argc - optind, argv + optind, &selection, &assignment);
+}
index df8b980adc6b3b1ecc4ba02966c62a0a64db16e6..52f0327e3a58cd8c7bc26dec07d5d5ed8c92fbe2 100644 (file)
@@ -436,6 +436,7 @@ struct QMGR_PEER {
 
 extern QMGR_ENTRY *qmgr_job_entry_select(QMGR_TRANSPORT *);
 extern QMGR_PEER *qmgr_peer_select(QMGR_JOB *);
+extern void qmgr_job_blocker_update(QMGR_QUEUE *);
 
 extern QMGR_JOB *qmgr_job_obtain(QMGR_MESSAGE *, QMGR_TRANSPORT *);
 extern void qmgr_job_free(QMGR_JOB *);
index 9f89e0a7335dfb7aeddebffaa937204a38d1af20..71eba9f0ad23184d51b288ffe673ac467b2aec17 100644 (file)
@@ -299,29 +299,25 @@ void    qmgr_entry_done(QMGR_ENTRY *entry, int which)
     }
 
     /*
-     * If the queue was blocking some of the jobs on the job list, check if
-     * the concurrency limit has lifted. If there are still some pending
-     * deliveries, give it a try and unmark all transport blockers at once.
-     * The qmgr_job_entry_select() will do the rest. In either case make sure
-     * the queue is not marked as a blocker anymore, with extra handling of
-     * queues which were declared dead.
+     * We implement a rate-limited queue by emulating a slow delivery
+     * channel. We insert the artificial delays with qmgr_queue_suspend().
      * 
-     * Note that changing the blocker status also affects the candidate cache.
-     * Most of the cases would be automatically recognized by the current job
-     * change, but we play safe and reset the cache explicitly below.
-     * 
-     * Keeping the transport blocker tag odd is an easy way to make sure the tag
-     * never matches jobs that are not explicitly marked as blockers.
+     * When a queue is suspended, we must postpone any job scheduling decisions
+     * until the queue is resumed. Otherwise, we make those decisions now.
+     * The job scheduling decisions are made by qmgr_job_blocker_update().
      */
-    if (queue->blocker_tag == transport->blocker_tag) {
-       if (queue->window > queue->busy_refcount && queue->todo.next != 0) {
-           transport->blocker_tag += 2;
-           transport->job_current = transport->job_list.next;
-           transport->candidate_cache_current = 0;
-       }
-       if (queue->window > queue->busy_refcount || QMGR_QUEUE_THROTTLED(queue))
-           queue->blocker_tag = 0;
+    if (which == QMGR_QUEUE_BUSY && transport->rate_delay > 0) {
+       if (queue->window > 1)
+           msg_panic("%s: queue %s/%s: window %d > 1 on rate-limited service",
+                     myname, transport->name, queue->name, queue->window);
+       if (QMGR_QUEUE_THROTTLED(queue))        /* XXX */
+           qmgr_queue_unthrottle(queue);
+       if (QMGR_QUEUE_READY(queue))
+           qmgr_queue_suspend(queue, transport->rate_delay);
     }
+    if (!QMGR_QUEUE_SUSPENDED(queue)
+       && queue->blocker_tag == transport->blocker_tag)
+       qmgr_job_blocker_update(queue);
 
     /*
      * When there are no more entries for this peer, discard the peer
@@ -337,19 +333,6 @@ void    qmgr_entry_done(QMGR_ENTRY *entry, int which)
     if (which == QMGR_QUEUE_BUSY)
        queue->last_done = event_time();
 
-    /*
-     * Suspend a rate-limited queue, so that mail trickles out.
-     */
-    if (which == QMGR_QUEUE_BUSY && transport->rate_delay > 0) {
-       if (queue->window > 1)
-           msg_panic("%s: queue %s/%s: window %d > 1 on rate-limited service",
-                     myname, transport->name, queue->name, queue->window);
-       if (QMGR_QUEUE_THROTTLED(queue))        /* XXX */
-           qmgr_queue_unthrottle(queue);
-       if (QMGR_QUEUE_READY(queue))
-           qmgr_queue_suspend(queue, transport->rate_delay);
-    }
-
     /*
      * When the in-core queue for this site is empty and when this site is
      * not dead or suspended, discard the in-core queue. When this site is
index ad727f43a6da538d07e06bf0c5adce97b79b56e5..7de70f25c3f1b7115c35780f152fefc68aa16ffe 100644 (file)
@@ -18,6 +18,9 @@
 /*
 /*     QMGR_ENTRY *qmgr_job_entry_select(transport)
 /*     QMGR_TRANSPORT *transport;
+/*
+/*     void    qmgr_job_blocker_update(queue)
+/*     QMGR_QUEUE *queue;
 /* DESCRIPTION
 /*     These routines add/delete/manipulate per-transport jobs.
 /*     Each job corresponds to a specific transport and message.
 /*     If necessary, an attempt to read more recipients into core is made.
 /*     This can result in creation of more job, queue and entry structures.
 /*
+/*     qmgr_job_blocker_update() updates the status of blocked
+/*     jobs after a decrease in the queue's concurrency level,
+/*     after the queue is throttled, or after the queue is resumed
+/*     from suspension.
+/*
 /*     qmgr_job_move_limits() takes care of proper distribution of the
 /*     per-transport recipients limit among the per-transport jobs.
 /*     Should be called whenever a job's recipient slot becomes available.
@@ -937,3 +945,36 @@ QMGR_ENTRY *qmgr_job_entry_select(QMGR_TRANSPORT *transport)
     transport->job_current = 0;
     return (0);
 }
+
+/* qmgr_job_blocker_update - update "blocked job" status */
+
+void     qmgr_job_blocker_update(QMGR_QUEUE *queue)
+{
+    QMGR_TRANSPORT *transport = queue->transport;
+
+    /*
+     * If the queue was blocking some of the jobs on the job list, check if
+     * the concurrency limit has lifted. If there are still some pending
+     * deliveries, give it a try and unmark all transport blockers at once.
+     * The qmgr_job_entry_select() will do the rest. In either case make sure
+     * the queue is not marked as a blocker anymore, with extra handling of
+     * queues which were declared dead.
+     * 
+     * Note that changing the blocker status also affects the candidate cache.
+     * Most of the cases would be automatically recognized by the current job
+     * change, but we play safe and reset the cache explicitly below.
+     * 
+     * Keeping the transport blocker tag odd is an easy way to make sure the tag
+     * never matches jobs that are not explicitly marked as blockers.
+     */
+    if (queue->blocker_tag == transport->blocker_tag) {
+       if (queue->window > queue->busy_refcount && queue->todo.next != 0) {
+           transport->blocker_tag += 2;
+           transport->job_current = transport->job_list.next;
+           transport->candidate_cache_current = 0;
+       }
+       if (queue->window > queue->busy_refcount || QMGR_QUEUE_THROTTLED(queue))
+           queue->blocker_tag = 0;
+    }
+}
+
index 3bc6782b2f73efbd51694edda28c5928627bf860..d35b7db0cb9249733bd93b3fb3d54e8d21459595 100644 (file)
 /*     "slow open" mode, and eliminates the "thundering herd" problem.
 /*
 /*     qmgr_queue_suspend() suspends delivery for this destination
-/*     briefly.
+/*     briefly. This function invalidates any scheduling decisions
+/*     that are based on the present queue's concurrency window.
+/*     To compensate for work skipped by qmgr_entry_done(), the
+/*     status of blocker jobs is re-evaluated after the queue is
+/*     resumed.
 /* DIAGNOSTICS
 /*     Panic: consistency check failure.
 /* LICENSE
@@ -152,9 +156,20 @@ static void qmgr_queue_resume(int event, char *context)
     /*
      * Every event handler that leaves a queue in the "ready" state should
      * remove the queue when it is empty.
+     * 
+     * XXX Do not omit the redundant test below. It is here to simplify code
+     * consistency checks. The check is trivially eliminated by the compiler
+     * optimizer. There is no need to sacrifice code clarity for the sake of
+     * performance.
+     * 
+     * XXX Do not expose the blocker job logic here. Rate-limited queues are not
+     * a performance-critical feature. Here, too, there is no need to sacrifice
+     * code clarity for the sake of performance.
      */
     if (QMGR_QUEUE_READY(queue) && queue->todo.next == 0 && queue->busy.next == 0)
        qmgr_queue_done(queue);
+    else
+       qmgr_job_blocker_update(queue);
 }
 
 /* qmgr_queue_suspend - briefly suspend a destination */
index 29a1f53e1ce9f12b093ea042c92494cb382060d0..434d75efc38503b8298e0f29fe4c8c32ba71d078 100644 (file)
@@ -291,6 +291,8 @@ QMGR_TRANSPORT *qmgr_transport_select(void)
            continue;
        need = xport->pending + 1;
        for (queue = xport->queue_list.next; queue; queue = queue->peers.next) {
+           if (QMGR_QUEUE_READY(queue) == 0)
+               continue;
            if ((need -= MIN5af51743e4eef(queue->window - queue->busy_refcount,
                                          queue->todo_refcount)) <= 0) {
                QMGR_LIST_ROTATE(qmgr_transport_list, xport, peers);
index e5b1472489153d9a9da1f1a8df884c3ad67dd321..14bd673d7fcfda1d4ca1cb28cd08ea0d7905d0ef 100644 (file)
 /*     append the specified domain name to incomplete addresses.
 /* .IP "\fBsyslog_facility (mail)\fR"
 /*     The syslog facility of Postfix logging.
-/* .IP "\fBsyslog_name (postfix)\fR"
+/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 /*     The mail system name that is prepended to the process name in syslog
 /*     records, so that "smtpd" becomes, for example, "postfix/smtpd".
 /* FILES
 /*     postqueue(1), mail queue control
 /*     syslogd(8), system logging
 /* README_FILES
+/* .ad
+/* .fi
 /*     Use "\fBpostconf readme_directory\fR" or
 /*     "\fBpostconf html_directory\fR" to locate this information.
+/* .na
+/* .nf
 /*     DEBUG_README, Postfix debugging howto
 /*     ETRN_README, Postfix ETRN howto
 /*     VERP_README, Postfix VERP howto
@@ -754,7 +758,7 @@ static void enqueue(const int flags, const char *encoding,
            rec_fprintf(dst, REC_TYPE_NORM, "From: %s", saved_sender);
        rec_fprintf(dst, REC_TYPE_NORM, "Subject: probe");
        if (recipients) {
-           rec_fprintf(dst, REC_TYPE_NORM, "To:");
+           rec_fprintf(dst, REC_TYPE_CONT, "To:");
            for (cpp = recipients; *cpp != 0; cpp++) {
                rec_fprintf(dst, REC_TYPE_NORM, "       %s%s",
                            *cpp, cpp[1] ? "," : "");
index 2d24a069c1c65266a5655573a526ce224d8887e1..64b8ffbb86864d77c75cf8a2d6bcd4a075049aa7 100644 (file)
@@ -355,6 +355,7 @@ smtp_rcpt.o: ../../include/dsn_mask.h
 smtp_rcpt.o: ../../include/header_body_checks.h
 smtp_rcpt.o: ../../include/header_opts.h
 smtp_rcpt.o: ../../include/htable.h
+smtp_rcpt.o: ../../include/mail_params.h
 smtp_rcpt.o: ../../include/maps.h
 smtp_rcpt.o: ../../include/match_list.h
 smtp_rcpt.o: ../../include/match_ops.h
index b202fd21938b4d26f90e358244a276a4943264f8..645d5ae2a1efbd26c60b1e29276c5e9484cd49a7 100644 (file)
        VAR_LMTP_SENDER_AUTH, DEF_LMTP_SENDER_AUTH, &var_smtp_sender_auth,
        VAR_LMTP_CNAME_OVERR, DEF_LMTP_CNAME_OVERR, &var_smtp_cname_overr,
        VAR_LMTP_SASL_AUTH_SOFT_BOUNCE, DEF_LMTP_SASL_AUTH_SOFT_BOUNCE, &var_smtp_sasl_auth_soft_bounce,
+       VAR_LMTP_ASSUME_FINAL, DEF_LMTP_ASSUME_FINAL, &var_lmtp_assume_final,
        0,
     };
index d4c7314bd391b73599c04b55991e5843e84b026c..7546bcf5b30bc4f78f9ead13e642ccd5d8f2ec26 100644 (file)
 /* .IP "\fBipc_timeout (3600s)\fR"
 /*     The time limit for sending or receiving information over an internal
 /*     communication channel.
+/* .IP "\fBlmtp_assume_final (no)\fR"
+/*     When an LMTP server announces no DSN support, assume that the
+/*     server performs final delivery, and send "delivered" delivery status
+/*     notifications instead of "relayed".
 /* .IP "\fBlmtp_tcp_port (24)\fR"
 /*     The default TCP port that the Postfix LMTP client connects to.
 /* .IP "\fBmax_idle (100s)\fR"
 /*     Randomize the order of equal-preference MX host addresses.
 /* .IP "\fBsyslog_facility (mail)\fR"
 /*     The syslog facility of Postfix logging.
-/* .IP "\fBsyslog_name (postfix)\fR"
+/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 /*     The mail system name that is prepended to the process name in syslog
 /*     records, so that "smtpd" becomes, for example, "postfix/smtpd".
 /* .PP
@@ -781,6 +785,7 @@ char   *var_smtp_head_chks;
 char   *var_smtp_mime_chks;
 char   *var_smtp_nest_chks;
 char   *var_smtp_body_chks;
+bool    var_lmtp_assume_final;
 
  /* Special handling of 535 AUTH errors. */
 char   *var_smtp_sasl_auth_cache_name;
index 31599464b2edb52baab59e8cb696029c01289bb5..ebfb5e328b72fa58342cacd52f2fd7b5d387d083 100644 (file)
 
 /* Global library. */
 
+#include <mail_params.h>
 #include <deliver_request.h>           /* smtp_rcpt_done */
 #include <deliver_completed.h>         /* smtp_rcpt_done */
 #include <sent.h>                      /* smtp_rcpt_done */
@@ -132,19 +133,36 @@ void    smtp_rcpt_done(SMTP_STATE *state, SMTP_RESP *resp, RECIPIENT *rcpt)
     DELIVER_REQUEST *request = state->request;
     SMTP_SESSION *session = state->session;
     DSN_BUF *why = state->why;
+    const char *dsn_action = "relayed";
     int     status;
 
     /*
-     * Report success and delete the recipient from the delivery request.
-     * Defer if the success can't be reported. Don't send a DSN "SUCCESS"
-     * notification if the receiving site announced DSN support.
-     * 
-     * Note: the DSN action is ignored in case of address probes.
+     * Assume this was intermediate delivery when the server announced DSN
+     * support, and don't send a DSN "SUCCESS" notification.
      */
     if (session->features & SMTP_FEATURE_DSN)
        rcpt->dsn_notify &= ~DSN_NOTIFY_SUCCESS;
 
-    dsb_update(why, resp->dsn, "relayed", DSB_MTYPE_DNS, session->host,
+    /*
+     * Assume this was final delivery when the LMTP server announced no DSN
+     * support. In backwards compatibility mode, send a "relayed" instead of
+     * a "delivered" DSN "SUCCESS" notification. Do not attempt to "simplify"
+     * the expression. The redundancy is for clarity. It is trivially
+     * eliminated by the compiler. There is no need to sacrifice clarity for
+     * the sake of "performance".
+     */
+    if ((session->features & SMTP_FEATURE_DSN) == 0
+       && (state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) != 0
+       && var_lmtp_assume_final != 0)
+       dsn_action = "delivered";
+
+    /*
+     * Report success and delete the recipient from the delivery request.
+     * Defer if the success can't be reported.
+     * 
+     * Note: the DSN action is ignored in case of address probes.
+     */
+    dsb_update(why, resp->dsn, dsn_action, DSB_MTYPE_DNS, session->host,
               DSB_DTYPE_SMTP, resp->str, "%s", resp->str);
 
     status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
index 5c9e78f4fca227a5dc6a18357be8ba984f91f694..c5dcc8921890bda5e83c7e45527c1e013a66b73d 100644 (file)
@@ -2248,6 +2248,7 @@ static void mail_reset(SMTPD_STATE *state)
 {
     state->msg_size = 0;
     state->act_size = 0;
+    state->flags &= SMTPD_MASK_MAIL_KEEP;
 
     /*
      * Unceremoniously close the pipe to the cleanup service. The cleanup
@@ -2861,6 +2862,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
 #endif
     }
     smtpd_chat_reply(state, "354 End data with <CR><LF>.<CR><LF>");
+    state->where = SMTPD_AFTER_DATA;
 
     /*
      * Copy the message content. If the cleanup process has a problem, keep
@@ -4119,6 +4121,7 @@ typedef struct SMTPD_CMD {
 
 #define SMTPD_CMD_FLAG_LIMIT   (1<<0)  /* limit usage */
 #define SMTPD_CMD_FLAG_PRE_TLS (1<<1)  /* allow before STARTTLS */
+#define SMTPD_CMD_FLAG_LAST    (1<<2)  /* last in PIPELINING command group */
 
 static SMTPD_CMD smtpd_cmd_table[] = {
     SMTPD_CMD_HELO, helo_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS,
@@ -4131,14 +4134,14 @@ static SMTPD_CMD smtpd_cmd_table[] = {
 #endif
     SMTPD_CMD_MAIL, mail_cmd, 0,
     SMTPD_CMD_RCPT, rcpt_cmd, 0,
-    SMTPD_CMD_DATA, data_cmd, 0,
+    SMTPD_CMD_DATA, data_cmd, SMTPD_CMD_FLAG_LAST,
     SMTPD_CMD_RSET, rset_cmd, SMTPD_CMD_FLAG_LIMIT,
     SMTPD_CMD_NOOP, noop_cmd, SMTPD_CMD_FLAG_LIMIT | SMTPD_CMD_FLAG_PRE_TLS,
     SMTPD_CMD_VRFY, vrfy_cmd, SMTPD_CMD_FLAG_LIMIT,
     SMTPD_CMD_ETRN, etrn_cmd, SMTPD_CMD_FLAG_LIMIT,
     SMTPD_CMD_QUIT, quit_cmd, SMTPD_CMD_FLAG_PRE_TLS,
-    SMTPD_CMD_XCLIENT, xclient_cmd, SMTPD_CMD_FLAG_LIMIT,
-    SMTPD_CMD_XFORWARD, xforward_cmd, SMTPD_CMD_FLAG_LIMIT,
+    SMTPD_CMD_XCLIENT, xclient_cmd, 0,
+    SMTPD_CMD_XFORWARD, xforward_cmd, 0,
     0,
 };
 
@@ -4321,7 +4324,55 @@ static void smtpd_proto(SMTPD_STATE *state)
                smtpd_chat_reply(state, "421 %s Service unavailable - try again later",
                                 var_myhostname);
                /* Not: state->error_count++; */
+#ifdef notdef
+           } else if (strcmp(state->name, "unknown") == 0) {
+               static char *greet_chunks[] = {
+                   "220 ", 0, " ESMTP ", 0, 0,
+               };
+               char  **cpp;
+               char   *cp;
+
+               greet_chunks[1] = var_myhostname;
+               greet_chunks[3] = var_mail_name;
+               for (cpp = greet_chunks; *cpp; cpp++) {
+                   for (cp = *cpp; *cp; cp++)
+                       smtp_fputc(*(unsigned char *) cp, state->client);
+                   smtp_flush(state->client);
+                   if (read_wait(vstream_fileno(state->client), 2) == 0) {
+                       smtpd_chat_query(state);
+                       msg_info("PREGREET from %s: %s",
+                                state->namaddr, vstring_str(state->buffer));
+                       state->error_mask |= MAIL_ERROR_POLICY;
+                       smtpd_chat_reply(state,
+                                  "521 %s ESMTP not accepting connections",
+                                        var_myhostname);
+                       /* Not: state->error_count++; */
+                       break;
+                   }
+               }
+               smtp_fputs("", 0, state->client);
+               smtp_flush(state->client);
+#endif
            } else {
+#ifdef PREGREET
+               if (*var_stress == 0 && strcmp(state->name, "unknown") == 0) {
+                   smtpd_chat_reply(state, "220-%s", var_smtpd_banner);
+                   smtp_flush(state->client);
+                   if (read_wait(vstream_fileno(state->client), 1) == 0) {
+                       int     n = peekfd(vstream_fileno(state->client));
+
+                       smtpd_chat_query(state);
+                       msg_info("PREGREET %d from %s: %s",
+                            n, state->namaddr, vstring_str(state->buffer));
+                       state->error_mask |= MAIL_ERROR_POLICY;
+                       smtpd_chat_reply(state,
+                                  "521 %s ESMTP not accepting connections",
+                                        var_myhostname);
+                       /* Not: state->error_count++; */
+                       break;
+                   }
+               }
+#endif
                smtpd_chat_reply(state, "220 %s", var_smtpd_banner);
            }
        }
@@ -4427,6 +4478,16 @@ static void smtpd_proto(SMTPD_STATE *state)
            }
 #endif
            state->where = cmdp->name;
+           if (SMTPD_STAND_ALONE(state) == 0
+               && (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0
+                   || (cmdp->flags & SMTPD_CMD_FLAG_LAST))
+               && (state->flags & SMTPD_FLAG_ILL_PIPELINING) == 0
+               && (vstream_peek(state->client) > 0
+                   || peekfd(vstream_fileno(state->client)) > 0)) {
+               msg_info("improper command pipelining after %s from %s",
+                        cmdp->name, state->namaddr);
+               state->flags |= SMTPD_FLAG_ILL_PIPELINING;
+           }
            if (cmdp->action(state, argc, argv) != 0)
                state->error_count++;
            if ((cmdp->flags & SMTPD_CMD_FLAG_LIMIT)
@@ -4463,9 +4524,9 @@ static void smtpd_proto(SMTPD_STATE *state)
      * troubles.
      */
     if (state->reason && state->where) {
-       if (strcmp(state->where, SMTPD_CMD_DATA) == 0) {
-           msg_info("%s after %s (approximately %lu bytes) from %s",
-                    state->reason, state->where,
+       if (strcmp(state->where, SMTPD_AFTER_DATA) == 0) {
+           msg_info("%s after %s (%lu bytes) from %s", /* 2.5 compat */
+                    state->reason, SMTPD_CMD_DATA,     /* 2.5 compat */
                     (long) (state->act_size + vstream_peek(state->client)),
                     state->namaddr);
        } else if (strcmp(state->where, SMTPD_AFTER_DOT)
@@ -4829,13 +4890,13 @@ MAIL_VERSION_STAMP_DECLARE;
 int     main(int argc, char **argv)
 {
     static const CONFIG_NINT_TABLE nint_table[] = {
-       VAR_SMTPD_RCPT_LIMIT, DEF_SMTPD_RCPT_LIMIT, &var_smtpd_rcpt_limit, 1, 0,
        VAR_SMTPD_SOFT_ERLIM, DEF_SMTPD_SOFT_ERLIM, &var_smtpd_soft_erlim, 1, 0,
        VAR_SMTPD_HARD_ERLIM, DEF_SMTPD_HARD_ERLIM, &var_smtpd_hard_erlim, 1, 0,
        VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit, 1, 0,
        0,
     };
     static const CONFIG_INT_TABLE int_table[] = {
+       VAR_SMTPD_RCPT_LIMIT, DEF_SMTPD_RCPT_LIMIT, &var_smtpd_rcpt_limit, 1, 0,
        VAR_QUEUE_MINFREE, DEF_QUEUE_MINFREE, &var_queue_minfree, 0, 0,
        VAR_UNK_CLIENT_CODE, DEF_UNK_CLIENT_CODE, &var_unk_client_code, 0, 0,
        VAR_BAD_NAME_CODE, DEF_BAD_NAME_CODE, &var_bad_name_code, 0, 0,
index cef00062f05eb74c4c73342c5f1323e66e47f3a8..fc7ac56ed4716158fbe227ccb885153a16d19430 100644 (file)
@@ -180,7 +180,10 @@ typedef struct SMTPD_STATE {
     ssize_t milter_argc;
 } SMTPD_STATE;
 
-#define SMTPD_FLAG_HANGUP      (1<<0)  /* disconnect */
+#define SMTPD_FLAG_HANGUP         (1<<0)       /* 421/521 disconnect */
+#define SMTPD_FLAG_ILL_PIPELINING  (1<<1)      /* inappropriate pipelining */
+
+#define SMTPD_MASK_MAIL_KEEP           ~0      /* keep all after MAIL reset */
 
 #define SMTPD_STATE_XFORWARD_INIT  (1<<0)      /* xforward preset done */
 #define SMTPD_STATE_XFORWARD_NAME  (1<<1)      /* client name received */
@@ -204,6 +207,7 @@ extern void smtpd_state_reset(SMTPD_STATE *);
   * diagnostics.
   */
 #define SMTPD_AFTER_CONNECT    "CONNECT"
+#define SMTPD_AFTER_DATA       "DATA content"
 #define SMTPD_AFTER_DOT                "END-OF-MESSAGE"
 
  /*
index f39eaf1c696458029b25a1b589e9c8ee79f5e32e..e78f5936df3aab42420cc92653fd2120887c522c 100644 (file)
@@ -200,9 +200,10 @@ void    smtpd_chat_reply(SMTPD_STATE *state, const char *format,...)
        vstream_longjmp(state->client, SMTP_ERR_EOF);
 
     /*
-     * Orderly disconnect in case of 421 reply.
+     * Orderly disconnect in case of 421 or 521 reply.
      */
-    if (strncmp(STR(state->buffer), "421", 3) == 0)
+    if (strncmp(STR(state->buffer), "421", 3) == 0
+       || strncmp(STR(state->buffer), "521", 3) == 0)
        state->flags |= SMTPD_FLAG_HANGUP;
 }
 
index 70428d546d0bcbfb464ff3023882cffd518ba5c6..cbe8c69edfa1587c6763c8b04f29ac5d1449550f 100644 (file)
@@ -1421,17 +1421,12 @@ static int reject_unauth_pipelining(SMTPD_STATE *state,
     if (msg_verbose)
        msg_info("%s: %s", myname, state->where);
 
-    if (state->client != 0
-       && SMTPD_STAND_ALONE(state) == 0
-       && (vstream_peek(state->client) > 0
-           || peekfd(vstream_fileno(state->client)) > 0)
-       && (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0
-           || strcasecmp(state->where, SMTPD_CMD_DATA) == 0)) {
+    if (state->flags & SMTPD_FLAG_ILL_PIPELINING)
        return (smtpd_check_reject(state, MAIL_ERROR_PROTOCOL,
                                   503, "5.5.0",
               "<%s>: %s rejected: Improper use of SMTP command pipelining",
                                   reply_name, reply_class));
-    }
+
     return (SMTPD_CHECK_DUNNO);
 }
 
index c2fa84102bde04b3563d82b95030685b41924182..cfefe7e3dde80307c66b7f02d4b420ca87accad0 100644 (file)
@@ -564,11 +564,23 @@ int     smtpd_proxy_cmd(SMTPD_STATE *state, int expect, const char *fmt,...)
     /*
      * Log a warning in case the proxy does not send the expected response.
      * Silently accept any response when the client expressed no expectation.
+     * 
+     * Don't pass through misleading 2xx replies. it confuses naive users and
+     * SMTP clients, and creates support problems.
      */
     if (expect != SMTPD_PROX_WANT_ANY && expect != *STR(state->proxy_buffer)) {
        va_start(ap, fmt);
        smtpd_proxy_cmd_error(state, fmt, ap);
        va_end(ap);
+       if (*STR(state->proxy_buffer) == SMTPD_PROX_WANT_OK
+           || *STR(state->proxy_buffer) == SMTPD_PROX_WANT_MORE) {
+           state->error_mask |= MAIL_ERROR_SOFTWARE;
+           state->err |= CLEANUP_STAT_PROXY;
+           detail = cleanup_stat_detail(CLEANUP_STAT_PROXY);
+           vstring_sprintf(state->proxy_buffer,
+                           "%d %s Error: %s",
+                           detail->smtp, detail->dsn, detail->text);
+       }
        return (-1);
     } else {
        return (0);
index a9153ac753f6fc8c6cc9731e3349182b303d5cbb..ad6dd82c06cbcbe1e196d3099e88c7ce533a00cc 100644 (file)
 #include "sock_addr.h"
 #include "inet_proto.h"
 
- /*
-  * Tunable to work around broken routers.
-  */
-int     inet_windowsize = 0;
-
 /* inet_listen - create TCP listener */
 
 int     inet_listen(const char *addr, int backlog, int block_mode)
index cbe3a8b93b07eba7d7cfd555fe15e15af98362ce..ae2b170f4a55f8a45e3c3bc11e36034ab2327f11 100644 (file)
 
 /* Application storage. */
 
-int     inet_windowsize;
+ /*
+  * Tunable to work around broken routers.
+  */
+int     inet_windowsize = 0;
 
 /* set_inet_windowsize - set TCP send/receive window size */
 
index bf1680cc2f5680baa2b21e9c64218596e5bf1729..80399842883bcd4fbb93fd79c89d24e30fb4367f 100644 (file)
 /*     The location of the Postfix top-level queue directory.
 /* .IP "\fBsyslog_facility (mail)\fR"
 /*     The syslog facility of Postfix logging.
-/* .IP "\fBsyslog_name (postfix)\fR"
+/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 /*     The mail system name that is prepended to the process name in syslog
 /*     records, so that "smtpd" becomes, for example, "postfix/smtpd".
 /* SEE ALSO
index d3b80210791804f5111bb181639e85b3089c19f6..a86602d65771e0a6d55828f497f683ff99d5300a 100644 (file)
@@ -307,7 +307,7 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl,
 
     /*
      * Don't give any IP address information to SASL.  SASLv1 doesn't use it,
-     * and in SASLv2 this will disable any mechaniams that do.
+     * and in SASLv2 this will disable any mechanisms that do.
      */
     server_address = 0;
     client_address = 0;