]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.0.10-20030526
authorWietse Venema <wietse@porcupine.org>
Mon, 26 May 2003 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:28:54 +0000 (06:28 +0000)
27 files changed:
postfix/HISTORY
postfix/INSTALL
postfix/README_FILES/ADDRESS_VERIFICATION_README
postfix/README_FILES/FILTER_README
postfix/examples/chroot-setup/Solaris8 [new file with mode: 0644]
postfix/src/cleanup/cleanup.h
postfix/src/cleanup/cleanup_envelope.c
postfix/src/cleanup/cleanup_extracted.c
postfix/src/cleanup/cleanup_message.c
postfix/src/cleanup/cleanup_output.txt [new file with mode: 0644]
postfix/src/cleanup/cleanup_state.c
postfix/src/global/cleanup_strerror.c
postfix/src/global/cleanup_user.h
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/nqmgr/qmgr.h
postfix/src/nqmgr/qmgr_message.c
postfix/src/qmgr/qmgr_message.c
postfix/src/qmqpd/qmqpd.c
postfix/src/sendmail/sendmail.c
postfix/src/showq/showq.c
postfix/src/smtp/smtp_connect.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_check.h
postfix/src/smtpd/smtpd_state.c

index 66a4dd33622f87b5c15ffb3b89e6e51e2eb6bbb5..05995f9c7318242c3f52e12b405fa3435ac9b36a 100644 (file)
@@ -104,8 +104,8 @@ Apologies for any names omitted.
        that use short hostnames will have to specify their FQDN
        in main.cf (this will eventually be done by the system
        installation/configuration procedure). Should the config
-       language support backticks so one can say `domainname`? What
-       about $name stuff between the backtics?
+       language support backticks so one can say `domainname`?
+       What about $name stuff between the backtics?
 
        Security: the master now creates FIFOs and UNIX-domain
        sockets as the mail owner instead of as root, for better
@@ -977,7 +977,7 @@ Apologies for any names omitted.
 
 19980824
 
-       Bugfix: transport table lookup keys were case sensitive.  
+       Bugfix: transport table lookup keys were case sensitive.
 
 19980825
 
@@ -1030,10 +1030,11 @@ Apologies for any names omitted.
        Feature: site!user is rewritten to user@site, under control
        of the boolean parameter swap_bangpath (default: yes).
 
-       Feature: permit a naked IP address in HELO commands (i.e. an
-       address without the enclosing [] as required by the RFC), by
-       specifying "permit_naked_ip_address" as one of the restrictions
-       in the "smtpd_helo_restrictions" config parameter.
+       Feature: permit a naked IP address in HELO commands (i.e.
+       an address without the enclosing [] as required by the
+       RFC), by specifying "permit_naked_ip_address" as one of
+       the restrictions in the "smtpd_helo_restrictions" config
+       parameter.
 
 19980904
 
@@ -1052,8 +1053,8 @@ Apologies for any names omitted.
        separate file global/mail_version.h, so that a version
        change no longer results in massive recompilation.
 
-       Bugfix: Errors-To was flagged as a sender address, so
-       the address never was picked up.
+       Bugfix: Errors-To was flagged as a sender address, so the
+       address never was picked up.
 
        Code cleanup: support for Errors-To: headers completed.
 
@@ -1128,7 +1129,8 @@ Apologies for any names omitted.
        Bugfix: after vmailer reload, single-threaded servers could
        exit before flushing unwritten data to the client. Example:
        cleanup would exit before acking success to pickup, so the
-       message would be delivered twice. Bug reported by Brian Candler.
+       message would be delivered twice. Bug reported by Brian
+       Candler.
 
        Cleanup: removed spurious error output from vmailer-script.
        Reported by Brian Candler.
@@ -1220,8 +1222,8 @@ Apologies for any names omitted.
 
        Bugfix: the change in virtual/canonical map search order
        broke @domain entries; they would never be looked up if
-       the address matched $myorigin or $mydestinations. Found
-       by Chip Christian who now regrets asking for the change.
+       the address matched $myorigin or $mydestinations. Found by
+       Chip Christian who now regrets asking for the change.
 
        Bugfix: cleanup initialized an error mask incorrectly, so
        that it would keep writing to a file larger than the queue
@@ -1264,8 +1266,8 @@ Apologies for any names omitted.
 
 10091002
 
-       SMTPD now logs "lost connection after end-of-message" instead
-       of "lost connection after DATA".
+       SMTPD now logs "lost connection after end-of-message"
+       instead of "lost connection after DATA".
 
 10091005
 
@@ -1339,7 +1341,8 @@ Apologies for any names omitted.
 
        Workaround: with UNIX-domain sockets, LINUX connect() blocks
        until the server calls accept(). File: qmgr/qmgr_transport.c.
-       Terry Lorrah and Scott Cotton provided the necessary evidence.
+       Terry Lorrah and Scott Cotton provided the necessary
+       evidence.
 
 19981020
 
@@ -1492,7 +1495,7 @@ Apologies for any names omitted.
        Compatibility: the tokenizer for alias/forward/etc.
        expansion now updates an optional counter with the number
        of destinations found; If no destinations is found in a
-       .forward file, deliver to the mailbox instead. Thanks, 
+       .forward file, deliver to the mailbox instead. Thanks,
        Daniel Eisenbud, for showing the way to go.
 
        Robustness: the pickup daemon should always include a
@@ -1503,9 +1506,9 @@ Apologies for any names omitted.
        Robustness: duplicate entries in aliases or maps now cause
        a warning instead of a fatal error (and an incomplete file).
 
-       Robustness: mkmap now prints a warning when an entry is
-       in "key: value" format, which is the format expected for
-       alias databases, not for maps.  
+       Robustness: mkmap now prints a warning when an entry is in
+       "key: value" format, which is the format expected for alias
+       databases, not for maps.
 
        Portability: on LINUX, prepend "+" to the getopt() options
        string so that getopt() will stop at the first non-option
@@ -1589,7 +1592,8 @@ Apologies for any names omitted.
 
 19981108
 
-       Bugfix: minor memory leak in the user+foo table lookup code.
+       Bugfix: minor memory leak in the user+foo table lookup
+       code.
 
        Configurability: specify virtual.domain in the virtual map,
        and mail for unknown@virtual.domain will bounce automatically.
@@ -1598,7 +1602,8 @@ Apologies for any names omitted.
        d'Itri put me on the right track.
 
        Configurability: The mydestinations configuration parameter
-       now accepts /file/name expressions and type:name lookup tables.
+       now accepts /file/name expressions and type:name lookup
+       tables.
 
        Code cleanup: in order to make the previous two enhancements
        possible, revised the string/host/address matching engine
@@ -1812,8 +1817,9 @@ Apologies for any names omitted.
        by hand).
 
        Feature: when a writable maildrop directory is a problem,
-       sites can make the new "postdrop" utility set-gid. This command
-       is never used when the maildrop directory is world-writable.
+       sites can make the new "postdrop" utility set-gid. This
+       command is never used when the maildrop directory is
+       world-writable.
 
        Robustness: make the queue file creation routine more
        resistant against denial of service race attack. File:
@@ -1930,8 +1936,8 @@ Apologies for any names omitted.
        Hewlett-Packard). File: cleanup/cleanup_envelope.c.
 
        Compatibility: the transport table now uses .domain.name
-       to match subdomains, just like sendmail mailer tables
-       (patch by Lamont Jones, Hewlett-Packard).
+       to match subdomains, just like sendmail mailer tables (patch
+       by Lamont Jones, Hewlett-Packard).
 
        Feature: mailq now ends with a total queue size summary
        (Eilon Gishri, Israel Inter University Computation Center).
@@ -1976,8 +1982,8 @@ Apologies for any names omitted.
 
 19990121
 
-       Feature: pickup (again) logs uid and sender address.
-       On repeated request by Scott Cotton, Internet Consultants
+       Feature: pickup (again) logs uid and sender address.  On
+       repeated request by Scott Cotton, Internet Consultants
        Group, Inc.
 
        Portability: doze() function for systems without usleep().
@@ -2230,14 +2236,14 @@ Apologies for any names omitted.
 
 19990307
 
-       Feature: LDAP lookups, updated by Jon Hensley, Merit
-       Network, USA.
+       Feature: LDAP lookups, updated by Jon Hensley, Merit Network,
+       USA.
 
        Feature: regular expression (PCRE) support by Andrew
        McNamara, connect.com.au Pty. Ltd., Australia. In order to
        use this code specify pcre:/file/name. You can use this
-       anywhere you would use a DB or DBM file, NIS or LDAP.
-       See: PCRE_README for how to enable this code.
+       anywhere you would use a DB or DBM file, NIS or LDAP.  See:
+       PCRE_README for how to enable this code.
 
        Feature: "delay_warning_time = 4" causes Postfix to send
        a "your mail is delayed" notice after approx. 4 hours.
@@ -2330,7 +2336,7 @@ Apologies for any names omitted.
 
        Enhancement: include the client network address in the
        rejected by RBL response. Lamont Jones, Hewlett-Packard.
-       
+
        Workaround: use fstat() to figure out if the maildrop is
        world-writable. access() uses the real uid, which stinks.
 
@@ -2358,7 +2364,7 @@ Apologies for any names omitted.
 
        Workaround: more watchdog timers for postfix-unfriendly
        systems. By now every Postfix daemon has one. Call it life
-       insurance. 
+       insurance.
 
        Robustness: increased the maximal time to receive or deliver
        mail from $ipc_timeout (default: 3600 seconds) to the more
@@ -2452,7 +2458,7 @@ Apologies for any names omitted.
 
        Bugfix: when a recipient appeared multiple times in a local
        alias or include expansion, the delivery status could be
-       left uninitialized, causing the mail to be deferred and 
+       left uninitialized, causing the mail to be deferred and
        delivered again. File: local/recipient.c.
 
 19990327
@@ -2547,8 +2553,8 @@ Apologies for any names omitted.
        mail is bounced with a "mail loops back to myself" error).
 
        Config: in order to make feature tracking easier the source
-       code distribution now has a copy of the default settings in
-       conf/main.cf.default.
+       code distribution now has a copy of the default settings
+       in conf/main.cf.default.
 
        Feature: separate configurable postmaster addresses for
        single bounces (bounce_notice_recipient), double bounces
@@ -2599,8 +2605,8 @@ Apologies for any names omitted.
 
 19990410
 
-       Bugfix: auto-detection of changes to DB or DBM lookup
-       tables wasn't done for TCP connections.
+       Bugfix: auto-detection of changes to DB or DBM lookup tables
+       wasn't done for TCP connections.
 
 19990410
 
@@ -2812,8 +2818,8 @@ Apologies for any names omitted.
 19990610
 
        Bugfix: the "is this the loopback interface" test was
-       broken.  Reported by Claus Fischer @microworld.com.
-       File: smtp/smtp_connect.c.
+       broken.  Reported by Claus Fischer @microworld.com.  File:
+       smtp/smtp_connect.c.
 
        Usability: added helpful warnings about restrictions that
        are being ignored after check_relay_domains, etc.
@@ -2863,8 +2869,8 @@ Apologies for any names omitted.
        File: smtpd/smtpd.c.
 
        Bugfix: fencepost error in the doze() routine (an usleep()
-       replacement for systems without one). Found by Simon J Mudd.
-       File: util/doze.c.
+       replacement for systems without one). Found by Simon J
+       Mudd.  File: util/doze.c.
 
 19990624
 
@@ -2890,8 +2896,8 @@ Apologies for any names omitted.
 
 19990628
 
-       Feature: the postlock command now returns EX_TEMPFAIL
-       when the destination file is locked by another process.
+       Feature: the postlock command now returns EX_TEMPFAIL when
+       the destination file is locked by another process.
 
 19990705
 
@@ -2917,8 +2923,8 @@ Apologies for any names omitted.
 19990714
 
        Robustness: add PATH statement to Solaris2 chroot setup
-       script to avoid running the ucb commands. Problem found
-       by Panagiotis Astithas @ ece.ntua.gr.
+       script to avoid running the ucb commands. Problem found by
+       Panagiotis Astithas @ ece.ntua.gr.
 
 19990721
 
@@ -2944,14 +2950,14 @@ Apologies for any names omitted.
 
 19990813
 
-       Bugfix: sendmail -t (extract recipients from headers) did not
-       work when the always_bcc feature was turned on. Reported
+       Bugfix: sendmail -t (extract recipients from headers) did
+       not work when the always_bcc feature was turned on. Reported
        by: Denis Shaposhnikov @ neva.vlink.ru.
 
 19990813
-       Bugfix: "sendmail -bd" returns a bogus exit status (the child
-       process ID). Fix by Lamont Jones of Hewlett-Packard. File:
-       sendmail/sendmail.c.
+       Bugfix: "sendmail -bd" returns a bogus exit status (the
+       child process ID). Fix by Lamont Jones of Hewlett-Packard.
+       File:  sendmail/sendmail.c.
 
 19990824
 
@@ -3087,8 +3093,8 @@ Apologies for any names omitted.
 
        Changed "permit_address_map" into "permit_recipient_map"
        and added a test for the case that they specify a lookup
-       table on the right-hand side of an SMTPD access map.
-       File: smtpd/smtpd_access.c.
+       table on the right-hand side of an SMTPD access map.  File:
+       smtpd/smtpd_access.c.
 
        Cleanup: removed spurious sender address checks for <>.
        File: smtpd/smtpd_check.c.
@@ -4063,8 +4069,8 @@ Apologies for any names omitted.
 20000623
 
        Bugfix: the SMTP server did not reset the so-called junk
-       command counter after successful delivery (Mark Hoffman
-       wallst.com).  File: smtpd/smtpd.c.
+       command counter after successful delivery (Mark Hoffman @
+       wallst.com).  File: smtpd/smtpd.c.
 
 20000625
 
@@ -4373,8 +4379,8 @@ Apologies for any names omitted.
 20001025
 
        Bugfix: virtual map expansion stopped too early with
-       self-referential aliases. Reported by Michael Douglass
-       datafoundry.net. File: cleanup/cleanup_map1n.c.
+       self-referential aliases. Reported by Michael Douglass @
+       datafoundry.net. File: cleanup/cleanup_map1n.c.
 
 20001026
 
@@ -4535,7 +4541,7 @@ Apologies for any names omitted.
        of the postlock command, and of local delivery to mailbox
        or /file/name.  Files: util/safe_open.c, util/myflock.c,
        global/deliver_flock.c, global/mbox_conf.c, global/mbox_open.c.
-       local/mailbox.c, local/file.c, postlock/postlock.c.  
+       local/mailbox.c, local/file.c, postlock/postlock.c.
 
        Compatibility: the old sun_mailtool_compatibility parameter
        is being phased out. It still works (by turning off
@@ -4662,8 +4668,8 @@ Apologies for any names omitted.
 20001217
 
        Bugfix: reorganized some code in the MYSQL client to end
-       a number of memory allocation/deallocation problems.
-       This code needs more work. File: dict_mysql.c.
+       a number of memory allocation/deallocation problems.  This
+       code needs more work. File: dict_mysql.c.
 
 20001218
 
@@ -4745,8 +4751,8 @@ Apologies for any names omitted.
 20010121
 
        Workaround: specify "broken_sasl_auth_clients = yes" in
-       order to support old Microsoft clients that implement
-       non-standard version of RFC 2554 (AUTH command).
+       order to support old Microsoft clients that implement a
+       non-standard version of RFC 2554 (AUTH command).
 
        Workaround: Lotus Domino 5.0.4 violates RFC 2554 and replies
        to EHLO with AUTH=LOGIN. File: smtp/smtp_proto.c.
@@ -4891,8 +4897,8 @@ Apologies for any names omitted.
        {qmgr,nqmgr}/qmgr_message.c.
 
        Workaround: Solaris socketpair() can fail with EINTR. Added
-       a sane_socketpair.c module that joins the ranks of the other
-       sane_whatever workarounds. Reported by Andrew McNamara.
+       a sane_socketpair.c module that joins the ranks of the
+       other sane_whatever workarounds. Reported by Andrew McNamara.
        File: util/sane_socketpair.[hc]
 
 20010222
@@ -4925,8 +4931,9 @@ Apologies for any names omitted.
        Portability: MACOSX patches by Gerben Wierda.
 
        Portability: Solaris /dev/null is a symlink, which tripped
-       up the code to safely open a file before local delivery. We now
-       grudgingly allow symlinks owned by root. File: util/safe_open.c.
+       up the code to safely open a file before local delivery.
+       We now grudgingly allow symlinks owned by root. File:
+       util/safe_open.c.
 
 20010224
 
@@ -5027,8 +5034,8 @@ Apologies for any names omitted.
        do not immediately close the client side, but close it from
        a background thread that waits until the server closes the
        socket first. This avoids trouble with socket implementations
-       that destroy a socket when the client closes a socket
-       before the server has received the client's data.  Files:
+       that destroy a socket when the client closes a socket before
+       the server has received the client's data.  Files:
        util/{inet,unix,stream}_trigger.c, util/events.c,
        master/master_trigger.c, postkick/postkick.c.
 
@@ -5266,8 +5273,8 @@ Apologies for any names omitted.
 
        Workaround: some MTAs fall on their face when they receive
        unexpectedly long lines. From now on, Postfix defaults to
-       breaking long lines at 2048 (like Sendmail so it has got to
-       be right). To get the old, content preserving, behavior
+       breaking long lines at 2048 (like Sendmail so it has got
+       to be right). To get the old, content preserving, behavior
        specify "smtp_truncate_lines = no". File: smtp/smtp_proto.c.
 
 20010614
@@ -5724,8 +5731,8 @@ Apologies for any names omitted.
 
        Robustness: add a file size limit to the sendmail and
        postdrop submission programs to stop run-away process
-       accidents. This is not a defense against DOS attack.
-       Files: sendmail/sendmail.c, postdrop/postdrop.c.
+       accidents. This is not a defense against DOS attack.  Files:
+       sendmail/sendmail.c, postdrop/postdrop.c.
 
        That resulted in a considerable amount of work to properly
        propagate "file too large" conditions back to the sendmail
@@ -5958,9 +5965,9 @@ Apologies for any names omitted.
 
 20020114
 
-       Bugfix: alternate_config_directories did not take comma
-       or whitespace as separators. File: global/mail_conf.c.
-       Victor Duchovni, Morgan Stanley.
+       Bugfix: alternate_config_directories did not take comma or
+       whitespace as separators. File: global/mail_conf.c.  Victor
+       Duchovni, Morgan Stanley.
 
        Bugfix: the rewritten postfix-install script did not chattr
        +S the Postfix queue.
@@ -6115,8 +6122,8 @@ Apologies for any names omitted.
 
        Documentation: add note to sendmail manual page that running
        "sendmail -bs" as $mail_owner enables SMTP server UCE and
-       access control checks. This is meant for use from inetd etc.
-       Matthias Andree.
+       access control checks. This is meant for use from inetd
+       etc.  Matthias Andree.
 
 20020311
 
@@ -6151,7 +6158,7 @@ Apologies for any names omitted.
        Cleanup: add a msg_warn() call when fork() fails in
        pipe_command(), to make problems easier to investigate.
        Chris Wedgwood. File:  global/pipe_command.c.
-       
+
 20020320
 
        Feature: smtp_helo_name parameter to specify the hostname
@@ -6254,8 +6261,8 @@ Apologies for any names omitted.
 
        Cleanup: install parameter defaults can now be overruled
        from makedefs: sendmail_path, mailq_path, newaliases_path,
-       command_directory, daemon_directory. Based on code by
-       Victor Duchovni, Morgan Stanley. File: util/sys_defs.h.
+       command_directory, daemon_directory. Based on code by Victor
+       Duchovni, Morgan Stanley. File: util/sys_defs.h.
 
 20020411
 
@@ -6273,8 +6280,8 @@ Apologies for any names omitted.
 20020418
 
        Documentation: added CPU saving patterns for quickly skipping
-       base 64 encoded text in message bodies.  Liviu Daia.
-       Files: {proto,conf}/pcre_table, {proto,conf}/regexp_table,
+       base 64 encoded text in message bodies.  Liviu Daia.  Files:
+       {proto,conf}/pcre_table, {proto,conf}/regexp_table,
        conf/sample_{regexp,pcre}_body.cf.
 
 20020426
@@ -6424,9 +6431,9 @@ Apologies for any names omitted.
        util/dict_ldap.c.
 
        Feature: lots of new LDAP stuff: result_filter (filter to
-       expand results from queries), chase_referrals,
-       LaMont Jones, HP. The LDAP bind timeout now works thanks
-       to Victor Duchovni, Morgan Stanley. File:  util/dict_ldap.c.
+       expand results from queries), chase_referrals, LaMont Jones,
+       HP. The LDAP bind timeout now works thanks to Victor
+       Duchovni, Morgan Stanley. File:  util/dict_ldap.c.
 
        Cleanup: specify "resolve_dequoted_address = no" to prevent
        Postfix from looking inside quotes for extra @ etc. characters
@@ -6483,8 +6490,8 @@ Apologies for any names omitted.
 
 20020521-22
 
-       Feature: 8-bit to quoted-printable conversion. First use in
-       the Postfix SMTP client. File: smtp/smtp_proto.c.
+       Feature: 8-bit to quoted-printable conversion. First use
+       in the Postfix SMTP client. File: smtp/smtp_proto.c.
 
        Logging: the Postfix SMTP and LMTP clients now report the
        the protocol stage when they report a server reply.  File:
@@ -6751,8 +6758,8 @@ Apologies for any names omitted.
 
 20020801
 
-       Cleanup: the warning message for matched header/body
-       content was misleading. File: cleanup/cleanup_message.c.
+       Cleanup: the warning message for matched header/body content
+       was misleading. File: cleanup/cleanup_message.c.
 
        Safety: moved the "postsuper -r ALL" operation after the
        "postsuper -s" check that makes queue file names match
@@ -6789,9 +6796,9 @@ Apologies for any names omitted.
 20020810
 
        Feature: new smtp-sink command-line options to specify the
-       SMTP hostname, to disable ESMTP protocol support, to
-       disable 8BITMIME support, and to syslog selected commands.
-       File: smtpstone/smtp-sink.c.
+       SMTP hostname, to disable ESMTP protocol support, to disable
+       8BITMIME support, and to syslog selected commands.  File:
+       smtpstone/smtp-sink.c.
 
 20020814
 
@@ -6852,8 +6859,8 @@ Apologies for any names omitted.
 20020821
 
        Feature: HOLD and DISCARD actions in SMTPD access tables.
-       These requests are propagated to the cleanup daemon.
-       Files: cleanup/cleanup_envelope.c smtpd/smtpd_check.c.
+       These requests are propagated to the cleanup daemon.  Files:
+       cleanup/cleanup_envelope.c smtpd/smtpd_check.c.
 
        Cleanup: eliminate unnecessary references to the obsolete
        program_directory configuration parameter (but keep the
@@ -6938,7 +6945,7 @@ Apologies for any names omitted.
        This involved a further rewrite of the regexp map code.
        File: util/dict_regexp.c.
 
+
 200209010
 
        Bugfix: the SMTP client produced suprious warnings about
@@ -7011,11 +7018,11 @@ Apologies for any names omitted.
 20020923
 
        Cleanup. Renamed the RBL features according to a scheme
-       that was suggested by Liviu Daia in October 2001. The
-       names are reject_rbl_client and reject_rhsbl_sender,
-       respectively.  Added domain name based reject_rhsbl_client
-       and reject_rhsbl_recipient restrictions for completeness.
-       The reject_rbl restriction name is still recognized for
+       that was suggested by Liviu Daia in October 2001. The names
+       are reject_rbl_client and reject_rhsbl_sender, respectively.
+       Added domain name based reject_rhsbl_client and
+       reject_rhsbl_recipient restrictions for completeness.  The
+       reject_rbl restriction name is still recognized for
        compatibility with systems maintained by LaMont Jones.
 
 20020924
@@ -7052,9 +7059,9 @@ Apologies for any names omitted.
        In the mean time, Linux mail delivery software seems to
        have standardized on fcntl() locks. File: util/sys_defs.h.
 
-       Feature: body_checks_size_limit parameter to specify how much
-       of a message body segment (or attachment, if you prefer to
-       use that term) is subjected to body_checks inspection.
+       Feature: body_checks_size_limit parameter to specify how
+       much of a message body segment (or attachment, if you prefer
+       to use that term) is subjected to body_checks inspection.
        Default limit:  50 kbytes. Files:  global/mime_state.c,
        cleanup/cleanup_message.c.
 
@@ -7298,8 +7305,8 @@ Apologies for any names omitted.
 
 20021124
 
-       Bugfix: don't use same VSTRING buffer for reading and writing.
-       File: verify/verify.c.
+       Bugfix: don't use same VSTRING buffer for reading and
+       writing.  File: verify/verify.c.
 
 20021128
 
@@ -7680,10 +7687,10 @@ Apologies for any names omitted.
        service.  Fix: use "private/proxymap" if possible, otherwise
        use "$queue_dir/private/proxymap".  File:  global/dict_proxy.c.
 
-       Robustness: daemons now chdir() to the queue directory before
-       running the pre-jail initialization code, so that daemons
-       running in stand-alone mode produce more consistent results.
-       Files:  master/single_server.c, master/multi_server.c.
+       Robustness: daemons now chdir() to the queue directory
+       before running the pre-jail initialization code, so that
+       daemons running in stand-alone mode produce more consistent
+       results.  Files:  master/single_server.c, master/multi_server.c.
        master/trigger_server.c.
 
        Bugfix: "sendmail -bs" tried to access the proxymap service.
@@ -8012,11 +8019,13 @@ Apologies for any names omitted.
 
 20030418
 
-       Bugfix: "sendmail -t" broke with unrecognized message headers.
+       Bugfix: "sendmail -t" broke with unrecognized message
+       headers.
 
 20030419
 
-       Feature: "postcat -q" searches the queue for the named file.
+       Feature: "postcat -q" searches the queue for the named
+       file.
 
        Cleanup: made postcat "record names" output more consistent.
 
@@ -8072,18 +8081,7 @@ Apologies for any names omitted.
 
        Workaround: IRIX select() reports that a non-blocking file
        descriptor is writable while write() transfers zero bytes.
-       File:  util/vstream.c.
-
-20030519
-
-       Feature: new require_{date,from,message_id,received}_header
-       restriction to reject SMTP mail when some message header
-       is missing.  Only the From: and Date: headers are actually
-       required by Internet mail standards; the Received:  and
-       Message-ID: headers are optional, but these are often
-       missing from SPAM email.  Files: global/cleanup_user.h,
-       global/cleanup_strerror.c, smtpd/smtpd_check.c,
-       cleanup/cleanup_message.c.
+       File:  util/vstream.c. Superseded by change 20030523.
 
 20030520
 
@@ -8100,7 +8098,13 @@ Apologies for any names omitted.
        Richard Stockton, Gramma Software. Files:
        cleanup/cleanup_envelope.c, cleanup/cleanup_extracted.c.
 
-2003052[34]
+20030523
+
+       Workaround: IRIX select() reports that a non-blocking file
+       descriptor is writable while write() transfers zero bytes.
+       File:  global/pipe_command.c.
+
+2003052[3-6]
 
        Cleanup: rewrote the queue file record processing loops in
        cleanup and in [n]qmgr. This code had deteriorated a lot
@@ -8110,8 +8114,15 @@ Apologies for any names omitted.
        *qmgr/qmgr_message.c.
 
        Cleanup: Postfix no longer produces queue files with
-       backwards compatibility for Postfix versions < 1.0 (a.k.a.
-       20010228). File: cleanup/cleanup_extracted.c.
+       backwards compatibility data for Postfix versions < 1.0
+       (a.k.a.  20010228). Files: cleanup/cleanup_extracted.c,
+       showq/showq.c.
+
+20030528
+
+       Compatibility: "sendmail -q<time>" without -bd option causes
+       the command to exit instead of waiting for input on the
+       standard input stream. File: sendmail/sendmail.c.
 
 Open problems:
 
index 8d807539be83a656b81a325a340e629e6d833fc3..4372df0aebe00dc937bb3ec42091a9f72ba52f54 100644 (file)
@@ -44,19 +44,19 @@ those embedded manual pages are available in the mantools directory.
 4 - Building on a supported system
 ==================================
 
-If your system is supported, it is one of
+At some point in time, a version of Postfix was supported on:
 
-    AIX 3.2.5 (long ago)
-    AIX 4.1.x (long ago)
-    AIX 4.2.0 (long ago)
-    AIX 4.3.x (long ago)
+    AIX 3.2.5
+    AIX 4.1.x
+    AIX 4.2.0
+    AIX 4.3.x
     AIX 5.2
-    BSD/OS 2.x (long ago)
-    BSD/OS 3.x (long ago)
-    BSD/OS 4.x (long ago)
-    Darwin 1.x (long ago)
-    FreeBSD 2.x (long ago)
-    FreeBSD 3.x (long ago)
+    BSD/OS 2.x
+    BSD/OS 3.x
+    BSD/OS 4.x
+    Darwin 1.x
+    FreeBSD 2.x
+    FreeBSD 3.x
     FreeBSD 4.x
     FreeBSD 5.x
     HP-UX  9.x
@@ -72,14 +72,14 @@ If your system is supported, it is one of
     Linux RedHat 5.x
     Linux RedHat 6.x
     Linux RedHat 7.x
-    Linux Slackware 3.x (long ago)
+    Linux Slackware 3.x
     Linux Slackware 4.x
     Linux Slackware 7.x
     Linux SuSE 5.x
     Linux SuSE 6.x
     Linux SuSE 7.x
     Mac OS X
-    NEXTSTEP 3.x (long ago)
+    NEXTSTEP 3.x
     NetBSD 1.x
     OPENSTEP 4.x
     OSF1.V3 (Digital UNIX)
index f9a5aeca4b2fc4d976fef1f38cf5944cc2ca9f7e..d6b2cd2d48876582301952a6785febccd91a690d 100644 (file)
@@ -28,6 +28,12 @@ nearest MTA accepts the recipient, then Postfix assumes that the
 address is deliverable, even when the address will bounce AFTER
 that MTA accepts it.
 
+Postfix assumes that an address is undeliverable when the nearest
+MTA for the address rejects the probe, regardless of the reason
+for rejection (client rejected, HELO rejected, MAIL FROM rejected,
+etc.).  Thus, Postfix rejects mail when the sender's MTA rejects
+mail from your machine.  This is a good thing.
+
 Unfortunately, some major sites such as YAHOO do not reject unknown
 addresses in reply to the RCPT TO command, but report a delivery
 failure in response to "end of data" after a message is transferred.
index ecdf61d717b55de1bc418717362f69c8b548e434..e403b523e336d64b79d983e208e1dd495227527f 100644 (file)
@@ -505,7 +505,7 @@ Limitations:
   precedence over filters specified with the main.cf content_filter 
   parameter.
 
-- Only the last FILTER action from smtpd access maps or in
+- Only the last FILTER action from smtpd access maps or from
   header/body_checks takes effect.
 
 - The same content filter is applied to all the recipients of a
diff --git a/postfix/examples/chroot-setup/Solaris8 b/postfix/examples/chroot-setup/Solaris8
new file mode 100644 (file)
index 0000000..ae7e5b1
--- /dev/null
@@ -0,0 +1,97 @@
+#!/bin/sh
+
+# Solaris 8 version by Matthew X. Economou. Caution: this copies
+# too many files. There is no need to copy libc.so and other files
+# that are already linked in before a Postfix daemon chroots itself.
+
+## Copy any shared libraries, device entries, or configuration files
+## needed by Postfix into the jail.
+binlist="
+/usr/libexec/postfix/virtual
+/usr/libexec/postfix/trivial-rewrite
+/usr/libexec/postfix/spawn
+/usr/libexec/postfix/smtpd
+/usr/libexec/postfix/smtp
+/usr/libexec/postfix/showq
+/usr/libexec/postfix/qmqpd
+/usr/libexec/postfix/qmgr
+/usr/libexec/postfix/proxymap
+/usr/libexec/postfix/pipe
+/usr/libexec/postfix/pickup
+/usr/libexec/postfix/nqmgr
+/usr/libexec/postfix/master
+/usr/libexec/postfix/local
+/usr/libexec/postfix/lmtp
+/usr/libexec/postfix/flush
+/usr/libexec/postfix/error
+/usr/libexec/postfix/cleanup
+/usr/libexec/postfix/bounce
+/usr/lib/sendmail
+/usr/sbin/postsuper
+/usr/sbin/postqueue
+/usr/sbin/postmap
+/usr/sbin/postlog
+/usr/sbin/postlock
+/usr/sbin/postkick
+/usr/sbin/postfix
+/usr/sbin/postdrop
+/usr/sbin/postconf
+/usr/sbin/postcat
+/usr/sbin/postalias
+"
+for i in `xargs ldd $binlist | grep -v '^[^:]*:' | sort | uniq | sed -e 's/^[^ ]* =>//' | awk '{print $1}'`; do
+    mkdir -p /var/spool/postfix`dirname $i`
+    ## Sun's version of tar sucks.  We'll have to remove the leading
+    ## slashes from file names ourself, otherwise the copy doesn't
+    ## work.
+    (cd / && tar cphf - `echo $i | sed -e 's/^\///'`) | (cd /var/spool/postfix && tar xpf -)
+done
+
+## More stuff for the jail, mostly discovered by inspection
+## (e.g. strings, lsof).
+for i in "
+/dev/zero
+/dev/null
+/dev/udp6
+/dev/tcp6
+/dev/udp
+/dev/tcp
+/dev/rawip
+/dev/ticlts
+/dev/ticotsord
+/dev/ticots
+/devices/pseudo/mm@0:zero
+/devices/pseudo/mm@0:null
+/devices/pseudo/udp6@0:udp6
+/devices/pseudo/tcp6@0:tcp6
+/devices/pseudo/udp@0:udp
+/devices/pseudo/tcp@0:tcp
+/devices/pseudo/icmp@0:icmp
+/devices/pseudo/tl@0:ticlts
+/devices/pseudo/tl@0:ticotsord
+/devices/pseudo/tl@0:ticots
+/etc/nsswitch.conf
+/etc/netconfig
+/etc/default/init
+/etc/inet/services
+/etc/services
+/usr/lib/ld.so
+/usr/lib/ld.so.1
+/usr/lib/sparcv9/straddr.so
+/usr/lib/straddr.so
+/usr/lib/libintl.so
+/usr/lib/libintl.so.1
+/usr/lib/libw.so
+/usr/lib/libw.so.1
+/usr/lib/nss_nis.so.1
+/usr/lib/nss_nisplus.so.1
+/usr/lib/nss_dns.so.1
+/usr/lib/nss_files.so.1
+/usr/share/lib/zoneinfo
+/var/ld/ld.config
+"; do
+    mkdir -p /var/spool/postfix`dirname $i`
+    (cd / && tar cpf - `echo $i | sed -e 's/^\///'`) | (cd /var/spool/postfix && tar xpf -)
+done
+
+exit 0
index ceaf212efac5d18fe6e18cd3d1f376abbecddc3f..bfca5262480fd0ec11aece4b350112b22b19dab9 100644 (file)
@@ -54,10 +54,10 @@ typedef struct CLEANUP_STATE {
     int     hop_count;                 /* count of received: headers */
     char   *resent;                    /* any resent- header seen */
     BH_TABLE *dups;                    /* recipient dup filter */
-    long    warn_time;                 /* cleanup_envelope.c */
     void    (*action) (struct CLEANUP_STATE *, int, const char *, int);
     off_t   data_offset;               /* start of message content */
     off_t   xtra_offset;               /* start of extracted content */
+    int     warn_seen;                 /* REC_TYPE_WARN seen */
     int     verp_seen;                 /* REC_TYPE_VERP seen */
     int     end_seen;                  /* REC_TYPE_END seen */
     int     rcpt_count;                        /* recipient count */
index a22bc6e9868301c1894c1fc1cf0822ed08a16357..2e731a9481a83dbf1254e5e1da4621bea1c497b7 100644 (file)
@@ -126,14 +126,22 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
        return;
     }
     if (strchr(REC_TYPE_ENVELOPE, type) == 0) {
-       msg_warn("%s: unexpected record type %d in envelope: message rejected",
+       msg_warn("%s: message rejected: unexpected record type %d in envelope",
                 state->queue_id, type);
        state->errs |= CLEANUP_STAT_BAD;
        return;
     }
+
+    /*
+     * The code for processing recipient records is first, because there can
+     * be lots of them. However, recipient records appear at the end of the
+     * initial or extracted envelope, so that the queue manager does not have
+     * to read the whole envelope before it can start deliveries.
+     */
     if (type == REC_TYPE_RCPT) {
+       state->flags |= CLEANUP_FLAG_INRCPT;
        if (state->sender == 0) {               /* protect showq */
-           msg_warn("%s: envelope recipient precedes sender: message rejected",
+           msg_warn("%s: message rejected: envelope recipient precedes sender",
                     state->queue_id);
            state->errs |= CLEANUP_STAT_BAD;
            return;
@@ -146,6 +154,7 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
        return;
     }
     if (type == REC_TYPE_DONE) {
+       state->flags |= CLEANUP_FLAG_INRCPT;
        if (state->orig_rcpt != 0) {
            myfree(state->orig_rcpt);
            state->orig_rcpt = 0;
@@ -154,17 +163,64 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
     }
     if (state->orig_rcpt != 0) {
        /* REC_TYPE_ORCP must be followed by REC_TYPE_RCPT or REC_TYPE DONE. */
-       msg_warn("%s: out-of-order original recipient record <%.200s>",
+       msg_warn("%s: ignoring out-of-order original recipient record <%.200s>",
                 state->queue_id, state->orig_rcpt);
        myfree(state->orig_rcpt);
        state->orig_rcpt = 0;
     }
     if (type == REC_TYPE_ORCP) {
+       state->flags |= CLEANUP_FLAG_INRCPT;
        state->orig_rcpt = mystrdup(buf);
        return;
     }
+
+    /*
+     * These non-recipient records may appear before or after recipient
+     * records. In order to keep recipient records pure, We take away these
+     * non-recipient records from the input, and output them at the start of
+     * the extracted envelope segment.
+     */
+    if (type == REC_TYPE_FILT) {
+       /* Last instance wins. */
+       if (strchr(buf, ':') == 0) {
+           msg_warn("%s: ignoring invalid content filter: %.100s",
+                    state->queue_id, buf);
+           return;
+       }
+       if (state->filter)
+           myfree(state->filter);
+       state->filter = mystrdup(buf);
+       return;
+    }
+    if (type == REC_TYPE_RDR) {
+       /* Last instance wins. */
+       if (strchr(buf, '@') == 0) {
+           msg_warn("%s: ignoring invalid redirect address: %.100s",
+                    state->queue_id, buf);
+           return;
+       }
+       if (state->redirect)
+           myfree(state->redirect);
+       state->redirect = mystrdup(buf);
+       return;
+    }
+
+    /*
+     * The following records must not appear after recipient records. We
+     * force the warning record before the sender record so we know when
+     * (not) to emit a warning record. A warning or size record may already
+     * be present when mail is requeued with "postsuper -r".
+     */
+    if (type != REC_TYPE_MESG && (state->flags & CLEANUP_FLAG_INRCPT) != 0) {
+       msg_warn("%s: ignoring %s record after initial envelope recipients",
+                state->queue_id, rec_type_name(type));
+       return;
+    }
+    if (type == REC_TYPE_SIZE)
+       /* Use our own SIZE record instead. */
+       return;
     if (type == REC_TYPE_TIME) {
-       /* First definition wins. */
+       /* First instance wins. */
        if (state->time == 0) {
            state->time = atol(buf);
            cleanup_out(state, type, buf, len);
@@ -172,7 +228,7 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
        return;
     }
     if (type == REC_TYPE_FULL) {
-       /* First definition wins. */
+       /* First instance wins. */
        if (state->fullname == 0) {
            state->fullname = mystrdup(buf);
            cleanup_out(state, type, buf, len);
@@ -182,30 +238,39 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
     if (type == REC_TYPE_FROM) {
        /* Allow only one instance. */
        if (state->sender != 0) {
-           msg_warn("%s: too many envelope sender records: message rejected",
+           msg_warn("%s: message rejected: multiple envelope sender records",
                     state->queue_id);
            state->errs |= CLEANUP_STAT_BAD;
            return;
        }
+       /* Kluge to force REC_TYPE_WARN before recipients. */
+       if (state->warn_seen == 0 && var_delay_warn_time > 0) {
+           cleanup_out_format(state, REC_TYPE_WARN, REC_TYPE_WARN_FORMAT,
+                              (long) var_delay_warn_time);
+           state->warn_seen = 1;
+       }
        cleanup_addr_sender(state, buf);
        return;
     }
     if (type == REC_TYPE_WARN) {
-       /* First definition wins. */
-       if (state->warn_time == 0) {
-           if ((state->warn_time = atol(buf)) < 0) {
-               msg_warn("%s: bad arrival time record: %s: message rejected",
+       /* First instance wins. */
+       if (state->warn_seen == 0) {
+           if (atoi(buf) < 0) {
+               msg_warn("%s: message rejected: bad warning time: %.100s",
                         state->queue_id, buf);
                state->errs |= CLEANUP_STAT_BAD;
+               return;
            }
+           state->warn_seen = 1;
+           cleanup_out(state, type, buf, len);
        }
        return;
     }
     if (type == REC_TYPE_VERP) {
-       /* First definition wins. */
+       /* First instance wins. */
        if (state->verp_seen == 0) {
            if ((error_text = verp_delims_verify(buf)) != 0) {
-               msg_warn("%s: %s: \"%s\": message rejected",
+               msg_warn("%s: message rejected: %s: %.100s",
                         state->queue_id, error_text, buf);
                state->errs |= CLEANUP_STAT_BAD;
                return;
@@ -216,19 +281,18 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
        return;
     }
     if (type == REC_TYPE_ATTR) {
-       /* Pass through. Last definition wins. */
+       /* Pass through. Last instance wins. */
        char   *sbuf;
 
        if (state->attr->used >= var_qattr_count_limit) {
-           msg_warn("%s: queue file attribute count exceeds safety limit %d"
-                    ": message rejected",
+           msg_warn("%s: message rejected: attribute count exceeds limit %d",
                     state->queue_id, var_qattr_count_limit);
            state->errs |= CLEANUP_STAT_BAD;
            return;
        }
        sbuf = mystrdup(buf);
        if ((error_text = split_nameval(sbuf, &attr_name, &attr_value)) != 0) {
-           msg_warn("%s: malformed attribute: %s: %.100s: message rejected",
+           msg_warn("%s: message rejected: malformed attribute: %s: %.100s",
                     state->queue_id, error_text, buf);
            state->errs |= CLEANUP_STAT_BAD;
            myfree(sbuf);
@@ -239,44 +303,32 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
        cleanup_out(state, type, buf, len);
        return;
     }
-    if (type == REC_TYPE_SIZE)
-       /* Use our own SIZE record instead. */
-       return;
     if (type != REC_TYPE_MESG) {
-       /* Anything else. Pass through. */
+       /* Any other allowed record type. Pass through. */
        cleanup_out(state, type, buf, len);
        return;
     }
 
     /*
-     * On the transition from envelope segment to content segment, do some
-     * sanity checks.
+     * On the transition from initial envelope segment to content segment, do
+     * some sanity checks.
      * 
-     * If senders can be specified in the extracted envelope segment, then we
-     * need to move the VERP test there, too.
+     * XXX If senders can be specified in the extracted envelope segment (this
+     * could reduce qmqpd's memory requirements), then we need to move the
+     * VERP test there, too.
      */
     if (state->sender == 0 || state->time == 0) {
-       msg_warn("%s: missing sender or time envelope record: message rejected",
+       msg_warn("%s: message rejected: missing sender or time envelope record",
                 state->queue_id);
        state->errs |= CLEANUP_STAT_BAD;
        return;
     }
     if (state->verp_seen && (state->sender == 0 || *state->sender == 0)) {
-       msg_warn("%s: VERP request with no or null sender: message rejected",
+       msg_warn("%s: message rejected: VERP request with no or null sender",
                 state->queue_id);
        state->errs |= CLEANUP_STAT_BAD;
        return;
     }
-
-    /*
-     * Emit records for information that we collected from the envelope
-     * segment.
-     */
-    if (state->warn_time == 0 && var_delay_warn_time > 0)
-       state->warn_time = state->time + var_delay_warn_time;
-    if (state->warn_time)
-       cleanup_out_format(state, REC_TYPE_WARN, REC_TYPE_WARN_FORMAT,
-                          state->warn_time);
-
+    state->flags &= ~CLEANUP_FLAG_INRCPT;
     state->action = cleanup_message;
 }
index e218fb72ed1432fa06f26264e5b47974d4bc3c00..d66eb65d3c15d7ba4d83670256e3c711e96f0867 100644 (file)
 /*     int     len;
 /* DESCRIPTION
 /*     This module processes message records with information extracted
-/*     from message content, or with recipients that are stored after the
-/*     message content. It updates recipient records, and writes extracted
-/*     information records to the output.
+/*     from the initial message envelope or from the message content, or
+/*     with recipients that are stored after the message content. It
+/*     updates recipient records, and writes extracted information records
+/*     to the output.
 /*
 /*     Arguments:
 /* .IP state
 
 #define STR(x) vstring_str(x)
 
-static void cleanup_extracted_process(CLEANUP_STATE *, int, const char *, int);
-
- /*
-  * The following queue file records are generated from message header or
-  * message body content. We may encounter them in extracted envelope
-  * segments after mail is re-injected with "postsuper -r" and we should
-  * ignore them. It might be infinitesimally faster to move this test to the
-  * pickup daemon, but that would make program maintenance more difficult.
-  */
-static char cleanup_extracted_generated[] = {
-    REC_TYPE_RRTO,                     /* return-receipt-to */
-    REC_TYPE_ERTO,                     /* errors-to */
-    REC_TYPE_FILT,                     /* content filter */
-    REC_TYPE_INSP,                     /* content inspector */
-    REC_TYPE_RDR,                      /* redirect address */
-    REC_TYPE_ATTR,                     /* some header attribute */
-    0,
-};
+static void cleanup_extracted_non_rcpt(CLEANUP_STATE *, int, const char *, int);
+static void cleanup_extracted_rcpt(CLEANUP_STATE *, int, const char *, int);
 
 /* cleanup_extracted - initialize extracted segment */
 
 void    cleanup_extracted(CLEANUP_STATE *state, int type,
                                  const char *buf, int len)
 {
-    const char *encoding;
 
     /*
      * Start the extracted segment.
@@ -101,105 +85,120 @@ void    cleanup_extracted(CLEANUP_STATE *state, int type,
     cleanup_out_string(state, REC_TYPE_XTRA, "");
 
     /*
-     * Postfix keeps all information related to an email message is in a
-     * write-once file, including the envelope sender and recipients, and the
-     * message content. This design maximizes robustness: one file is easier
-     * to keep track of than multiple files, and write-once means that no
-     * operation ever needs to be undone. This design also minimizes file
-     * system overhead, because creating and removing files is relatively
-     * expensive compared to writing files. Separate files are used for
-     * logging the causes of deferral or failed delivery.
-     * 
-     * A Postfix queue file consists of three segments.
-     * 
-     * 1) The initial envelope segment with the arrival time, sender address,
-     * recipients, and some other stuff that can be recorded before the
-     * message content is received, including non-recipient information that
-     * results from actions in Postfix SMTP server access tables. In this
-     * segment, recipient records may be preceded or followed by
-     * non-recipient records.
-     * 
-     * 2) The message content segment with the message headers and body. The
-     * message body includes all the MIME segments, if there are any.
-     * 
-     * 3) The extracted envelope segment with information that was extracted
-     * from message headers or from the message body, including recipient
-     * addresses that were extracted from message headers, and non-recipient
-     * information that results from actions in header/body_checks patterns.
-     * In this segment, all non-recipient records precede the recipient
-     * records.
-     * 
-     * There are two queue file layouts.
-     * 
-     * A) All recipient records are in the initial envelope segment, except for
-     * the optional always_bcc recipient which is always stored in the
-     * extracted envelope segment. The queue manager reads as many recipients
-     * as it can from the initial envelope segment, and then examines all
-     * remaining initial envelope records and all extracted envelope records,
-     * picking up non-recipient information. This organization favors
-     * messages with fewer than $qmgr_active_recipient_limit recipients.
-     * 
-     * B) All recipient records are stored in the extracted envelope segment,
-     * after all non-recipient records. The queue manager is guaranteed to
-     * have read all the non-recipient records before it sees the first
-     * recipient record. This organization can handle messages with very
-     * large numbers of recipients.
+     * Pass control to the actual envelope processing routine.
+     */
+    state->action = cleanup_extracted_non_rcpt;
+    cleanup_extracted_non_rcpt(state, type, buf, len);
+}
+
+/* cleanup_extracted_non_rcpt - process non-recipient records */
+
+void    cleanup_extracted_non_rcpt(CLEANUP_STATE *state, int type,
+                                          const char *buf, int len)
+{
+    const char *encoding;
+
+    if (msg_verbose)
+       msg_info("extracted envelope %c %.*s", type, len, buf);
+
+    if (strchr(REC_TYPE_EXTRACT, type) == 0) {
+       msg_warn("%s: message rejected: "
+                "unexpected record type %d in extracted envelope",
+                state->queue_id, type);
+       state->errs |= CLEANUP_STAT_BAD;
+       return;
+    }
+
+    /*
+     * The following records are taken away from the initial envelope segment
+     * and may be overruled by information from header/body_checks; then they
+     * are emitted at the start of the extracted envelope segment.
      * 
-     * All this is the result of an evolutionary process, where compatibility
-     * between Postfix versions was a major goal as new features were added.
-     * Therefore the file organization is not optimal from a performance
-     * point of view. In hindsight, the non-recipient information that
-     * follows recipients in the initial envelope segment could be moved to
-     * the extracted envelope segment. This would improve file organization
-     * A)'s performance with very large numbers of recipients, by eliminating
-     * the need to examine all initial envelope records before starting
-     * deliveries.
+     * If we encounter these records here, then the message was subjected to
+     * "postsuper -r" and we can ignore these records if we already have
+     * information from header/body_checks.
      */
-    if (state->filter != 0)
-       cleanup_out_string(state, REC_TYPE_FILT, state->filter);
+    if (type == REC_TYPE_FILT) {
+       /* Our own header/body_checks information wins. */
+       if (state->filter == 0)
+           state->filter = mystrdup(buf);
+       return;
+    }
+    if (type == REC_TYPE_RDR) {
+       /* Our own header/body_checks information wins. */
+       if (state->redirect == 0)
+           state->redirect = mystrdup(buf);
+       return;
+    }
 
     /*
-     * The optional redirect target address from header/body_checks actions.
+     * Ignore records that the cleanup server extracts from message headers.
+     * These records may appear in "postsuper -r" email.
      */
-    if (state->redirect != 0)
-       cleanup_out_string(state, REC_TYPE_RDR, state->redirect);
+    if (type == REC_TYPE_RRTO)
+       /* Use our own headers extracted return address. */
+       return;
+    if (type == REC_TYPE_ERTO)
+       /* Use our own headers extracted error address. */
+       return;
+    if (type == REC_TYPE_ATTR)
+       /* Use our own headers extracted content encoding. */
+       return;
+
+    if (type != REC_TYPE_END && type != REC_TYPE_FROM
+       && type != REC_TYPE_DONE && type != REC_TYPE_ORCP) {
+       /* Any other allowed non-recipient record. Pass through. */
+       cleanup_out(state, type, buf, len);
+       return;
+    }
 
     /*
-     * Older Postfix versions didn't MIME emit encoding information, so this
-     * record can only be optional.
+     * At the end of the non-recipient record section, emit optional
+     * information from header/body_checks actions, from the start of the
+     * extracted envelope, or from the initial envelope.
      */
+    if (state->filter != 0)
+       cleanup_out_string(state, REC_TYPE_FILT, state->filter);
+
+    if (state->redirect != 0)
+       cleanup_out_string(state, REC_TYPE_RDR, state->redirect);
+
     if ((encoding = nvtable_find(state->attr, MAIL_ATTR_ENCODING)) != 0)
        cleanup_out_format(state, REC_TYPE_ATTR, "%s=%s",
                           MAIL_ATTR_ENCODING, encoding);
 
     /*
-     * Return-Receipt-To and Errors-To records are now optional.
+     * Terminate the non-recipient records with the Return-Receipt-To and
+     * Errors-To records. The queue manager relies on this information.
      */
-    if (state->return_receipt)
-       cleanup_out_string(state, REC_TYPE_RRTO, state->return_receipt);
-    if (state->errors_to)
-       cleanup_out_string(state, REC_TYPE_ERTO, state->errors_to);
+    cleanup_out_string(state, REC_TYPE_RRTO, state->return_receipt ?
+                      state->return_receipt : "");
+
+    cleanup_out_string(state, REC_TYPE_ERTO, state->errors_to ?
+                      state->errors_to : state->sender);
 
     /*
-     * Pass control to the routine that processes the extracted segment.
+     * Pass control to the routine that processes the recipient portion of
+     * the extracted segment.
      */
-    state->action = cleanup_extracted_process;
-    cleanup_extracted_process(state, type, buf, len);
+    state->action = cleanup_extracted_rcpt;
+    cleanup_extracted_rcpt(state, type, buf, len);
 }
 
-/* cleanup_extracted_process - process extracted segment */
+/* cleanup_extracted_rcpt - process recipients in extracted segment */
 
-static void cleanup_extracted_process(CLEANUP_STATE *state, int type,
-                                             const char *buf, int len)
+static void cleanup_extracted_rcpt(CLEANUP_STATE *state, int type,
+                                          const char *buf, int len)
 {
-    char   *myname = "cleanup_extracted_process";
+    char   *myname = "cleanup_extracted_rcpt";
 
     if (msg_verbose)
        msg_info("extracted envelope %c %.*s", type, len, buf);
 
     if (strchr(REC_TYPE_EXTRACT, type) == 0) {
-       msg_warn("%s: unexpected record type %d in extracted envelope"
-                ": message rejected", state->queue_id, type);
+       msg_warn("%s: message rejected: "
+                "unexpected record type %d in extracted envelope",
+                state->queue_id, type);
        state->errs |= CLEANUP_STAT_BAD;
        return;
     }
@@ -229,12 +228,9 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type,
        state->orig_rcpt = mystrdup(buf);
        return;
     }
-    if (strchr(cleanup_extracted_generated, type) != 0)
-       /* Use our own message header extracted information instead. */
-       return;
     if (type != REC_TYPE_END) {
-       msg_warn("unexpected non-recipient record: %s", rec_type_name(type));
-       cleanup_out(state, type, buf, len);
+       msg_warn("%s: ignoring %s record after extracted envelope recipients",
+                state->queue_id, rec_type_name(type));
        return;
     }
 
index fc4868fd4d225b07494b447b2dad81c5dc4d3a69..81cf66287be97592309e729b54181fbc5787c5a8 100644 (file)
@@ -493,29 +493,6 @@ static void cleanup_header_callback(void *context, int header_class,
     }
 }
 
-/* cleanup_missing - handle missing message header */
-
-static void cleanup_missing(CLEANUP_STATE *state, const char *resent,
-                                   const char *header)
-{
-    const char *attr;
-
-    if ((attr = nvtable_find(state->attr, MAIL_ATTR_ORIGIN)) == 0)
-       attr = "unknown";
-    vstring_sprintf(state->temp1, "%s: reject: missing %s%s header from %s;",
-                   state->queue_id, resent, header, attr);
-    if (state->sender)
-       vstring_sprintf_append(state->temp1, " from=<%s>", state->sender);
-    if (state->recip)
-       vstring_sprintf_append(state->temp1, " to=<%s>", state->recip);
-    if ((attr = nvtable_find(state->attr, MAIL_ATTR_PROTO_NAME)) != 0)
-       vstring_sprintf_append(state->temp1, " proto=%s", attr);
-    if ((attr = nvtable_find(state->attr, MAIL_ATTR_HELO_NAME)) != 0)
-       vstring_sprintf_append(state->temp1, " helo=<%s>", attr);
-    msg_info("%s", vstring_str(state->temp1));
-    state->errs |= CLEANUP_STAT_MISS_HDR;
-}
-
 /* cleanup_header_done_callback - insert missing message headers */
 
 static void cleanup_header_done_callback(void *context)
@@ -525,15 +502,6 @@ static void cleanup_header_done_callback(void *context)
     struct tm *tp;
     TOK822 *token;
 
-    /*
-     * Postfix prepends a Received: message header, so we should see two when
-     * one is required.
-     */
-    if ((state->flags & CLEANUP_FLAG_NEED_RCVD) && state->hop_count < 2) {
-       cleanup_missing(state, "", "Received");
-       return;
-    }
-
     /*
      * Add a missing (Resent-)Message-Id: header. The message ID gives the
      * time in GMT units, plus the local queue ID.
@@ -545,10 +513,6 @@ static void cleanup_header_done_callback(void *context)
      */
     if ((state->headers_seen & (1 << (state->resent[0] ?
                           HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID))) == 0) {
-       if (state->flags & CLEANUP_FLAG_NEED_MSGID) {
-           cleanup_missing(state, state->resent, "Message-Id");
-           return;
-       }
        tp = gmtime(&state->time);
        strftime(time_stamp, sizeof(time_stamp), "%Y%m%d%H%M%S", tp);
        cleanup_out_format(state, REC_TYPE_NORM, "%sMessage-Id: <%s.%s@%s>",
@@ -564,10 +528,6 @@ static void cleanup_header_done_callback(void *context)
      */
     if ((state->headers_seen & (1 << (state->resent[0] ?
                                      HDR_RESENT_DATE : HDR_DATE))) == 0) {
-       if (state->flags & CLEANUP_FLAG_NEED_DATE) {
-           cleanup_missing(state, state->resent, "Date");
-           return;
-       }
        cleanup_out_format(state, REC_TYPE_NORM, "%sDate: %s",
                           state->resent, mail_date(state->time));
     }
@@ -577,10 +537,6 @@ static void cleanup_header_done_callback(void *context)
      */
     if ((state->headers_seen & (1 << (state->resent[0] ?
                                      HDR_RESENT_FROM : HDR_FROM))) == 0) {
-       if (state->flags & CLEANUP_FLAG_NEED_FROM) {
-           cleanup_missing(state, state->resent, "From");
-           return;
-       }
        quote_822_local(state->temp1, *state->sender ?
                        state->sender : MAIL_ADDR_MAIL_DAEMON);
        vstring_sprintf(state->temp2, "%sFrom: %s",
diff --git a/postfix/src/cleanup/cleanup_output.txt b/postfix/src/cleanup/cleanup_output.txt
new file mode 100644 (file)
index 0000000..f15d7b3
--- /dev/null
@@ -0,0 +1,57 @@
+
+    /*
+     * Postfix keeps all information related to an email message is in a
+     * write-once file, including the envelope sender and recipients, and the
+     * message content. This design maximizes robustness: one file is easier
+     * to keep track of than multiple files, and write-once means that no
+     * operation ever needs to be undone. This design also minimizes file
+     * system overhead, because creating and removing files is relatively
+     * expensive compared to writing files. Separate files are used for
+     * logging the causes of deferral or failed delivery.
+     * 
+     * A Postfix queue file consists of three segments.
+     * 
+     * 1) The initial envelope segment with the arrival time, sender address,
+     * recipients, and some other stuff that can be recorded before the
+     * message content is received, including non-recipient information that
+     * results from actions in Postfix SMTP server access tables. In this
+     * segment, recipient records may be preceded or followed by
+     * non-recipient records.
+     * 
+     * 2) The message content segment with the message headers and body. The
+     * message body includes all the MIME segments, if there are any.
+     * 
+     * 3) The extracted envelope segment with information that was extracted
+     * from message headers or from the message body, including recipient
+     * addresses that were extracted from message headers, and non-recipient
+     * information that results from actions in header/body_checks patterns.
+     * In this segment, all non-recipient records precede the recipient
+     * records. The last non-recipient records are return-receipt-to and
+     * errors-to.
+     * 
+     * There are two queue file layouts.
+     * 
+     * A) All recipient records are in the initial envelope segment, except for
+     * the optional always_bcc recipient which is always stored in the
+     * extracted envelope segment. The queue manager reads as many recipients
+     * as it can from the initial envelope segment, and then examines all
+     * remaining initial envelope records and all extracted envelope records,
+     * picking up non-recipient information. This organization favors
+     * messages with fewer than $qmgr_active_recipient_limit recipients.
+     * 
+     * B) All recipient records are stored in the extracted envelope segment,
+     * after all non-recipient records. The queue manager is guaranteed to
+     * have read all the non-recipient records before it sees the first
+     * recipient record. This organization can handle messages with very
+     * large numbers of recipients.
+     * 
+     * All this is the result of an evolutionary process, where compatibility
+     * between Postfix versions was a major goal as new features were added.
+     * Therefore the file organization is not optimal from a performance
+     * point of view. In hindsight, the non-recipient information that
+     * follows recipients in the initial envelope segment could be moved to
+     * the extracted envelope segment. This would improve file organization
+     * A)'s performance with very large numbers of recipients, by eliminating
+     * the need to examine all initial envelope records before starting
+     * deliveries.
+     */
index a03ae54d16aa0e0293d400793da44a05b034a41f..845cde7ec323097c428ffc22fee73ca70421a1af 100644 (file)
@@ -77,10 +77,10 @@ CLEANUP_STATE *cleanup_state_alloc(void)
     state->hop_count = 0;
     state->resent = "";
     state->dups = been_here_init(var_dup_filter_limit, BH_FLAG_FOLD);
-    state->warn_time = 0;
     state->action = cleanup_envelope;
     state->data_offset = -1;
     state->xtra_offset = -1;
+    state->warn_seen = 0;
     state->verp_seen = 0;
     state->end_seen = 0;
     state->rcpt_count = 0;
index e763ce950f9c528dbdd6b08f255dafcdcafab8fd..489093ed94e2e9cb367d099e611be3d980c5703e 100644 (file)
@@ -51,7 +51,6 @@ static struct cleanup_stat_map cleanup_stat_map[] = {
     CLEANUP_STAT_BAD, "Internal protocol error",
     CLEANUP_STAT_RCPT, "No recipients specified",
     CLEANUP_STAT_HOPS, "Too many hops",
-    CLEANUP_STAT_MISS_HDR, "Missing message header",
     CLEANUP_STAT_SIZE, "Message file too big",
     CLEANUP_STAT_CONT, "Message content rejected",
     CLEANUP_STAT_WRITE, "Error writing message file",
index 8c988251b9b5d7e6a51b648a0dbcfda89a136894..cb94eb6f777cb37e26cb7e8eee65743d33fa085d 100644 (file)
 #define CLEANUP_FLAG_HOLD      (1<<2)  /* Place message on hold */
 #define CLEANUP_FLAG_DISCARD   (1<<3)  /* Discard message silently */
 #define CLEANUP_FLAG_BCC_OK    (1<<4)  /* Ok to add auto-BCC addresses */
-#define CLEANUP_FLAG_NEED_DATE (1<<5)  /* Require (Resent:-)Date: */
-#define CLEANUP_FLAG_NEED_FROM (1<<6)  /* Require (Resent:-)From: */
-#define CLEANUP_FLAG_NEED_MSGID        (1<<7)  /* Require (Resent:-)Message-Id: */
-#define CLEANUP_FLAG_NEED_RCVD (1<<8)  /* Require two Received: headers */
+
+ /*
+  * Status.
+  */
+#define CLEANUP_FLAG_INRCPT    (1<<16) /* Expecting recipient records only */
 
  /*
   * These are set on the fly while processing SMTP envelopes or message
   * content.
   */
 #define CLEANUP_FLAG_MASK_EXTRA \
-       (CLEANUP_FLAG_HOLD | CLEANUP_FLAG_DISCARD | CLEANUP_FLAG_NEED_DATE | \
-           CLEANUP_FLAG_NEED_FROM | CLEANUP_FLAG_NEED_MSGID | \
-           CLEANUP_FLAG_NEED_RCVD)
+       (CLEANUP_FLAG_HOLD | CLEANUP_FLAG_DISCARD)
 
  /*
   * Diagnostics.
@@ -45,7 +44,6 @@
 #define CLEANUP_STAT_SIZE      (1<<2)  /* Message file too big */
 #define CLEANUP_STAT_CONT      (1<<3)  /* Message content rejected */
 #define CLEANUP_STAT_HOPS      (1<<4)  /* Too many hops */
-#define CLEANUP_STAT_MISS_HDR  (1<<5)  /* Some missing header */
 #define CLEANUP_STAT_RCPT      (1<<6)  /* No recipients found */
 
  /*
index 4b968416c5e9738cd804967b2710228764631a4c..3c8021d5d8f9092bcc13342ccf4a9ef0695956db 100644 (file)
@@ -1337,11 +1337,6 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`\
 abcdefghijklmnopqrstuvwxyz{|}~"
 extern char *var_smtpd_exp_filter;
 
-#define REQUIRE_DATE_HDR       "require_date_header"
-#define REQUIRE_FROM_HDR       "require_from_header"
-#define REQUIRE_MSGID_HDR      "require_message_id_header"
-#define REQUIRE_RCVD_HDR       "require_received_header"
-
  /*
   * Heuristic to reject unknown local recipients at the SMTP port.
   */
index 700a85cf488d7692c68c0340962a54848eb48a17..3aae7b741c510749c726ff45bd4e064a10eacf88 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only, unless they include the same bugfix as a patch release.
   */
-#define MAIL_RELEASE_DATE      "20030524"
+#define MAIL_RELEASE_DATE      "20030526"
 
 #define VAR_MAIL_VERSION       "mail_version"
 #define DEF_MAIL_VERSION       "2.0.10-" MAIL_RELEASE_DATE
index 34b54ffcdd5ef266fbcd8f1518ad5a60f6f9d5d1..2f17e595e87ae950665f54979e0a67473260caad 100644 (file)
@@ -263,7 +263,6 @@ struct QMGR_MESSAGE {
     long    warn_offset;               /* warning bounce flag offset */
     time_t  warn_time;                 /* time next warning to be sent */
     long    data_offset;               /* data seek offset */
-    long    extra_offset;              /* extracted data seek offset */
     char   *queue_name;                        /* queue name */
     char   *queue_id;                  /* queue file */
     char   *encoding;                  /* content encoding */
index 99576001dd8007ef0e6328442f76f8c3a20d6e0e..9ca0fcb00ee9c2ae42d07378c2e9dadd41686e56 100644 (file)
@@ -382,9 +382,15 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                    if ((message->rcpt_offset = vstream_ftell(message->fp)) < 0)
                        msg_fatal("vstream_ftell %s: %m",
                                  VSTREAM_PATH(message->fp));
-                   /* Must have examined all non-recipient records. */
-                   if (curr_offset > message->data_offset)
+                   /* We already examined all non-recipient records. */
+                   if (message->errors_to)
                        break;
+                   /* Examine non-recipient records in extracted segment. */
+                   if (curr_offset < message->data_offset
+                       && vstream_fseek(message->fp, message->data_offset
+                                        + message->data_size, SEEK_SET) < 0)
+                       msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
+                   continue;
                }
            }
            continue;
@@ -412,6 +418,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                orig_rcpt = mystrdup(start);
            continue;
        }
+       if (message->errors_to)
+           /* We already examined all non-recipient records. */
+           continue;
        if (rec_type == REC_TYPE_SIZE) {
            if (message->data_offset == 0) {
                if ((count = sscanf(start, "%ld %ld %d", &message->data_size,
@@ -489,6 +498,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
        if (rec_type == REC_TYPE_ERTO) {
            if (message->errors_to == 0)
                message->errors_to = mystrdup(start);
+           /* We already examined all non-recipient records. */
+           if (message->rcpt_offset)
+               break;
            continue;
        }
        if (rec_type == REC_TYPE_RRTO) {
@@ -531,12 +543,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
      * Avoid clumsiness elsewhere in the program. When sending data across an
      * IPC channel, sending an empty string is more convenient than sending a
      * null pointer.
-     * 
-     * Allow for Postfix versions that do not store return_receipt or errors_to
-     * records.
      */
     if (message->errors_to == 0)
-       message->errors_to = mystrdup("");
+       message->errors_to = mystrdup(message->sender);
     if (message->return_receipt == 0)
        message->return_receipt = mystrdup("");
     if (message->encoding == 0)
@@ -724,6 +733,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
            }
            rewrite_clnt_internal(REWRITE_CANON, message->redirect_addr,
                                  reply.recipient);
+
            UPDATE(recipient->address, STR(reply.recipient));
            if (qmgr_resolve_one(message, recipient,
                                 recipient->address, &reply) < 0)
index 29d4abdc248de0030af4a1a954a5e13674ddc530..7ae2839a0498a2f6b5999b1fdd17e0f5944c1f6a 100644 (file)
@@ -350,9 +350,15 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                    if ((message->rcpt_offset = vstream_ftell(message->fp)) < 0)
                        msg_fatal("vstream_ftell %s: %m",
                                  VSTREAM_PATH(message->fp));
-                   /* Must have examined all non-recipient records. */
-                   if (curr_offset > message->data_offset)
+                   /* We already examined all non-recipient records. */
+                   if (message->errors_to)
                        break;
+                   /* Examine non-recipient records in extracted segment. */
+                   if (curr_offset < message->data_offset
+                       && vstream_fseek(message->fp, message->data_offset
+                                        + message->data_size, SEEK_SET) < 0)
+                       msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
+                   continue;
                }
            }
            continue;
@@ -377,6 +383,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                orig_rcpt = mystrdup(start);
            continue;
        }
+       if (message->errors_to)
+           /* We already examined all non-recipient records. */
+           continue;
        if (rec_type == REC_TYPE_SIZE) {
            if (message->data_offset == 0) {
                if ((count = sscanf(start, "%ld %ld %d", &message->data_size,
@@ -454,6 +463,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
        if (rec_type == REC_TYPE_ERTO) {
            if (message->errors_to == 0)
                message->errors_to = mystrdup(start);
+           /* We already examined all non-recipient records. */
+           if (message->rcpt_offset)
+               break;
            continue;
        }
        if (rec_type == REC_TYPE_RRTO) {
@@ -496,12 +508,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
      * Avoid clumsiness elsewhere in the program. When sending data across an
      * IPC channel, sending an empty string is more convenient than sending a
      * null pointer.
-     * 
-     * Allow for Postfix versions that do not store return_receipt or errors_to
-     * records.
      */
     if (message->errors_to == 0)
-       message->errors_to = mystrdup("");
+       message->errors_to = mystrdup(message->sender);
     if (message->return_receipt == 0)
        message->return_receipt = mystrdup("");
     if (message->encoding == 0)
index 2e676001e6159cf9573662fe7284b68b5273c6a7..28cbbcd68947dfa8ca6bdd31ba38d6663c4cf17e 100644 (file)
@@ -482,9 +482,6 @@ static void qmqpd_send_status(QMQPD_STATE *state)
     } else if ((state->err & CLEANUP_STAT_RCPT) != 0) {
        qmqpd_reply(state, DO_LOG, QMQPD_STAT_HARD,
                    "Error: no recipients specified");
-    } else if ((state->err & CLEANUP_STAT_MISS_HDR) != 0) {
-       qmqpd_reply(state, DO_LOG, QMQPD_STAT_HARD,
-                   "Error: missing message header");
     } else {
        qmqpd_reply(state, DO_LOG, QMQPD_STAT_RETRY,
                    "Error: internal error %d", state->err);
index 83b7d46ffd165259013c93160431bc26ee872a53..ddd82369ea0d26498a00260d220f33606888b7ff 100644 (file)
@@ -725,6 +725,7 @@ int     main(int argc, char **argv)
     int     flags = SM_FLAG_DEFAULT;
     char   *site_to_flush = 0;
     char   *encoding = 0;
+    char   *qtime = 0;
 
     /*
      * Be consistent with file permissions.
@@ -925,11 +926,7 @@ int     main(int argc, char **argv)
            break;
        case 'q':
            if (ISDIGIT(optarg[0])) {
-               if (mode == SM_MODE_DAEMON) {
-                   if (msg_verbose)
-                       msg_info("-%c%s option ignored", c, optarg);
-
-               }
+               qtime = optarg;
            } else if (optarg[0] == 'R') {
                site_to_flush = optarg + 1;
                if (*site_to_flush == 0)
@@ -971,6 +968,8 @@ int     main(int argc, char **argv)
     /*
      * Start processing. Everything is delegated to external commands.
      */
+    if (qtime && mode != SM_MODE_DAEMON)
+       exit(0);
     switch (mode) {
     default:
        msg_panic("unknown operation mode: %d", mode);
index 395a849bdf611fa8668e4fd8b2f15675e7bc0a4d..536ddcd24d323478c96cefedba1148f6604b1405 100644 (file)
@@ -134,11 +134,10 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
            arrival_time = atol(start);
            break;
        case REC_TYPE_SIZE:
-           if (sscanf(start, "%ld %ld", &msg_size, &msg_offset) == 2) {
+           if (sscanf(start, "%ld %ld", &msg_size, &msg_offset) == 2)
                /* Postfix >= 1.0 (a.k.a. 20010228) style queue file. */
                if (msg_size <= 0)
                    msg_size = size;
-           }
            break;
        case REC_TYPE_FROM:
            if (*start == 0)
index 173ec7461dea7c9baa331d4fa408d931b61befaa..3e458429ce0421906d2f44ece782914136f26dda 100644 (file)
@@ -234,7 +234,7 @@ static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
      */
     stream = vstream_fdopen(sock, O_RDWR);
     if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
-       vstring_sprintf(why, "connect to %s[%s]: server dropped connection without sending the initial greeting",
+       vstring_sprintf(why, "connect to %s[%s]: server dropped connection without sending the initial SMTP greeting",
                        addr->name, inet_ntoa(sin.sin_addr));
        smtp_errno = SMTP_RETRY;
        vstream_fclose(stream);
index ee19dfc6f73b5842a3b2f7f856c26745202029e3..34441615d045cba3f3139abee6ad6c0bb9088daa 100644 (file)
@@ -904,6 +904,14 @@ static void mail_reset(SMTPD_STATE *state)
        smtpd_sasl_mail_reset(state);
 #endif
     state->discard = 0;
+    if (state->filter) {
+       myfree(state->filter);
+       state->filter = 0;
+    }
+    if (state->redirect) {
+       myfree(state->redirect);
+       state->redirect = 0;
+    }
 }
 
 /* rcpt_cmd - process RCPT TO command */
@@ -1096,24 +1104,32 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
     }
 
     /*
-     * Send the end-of-segment markers.
+     * Send the end-of-content marker, then do some post-message checks
+and send the end-of-file marker.
      */
-    if (state->err == CLEANUP_STAT_OK)
-       if (rec_fputs(state->cleanup, REC_TYPE_XTRA, "") < 0
-           || rec_fputs(state->cleanup, REC_TYPE_END, "") < 0
+    if (state->err == CLEANUP_STAT_OK) {
+       rec_fputs(state->cleanup, REC_TYPE_XTRA, "");
+       err = smtpd_check_dot(state);
+       if (rec_fputs(state->cleanup, REC_TYPE_END, "") < 0
            || vstream_fflush(state->cleanup))
            state->err = CLEANUP_STAT_WRITE;
+    }
 
     /*
      * Finish the queue file or finish the cleanup conversation.
      */
-    if (state->err == 0)
+    if (state->err == 0 && err == 0)
        state->err = mail_stream_finish(state->dest, why = vstring_alloc(10));
     else
        mail_stream_cleanup(state->dest);
     state->dest = 0;
     state->cleanup = 0;
 
+    if (err != 0) {
+       smtpd_chat_reply(state, "%s", err);
+       return (-1);
+    }
+
     /*
      * Handle any errors. One message may suffer from multiple errors, so
      * complain only about the most severe error. Forgive any previous client
@@ -1142,9 +1158,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
     } else if ((state->err & CLEANUP_STAT_WRITE) != 0) {
        state->error_mask |= MAIL_ERROR_RESOURCE;
        smtpd_chat_reply(state, "451 Error: queue file write error");
-    } else if ((state->err & CLEANUP_STAT_MISS_HDR) != 0) {
-       state->error_mask |= MAIL_ERROR_POLICY;
-       smtpd_chat_reply(state, "550 Error: missing message header");
     } else {
        state->error_mask |= MAIL_ERROR_SOFTWARE;
        smtpd_chat_reply(state, "451 Error: internal error %d", state->err);
index a369b7e8603abae1d5cbeb6925777f733d03c77f..faaeefe89260e9c28edf481ea63fe5cd339050f5 100644 (file)
@@ -95,6 +95,12 @@ typedef struct SMTPD_STATE {
     int     defer_if_permit_sender;    /* force permit into warning */
     int     discard;                   /* discard message */
     VSTRING *expand_buf;               /* scratch space for $name expansion */
+    int     session_hold;              /* per-session hold action */
+    int     session_discard;           /* per-session discard_action */
+    char   *session_filter;            /* per-session filter action */
+    char   *session_redirect;          /* per-session redirect action */
+    char   *filter;                    /* per-message filter action */
+    char   *redirect;                  /* per-message redirect action */
 } SMTPD_STATE;
 
 extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *);
index ee56be5236cafc313de3b86308075bf27808e90a..8773d06166ac5ec066633797798779981fd0d4e0 100644 (file)
 /*     Reject, defer or permit the request unconditionally. This is to be used
 /*     at the end of a restriction list in order to make the default
 /*     action explicit.
-/* .IP require_date_header
-/* .IP require_from_header
-/* .IP require_message_id_header
-/* .IP require_received_header
-/*     Reject the message when it does not contain a Date: etc. 
-/*     message header. Only the Date: header is required by mail
-/*     standards. The other headers are usually added by MTAs.
 /* .IP reject_unknown_client
 /*     Reject the request when the client hostname could not be found.
 /*     The \fIunknown_client_reject_code\fR configuration parameter
@@ -436,6 +429,19 @@ static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient);
   */
 #define STR    vstring_str
 #define CONST_STR(x)   ((const char *) vstring_str(x))
+#define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
+
+ /*
+  * Safety.
+  */
+#define SAFE_STRDUP(dst, src) { \
+       if (src) { \
+           if (dst) { \
+               myfree(dst); \
+           } \
+           dst = mystrdup(src); \
+       } \
+    }
 
  /*
   * If some decision can't be made due to a temporary error, then change
@@ -1793,9 +1799,14 @@ static int check_table_result(SMTPD_STATE *state, const char *table,
            vstring_sprintf(error_text, "<%s>: %s triggers FILTER %s",
                            reply_name, reply_class, cmd_text);
            log_whatsup(state, "filter", STR(error_text));
-#ifndef TEST
-           rec_fprintf(state->dest->stream, REC_TYPE_FILT, "%s", cmd_text);
-#endif
+           /* This action must execute with every MAIL FROM command. */
+           if (var_smtpd_delay_reject == 0
+               && (STREQ(reply_class, SMTPD_NAME_CLIENT)
+                   || STREQ(reply_class, SMTPD_NAME_HELO))) {
+               SAFE_STRDUP(state->session_filter, cmd_text);
+           } else {
+               SAFE_STRDUP(state->filter, cmd_text);
+           }
            return (SMTPD_CHECK_DUNNO);
        }
     }
@@ -1814,10 +1825,17 @@ static int check_table_result(SMTPD_STATE *state, const char *table,
        vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class,
                        *cmd_text ? cmd_text : "triggers HOLD action");
        log_whatsup(state, "hold", STR(error_text));
+       /* This action must execute with every MAIL FROM command. */
+       if (var_smtpd_delay_reject == 0
+           && (STREQ(reply_class, SMTPD_NAME_CLIENT)
+               || STREQ(reply_class, SMTPD_NAME_HELO))) {
+           state->session_hold = 1;
+       } else {
 #ifndef TEST
-       rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
-                   CLEANUP_FLAG_HOLD);
+           rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
+                       CLEANUP_FLAG_HOLD);
 #endif
+       }
        return (SMTPD_CHECK_DUNNO);
     }
 
@@ -1834,11 +1852,18 @@ static int check_table_result(SMTPD_STATE *state, const char *table,
        vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class,
                        *cmd_text ? cmd_text : "triggers DISCARD action");
        log_whatsup(state, "discard", STR(error_text));
+       /* This action must execute with every MAIL FROM command. */
+       if (var_smtpd_delay_reject == 0
+           && (STREQ(reply_class, SMTPD_NAME_CLIENT)
+               || STREQ(reply_class, SMTPD_NAME_HELO))) {
+           state->session_discard = 1;
+       } else {
 #ifndef TEST
-       rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
-                   CLEANUP_FLAG_DISCARD);
-       state->discard = 1;
+           state->discard = 1;
+           rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
+                       CLEANUP_FLAG_DISCARD);
 #endif
+       }
        return (SMTPD_CHECK_OK);
     }
 
@@ -1861,9 +1886,14 @@ static int check_table_result(SMTPD_STATE *state, const char *table,
            vstring_sprintf(error_text, "<%s>: %s triggers REDIRECT %s",
                            reply_name, reply_class, cmd_text);
            log_whatsup(state, "redirect", STR(error_text));
-#ifndef TEST
-           rec_fprintf(state->dest->stream, REC_TYPE_RDR, "%s", cmd_text);
-#endif
+           /* This action must execute with every MAIL FROM command. */
+           if (var_smtpd_delay_reject == 0
+               && (STREQ(reply_class, SMTPD_NAME_CLIENT)
+                   || STREQ(reply_class, SMTPD_NAME_HELO))) {
+               SAFE_STRDUP(state->session_redirect, cmd_text);
+           } else {
+               SAFE_STRDUP(state->redirect, cmd_text);
+           }
            return (SMTPD_CHECK_DUNNO);
        }
     }
@@ -2273,8 +2303,6 @@ static const char *smtpd_expand_addr(VSTRING *buf, const char *addr,
     /*
      * "sender_name" or "recipient_name".
      */
-#define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
-
     else if (STREQ(suffix, MAIL_ATTR_S_NAME)) {
        if (*addr) {
            if ((p = strrchr(addr, '@')) != 0) {
@@ -2757,26 +2785,6 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
            DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY,
                         "450 <%s>: %s rejected: defer_if_reject requested",
                             reply_name, reply_class);
-       } else if (strcasecmp(name, REQUIRE_DATE_HDR) == 0) {
-#ifndef TEST
-           rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
-                       CLEANUP_FLAG_NEED_DATE);
-#endif
-       } else if (strcasecmp(name, REQUIRE_FROM_HDR) == 0) {
-#ifndef TEST
-           rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
-                       CLEANUP_FLAG_NEED_FROM);
-#endif
-       } else if (strcasecmp(name, REQUIRE_MSGID_HDR) == 0) {
-#ifndef TEST
-           rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
-                       CLEANUP_FLAG_NEED_MSGID);
-#endif
-       } else if (strcasecmp(name, REQUIRE_RCVD_HDR) == 0) {
-#ifndef TEST
-           rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
-                       CLEANUP_FLAG_NEED_RCVD);
-#endif
        }
 
        /*
@@ -3115,6 +3123,24 @@ char   *smtpd_check_mail(SMTPD_STATE *state, char *sender)
     if (sender == 0)
        return (0);
 
+    /*
+     * Actions that were triggered during connect or HELO need to be repeated
+     * with each MAIL FROM command.
+     * 
+     * XXX Left-hand side should always be zero. But this may not be the case
+     * during stand-alone testing when commands can execute out of protocol.
+     */
+    if (var_smtpd_delay_reject == 0) {
+       if( state->session_hold)
+       rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
+                   CLEANUP_FLAG_HOLD);
+       if( state->session_discard)
+       rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d",
+                   CLEANUP_FLAG_DISCARD);
+       SAFE_STRDUP(state->filter, state->session_filter);
+       SAFE_STRDUP(state->redirect, state->session_redirect);
+    }
+
     /*
      * Minor kluge so that we can delegate work to the generic routine and so
      * that we can syslog the recipient with the reject messages.
@@ -3524,6 +3550,19 @@ char   *smtpd_check_data(SMTPD_STATE *state)
     return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
 }
 
+/* smtpd_check_dot - do stuff after message transfer */
+
+char   *smtpd_check_dot(SMTPD_STATE *state)
+{
+    if (state->redirect)
+       rec_fprintf(state->dest->stream, REC_TYPE_RDR, "%s",
+                   state->redirect);
+    if (state->filter)
+       rec_fprintf(state->dest->stream, REC_TYPE_FILT, "%s",
+                   state->filter);
+    return (0);
+}
+
 #ifdef TEST
 
  /*
index 302e2690354b3fad5d65b6f1ef672a8b692590f9..26573d334ea414cf8f9de8ea9a62f9fe4732cc82 100644 (file)
@@ -20,6 +20,7 @@ extern char *smtpd_check_size(SMTPD_STATE *, off_t);
 extern char *smtpd_check_rcpt(SMTPD_STATE *, char *);
 extern char *smtpd_check_etrn(SMTPD_STATE *, char *);
 extern char *smtpd_check_data(SMTPD_STATE *);
+extern char *smtpd_check_dot(SMTPD_STATE *);
 
 /* LICENSE
 /* .ad
index 6475ae49b05f220bcbd470511cd37ed5f1f8de76..599d53854e2681c2a27bfd613f4100f60a09d0b2 100644 (file)
@@ -99,6 +99,10 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
     state->defer_if_permit.reason = 0;
     state->discard = 0;
     state->expand_buf = 0;
+    state->session_hold = 0;
+    state->session_discard = 0;
+    state->session_filter = 0;
+    state->session_redirect = 0;
 
 #ifdef USE_SASL_AUTH
     if (SMTPD_STAND_ALONE(state))
@@ -137,6 +141,10 @@ void    smtpd_state_reset(SMTPD_STATE *state)
        vstring_free(state->defer_if_reject.reason);
     if (state->expand_buf)
        vstring_free(state->expand_buf);
+    if (state->session_filter)
+       myfree(state->session_filter);
+    if (state->session_redirect)
+       myfree(state->session_redirect);
 
 #ifdef USE_SASL_AUTH
     if (var_smtpd_sasl_enable)