]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.3-20060112
authorWietse Venema <wietse@porcupine.org>
Thu, 12 Jan 2006 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:32:03 +0000 (06:32 +0000)
104 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/OVERVIEW
postfix/RELEASE_NOTES
postfix/html/bounce.5.html
postfix/html/bounce.8.html
postfix/html/discard.8.html
postfix/html/error.8.html
postfix/html/pipe.8.html
postfix/html/postconf.5.html
postfix/html/showq.8.html
postfix/html/smtp.8.html
postfix/html/smtpd.8.html
postfix/html/verify.8.html
postfix/man/man5/bounce.5
postfix/man/man5/postconf.5
postfix/man/man8/pipe.8
postfix/man/man8/smtp.8
postfix/man/man8/smtpd.8
postfix/mantools/postlink
postfix/proto/bounce
postfix/proto/postconf.proto
postfix/src/bounce/bounce.c
postfix/src/bounce/bounce_append_service.c
postfix/src/bounce/bounce_notify_service.c
postfix/src/bounce/bounce_notify_util.c
postfix/src/bounce/bounce_notify_verp.c
postfix/src/bounce/bounce_one_service.c
postfix/src/bounce/bounce_service.h
postfix/src/bounce/bounce_templates.c
postfix/src/bounce/bounce_trace_service.c
postfix/src/bounce/bounce_warn_service.c
postfix/src/dns/dns.h
postfix/src/dns/dns_rr.c
postfix/src/error/error.c
postfix/src/global/Makefile.in
postfix/src/global/bounce.h
postfix/src/global/bounce_log.c
postfix/src/global/bounce_log.h
postfix/src/global/deliver_pass.c
postfix/src/global/deliver_request.c
postfix/src/global/dsn.c
postfix/src/global/dsn.h
postfix/src/global/dsn_buf.c
postfix/src/global/dsn_buf.h
postfix/src/global/dsn_print.c
postfix/src/global/dsn_util.c
postfix/src/global/dsn_util.h
postfix/src/global/mail_copy.c
postfix/src/global/mail_params.h
postfix/src/global/mail_proto.h
postfix/src/global/mail_version.h
postfix/src/global/msg_stats_print.c
postfix/src/global/pipe_command.c
postfix/src/global/post_mail.c
postfix/src/global/post_mail.h
postfix/src/global/rcpt_buf.c
postfix/src/global/rcpt_buf.h
postfix/src/global/rcpt_print.c
postfix/src/global/recipient_list.c
postfix/src/global/recipient_list.h
postfix/src/global/smtp_stream.c
postfix/src/global/smtp_stream.h
postfix/src/local/local.h
postfix/src/local/unknown.c
postfix/src/master/Makefile.in
postfix/src/oqmgr/Makefile.in
postfix/src/oqmgr/qmgr_deliver.c
postfix/src/oqmgr/qmgr_message.c
postfix/src/oqmgr/qmgr_transport.c
postfix/src/pipe/pipe.c
postfix/src/postlock/Makefile.in
postfix/src/qmgr/Makefile.in
postfix/src/qmgr/qmgr_deliver.c
postfix/src/qmgr/qmgr_message.c
postfix/src/qmgr/qmgr_transport.c
postfix/src/qmqpd/Makefile.in
postfix/src/sendmail/Makefile.in
postfix/src/showq/showq.c
postfix/src/smtp/Makefile.in
postfix/src/smtp/lmtp_params.c
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_addr.c
postfix/src/smtp/smtp_chat.c
postfix/src/smtp/smtp_connect.c
postfix/src/smtp/smtp_dsn.c [deleted file]
postfix/src/smtp/smtp_params.c
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_rcpt.c
postfix/src/smtp/smtp_sasl_glue.c
postfix/src/smtp/smtp_sasl_proto.c
postfix/src/smtp/smtp_state.c
postfix/src/smtp/smtp_trouble.c
postfix/src/smtpd/Makefile.in
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_chat.c
postfix/src/util/mymalloc.c
postfix/src/util/netstring.c
postfix/src/util/vstring.c
postfix/src/verify/Makefile.in
postfix/src/verify/verify.c
postfix/src/virtual/unknown.c
postfix/src/virtual/virtual.h

index 77268881747d7fe985f8881f0fc8f0aa60791d06..1d5e8ce8e824fad189729e37a4272a4edae115f2 100644 (file)
@@ -19,6 +19,7 @@
 -TBOUNCE_INFO
 -TBOUNCE_LOG
 -TBOUNCE_LOG_DSN_BUF
+-TBOUNCE_LOG_FORGE
 -TBOUNCE_LOG_RCPT_BUF
 -TBOUNCE_STAT
 -TBOUNCE_TEMPLATE
@@ -91,7 +92,7 @@
 -TDSN
 -TDSN_BUF
 -TDSN_SPLIT
--TDSN_VAR
+-TDSN_STAT
 -TEXPAND_ATTR
 -TFILE
 -TFORWARD_INFO
 -TRCPT_BUF
 -TRECIPIENT
 -TRECIPIENT_LIST
--TRECIPIENT_VAR
 -TREC_TYPE_NAME
 -TRESOLVE_REPLY
 -TRESPONSE
index 87355d1e6d5c3f3da2a5b3e06918693295827e49..8a4f3200f3f1e0ca7c91bd7fe84019946c672895 100644 (file)
@@ -11692,6 +11692,8 @@ Apologies for any names omitted.
 
 20051229
 
+       The following workaround was removed 20060103.
+
        Workaround: when mail is still queued after 3000 seconds,
        the SMTP client no longer pipelines the DOT+QUIT commands.
        The 20050929 paranoia about malformed server replies
@@ -11727,8 +11729,108 @@ Apologies for any names omitted.
        The administrator still has the option to turn off pipelining
        by hand if loss of mail is a concern.
 
+20060103
+
+       Bugfix: the 20051217 fix (when a SASL client password is
+       found, defer delivery when no server-announced mechanism
+       survives the smtp_sasl_mechanism_filter) did the mechanism
+       test too early, so that it could trip up with deliveries
+       to servers that we don't have a SASL password for.  Files:
+       smtp/smtp_sasl_proto.c, smtp/smtp_proto.c.
+
+20060104
+
+       Safety: new "smtp_cname_overrides_servername" parameter.
+       The default value ("no") is NOT backwards compatible. This
+       avoids surprises with the hostname that is used for logging,
+       SASL password lookup, TLS policy decisions, or TLS certificate
+       verification.  The change makes the 20051221 behavior more
+       configurable.  Files: smtp/smtp_addr.c, smtp/smtp_connect.c,
+       proto/postconf.proto.
+
+20060105
+
+       Cleanup: removed the unused DSN "code" attribute; removed
+       surrogate SMTP replies for errors that were not reported
+       by a remote SMTP server, making several DSN-related functions
+       and macros redundant; cleaned up some bizarre code for DSN
+       attribute memory management in the SMTP client.
+
+20060106
+
+       Cleanup: eliminated the global smtp_errno variable, which
+       had become redundant after introducing DSN support. Files:
+       smtp/smtp_addr.c, smtp/smtp_connect.c.
+
+20060107
+
+       Cleanup: removed more bizarre code for DSN attribute memory
+       management in the queue manager, bounce server, and in
+       delivery agents.
+
+20060109
+
+       Bugfix: smtp_sasl_tls_opts was unimplemented. File:
+       smtp/smtp_sasl_proto.c.
+
+       Cleanup: more bounce logfile code cleanup.  Files:
+       global/bounce_log.c, bounce/bounce_notify_util.c,
+       bounce/bounce.c, bounce/bounce_notify_verp.c,
+       bounce/bounce_one_service.c, showq/showq.c
+
+20060110
+
+       Cleanup: more bounce logfile code cleanup.  Files:
+       global/bounce_log.c, bounce/bounce_notify_util.c.
+
+       Bugfix: the VERP bouncer never handled the case of a missing
+       bounce logfile. Found while doing more logfile code cleanup.
+       File: bounce/bounce_notify_verp.c.
+
+       Feature: smtp_sasl_tls_verified_security_options for
+       connections where the server certificate passed verification.
+       The default value is $smtp_sasl_tls_security_options, which
+       in turn defaults to $smtp_sasl_security_options.
+
+20060111
+
+       Optimization: mystrdup() and mystrndup() now return a pointer
+       to a fixed read-only memory location instead of allocating
+       memory for zero-length null-terminated strings.  This saves
+       lots of memory for unused recipient attributes. If this
+       change causes problems (for example, you have an ancient
+       sscanf() implementation that writes to its input) then
+       compile Postfix with -DNO_SHARED_EMPTY_STRINGS.
+
+       Cleanup: eliminated null pointer members in DSN structures.
+       Instead we now use the optimized mystrdup() for empty
+       strings. For safety sake we keep the tests for null pointers
+       in input, but we always produce empty strings on output.
+       Files: global/dsn.c, global/dsn.h, global/dsn_buf.h,
+       global/dsn_print.c.
+
+       Cleanup: eliminated ad-hoc code for passing recipients in
+       the queue manager delivery request protocol. Postfix now
+       uses proper object activation/passivation instead. Files:
+       *qmgr/qmgr_deliver.c, global/deliver_request.c,
+       global/deliver_pass.c.
+
+20060112
+
+       Feature: to simplify debugging the bounce server logs the
+       old and new queue ID when notifying the sender or postmaster.
+       Files: global/post_mail.c, bounce/bounce_notify_service.c,
+       bounce/bounce_one_service.c, bounce/bounce_notify_verp.c,
+       bounce/bounce_warn_service.c, bounce/bounce_trace_service.c.
+
 Open problems:
 
+       Privacy: remove local command/pathname details from remote
+       delivery status reports, and log them via local msg_warn().
+
+       Remove defer(8) and trace(8) references and man pages. These
+       are services not program names.
+
        "postsuper -r" no longer resets the message arrival time,
        because pickup(8) no longer overrides queue file time stamp
        information. This can be a problem when mail "on hold" is
index 1d9ae180f5118dbbdfefb2145f7b41a607c9f67e..c9d40269f3cb44fb27dc6083d4b08e1c3995edd5 100644 (file)
@@ -210,11 +210,12 @@ queues.
 
     Network -> smtpd(8) <-> anvil(8)
 
-  * The bounce(8), defer(8) and trace(8) servers each maintain their own queue
-    directory trees with per-message logfiles. This information is used to send
-    delivery or non-delivery notifications to the sender.
+  * The bounce(8) server implements the bounce, defer and trace services, which
+    maintain separate directory trees with per-message logfiles. This
+    information is used to send delivery or non-delivery notifications to the
+    sender.
 
-    The trace(8) service implements support for the Postfix "sendmail -bv" and
+    The trace service implements support for the Postfix "sendmail -bv" and
     "sendmail -v" commands which produce reports about how Postfix delivers
     mail, and is available with Postfix version 2.1 and later. See DEBUG_README
     for examples.
@@ -227,8 +228,8 @@ queues.
           |             v            v
 
       (Non-)      bounce(8)    Queue id,
-     delivery  <- defer(8)  <- recipient,
-      notice      trace(8)       status
+     delivery  <-   defer   <- recipient,
+      notice        trace        status
 
                       ^ |
                       | v
index fe5033314fb118df8918ac52c81a0555fd0ea477..96233b96b7b6b3a88fec7ebbb5a407b12f7452ef 100644 (file)
@@ -17,6 +17,23 @@ Incompatibility with Postfix 2.1 and earlier
 If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
 before proceeding.
 
+Incompatibility with snapshot 20060112
+======================================
+
+The queue manager delivery request protocol has changed. You must
+reload Postfix when upgrading. If you omit this step, delivery
+agents complain with "warning: unexpected attribute original_recipient"
+and mail will not be delivered.
+
+The Postfix SMTP/LMTP client by default no longer allows DNS CNAME
+records to override the server hostname that is used for logging,
+SASL password lookup, TLS policy selection and TLS server certificate
+verification. Specify "smtp_cname_overrides_servername = no" to get
+the old behavior.
+
+Postfix DSN reports no longer make up their own surrogate SMTP
+replies for errors that were not reported by a remote SMTP server.
+
 Incompatibility with snapshot 20060103
 ======================================
 
index b4900f166a99bdbda9659eeb8c6e5fd2877cc46d..104247f9ee54f56de4d931f4a6aa36fda29120f1 100644 (file)
@@ -48,10 +48,10 @@ BOUNCE(5)                                                            BOUNCE(5)
        appear in the delayed mail notification text.
 
        Once the result is satisfactory, copy the template to  the
-       Postfix  configuration  directory  and  specify in main.cf
+       Postfix  configuration  directory  and  specify in <a href="postconf.5.html">main.cf</a>
        something like:
 
-       /etc/postfix/main.cf:
+       /etc/postfix/<a href="postconf.5.html">main.cf</a>:
                <a href="postconf.5.html#bounce_template_file">bounce_template_file</a> = /etc/postfix/bounce.cf
 
 <b>TEMPLATE FILE FORMAT</b>
@@ -68,33 +68,41 @@ BOUNCE(5)                                                            BOUNCE(5)
        with the shell or with  Perl  (<i>template</i><b>_</b><i>name</i>  <b>=</b>  &lt;&lt;<b>'EOF'</b>).
        Here is an example:
 
-         # The failure template is used for undeliverable mail.
+           # The failure template is used for undeliverable mail.
 
-         failure_template = &lt;&lt;EOF
-         Charset: us-ascii
-         From: MAILER-DAEMON (Mail Delivery System)
-         Subject: Undelivered Mail Returned to Sender
-         Postmaster-Subject: Postmaster Copy: Undelivered Mail
+           failure_template = &lt;&lt;EOF
+           Charset: us-ascii
+           From: MAILER-DAEMON (Mail Delivery System)
+           Subject: Undelivered Mail Returned to Sender
+           Postmaster-Subject: Postmaster Copy: Undelivered Mail
 
-         This is the $<a href="postconf.5.html#mail_name">mail_name</a> program at host $<a href="postconf.5.html#myhostname">myhostname</a>.
+           This is the $<a href="postconf.5.html#mail_name">mail_name</a> program at host $<a href="postconf.5.html#myhostname">myhostname</a>.
 
-         I'm sorry to have to inform you that your message could not
-         be delivered to one or more recipients. It's attached below.
+           I'm sorry to have to inform you that your message could not
+           be delivered to one or more recipients. It's attached below.
 
-         For further assistance, please send mail to &lt;postmaster&gt;
+           For further assistance, please send mail to &lt;postmaster&gt;
 
-         If you do so, please include this problem report. You can
-         delete your own text from the attached returned message.
+           If you do so, please include this problem report. You can
+           delete your own text from the attached returned message.
 
-                                        The $<a href="postconf.5.html#mail_name">mail_name</a> program
-         EOF
+                                          The $<a href="postconf.5.html#mail_name">mail_name</a> program
+           EOF
 
-       No  special meaning is given to the backslash character or
-       to leading whitespace; these are always taken literally.
+       The usage and specification of bounce templates is subject
+       to the following restrictions:
 
-       Outside the &lt;&lt;  context,  lines  beginning  with  "#"  are
-       ignored,  as  are  empty  lines,  and  lines consisting of
-       whitespace only.
+       <b>o</b>      No special meaning is given to the backslash  char-
+              acter  or  to  leading whitespace; these are always
+              taken literally.
+
+       <b>o</b>      Inside the &lt;&lt; context, the "$"  character  is  spe-
+              cial. To produce a "$" character as output, specify
+              "$$".
+
+       <b>o</b>      Outside the &lt;&lt; context, lines  beginning  with  "#"
+              are ignored, as are empty lines, and lines consist-
+              ing of whitespace only.
 
        Examples of  all  templates  can  be  found  in  the  file
        <b>bounce.cf.default</b>  in the Postfix configuration directory.
@@ -137,7 +145,7 @@ BOUNCE(5)                                                            BOUNCE(5)
        <b>o</b>      Template  message  headers  must  not span multiple
               lines.
 
-       <b>o</b>      Template message headers must not  contain  main.cf
+       <b>o</b>      Template message headers must not  contain  <a href="postconf.5.html">main.cf</a>
               $parameters.
 
        <b>o</b>      Template message headers must contain ASCII charac-
@@ -146,8 +154,8 @@ BOUNCE(5)                                                            BOUNCE(5)
 <b>TEMPLATE MESSAGE TEXT FORMAT</b>
        The second portion of a bounce template consists  of  mes-
        sage  text.  As  the above example shows, template message
-       text may contain main.cf $parameters. Besides the  parame-
-       ters that are defined in main.cf, the following parameters
+       text may contain <a href="postconf.5.html">main.cf</a> $parameters. Besides the  parame-
+       ters that are defined in <a href="postconf.5.html">main.cf</a>, the following parameters
        are treated specially depending  on  the  suffix  that  is
        appended to their name.
 
index b636478714c2c69cbe91a17eea32dfd24e4865a8..da749a9916a2677abe4226b59e9e3bea4479bec3 100644 (file)
@@ -17,7 +17,7 @@ BOUNCE(8)                                                            BOUNCE(8)
        delivery status information. Each log file is named  after
        the  queue  file  that it corresponds to, and is kept in a
        queue subdirectory named after the  service  name  in  the
-       <b>master.cf</b> file (either <b>bounce</b>, <b>defer</b> or <b>trace</b>).  This pro-
+       <a href="master.5.html"><b>master.cf</b></a> file (either <b>bounce</b>, <b>defer</b> or <b>trace</b>).  This pro-
        gram expects to be run from the <a href="master.8.html"><b>master</b>(8)</a> process manager.
 
        The  <a href="bounce.8.html"><b>bounce</b>(8)</a>  daemon  processes  two  types  of  service
@@ -52,7 +52,7 @@ BOUNCE(8)                                                            BOUNCE(8)
        Problems and transactions are logged to <b>syslogd</b>(8).
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes  to  <b>main.cf</b>  are  picked  up  automatically,   as
+       Changes  to  <a href="postconf.5.html"><b>main.cf</b></a>  are  picked  up  automatically,   as
        <a href="bounce.8.html"><b>bounce</b>(8)</a> processes run for only a limited amount of time.
        Use the command "<b>postfix reload</b>" to speed up a change.
 
@@ -82,8 +82,8 @@ BOUNCE(8)                                                            BOUNCE(8)
               sage templates.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              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
index 01fd6d4596281ecf9ab0dd0dc0bb46562468e4e1..2fb77c2e1ebd6fade8d56a14762f4865cc17a93e 100644 (file)
@@ -47,7 +47,7 @@ DISCARD(8)                                                          DISCARD(8)
        ble.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes  to  <b>main.cf</b>  are  picked up automatically as <a href="discard.8.html"><b>dis-</b></a>
+       Changes  to  <a href="postconf.5.html"><b>main.cf</b></a>  are  picked up automatically as <a href="discard.8.html"><b>dis-</b></a>
        <a href="discard.8.html"><b>card</b>(8)</a> processes run for only a limited amount  of  time.
        Use the command "<b>postfix reload</b>" to speed up a change.
 
@@ -55,8 +55,8 @@ DISCARD(8)                                                          DISCARD(8)
        <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              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
index 338b6c9fd037d8cab6e95808bb1be974c9ab8b13..5cf408609f34d122f927925b90203a209337b40c 100644 (file)
@@ -47,7 +47,7 @@ ERROR(8)                                                              ERROR(8)
        ble.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes to <b>main.cf</b> are picked up automatically as <a href="error.8.html"><b>error</b>(8)</a>
+       Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically as <a href="error.8.html"><b>error</b>(8)</a>
        processes run for only a limited amount of time.  Use  the
        command "<b>postfix reload</b>" to speed up a change.
 
@@ -65,8 +65,8 @@ ERROR(8)                                                              ERROR(8)
               mail that Postfix did not receive.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
-              master.cf configuration files.
+              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
index faa3c00f4890205415155d6959876f739692743d..8eda4d5f3c321ed680fc97e5343e46f12bbd06c8 100644 (file)
@@ -32,19 +32,19 @@ PIPE(8)                                                                PIPE(8)
 <b>SINGLE-RECIPIENT DELIVERY</b>
        Some external commands cannot handle more than one recipi-
        ent per delivery request. Examples of such transports  are
-       pagers, fax machines, and so on.
+       pagers or fax machines.
 
        To  prevent  Postfix  from sending multiple recipients per
        delivery request, specify
 
            <i>transport</i><b>_destination_recipient_limit = 1</b>
 
-       in the Postfix <b>main.cf</b> file, where <i>transport</i> is  the  name
-       in the first column of the Postfix <b>master.cf</b> entry for the
+       in the Postfix <a href="postconf.5.html"><b>main.cf</b></a> file, where <i>transport</i> is  the  name
+       in the first column of the Postfix <a href="master.5.html"><b>master.cf</b></a> entry for the
        pipe-based delivery transport.
 
 <b>COMMAND ATTRIBUTE SYNTAX</b>
-       The external command attributes are given in the <b>master.cf</b>
+       The external command attributes are given in the <a href="master.5.html"><b>master.cf</b></a>
        file at the end of a service definition.  The syntax is as
        follows:
 
@@ -330,7 +330,7 @@ PIPE(8)                                                                PIPE(8)
        fore security sensitive.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes to <b>main.cf</b> are picked up automatically as  <a href="pipe.8.html"><b>pipe</b>(8)</a>
+       Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically as  <a href="pipe.8.html"><b>pipe</b>(8)</a>
        processes  run  for only a limited amount of time. Use the
        command "<b>postfix reload</b>" to speed up a change.
 
@@ -360,8 +360,8 @@ PIPE(8)                                                                PIPE(8)
 
 <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 main.cf and
-              master.cf configuration files.
+              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
index 44758e17ef9192d9feef354efce5a436b54e7f2c..6a8686f24da1ebc5c8a58f52bbcd77b5f7fe7e53 100644 (file)
@@ -3091,6 +3091,17 @@ programs.
 </p>
 
 
+</DD>
+
+<DT><b><a name="lmtp_cname_overrides_servername">lmtp_cname_overrides_servername</a>
+(default: yes)</b></DT><DD>
+
+<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_cname_overrides_servername">smtp_cname_overrides_servername</a>
+configuration parameter.  See there for details. </p>
+
+<p> This feature is available in Postfix 2.3 and later. </p>
+
+
 </DD>
 
 <DT><b><a name="lmtp_connect_timeout">lmtp_connect_timeout</a>
@@ -3582,7 +3593,7 @@ Example:
 </DD>
 
 <DT><b><a name="lmtp_sasl_tls_security_options">lmtp_sasl_tls_security_options</a>
-(default: $var_lmtp_sasl_opts)</b></DT><DD>
+(default: $<a href="postconf.5.html#lmtp_sasl_security_options">lmtp_sasl_security_options</a>)</b></DT><DD>
 
 <p> The LMTP-specific version of the <a href="postconf.5.html#smtp_sasl_tls_security_options">smtp_sasl_tls_security_options</a>
 configuration parameter.  See there for details. </p>
@@ -3590,6 +3601,18 @@ configuration parameter.  See there for details. </p>
 <p> This feature is available in Postfix 2.3 and later. </p>
 
 
+</DD>
+
+<DT><b><a name="lmtp_sasl_tls_verified_security_options">lmtp_sasl_tls_verified_security_options</a>
+(default: $<a href="postconf.5.html#lmtp_sasl_tls_security_options">lmtp_sasl_tls_security_options</a>)</b></DT><DD>
+
+<p> The LMTP-specific version of the
+<a href="postconf.5.html#smtp_sasl_tls_verified_security_options">smtp_sasl_tls_verified_security_options</a> configuration parameter.
+See there for details. </p>
+
+<p> This feature is available in Postfix 2.3 and later. </p>
+
+
 </DD>
 
 <DT><b><a name="lmtp_sasl_type">lmtp_sasl_type</a>
@@ -6399,6 +6422,22 @@ IP hosting, but can be a problem on multi-homed firewalls. See the
 but this form is not recommended here. </p>
 
 
+</DD>
+
+<DT><b><a name="smtp_cname_overrides_servername">smtp_cname_overrides_servername</a>
+(default: version dependent)</b></DT><DD>
+
+<p> Allow DNS CNAME records to override the servername that the
+Postfix SMTP client uses for logging, SASL password lookup, TLS
+policy decisions, or TLS certificate verification. The value "no"
+hardens Postfix <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> hostname-based policies against
+false hostname information in DNS CNAME records, and makes SASL
+password file lookups more predictable. This is the default setting
+as of Postfix 2.3. </p>
+
+<p> This feature is available in Postfix 2.2.9 and later. </p>
+
+
 </DD>
 
 <DT><b><a name="smtp_connect_timeout">smtp_connect_timeout</a>
@@ -7192,6 +7231,18 @@ Example:
 client uses for TLS encrypted SMTP sessions. </p>
 
 
+</DD>
+
+<DT><b><a name="smtp_sasl_tls_verified_security_options">smtp_sasl_tls_verified_security_options</a>
+(default: $<a href="postconf.5.html#smtp_sasl_tls_security_options">smtp_sasl_tls_security_options</a>)</b></DT><DD>
+
+<p> The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions with a verified server
+certificate. </p>
+
+<p> This feature is available in Postfix 2.3 and later. </p>
+
+
 </DD>
 
 <DT><b><a name="smtp_sasl_type">smtp_sasl_type</a>
@@ -7527,12 +7578,47 @@ server certificate was issued by a trusted CA. </dd>
 
 </dl>
 
-<p> Special hint for enforcement mode:  since no secure DNS lookup
-mechanism is available, the recommended setup is:  specify local
-<a href="transport.5.html">transport(5)</a> table entries for sensitive domains with explicit
-<a href="smtp.8.html">smtp</a>:[mailhost] destinations (since you can assure security of this
-table unlike DNS), then specify MUST for these mail hosts in the
-<a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> table. </p>
+<p> Special hints for enforcement mode:  since no secure DNS lookup
+mechanism is available, the recommended setup is:  </p>
+
+<dl>
+
+<dt> Postfix 2.2.9 </dt>
+
+<dd> <ul>
+
+<li> Specify "<a href="postconf.5.html#smtp_cname_overrides_servername">smtp_cname_overrides_servername</a> = no". This avoids
+false hostname information in DNS CNAME records that could bypass
+a hostname-based TLS usage policy.
+
+<li> Specify local <a href="transport.5.html">transport(5)</a> table entries for sensitive domains
+with explicit <a href="smtp.8.html">smtp</a>:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy.
+
+<li> Specify MUST for these mail hosts in the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>
+table.
+
+</ul> </dd>
+
+<dt> Postfix &lt; 2.2.9 </dt>
+
+<dd> <ul>
+
+<li> Specify local <a href="transport.5.html">transport(5)</a> table entries for sensitive domains
+with explicit <a href="smtp.8.html">smtp</a>:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy, but cannot avoid false hostname
+information in DNS CNAME records.
+
+<li> Specify MUST for these mail hosts in the <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a>
+table.
+
+</ul> </dd>
+
+</dl>
+
+<p> </p>
 
 
 </DD>
index 2638a0f60cd5507449dfc4d93031e0c1ebb5903a..5cb1f446f6354b68795640d13c996b3200fbc41d 100644 (file)
@@ -40,7 +40,7 @@ SHOWQ(8)                                                              SHOWQ(8)
        the <b>maildrop</b> directory.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes to <b>main.cf</b> are picked up automatically as <a href="showq.8.html"><b>showq</b>(8)</a>
+       Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically as <a href="showq.8.html"><b>showq</b>(8)</a>
        processes  run  for only a limited amount of time. Use the
        command "<b>postfix reload</b>" to speed up a change.
 
@@ -48,8 +48,8 @@ SHOWQ(8)                                                              SHOWQ(8)
        <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The  default  location  of  the Postfix main.cf and
-              master.cf configuration files.
+              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
index 9c0b5d460ac1897b21778d9cce3a6e4124b7a17a..54aef3151773e33cb9b7d215d8388c124d9f22f3 100644 (file)
@@ -105,7 +105,6 @@ SMTP(8)                                                                SMTP(8)
        <a href="http://www.faqs.org/rfcs/rfc1652.html">RFC 1652</a> (8bit-MIME transport)
        <a href="http://www.faqs.org/rfcs/rfc1870.html">RFC 1870</a> (Message Size Declaration)
        <a href="http://www.faqs.org/rfcs/rfc2033.html">RFC 2033</a> (LMTP protocol)
-       <a href="http://www.faqs.org/rfcs/rfc2034.html">RFC 2034</a> (Enhanced Status Codes)
        <a href="http://www.faqs.org/rfcs/rfc2045.html">RFC 2045</a> (MIME: Format of Internet Message Bodies)
        <a href="http://www.faqs.org/rfcs/rfc2046.html">RFC 2046</a> (MIME: Media Types)
        <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a> (AUTH command)
@@ -220,18 +219,26 @@ SMTP(8)                                                                SMTP(8)
               locally valid address into a globally valid address
               when sending mail across the Internet.
 
+       Available in Postfix version 2.2.9 and later:
+
+       <b><a href="postconf.5.html#smtp_cname_overrides_servername">smtp_cname_overrides_servername</a> (version dependent)</b>
+              Allow DNS CNAME records to override the  servername
+              that the Postfix SMTP client uses for logging, SASL
+              password lookup, TLS policy decisions, or TLS  cer-
+              tificate verification.
+
        Available in Postfix version 2.3 and later:
 
        <b><a href="postconf.5.html#lmtp_discard_lhlo_keyword_address_maps">lmtp_discard_lhlo_keyword_address_maps</a> (empty)</b>
-              Lookup tables, indexed by the  remote  LMTP  server
-              address,  with  case insensitive lists of LHLO key-
-              words (pipelining, starttls, auth, etc.)  that  the
+              Lookup  tables,  indexed  by the remote LMTP server
+              address, with case insensitive lists of  LHLO  key-
+              words  (pipelining,  starttls, auth, etc.) that the
               LMTP client will ignore in the LHLO response from a
               remote LMTP server.
 
        <b><a href="postconf.5.html#lmtp_discard_lhlo_keywords">lmtp_discard_lhlo_keywords</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
-              A case insensitive list of LHLO keywords  (pipelin-
-              ing,  starttls,  auth,  etc.)  that the LMTP client
+              A  case insensitive list of LHLO keywords (pipelin-
+              ing, starttls, auth, etc.)  that  the  LMTP  client
               will ignore in the LHLO response from a remote LMTP
               server.
 
@@ -239,7 +246,7 @@ SMTP(8)                                                                SMTP(8)
        Available in Postfix version 2.0 and later:
 
        <b><a href="postconf.5.html#disable_mime_output_conversion">disable_mime_output_conversion</a> (no)</b>
-              Disable  the  conversion of 8BITMIME format to 7BIT
+              Disable the conversion of 8BITMIME format  to  7BIT
               format.
 
        <b><a href="postconf.5.html#mime_boundary_length_limit">mime_boundary_length_limit</a> (2048)</b>
@@ -254,132 +261,132 @@ SMTP(8)                                                                SMTP(8)
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#smtp_send_xforward_command">smtp_send_xforward_command</a> (no)</b>
-              Send the non-standard  XFORWARD  command  when  the
-              Postfix  SMTP  server EHLO response announces XFOR-
+              Send  the  non-standard  XFORWARD  command when the
+              Postfix SMTP server EHLO response  announces  XFOR-
               WARD support.
 
 <b>SASL AUTHENTICATION CONTROLS</b>
        <b><a href="postconf.5.html#smtp_sasl_auth_enable">smtp_sasl_auth_enable</a> (no)</b>
-              Enable SASL  authentication  in  the  Postfix  SMTP
+              Enable  SASL  authentication  in  the  Postfix SMTP
               client.
 
        <b><a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> (empty)</b>
-              Optional  SMTP  client lookup tables with one user-
-              name:password entry per remote hostname or  domain,
+              Optional SMTP client lookup tables with  one  user-
+              name:password  entry per remote hostname or domain,
               or sender address when sender-dependent authentica-
               tion is enabled.
 
        <b><a href="postconf.5.html#smtp_sasl_security_options">smtp_sasl_security_options</a> (noplaintext, noanonymous)</b>
-              SASL security options; as of Postfix 2.3  the  list
-              of  available  features  depends on the SASL client
-              implementation    that     is     selected     with
+              SASL  security  options; as of Postfix 2.3 the list
+              of available features depends on  the  SASL  client
+              implementation     that     is     selected    with
               <b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a></b>.
 
        Available in Postfix version 2.2 and later:
 
        <b><a href="postconf.5.html#smtp_sasl_mechanism_filter">smtp_sasl_mechanism_filter</a> (empty)</b>
-              If  non-empty, a Postfix SMTP client filter for the
-              remote SMTP server's list of  offered  SASL  mecha-
+              If non-empty, a Postfix SMTP client filter for  the
+              remote  SMTP  server's  list of offered SASL mecha-
               nisms.
 
        Available in Postfix version 2.3 and later:
 
        <b><a href="postconf.5.html#smtp_sender_dependent_authentication">smtp_sender_dependent_authentication</a> (no)</b>
-              Enable  sender-dependent authentication in the SMTP
-              client; this is available only with SASL  authenti-
-              cation,  and  disables  SMTP  connection caching to
-              ensure that mail from different  senders  will  use
+              Enable sender-dependent authentication in the  SMTP
+              client;  this is available only with SASL authenti-
+              cation, and disables  SMTP  connection  caching  to
+              ensure  that  mail  from different senders will use
               the appropriate credentials.
 
        <b><a href="postconf.5.html#smtp_sasl_path">smtp_sasl_path</a> (empty)</b>
-              Implementation-specific  information that is passed
-              through to the SASL plug-in implementation that  is
+              Implementation-specific information that is  passed
+              through  to the SASL plug-in implementation that is
               selected with <b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a></b>.
 
        <b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a> (cyrus)</b>
-              The  SASL plug-in type that the Postfix SMTP client
+              The SASL plug-in type that the Postfix SMTP  client
               should use for authentication.
 
 <b>STARTTLS SUPPORT CONTROLS</b>
-       Detailed information about STARTTLS configuration  may  be
+       Detailed  information  about STARTTLS configuration may be
        found in the <a href="TLS_README.html">TLS_README</a> document.
 
        <b><a href="postconf.5.html#smtp_use_tls">smtp_use_tls</a> (no)</b>
-              Opportunistic  mode:  use  TLS  when  a remote SMTP
-              server announces STARTTLS support,  otherwise  send
+              Opportunistic mode: use  TLS  when  a  remote  SMTP
+              server  announces  STARTTLS support, otherwise send
               the mail in the clear.
 
        <b><a href="postconf.5.html#smtp_enforce_tls">smtp_enforce_tls</a> (no)</b>
-              Enforcement  mode: require that remote SMTP servers
-              use TLS encryption, and  never  send  mail  in  the
+              Enforcement mode: require that remote SMTP  servers
+              use  TLS  encryption,  and  never  send mail in the
               clear.
 
        <b><a href="postconf.5.html#smtp_sasl_tls_security_options">smtp_sasl_tls_security_options</a>           ($<a href="postconf.5.html#smtp_sasl_security_options">smtp_sasl_secu</a>-</b>
        <b><a href="postconf.5.html#smtp_sasl_security_options">rity_options</a>)</b>
-              The  SASL  authentication security options that the
-              Postfix SMTP client uses  for  TLS  encrypted  SMTP
+              The SASL authentication security options  that  the
+              Postfix  SMTP  client  uses  for TLS encrypted SMTP
               sessions.
 
        <b><a href="postconf.5.html#smtp_starttls_timeout">smtp_starttls_timeout</a> (300s)</b>
-              Time  limit  for Postfix SMTP client write and read
-              operations during TLS startup  and  shutdown  hand-
+              Time limit for Postfix SMTP client write  and  read
+              operations  during  TLS  startup and shutdown hand-
               shake procedures.
 
        <b><a href="postconf.5.html#smtp_tls_CAfile">smtp_tls_CAfile</a> (empty)</b>
-              The  file with the certificate of the certification
-              authority (CA) that issued the Postfix SMTP  client
+              The file with the certificate of the  certification
+              authority  (CA) that issued the Postfix SMTP client
               certificate.
 
        <b><a href="postconf.5.html#smtp_tls_CApath">smtp_tls_CApath</a> (empty)</b>
-              Directory  with  PEM  format  certificate authority
-              certificates that the Postfix SMTP client  uses  to
+              Directory with  PEM  format  certificate  authority
+              certificates  that  the Postfix SMTP client uses to
               verify a remote SMTP server certificate.
 
        <b><a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a> (empty)</b>
-              File  with  the Postfix SMTP client RSA certificate
+              File with the Postfix SMTP client  RSA  certificate
               in PEM format.
 
        <b><a href="postconf.5.html#smtp_tls_cipherlist">smtp_tls_cipherlist</a> (empty)</b>
-              Controls the Postfix SMTP client TLS cipher  selec-
+              Controls  the Postfix SMTP client TLS cipher selec-
               tion scheme.
 
        <b><a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a> (empty)</b>
-              File  with  the Postfix SMTP client DSA certificate
+              File with the Postfix SMTP client  DSA  certificate
               in PEM format.
 
        <b><a href="postconf.5.html#smtp_tls_dkey_file">smtp_tls_dkey_file</a> ($<a href="postconf.5.html#smtp_tls_dcert_file">smtp_tls_dcert_file</a>)</b>
-              File with the Postfix SMTP client DSA  private  key
+              File  with  the Postfix SMTP client DSA private key
               in PEM format.
 
        <b><a href="postconf.5.html#smtp_tls_enforce_peername">smtp_tls_enforce_peername</a> (yes)</b>
-              When  TLS  encryption is enforced, require that the
+              When TLS encryption is enforced, require  that  the
               remote SMTP server hostname matches the information
               in the remote SMTP server certificate.
 
        <b><a href="postconf.5.html#smtp_tls_key_file">smtp_tls_key_file</a> ($<a href="postconf.5.html#smtp_tls_cert_file">smtp_tls_cert_file</a>)</b>
-              File  with  the Postfix SMTP client RSA private key
+              File with the Postfix SMTP client RSA  private  key
               in PEM format.
 
        <b><a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a> (0)</b>
-              Enable additional Postfix SMTP  client  logging  of
+              Enable  additional  Postfix  SMTP client logging of
               TLS activity.
 
        <b><a href="postconf.5.html#smtp_tls_note_starttls_offer">smtp_tls_note_starttls_offer</a> (no)</b>
-              Log  the  hostname  of  a  remote  SMTP server that
-              offers STARTTLS, when TLS is  not  already  enabled
+              Log the hostname  of  a  remote  SMTP  server  that
+              offers  STARTTLS,  when  TLS is not already enabled
               for that server.
 
        <b><a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> (empty)</b>
               Optional lookup tables with the Postfix SMTP client
-              TLS usage policy by next-hop  domain  name  and  by
+              TLS  usage  policy  by  next-hop domain name and by
               remote SMTP server hostname.
 
        <b><a href="postconf.5.html#smtp_tls_scert_verifydepth">smtp_tls_scert_verifydepth</a> (5)</b>
-              The  verification depth for remote SMTP server cer-
+              The verification depth for remote SMTP server  cer-
               tificates.
 
        <b><a href="postconf.5.html#smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> (empty)</b>
-              Name of the file containing  the  optional  Postfix
+              Name  of  the  file containing the optional Postfix
               SMTP client TLS session cache.
 
        <b><a href="postconf.5.html#smtp_tls_session_cache_timeout">smtp_tls_session_cache_timeout</a> (3600s)</b>
@@ -387,35 +394,43 @@ SMTP(8)                                                                SMTP(8)
               sion cache information.
 
        <b><a href="postconf.5.html#tls_daemon_random_bytes">tls_daemon_random_bytes</a> (32)</b>
-              The number of pseudo-random bytes that  an  <a href="smtp.8.html"><b>smtp</b>(8)</a>
-              or  <a href="smtpd.8.html"><b>smtpd</b>(8)</a>  process  requests  from the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a>
-              server in order to seed its internal pseudo  random
+              The  number  of pseudo-random bytes that an <a href="smtp.8.html"><b>smtp</b>(8)</a>
+              or <a href="smtpd.8.html"><b>smtpd</b>(8)</a> process  requests  from  the  <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a>
+              server  in order to seed its internal pseudo random
               number generator (PRNG).
 
+       Available in Postfix version 2.3 and later:
+
+       <b><a href="postconf.5.html#smtp_sasl_tls_verified_security_options">smtp_sasl_tls_verified_security_options</a></b>
+       <b>($<a href="postconf.5.html#smtp_sasl_tls_security_options">smtp_sasl_tls_security_options</a>)</b>
+              The SASL authentication security options  that  the
+              Postfix  SMTP  client  uses  for TLS encrypted SMTP
+              sessions with a verified server certificate.
+
 <b>RESOURCE AND RATE CONTROLS</b>
        <b><a href="postconf.5.html#smtp_destination_concurrency_limit">smtp_destination_concurrency_limit</a>      ($<a href="postconf.5.html#default_destination_concurrency_limit">default_destina</a>-</b>
        <b><a href="postconf.5.html#default_destination_concurrency_limit">tion_concurrency_limit</a>)</b>
-              The  maximal  number  of parallel deliveries to the
-              same destination  via  the  smtp  message  delivery
+              The maximal number of parallel  deliveries  to  the
+              same  destination  via  the  smtp  message delivery
               transport.
 
        <b><a href="postconf.5.html#smtp_destination_recipient_limit">smtp_destination_recipient_limit</a>        ($<a href="postconf.5.html#default_destination_recipient_limit">default_destina</a>-</b>
        <b><a href="postconf.5.html#default_destination_recipient_limit">tion_recipient_limit</a>)</b>
-              The  maximal  number of recipients per delivery via
+              The maximal number of recipients per  delivery  via
               the smtp message delivery transport.
 
        <b><a href="postconf.5.html#smtp_connect_timeout">smtp_connect_timeout</a> (30s)</b>
-              The SMTP client time limit  for  completing  a  TCP
+              The  SMTP  client  time  limit for completing a TCP
               connection,  or  zero  (use  the  operating  system
               built-in time limit).
 
        <b><a href="postconf.5.html#smtp_helo_timeout">smtp_helo_timeout</a> (300s)</b>
-              The SMTP client time limit for sending the HELO  or
-              EHLO  command, and for receiving the initial server
+              The  SMTP client time limit for sending the HELO or
+              EHLO command, and for receiving the initial  server
               response.
 
        <b><a href="postconf.5.html#lmtp_lhlo_timeout">lmtp_lhlo_timeout</a> (300s)</b>
-              The LMTP client time limit  for  sending  the  LHLO
+              The  LMTP  client  time  limit for sending the LHLO
               command,  and  for  receiving  the  initial  server
               response.
 
@@ -424,30 +439,30 @@ SMTP(8)                                                                SMTP(8)
               command, and for receiving the server response.
 
        <b><a href="postconf.5.html#smtp_mail_timeout">smtp_mail_timeout</a> (300s)</b>
-              The  SMTP  client  time  limit for sending the MAIL
-              FROM  command,  and  for   receiving   the   server
+              The SMTP client time limit  for  sending  the  MAIL
+              FROM   command,   and   for  receiving  the  server
               response.
 
        <b><a href="postconf.5.html#smtp_rcpt_timeout">smtp_rcpt_timeout</a> (300s)</b>
-              The  SMTP  client  time  limit for sending the SMTP
-              RCPT TO  command,  and  for  receiving  the  server
+              The SMTP client time limit  for  sending  the  SMTP
+              RCPT  TO  command,  and  for  receiving  the server
               response.
 
        <b><a href="postconf.5.html#smtp_data_init_timeout">smtp_data_init_timeout</a> (120s)</b>
-              The  SMTP  client  time  limit for sending the SMTP
-              DATA  command,  and  for   receiving   the   server
+              The SMTP client time limit  for  sending  the  SMTP
+              DATA   command,   and   for  receiving  the  server
               response.
 
        <b><a href="postconf.5.html#smtp_data_xfer_timeout">smtp_data_xfer_timeout</a> (180s)</b>
-              The  SMTP  client  time  limit for sending the SMTP
+              The SMTP client time limit  for  sending  the  SMTP
               message content.
 
        <b><a href="postconf.5.html#smtp_data_done_timeout">smtp_data_done_timeout</a> (600s)</b>
-              The SMTP client time limit  for  sending  the  SMTP
+              The  SMTP  client  time  limit for sending the SMTP
               ".", and for receiving the server response.
 
        <b><a href="postconf.5.html#smtp_quit_timeout">smtp_quit_timeout</a> (300s)</b>
-              The  SMTP  client  time  limit for sending the QUIT
+              The SMTP client time limit  for  sending  the  QUIT
               command, and for receiving the server response.
 
        Available in Postfix version 2.1 and later:
@@ -458,12 +473,12 @@ SMTP(8)                                                                SMTP(8)
               lookups, or zero (no limit).
 
        <b><a href="postconf.5.html#smtp_mx_session_limit">smtp_mx_session_limit</a> (2)</b>
-              The maximal number of SMTP  sessions  per  delivery
-              request  before  giving up or delivering to a fall-
+              The  maximal  number  of SMTP sessions per delivery
+              request before giving up or delivering to  a  fall-
               back <a href="postconf.5.html#relayhost">relay host</a>, or zero (no limit).
 
        <b><a href="postconf.5.html#smtp_rset_timeout">smtp_rset_timeout</a> (20s)</b>
-              The SMTP client time limit  for  sending  the  RSET
+              The  SMTP  client  time  limit for sending the RSET
               command, and for receiving the server response.
 
        Available in Postfix version 2.2 and earlier:
@@ -475,11 +490,11 @@ SMTP(8)                                                                SMTP(8)
        Available in Postfix version 2.2 and later:
 
        <b><a href="postconf.5.html#smtp_connection_cache_destinations">smtp_connection_cache_destinations</a> (empty)</b>
-              Permanently enable SMTP connection caching for  the
+              Permanently  enable SMTP connection caching for the
               specified destinations.
 
        <b><a href="postconf.5.html#smtp_connection_cache_on_demand">smtp_connection_cache_on_demand</a> (yes)</b>
-              Temporarily  enable SMTP connection caching while a
+              Temporarily enable SMTP connection caching while  a
               destination has a high volume of mail in the active
               queue.
 
@@ -489,57 +504,57 @@ SMTP(8)                                                                SMTP(8)
 
        <b><a href="postconf.5.html#smtp_connection_cache_time_limit">smtp_connection_cache_time_limit</a> (2s)</b>
               When SMTP connection caching is enabled, the amount
-              of  time  that an unused SMTP client socket is kept
+              of time that an unused SMTP client socket  is  kept
               open before it is closed.
 
        Available in Postfix version 2.3 and later:
 
        <b><a href="postconf.5.html#connection_cache_protocol_timeout">connection_cache_protocol_timeout</a> (5s)</b>
-              Time limit for connection cache  connect,  send  or
+              Time  limit  for  connection cache connect, send or
               receive operations.
 
 <b>TROUBLE SHOOTING CONTROLS</b>
        <b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a> (2)</b>
-              The  increment  in  verbose  logging  level  when a
-              remote client or server matches a  pattern  in  the
+              The increment  in  verbose  logging  level  when  a
+              remote  client  or  server matches a pattern in the
               <a href="postconf.5.html#debug_peer_list">debug_peer_list</a> parameter.
 
        <b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a> (empty)</b>
-              Optional  list  of remote client or server hostname
-              or network address patterns that cause the  verbose
-              logging  level  to increase by the amount specified
+              Optional list of remote client or  server  hostname
+              or  network address patterns that cause the verbose
+              logging level to increase by the  amount  specified
               in $<a href="postconf.5.html#debug_peer_level">debug_peer_level</a>.
 
        <b><a href="postconf.5.html#error_notice_recipient">error_notice_recipient</a> (postmaster)</b>
-              The recipient  of  postmaster  notifications  about
-              mail  delivery  problems that are caused by policy,
+              The  recipient  of  postmaster  notifications about
+              mail delivery problems that are caused  by  policy,
               resource, software or protocol errors.
 
        <b><a href="postconf.5.html#notify_classes">notify_classes</a> (resource, software)</b>
-              The list of error classes that are reported to  the
+              The  list of error classes that are reported to the
               postmaster.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#best_mx_transport">best_mx_transport</a> (empty)</b>
-              Where  the  Postfix SMTP client should deliver mail
+              Where the Postfix SMTP client should  deliver  mail
               when it detects a "mail loops back to myself" error
               condition.
 
        <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#disable_dns_lookups">disable_dns_lookups</a> (no)</b>
-              Disable  DNS  lookups  in the Postfix SMTP and LMTP
+              Disable DNS lookups in the Postfix  SMTP  and  LMTP
               clients.
 
        <b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
@@ -547,7 +562,7 @@ SMTP(8)                                                                SMTP(8)
               tem receives mail on.
 
        <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (ipv4)</b>
-              The  Internet protocols Postfix will attempt to use
+              The Internet protocols Postfix will attempt to  use
               when making or accepting connections.
 
        <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
@@ -555,74 +570,74 @@ SMTP(8)                                                                SMTP(8)
               over an internal communication channel.
 
        <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 the next service request
+              The  maximum  amount  of  time that an idle Postfix
+              daemon process waits for the next  service  request
               before exiting.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The maximal number of connection requests before  a
+              The  maximal number of connection requests before a
               Postfix daemon process terminates.
 
        <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 SMTP
-              client should bind to when making an  IPv4  connec-
+              client  should  bind to when making an IPv4 connec-
               tion.
 
        <b><a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> (empty)</b>
               An optional numerical network address that the SMTP
-              client should bind to when making an  IPv6  connec-
+              client  should  bind to when making an IPv6 connec-
               tion.
 
        <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 SMTP client uses  to  look
+              What  mechanisms  when the 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"
+              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>
@@ -640,7 +655,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 4304450d9c09ccc40c29971f64c7f0dc17b4dc19..371d10f562bf0094028eea89d664a6cbfe8fbb75 100644 (file)
@@ -33,7 +33,7 @@ SMTPD(8)                                                              SMTPD(8)
        The SMTP server implements a variety of policies for  con-
        nection  requests, and for parameters given to <b>HELO, ETRN,</b>
        <b>MAIL FROM, VRFY</b> and <b>RCPT TO</b> commands.  They  are  detailed
-       below and in the <b>main.cf</b> configuration file.
+       below and in the <a href="postconf.5.html"><b>main.cf</b></a> configuration file.
 
 <b>SECURITY</b>
        The SMTP server is moderately security-sensitive. It talks
@@ -47,7 +47,6 @@ SMTPD(8)                                                              SMTPD(8)
        <a href="http://www.faqs.org/rfcs/rfc1869.html">RFC 1869</a> (SMTP service extensions)
        <a href="http://www.faqs.org/rfcs/rfc1870.html">RFC 1870</a> (Message Size Declaration)
        <a href="http://www.faqs.org/rfcs/rfc1985.html">RFC 1985</a> (ETRN command)
-       <a href="http://www.faqs.org/rfcs/rfc2034.html">RFC 2034</a> (Enhanced Status Codes)
        <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC 2554</a> (AUTH command)
        <a href="http://www.faqs.org/rfcs/rfc2821.html">RFC 2821</a> (SMTP protocol)
        <a href="http://www.faqs.org/rfcs/rfc2920.html">RFC 2920</a> (SMTP Pipelining)
@@ -63,7 +62,7 @@ SMTPD(8)                                                              SMTPD(8)
        policy violations, and of other trouble.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes   to  <b>main.cf</b>  are  picked  up  automatically,  as
+       Changes   to  <a href="postconf.5.html"><b>main.cf</b></a>  are  picked  up  automatically,  as
        <a href="smtpd.8.html"><b>smtpd</b>(8)</a> processes run for only a limited amount of  time.
        Use the command "<b>postfix reload</b>" to speed up a change.
 
@@ -872,8 +871,8 @@ SMTPD(8)                                                              SMTPD(8)
 
 <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 main.cf and
-              master.cf configuration files.
+              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
index 9f12a5d4173a7755e1337852964456ef8383ef0a..23dce716744fd8454a75207e22523cfba504a347 100644 (file)
@@ -70,7 +70,7 @@ VERIFY(8)                                                            VERIFY(8)
        This violates a basic Postfix principle.
 
 <b>CONFIGURATION PARAMETERS</b>
-       Changes to <b>main.cf</b> are not  picked  up  automatically,  as
+       Changes to <a href="postconf.5.html"><b>main.cf</b></a> are not  picked  up  automatically,  as
        <a href="verify.8.html"><b>verify</b>(8)</a> processes are persistent. Use the command "<b>post-</b>
        <b>fix reload</b>" after a configuration change.
 
@@ -137,8 +137,8 @@ VERIFY(8)                                                            VERIFY(8)
 
 <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  main.cf  and
-              master.cf configuration files.
+              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
index 4bbe6463aa47a5c7d77e01b8b4e1224cec019e95..4d2d591f08dcb60ff3d979ddc5f1588ae86c1c98 100644 (file)
@@ -75,7 +75,7 @@ only. You can change the word EOF, but you can't enclose
 it in quotes as with the shell or with Perl (\fItemplate_name\fB
 = <<'EOF'\fR). Here is an example:
 
-.in +2
+.in +4
 .nf
 .na
 # The failure template is used for undeliverable mail.
@@ -99,16 +99,22 @@ delete your own text from the attached returned message.
 .ti +12
                    The $mail_name program
 EOF
-.in -2
+.in -4
 .ad
 .fi
-
+.PP
+The usage and specification of bounce templates is
+subject to the following restrictions:
+.IP \(bu
 No special meaning is given to the backslash character or
 to leading whitespace; these are always taken literally.
-
+.IP \(bu
+Inside the << context, the "$" character is special. To
+produce a "$" character as output, specify "$$".
+.IP \(bu
 Outside the << context, lines beginning with "#" are ignored,
 as are empty lines, and lines consisting of whitespace only.
-
+.PP
 Examples of all templates can be found in the file
 \fBbounce.cf.default\fR in the Postfix configuration
 directory.
index 7e1dece6e68ded9931d00b99043eba0b73202089..ddde62dd4564c6ac5714e80a793c80581b8e2cfc 100644 (file)
@@ -1666,6 +1666,11 @@ command.
 Most of these limitations will be removed after Postfix implements
 a connection cache that is shared among multiple LMTP client
 programs.
+.SH lmtp_cname_overrides_servername (default: yes)
+The LMTP-specific version of the smtp_cname_overrides_servername
+configuration parameter.  See there for details.
+.PP
+This feature is available in Postfix 2.3 and later.
 .SH lmtp_connect_timeout (default: 0s)
 The LMTP client time limit for completing a TCP connection, or
 zero (use the operating system built-in time limit).  When no
@@ -1910,11 +1915,17 @@ lmtp_sasl_security_options = noplaintext
 .fi
 .ad
 .ft R
-.SH lmtp_sasl_tls_security_options (default: $var_lmtp_sasl_opts)
+.SH lmtp_sasl_tls_security_options (default: $lmtp_sasl_security_options)
 The LMTP-specific version of the smtp_sasl_tls_security_options
 configuration parameter.  See there for details.
 .PP
 This feature is available in Postfix 2.3 and later.
+.SH lmtp_sasl_tls_verified_security_options (default: $lmtp_sasl_tls_security_options)
+The LMTP-specific version of the
+smtp_sasl_tls_verified_security_options configuration parameter.
+See there for details.
+.PP
+This feature is available in Postfix 2.3 and later.
 .SH lmtp_sasl_type (default: cyrus)
 The SASL plug-in type that the Postfix LMTP client should use
 for authentication.  The available types are listed with the
@@ -3569,6 +3580,16 @@ inet_interfaces documentation for more detail.
 .PP
 Note 2: address information may be enclosed inside [],
 but this form is not recommended here.
+.SH smtp_cname_overrides_servername (default: version dependent)
+Allow DNS CNAME records to override the servername that the
+Postfix SMTP client uses for logging, SASL password lookup, TLS
+policy decisions, or TLS certificate verification. The value "no"
+hardens Postfix smtp_tls_per_site hostname-based policies against
+false hostname information in DNS CNAME records, and makes SASL
+password file lookups more predictable. This is the default setting
+as of Postfix 2.3.
+.PP
+This feature is available in Postfix 2.2.9 and later.
 .SH smtp_connect_timeout (default: 30s)
 The SMTP client time limit for completing a TCP connection, or
 zero (use the operating system built-in time limit).
@@ -4014,6 +4035,12 @@ smtp_sasl_security_options = noplaintext
 .SH smtp_sasl_tls_security_options (default: $smtp_sasl_security_options)
 The SASL authentication security options that the Postfix SMTP
 client uses for TLS encrypted SMTP sessions.
+.SH smtp_sasl_tls_verified_security_options (default: $smtp_sasl_tls_security_options)
+The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions with a verified server
+certificate.
+.PP
+This feature is available in Postfix 2.3 and later.
 .SH smtp_sasl_type (default: cyrus)
 The SASL plug-in type that the Postfix SMTP client should use
 for authentication.  The available types are listed with the
@@ -4239,12 +4266,32 @@ not require that the remote SMTP server hostname matches the
 information in the remote SMTP server certificate, or that the
 server certificate was issued by a trusted CA.
 .PP
-Special hint for enforcement mode:  since no secure DNS lookup
-mechanism is available, the recommended setup is:  specify local
-\fBtransport\fR(5) table entries for sensitive domains with explicit
-smtp:[mailhost] destinations (since you can assure security of this
-table unlike DNS), then specify MUST for these mail hosts in the
-smtp_tls_per_site table.
+Special hints for enforcement mode:  since no secure DNS lookup
+mechanism is available, the recommended setup is:
+.IP "Postfix 2.2.9"
+.IP \(bu
+Specify "smtp_cname_overrides_servername = no". This avoids
+false hostname information in DNS CNAME records that could bypass
+a hostname-based TLS usage policy.
+.IP \(bu
+Specify local \fBtransport\fR(5) table entries for sensitive domains
+with explicit smtp:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy.
+.IP \(bu
+Specify MUST for these mail hosts in the smtp_tls_per_site
+table.
+.IP "Postfix < 2.2.9"
+.IP \(bu
+Specify local \fBtransport\fR(5) table entries for sensitive domains
+with explicit smtp:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy, but cannot avoid false hostname
+information in DNS CNAME records.
+.IP \(bu
+Specify MUST for these mail hosts in the smtp_tls_per_site
+table.
+.PP
 .SH smtp_tls_scert_verifydepth (default: 5)
 The verification depth for remote SMTP server certificates. A
 depth of 1 is sufficient, if the certificate is directly issued by
index 70da797c9496057dd3b8a44a6b847e252cbf3bfe..c3f653824e63ed213f7b5435779faf9422f770ab 100644 (file)
@@ -32,8 +32,8 @@ appropriate.
 .ad
 .fi
 Some external commands cannot handle more than one recipient
-per delivery request. Examples of such transports are pagers,
-fax machines, and so on.
+per delivery request. Examples of such transports are pagers
+or fax machines.
 
 To prevent Postfix from sending multiple recipients per delivery
 request, specify
index 0b3b09396dc45b6f31d63d177580a1e15973272a..5c82b4c33e2258092436506dc0d891edc4f7d3b0 100644 (file)
@@ -99,7 +99,6 @@ RFC 1651 (SMTP service extensions)
 RFC 1652 (8bit-MIME transport)
 RFC 1870 (Message Size Declaration)
 RFC 2033 (LMTP protocol)
-RFC 2034 (Enhanced Status Codes)
 RFC 2045 (MIME: Format of Internet Message Bodies)
 RFC 2046 (MIME: Media Types)
 RFC 2554 (AUTH command)
@@ -202,6 +201,12 @@ Optional lookup tables that perform address rewriting in the
 SMTP client, typically to transform a locally valid address into
 a globally valid address when sending mail across the Internet.
 .PP
+Available in Postfix version 2.2.9 and later:
+.IP "\fBsmtp_cname_overrides_servername (version dependent)\fR"
+Allow DNS CNAME records to override the servername that the
+Postfix SMTP client uses for logging, SASL password lookup, TLS
+policy decisions, or TLS certificate verification.
+.PP
 Available in Postfix version 2.3 and later:
 .IP "\fBlmtp_discard_lhlo_keyword_address_maps (empty)\fR"
 Lookup tables, indexed by the remote LMTP server address, with
@@ -327,6 +332,12 @@ information.
 The number of pseudo-random bytes that an \fBsmtp\fR(8) or \fBsmtpd\fR(8)
 process requests from the \fBtlsmgr\fR(8) server in order to seed its
 internal pseudo random number generator (PRNG).
+.PP
+Available in Postfix version 2.3 and later:
+.IP "\fBsmtp_sasl_tls_verified_security_options ($smtp_sasl_tls_security_options)\fR"
+The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions with a verified server
+certificate.
 .SH "RESOURCE AND RATE CONTROLS"
 .na
 .nf
index 2a8762e818252e579a1a4eb8a9553ca4e7a946e3..fdc89d215175836a9a9868fc5477f9735854f211 100644 (file)
@@ -50,7 +50,6 @@ RFC 1652 (8bit-MIME transport)
 RFC 1869 (SMTP service extensions)
 RFC 1870 (Message Size Declaration)
 RFC 1985 (ETRN command)
-RFC 2034 (Enhanced Status Codes)
 RFC 2554 (AUTH command)
 RFC 2821 (SMTP protocol)
 RFC 2920 (SMTP Pipelining)
@@ -114,9 +113,9 @@ What SMTP clients Postfix will not offer AUTH support to.
 Available in Postfix version 2.2 and later:
 .IP "\fBsmtpd_discard_ehlo_keyword_address_maps (empty)\fR"
 Lookup tables, indexed by the remote SMTP client address, with
-case insensitive lists of EHLO keywords (pipelining, starttls,
-auth, etc.) that the SMTP server will not send in the EHLO response
-to a remote SMTP client.
+case insensitive lists of EHLO keywords (pipelining, starttls, auth,
+etc.) that the SMTP server will not send in the EHLO response to a
+remote SMTP client.
 .IP "\fBsmtpd_discard_ehlo_keywords (empty)\fR"
 A case insensitive list of EHLO keywords (pipelining, starttls,
 auth, etc.) that the SMTP server will not send in the EHLO response
index c2c674a05f4cdc9e85e447325dbc021acbade9d9..8af68581fd67bc4b745d58a1250722dcd9c1cbac 100755 (executable)
@@ -199,6 +199,7 @@ while (<>) {
     s;\blmtp_discard_lhlo_keyword_address_maps\b;<a href="postconf.5.html#lmtp_discard_lhlo_keyword_address_maps">$&</a>;g;
     s;\blmtp_discard_lhlo_keywords\b;<a href="postconf.5.html#lmtp_discard_lhlo_keywords">$&</a>;g;
     s;\blmtp_sasl_tls_security_options\b;<a href="postconf.5.html#lmtp_sasl_tls_security_options">$&</a>;g;
+    s;\blmtp_sasl_tls_verified_security_options\b;<a href="postconf.5.html#lmtp_sasl_tls_verified_security_options">$&</a>;g;
     s;\blmtp_sasl_mechanism_filter\b;<a href="postconf.5.html#lmtp_sasl_mechanism_filter">$&</a>;g;
     s;\blmtp_host_lookup\b;<a href="postconf.5.html#lmtp_host_lookup">$&</a>;g;
     s;\blmtp_connection_cache_destinations\b;<a href="postconf.5.html#lmtp_connection_cache_destinations">$&</a>;g;
@@ -355,6 +356,7 @@ while (<>) {
     s;\bsmtp_always_send_ehlo\b;<a href="postconf.5.html#smtp_always_send_ehlo">$&</a>;g;
     s;\bsmtp_bind_address\b;<a href="postconf.5.html#smtp_bind_address">$&</a>;g;
     s;\bsmtp_bind_address6\b;<a href="postconf.5.html#smtp_bind_address6">$&</a>;g;
+    s;\bsmtp_cname_overrides_servername\b;<a href="postconf.5.html#smtp_cname_overrides_servername">$&</a>;g;
     s;\bsmtp_connect_timeout\b;<a href="postconf.5.html#smtp_connect_timeout">$&</a>;g;
 
     s;\bsmtp_connection_cache_on_demand\b;<a href="postconf.5.html#smtp_connection_cache_on_demand">$&</a>;g;
@@ -499,8 +501,8 @@ while (<>) {
 
     s;\bsmtp_enforce_tls\b;<a href="postconf.5.html#smtp_enforce_tls">$&</a>;g;
     s;\bsmtp_fallback_relay\b;<a href="postconf.5.html#smtp_fallback_relay">$&</a>;g;
-    s;\bsmtp_sasl_tls_security_options\b;<a href="postconf.5.html#smtp_sasl_tls_security_options">$&</a>;g;
-    s;\bsmtp_sasl_tls_verified_security_options\b;<a href="postconf.5.html#smtp_sasl_tls_verified_security_options">$&</a>;g;
+    s;\bsmtp_[-</Bb>]*\n* *[<Bb>]*sasl_[-</Bb>]*\n* *[<Bb>]*tls_[-</Bb>]*\n* *[<Bb>]*secu[-</Bb>]*\n* *[<Bb>]*rity_options\b;<a href="postconf.5.html#smtp_sasl_tls_security_options">$&</a>;g;
+    s;\bsmtp_sasl_tls_verified_secu[-</Bb>]*\n* *[<Bb>]*rity_options\b;<a href="postconf.5.html#smtp_sasl_tls_verified_security_options">$&</a>;g;
     s;\bsmtp_sasl_type\b;<a href="postconf.5.html#smtp_sasl_type">$&</a>;g;
     s;\bsmtp_starttls_timeout\b;<a href="postconf.5.html#smtp_starttls_timeout">$&</a>;g;
     s;\bsmtp_tls_CAfile\b;<a href="postconf.5.html#smtp_tls_CAfile">$&</a>;g;
index f8ffca51bb1ebc34cb0db31db7c0174af74cbb4c..aaf5fd43f75d820f24ca3a051562d1e59191f6aa 100644 (file)
@@ -65,7 +65,7 @@
 #      it in quotes as with the shell or with Perl (\fItemplate_name\fB
 #      = <<'EOF'\fR). Here is an example:
 #
-# .in +2
+# .in +4
 # .nf
 # .na
 #      # The failure template is used for undeliverable mail.
 # .ti +12
 #                         The $mail_name program
 #      EOF
-# .in -2
+# .in -4
 # .ad
 # .fi
-#
+# .PP
+#      The usage and specification of bounce templates is
+#      subject to the following restrictions:
+# .IP \(bu
 #      No special meaning is given to the backslash character or
 #      to leading whitespace; these are always taken literally.
-#
+# .IP \(bu
+#      Inside the << context, the "$" character is special. To
+#      produce a "$" character as output, specify "$$".
+# .IP \(bu
 #      Outside the << context, lines beginning with "#" are ignored,
 #      as are empty lines, and lines consisting of whitespace only.
-#
+# .PP
 #      Examples of all templates can be found in the file
 #      \fBbounce.cf.default\fR in the Postfix configuration
 #      directory.
index 65e620d06759885e203d76ebdd526b6fb5782a37..e4ac74bfbc80bae7557aaca66af0f4e570394459 100644 (file)
@@ -8538,12 +8538,47 @@ server certificate was issued by a trusted CA. </dd>
 
 </dl>
 
-<p> Special hint for enforcement mode:  since no secure DNS lookup
-mechanism is available, the recommended setup is:  specify local
-transport(5) table entries for sensitive domains with explicit
-smtp:[mailhost] destinations (since you can assure security of this
-table unlike DNS), then specify MUST for these mail hosts in the
-smtp_tls_per_site table. </p>
+<p> Special hints for enforcement mode:  since no secure DNS lookup
+mechanism is available, the recommended setup is:  </p>
+
+<dl>
+
+<dt> Postfix 2.2.9 </dt>
+
+<dd> <ul>
+
+<li> Specify "smtp_cname_overrides_servername = no". This avoids
+false hostname information in DNS CNAME records that could bypass
+a hostname-based TLS usage policy.
+
+<li> Specify local transport(5) table entries for sensitive domains
+with explicit smtp:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy.
+
+<li> Specify MUST for these mail hosts in the smtp_tls_per_site
+table.
+
+</ul> </dd>
+
+<dt> Postfix &lt; 2.2.9 </dt>
+
+<dd> <ul>
+
+<li> Specify local transport(5) table entries for sensitive domains
+with explicit smtp:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy, but cannot avoid false hostname
+information in DNS CNAME records.
+
+<li> Specify MUST for these mail hosts in the smtp_tls_per_site
+table.
+
+</ul> </dd>
+
+</dl>
+
+<p> </p>
 
 %PARAM smtp_tls_scert_verifydepth 5
 
@@ -8866,7 +8901,7 @@ for receiving the initial server response. </p>
 <p> Time units: s (seconds), m (minutes), h (hours), d (days), w
 (weeks).  The default time unit is s (seconds).  </p>
 
-%PARAM lmtp_sasl_tls_security_options $var_lmtp_sasl_opts
+%PARAM lmtp_sasl_tls_security_options $lmtp_sasl_security_options
 
 <p> The LMTP-specific version of the smtp_sasl_tls_security_options
 configuration parameter.  See there for details. </p>
@@ -9148,3 +9183,38 @@ mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_directory,
 fallback_transport_maps, fallback_transport and luser_relay.  </p>
  
 <p> This feature is available in Postfix 2.3 and later. </p>
+
+%PARAM smtp_cname_overrides_servername version dependent
+
+<p> Allow DNS CNAME records to override the servername that the
+Postfix SMTP client uses for logging, SASL password lookup, TLS
+policy decisions, or TLS certificate verification. The value "no"
+hardens Postfix smtp_tls_per_site hostname-based policies against
+false hostname information in DNS CNAME records, and makes SASL
+password file lookups more predictable. This is the default setting
+as of Postfix 2.3. </p>
+
+<p> This feature is available in Postfix 2.2.9 and later. </p>
+
+%PARAM lmtp_cname_overrides_servername yes
+
+<p> The LMTP-specific version of the smtp_cname_overrides_servername
+configuration parameter.  See there for details. </p>
+
+<p> This feature is available in Postfix 2.3 and later. </p>
+
+%PARAM smtp_sasl_tls_verified_security_options $smtp_sasl_tls_security_options
+
+<p> The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions with a verified server
+certificate. </p>
+
+<p> This feature is available in Postfix 2.3 and later. </p>
+
+%PARAM lmtp_sasl_tls_verified_security_options $lmtp_sasl_tls_security_options
+
+<p> The LMTP-specific version of the
+smtp_sasl_tls_verified_security_options configuration parameter.
+See there for details. </p>
+
+<p> This feature is available in Postfix 2.3 and later. </p>
index 1a19890c73276f3523dcb39a86a4a4ac1d29e7b5..c7a824ca5dec327fd01f32a07277e12ebac94c13 100644 (file)
@@ -194,14 +194,14 @@ BOUNCE_TEMPLATES *bounce_templates;
 
 #define STR vstring_str
 
+#define VS_NEUTER(s) printable(vstring_str(s), '?')
+
 /* bounce_append_proto - bounce_append server protocol */
 
 static int bounce_append_proto(char *service_name, VSTREAM *client)
 {
     char   *myname = "bounce_append_proto";
     int     flags;
-    RECIPIENT_VAR rcpt;
-    DSN_VAR dsn;
 
     /*
      * Read and validate the client request.
@@ -215,17 +215,31 @@ static int bounce_append_proto(char *service_name, VSTREAM *client)
        msg_warn("malformed request");
        return (-1);
     }
+
+    /*
+     * Sanitize input.
+     */
     if (mail_queue_id_ok(STR(queue_id)) == 0) {
        msg_warn("malformed queue id: %s", printable(STR(queue_id), '?'));
        return (-1);
     }
-    (void) RECIPIENT_FROM_RCPT_BUF(&rcpt, rcpt_buf);
-    (void) DSN_FROM_DSN_BUF(&dsn, dsn_buf);
+    VS_NEUTER(rcpt_buf->address);
+    VS_NEUTER(rcpt_buf->orig_addr);
+    VS_NEUTER(rcpt_buf->dsn_orcpt);
+    VS_NEUTER(dsn_buf->status);
+    VS_NEUTER(dsn_buf->action);
+    VS_NEUTER(dsn_buf->reason);
+    VS_NEUTER(dsn_buf->dtype);
+    VS_NEUTER(dsn_buf->dtext);
+    VS_NEUTER(dsn_buf->mtype);
+    VS_NEUTER(dsn_buf->mname);
+    (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf);
+    (void) DSN_FROM_DSN_BUF(dsn_buf);
 
     /*
-     * Beware: some dsn or rcpt fields may be null; access dsn_buf and
-     * rcpt_buf instead. See DSN_FROM_DSN_BUF(), RECIPIENT_FROM_RCPT_BUF(),
-     * and bounce_log(3).
+     * Beware: some DSN or RECIPIENT fields may be null; access dsn_buf and
+     * rcpt_buf buffers instead. See DSN_FROM_DSN_BUF() and
+     * RECIPIENT_FROM_RCPT_BUF().
      */
     if (msg_verbose)
        msg_info("%s: flags=0x%x service=%s id=%s org_to=%s to=%s off=%ld dsn_org=%s, notif=0x%x stat=%s act=%s why=%s",
@@ -246,7 +260,7 @@ static int bounce_append_proto(char *service_name, VSTREAM *client)
      * Execute the request.
      */
     return (bounce_append_service(flags, service_name, STR(queue_id),
-                                 &rcpt, &dsn));
+                                 &rcpt_buf->rcpt, &dsn_buf->dsn));
 }
 
 /* bounce_notify_proto - bounce_notify server protocol */
@@ -275,6 +289,10 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client,
        msg_warn("malformed request");
        return (-1);
     }
+
+    /*
+     * Sanitize input.
+     */
     if (mail_queue_name_ok(STR(queue_name)) == 0) {
        msg_warn("malformed queue name: %s", printable(STR(queue_name), '?'));
        return (-1);
@@ -329,6 +347,10 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client)
        msg_warn("malformed request");
        return (-1);
     }
+
+    /*
+     * Sanitize input.
+     */
     if (mail_queue_name_ok(STR(queue_name)) == 0) {
        msg_warn("malformed queue name: %s", printable(STR(queue_name), '?'));
        return (-1);
@@ -380,8 +402,6 @@ static int bounce_one_proto(char *service_name, VSTREAM *client)
     char   *myname = "bounce_one_proto";
     int     flags;
     int     dsn_ret;
-    RECIPIENT rcpt;
-    DSN     dsn;
 
     /*
      * Read and validate the client request.
@@ -400,6 +420,10 @@ static int bounce_one_proto(char *service_name, VSTREAM *client)
        msg_warn("malformed request");
        return (-1);
     }
+
+    /*
+     * Sanitize input.
+     */
     if (strcmp(service_name, MAIL_SERVICE_BOUNCE) != 0) {
        msg_warn("wrong service name \"%s\" for one-recipient bouncing",
                 service_name);
@@ -414,13 +438,23 @@ static int bounce_one_proto(char *service_name, VSTREAM *client)
        return (-1);
     }
     printable(STR(dsn_envid), '?');
-    (void) RECIPIENT_FROM_RCPT_BUF(&rcpt, rcpt_buf);
-    (void) DSN_FROM_DSN_BUF(&dsn, dsn_buf);
+    VS_NEUTER(rcpt_buf->address);
+    VS_NEUTER(rcpt_buf->orig_addr);
+    VS_NEUTER(rcpt_buf->dsn_orcpt);
+    VS_NEUTER(dsn_buf->status);
+    VS_NEUTER(dsn_buf->action);
+    VS_NEUTER(dsn_buf->reason);
+    VS_NEUTER(dsn_buf->dtype);
+    VS_NEUTER(dsn_buf->dtext);
+    VS_NEUTER(dsn_buf->mtype);
+    VS_NEUTER(dsn_buf->mname);
+    (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf);
+    (void) DSN_FROM_DSN_BUF(dsn_buf);
 
     /*
-     * Beware: some dsn or rcpt fields may be null; access dsn_buf and
-     * rcpt_buf instead. See DSN_FROM_DSN_BUF(), RECIPIENT_FROM_RCPT_BUF(),
-     * and bounce_log(3).
+     * Beware: some DSN or RECIPIENT fields may be null; access dsn_buf and
+     * rcpt_buf buffers instead. See DSN_FROM_DSN_BUF() and
+     * RECIPIENT_FROM_RCPT_BUF().
      */
     if (msg_verbose)
        msg_info("%s: flags=0x%x queue=%s id=%s encoding=%s sender=%s envid=%s dsn_ret=0x%x orig_to=%s to=%s off=%ld dsn_orig=%s notif=0x%x stat=%s act=%s why=%s",
@@ -436,7 +470,7 @@ static int bounce_one_proto(char *service_name, VSTREAM *client)
      */
     return (bounce_one_service(flags, STR(queue_name), STR(queue_id),
                               STR(encoding), STR(sender), STR(dsn_envid),
-                              dsn_ret, &rcpt, &dsn, bounce_templates));
+                            dsn_ret, rcpt_buf, dsn_buf, bounce_templates));
 }
 
 /* bounce_service - parse bounce command type and delegate */
@@ -536,7 +570,9 @@ static void post_jail_init(char *service_name, char **unused_argv)
 
     /*
      * Special case: dump bounce templates. This is not part of the master(5)
-     * public interface.
+     * public interface. This internal interface is used by the postconf
+     * command. It was implemented before bounce templates were isolated
+     * into modules that could have been called directly.
      */
     if (strcmp(service_name, "dump_templates") == 0) {
        bounce_templates_dump(VSTREAM_OUT, bounce_templates);
index 868b03e68e5714a4255a3bceb84fe427f93c1fd0..582bb1977bcc70fe4efd16a85bccea812b08e085 100644 (file)
@@ -10,8 +10,8 @@
 /*     int     flags;
 /*     char    *service;
 /*     char    *queue_id;
-/*     RECIPIENT_VAR *rcpt;
-/*     DSN_VAR *dsn;
+/*     RECIPIENT *rcpt;
+/*     DSN     *dsn;
 /* DESCRIPTION
 /*     This module implements the server side of the bounce_append()
 /*     (append bounce log) request. This routine either succeeds or
@@ -67,7 +67,7 @@
 /* bounce_append_service - append bounce log */
 
 int     bounce_append_service(int unused_flags, char *service, char *queue_id,
-                                     RECIPIENT_VAR *rcpt, DSN_VAR *dsn)
+                                     RECIPIENT *rcpt, DSN *dsn)
 {
     VSTRING *in_buf = vstring_alloc(100);
     VSTREAM *log;
@@ -113,49 +113,41 @@ int     bounce_append_service(int unused_flags, char *service, char *queue_id,
        msg_fatal("seek file %s %s: %m", service, queue_id);
 
 #define NOT_NULL_EMPTY(s) ((s) != 0 && *(s) != 0)
-#define ST_NEUTER(s) printable((s), '?')
-#define VS_NEUTER(s) printable(vstring_str(s), '?')
+#define STR(x) vstring_str(x)
 
     vstream_fputs("\n", log);
     if (var_oldlog_compat) {
        vstream_fprintf(log, "<%s>: %s\n", *rcpt->address == 0 ? "" :
-                       VS_NEUTER(quote_822_local(in_buf, rcpt->address)),
-                       ST_NEUTER(dsn->reason));
+                       STR(quote_822_local(in_buf, rcpt->address)),
+                       dsn->reason);
     }
     vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_RECIP, *rcpt->address ?
-                 VS_NEUTER(quote_822_local(in_buf, rcpt->address)) : "<>");
+                 STR(quote_822_local(in_buf, rcpt->address)) : "<>");
     if (NOT_NULL_EMPTY(rcpt->orig_addr)
        && strcasecmp(rcpt->address, rcpt->orig_addr) != 0)
        vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_ORCPT,
-                       VS_NEUTER(quote_822_local(in_buf, rcpt->orig_addr)));
+                       STR(quote_822_local(in_buf, rcpt->orig_addr)));
     if (rcpt->offset > 0)
        vstream_fprintf(log, "%s=%ld\n", MAIL_ATTR_OFFSET, rcpt->offset);
     if (NOT_NULL_EMPTY(rcpt->dsn_orcpt))
-       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_ORCPT,
-                       ST_NEUTER(rcpt->dsn_orcpt));
+       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt);
     if (rcpt->dsn_notify != 0)
        vstream_fprintf(log, "%s=%d\n", MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify);
 
     if (NOT_NULL_EMPTY(dsn->status))
-       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_STATUS,
-                       ST_NEUTER(dsn->status));
+       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_STATUS, dsn->status);
     if (NOT_NULL_EMPTY(dsn->action))
-       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_ACTION,
-                       ST_NEUTER(dsn->action));
+       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_ACTION, dsn->action);
     if (NOT_NULL_EMPTY(dsn->dtype) && NOT_NULL_EMPTY(dsn->dtext)) {
-       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_DTYPE,
-                       ST_NEUTER(dsn->dtype));
-       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_DTEXT,
-                       ST_NEUTER(dsn->dtext));
+       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_DTYPE, dsn->dtype);
+       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_DTEXT, dsn->dtext);
     }
     if (NOT_NULL_EMPTY(dsn->mtype) && NOT_NULL_EMPTY(dsn->mname)) {
-       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_MTYPE,
-                       ST_NEUTER(dsn->mtype));
-       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_MNAME,
-                       ST_NEUTER(dsn->mname));
+       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_MTYPE, dsn->mtype);
+       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_MNAME, dsn->mname);
     }
     if (NOT_NULL_EMPTY(dsn->reason))
-       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_WHY, ST_NEUTER(dsn->reason));
+       vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_WHY, dsn->reason);
     vstream_fputs("\n", log);
 
     if (vstream_fflush(log) != 0 || fsync(vstream_fileno(log)) < 0) {
index c02ffb9c3cdee4120968c0c971baf484a42ed2df..8c35505942c2cf25b82f88fc51e882396280a471 100644 (file)
@@ -92,6 +92,7 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
     VSTREAM *bounce;
     int     notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
                                    var_notify_classes);
+    VSTRING *new_id = vstring_alloc(10);
     char   *postmaster;
     int     count;
 
@@ -174,7 +175,8 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
            if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
                                                 postmaster,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
-                                                NULL_TRACE_FLAGS)) != 0) {
+                                                NULL_TRACE_FLAGS,
+                                                new_id)) != 0) {
 
                /*
                 * Double bounce to Postmaster. This is the last opportunity
@@ -192,6 +194,9 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
                                             DSN_NOTIFY_OVERRIDE) > 0) {
                    bounce_original(bounce, bounce_info, DSN_RET_FULL);
                    bounce_status = post_mail_fclose(bounce);
+                   if (bounce_status == 0)
+                       msg_info("%s: postmaster non-delivery notification: %s",
+                                queue_id, STR(new_id));
                } else {
                    /* No applicable recipients found - cancel this notice. */
                    (void) vstream_fclose(bounce);
@@ -209,7 +214,8 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
     else {
        if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
                                             CLEANUP_FLAG_MASK_INTERNAL,
-                                            NULL_TRACE_FLAGS)) != 0) {
+                                            NULL_TRACE_FLAGS,
+                                            new_id)) != 0) {
 
            /*
             * Send the bounce message header, some boilerplate text that
@@ -228,6 +234,9 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
                bounce_original(bounce, bounce_info, dsn_ret ?
                                dsn_ret : DSN_RET_FULL);
                bounce_status = post_mail_fclose(bounce);
+               if (bounce_status == 0)
+                   msg_info("%s: sender non-delivery notification: %s",
+                            queue_id, STR(new_id));
            } else {
                /* No applicable recipients found - cancel this notice. */
                (void) vstream_fclose(bounce);
@@ -259,7 +268,8 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
            if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
                                                 postmaster,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
-                                                NULL_TRACE_FLAGS)) != 0) {
+                                                NULL_TRACE_FLAGS,
+                                                new_id)) != 0) {
                count = -1;
                if (bounce_header(bounce, bounce_info, postmaster,
                                  POSTMASTER_COPY) == 0
@@ -270,6 +280,9 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
                                             DSN_NOTIFY_OVERRIDE) > 0) {
                    bounce_original(bounce, bounce_info, DSN_RET_HDRS);
                    postmaster_status = post_mail_fclose(bounce);
+                   if (postmaster_status == 0)
+                       msg_info("%s: postmaster non-delivery notification: %s",
+                                queue_id, STR(new_id));
                } else {
                    /* No applicable recipients found - cancel this notice. */
                    (void) vstream_fclose(bounce);
@@ -278,8 +291,8 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
                }
            }
            if (postmaster_status)
-               msg_warn("postmaster notice failed while bouncing to %s",
-                        recipient);
+               msg_warn("%s: postmaster notice failed while bouncing to %s",
+                        queue_id, recipient);
        }
     }
 
@@ -302,6 +315,7 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
      * Cleanup.
      */
     bounce_mail_free(bounce_info);
+    vstring_free(new_id);
 
     return (bounce_status);
 }
index 0078b680c1bf51e1cc9cb56798b546de32ed9904..39dc887e77694fdfbb111116b823607cace9d9b2 100644 (file)
 /*     const BOUNCE_TEMPLATE *template;
 /*
 /*     BOUNCE_INFO *bounce_mail_one_init(queue_name, queue_id, encoding,
-/*                                     dsn_envid, dsn_notify, rcpt, dsn,
-/*                                     template)
+/*                                     dsn_envid, dsn_notify, rcpt_buf,
+/*                                     dsn_buf, template)
 /*     const char *queue_name;
 /*     const char *queue_id;
 /*     const char *encoding;
 /*     int     dsn_notify;
 /*     const char *dsn_envid;
-/*     RECIPIENT *rcpt;
-/*     DSN     *dsn;
+/*     RCPT_BUF *rcpt_buf;
+/*     DSN_BUF *dsn_buf;
 /*     const BOUNCE_TEMPLATE *template;
 /*
 /*     void    bounce_mail_free(bounce_info)
 #include <sys_defs.h>
 #include <sys/stat.h>
 #include <stdlib.h>
+#include <stdio.h>                     /* sscanf() */
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
@@ -211,6 +212,8 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
                                              const char *queue_id,
                                              const char *encoding,
                                              const char *dsn_envid,
+                                             RCPT_BUF *rcpt_buf,
+                                             DSN_BUF *dsn_buf,
                                              BOUNCE_TEMPLATE *template,
                                              BOUNCE_LOG *log_handle)
 {
@@ -218,7 +221,7 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
     int     rec_type;
 
     /*
-     * Bundle up a bunch of parameters and initialize information. that will
+     * Bundle up a bunch of parameters and initialize information that will
      * be discovered on the fly.
      */
     bounce_info = (BOUNCE_INFO *) mymalloc(sizeof(*bounce_info));
@@ -245,6 +248,8 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
     bounce_info->arrival_time = 0;
     bounce_info->orig_offs = 0;
     bounce_info->message_size = 0;
+    bounce_info->rcpt_buf = rcpt_buf;
+    bounce_info->dsn_buf = dsn_buf;
     bounce_info->log_handle = log_handle;
 
     /*
@@ -278,9 +283,9 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
        msg_fatal("open %s %s: %m", service, queue_id);
 
     /*
-     * Skip over the original message envelope records. If the envelope is
-     * corrupted just send whatever we can (remember this is a best effort,
-     * it does not have to be perfect).
+     * Get time/size/sender information from the original message envelope
+     * records. If the envelope is corrupted just send whatever we can
+     * (remember this is a best effort, it does not have to be perfect).
      * 
      * Lock the file for shared use, so that queue manager leaves it alone after
      * restarting.
@@ -294,20 +299,44 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
                      VSTREAM_PATH(bounce_info->orig_fp));
        while ((rec_type = rec_get(bounce_info->orig_fp,
                                   bounce_info->buf, 0)) > 0) {
+
+           /*
+            * Postfix version dependent: data offset in SIZE record.
+            */
            if (rec_type == REC_TYPE_SIZE) {
-               if (bounce_info->message_size == 0
-                   && (bounce_info->message_size = atol(STR(bounce_info->buf))) < 0)
+               if (bounce_info->message_size == 0)
+                   sscanf(STR(bounce_info->buf), "%ld %ld",
+                          &bounce_info->message_size,
+                          &bounce_info->orig_offs);
+               if (bounce_info->message_size < 0)
                    bounce_info->message_size = 0;
-           } else if (rec_type == REC_TYPE_TIME) {
+               if (bounce_info->orig_offs < 0)
+                   bounce_info->orig_offs = 0;
+           }
+
+           /*
+            * Information for the Arrival-Date: attribute.
+            */
+           else if (rec_type == REC_TYPE_TIME) {
                if (bounce_info->arrival_time == 0
                    && (bounce_info->arrival_time = atol(STR(bounce_info->buf))) < 0)
                    bounce_info->arrival_time = 0;
-           } else if (rec_type == REC_TYPE_FROM) {
+           }
+
+           /*
+            * Information for the X-Postfix-Sender: attribute.
+            */
+           else if (rec_type == REC_TYPE_FROM) {
                quote_822_local_flags(bounce_info->sender,
                                      VSTRING_LEN(bounce_info->buf) ?
                                      STR(bounce_info->buf) :
                                      mail_addr_mail_daemon(), 0);
-           } else if (rec_type == REC_TYPE_MESG) {
+           }
+
+           /*
+            * Backwards compatibility: no data offset in SIZE record.
+            */
+           else if (rec_type == REC_TYPE_MESG) {
                /* XXX Future: sender+recipient after message content. */
                if (VSTRING_LEN(bounce_info->sender) == 0)
                    msg_warn("%s: no sender before message content record",
@@ -315,6 +344,10 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
                bounce_info->orig_offs = vstream_ftell(bounce_info->orig_fp);
                break;
            }
+           if (bounce_info->orig_offs > 0
+               && bounce_info->arrival_time > 0
+               && VSTRING_LEN(bounce_info->sender) > 0)
+               break;
        }
     }
     return (bounce_info);
@@ -331,6 +364,8 @@ BOUNCE_INFO *bounce_mail_init(const char *service,
 {
     BOUNCE_INFO *bounce_info;
     BOUNCE_LOG *log_handle;
+    RCPT_BUF *rcpt_buf;
+    DSN_BUF *dsn_buf;
 
     /*
      * Initialize the bounce_info structure. If the bounce log cannot be
@@ -340,11 +375,18 @@ BOUNCE_INFO *bounce_mail_init(const char *service,
      * job. But if the system IS running out of resources, raise a fatal
      * run-time error and force a backoff.
      */
-    if ((log_handle = bounce_log_open(service, queue_id, O_RDONLY, 0)) == 0
-       && errno != ENOENT)
-       msg_fatal("open %s %s: %m", service, queue_id);
+    if ((log_handle = bounce_log_open(service, queue_id, O_RDONLY, 0)) == 0) {
+       if (errno != ENOENT)
+           msg_fatal("open %s %s: %m", service, queue_id);
+       rcpt_buf = 0;
+       dsn_buf = 0;
+    } else {
+       rcpt_buf = rcpb_create();
+       dsn_buf = dsb_create();
+    }
     bounce_info = bounce_mail_alloc(service, queue_name, queue_id, encoding,
-                                   dsn_envid, template, log_handle);
+                                   dsn_envid, rcpt_buf, dsn_buf,
+                                   template, log_handle);
     return (bounce_info);
 }
 
@@ -354,20 +396,18 @@ BOUNCE_INFO *bounce_mail_one_init(const char *queue_name,
                                          const char *queue_id,
                                          const char *encoding,
                                          const char *dsn_envid,
-                                         RECIPIENT *rcpt,
-                                         DSN *dsn,
+                                         RCPT_BUF *rcpt_buf,
+                                         DSN_BUF *dsn_buf,
                                          BOUNCE_TEMPLATE *template)
 {
     BOUNCE_INFO *bounce_info;
-    BOUNCE_LOG *log_handle;
 
     /*
-     * Initialize the bounce_info structure. Forge a logfile record for just
-     * one recipient.
+     * Initialize the bounce_info structure for just one recipient.
      */
-    log_handle = bounce_log_forge(rcpt, dsn);
     bounce_info = bounce_mail_alloc("none", queue_name, queue_id, encoding,
-                                   dsn_envid, template, log_handle);
+                                   dsn_envid, rcpt_buf, dsn_buf, template,
+                                   (BOUNCE_LOG *) 0);
     return (bounce_info);
 }
 
@@ -375,9 +415,13 @@ BOUNCE_INFO *bounce_mail_one_init(const char *queue_name,
 
 void    bounce_mail_free(BOUNCE_INFO *bounce_info)
 {
-    if (bounce_info->log_handle && bounce_log_close(bounce_info->log_handle))
-       msg_warn("%s: read bounce log %s: %m",
-                bounce_info->queue_id, bounce_info->queue_id);
+    if (bounce_info->log_handle) {
+       if (bounce_log_close(bounce_info->log_handle))
+           msg_warn("%s: read bounce log %s: %m",
+                    bounce_info->queue_id, bounce_info->queue_id);
+       rcpb_free(bounce_info->rcpt_buf);
+       dsb_free(bounce_info->dsn_buf);
+    }
     if (bounce_info->orig_fp && vstream_fclose(bounce_info->orig_fp))
        msg_warn("%s: read message file %s %s: %m",
                 bounce_info->queue_id, bounce_info->queue_name,
@@ -480,6 +524,8 @@ static void bounce_print_wrap(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
 
 int     bounce_recipient_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
 {
+    RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
+    DSN    *dsn = &bounce_info->dsn_buf->dsn;
 
     /*
      * Mask control and non-ASCII characters (done in bounce_log_read()),
@@ -487,16 +533,15 @@ int     bounce_recipient_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
      * piped into other programs. Sort of like TCP Wrapper's safe_finger
      * program.
      */
+#define NON_NULL_EMPTY(s) ((s) && *(s))
+
     post_mail_fputs(bounce, "");
-    if (bounce_info->log_handle->rcpt.orig_addr) {
+    if (NON_NULL_EMPTY(rcpt->orig_addr)) {
        bounce_print_wrap(bounce, bounce_info, "<%s> (expanded from <%s>): %s",
-                         bounce_info->log_handle->rcpt.address,
-                         bounce_info->log_handle->rcpt.orig_addr,
-                         bounce_info->log_handle->dsn.reason);
+                         rcpt->address, rcpt->orig_addr, dsn->reason);
     } else {
        bounce_print_wrap(bounce, bounce_info, "<%s>: %s",
-                         bounce_info->log_handle->rcpt.address,
-                         bounce_info->log_handle->dsn.reason);
+                         rcpt->address, dsn->reason);
     }
     return (vstream_ferror(bounce));
 }
@@ -506,6 +551,7 @@ int     bounce_recipient_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
 int     bounce_diagnostic_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
                                      int notify_filter)
 {
+    RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
     int     count = 0;
 
     /*
@@ -520,13 +566,15 @@ int     bounce_diagnostic_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
     if (bounce_info->log_handle == 0
        || bounce_log_rewind(bounce_info->log_handle)) {
        if (IS_FAILURE_TEMPLATE(bounce_info->template)) {
+           post_mail_fputs(bounce, "");
            post_mail_fputs(bounce, "\t--- Delivery report unavailable ---");
            count = 1;                          /* XXX don't abort */
        }
     } else {
-       while (bounce_log_read(bounce_info->log_handle) != 0) {
-           if (bounce_info->log_handle->rcpt.dsn_notify == 0   /* compat */
-           || (bounce_info->log_handle->rcpt.dsn_notify & notify_filter)) {
+       while (bounce_log_read(bounce_info->log_handle, bounce_info->rcpt_buf,
+                              bounce_info->dsn_buf) != 0) {
+           if (rcpt->dsn_notify == 0           /* compat */
+               || (rcpt->dsn_notify & notify_filter)) {
                count++;
                if (bounce_recipient_log(bounce, bounce_info) != 0)
                    break;
@@ -561,7 +609,7 @@ int     bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
 #if 0
     post_mail_fprintf(bounce, "Received-From-MTA: dns; %s", "whatever");
 #endif
-    if (bounce_info->dsn_envid) {
+    if (NON_NULL_EMPTY(bounce_info->dsn_envid)) {
        post_mail_fprintf(bounce, "Original-Envelope-Id: %s",
                          bounce_info->dsn_envid);
     }
@@ -580,9 +628,11 @@ int     bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
 
 int     bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
 {
+    RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
+    DSN    *dsn = &bounce_info->dsn_buf->dsn;
+
     post_mail_fputs(bounce, "");
-    post_mail_fprintf(bounce, "Final-Recipient: rfc822; %s",
-                     bounce_info->log_handle->rcpt.address);
+    post_mail_fprintf(bounce, "Final-Recipient: rfc822; %s", rcpt->address);
 
     /*
      * XXX DSN
@@ -603,35 +653,29 @@ int     bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
      * Postfix always reports an Original-Recipient field, because it is more
      * more useful and more consistent.
      */
-    if (bounce_info->log_handle->rcpt.dsn_orcpt) {
-       post_mail_fprintf(bounce, "Original-Recipient: %s",
-                         bounce_info->log_handle->rcpt.dsn_orcpt);
-    } else if (bounce_info->log_handle->rcpt.orig_addr) {
+    if (NON_NULL_EMPTY(rcpt->dsn_orcpt)) {
+       post_mail_fprintf(bounce, "Original-Recipient: %s", rcpt->dsn_orcpt);
+    } else if (NON_NULL_EMPTY(rcpt->orig_addr)) {
        post_mail_fprintf(bounce, "Original-Recipient: rfc822; %s",
-                         bounce_info->log_handle->rcpt.orig_addr);
+                         rcpt->orig_addr);
     }
     post_mail_fprintf(bounce, "Action: %s",
                      IS_FAILURE_TEMPLATE(bounce_info->template) ?
-                     "failed" : bounce_info->log_handle->dsn.action);
-    post_mail_fprintf(bounce, "Status: %s",
-                     bounce_info->log_handle->dsn.status);
-    if (bounce_info->log_handle->dsn.mtype
-       && bounce_info->log_handle->dsn.mname)
+                     "failed" : dsn->action);
+    post_mail_fprintf(bounce, "Status: %s", dsn->status);
+    if (NON_NULL_EMPTY(dsn->mtype) && NON_NULL_EMPTY(dsn->mname))
        bounce_print_wrap(bounce, bounce_info, "Remote-MTA: %s; %s",
-                         bounce_info->log_handle->dsn.mtype,
-                         bounce_info->log_handle->dsn.mname);
-    if (bounce_info->log_handle->dsn.dtype
-       && bounce_info->log_handle->dsn.dtext)
+                         dsn->mtype, dsn->mname);
+    if (NON_NULL_EMPTY(dsn->dtype) && NON_NULL_EMPTY(dsn->dtext))
        bounce_print_wrap(bounce, bounce_info, "Diagnostic-Code: %s; %s",
-                         bounce_info->log_handle->dsn.dtype,
-                         bounce_info->log_handle->dsn.dtext);
+                         dsn->dtype, dsn->dtext);
     else
        bounce_print_wrap(bounce, bounce_info, "Diagnostic-Code: X-%s; %s",
-                         bounce_info->mail_name,
-                         bounce_info->log_handle->dsn.reason);
+                         bounce_info->mail_name, dsn->reason);
 #if 0
-    post_mail_fprintf(bounce, "Last-Attempt-Date: %s",
-                     bounce_info->log_handle->log_time);
+    if (dsn->time > 0)
+       post_mail_fprintf(bounce, "Last-Attempt-Date: %s",
+                         mail_date(dsn->time));
 #endif
     if (IS_DELAY_TEMPLATE(bounce_info->template))
        post_mail_fprintf(bounce, "Will-Retry-Until: %s",
@@ -644,6 +688,7 @@ int     bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
 int     bounce_diagnostic_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
                                      int notify_filter)
 {
+    RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
     int     count = 0;
 
     /*
@@ -660,9 +705,10 @@ int     bounce_diagnostic_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
        if (IS_FAILURE_TEMPLATE(bounce_info->template))
            count = 1;                          /* XXX don't abort */
     } else {
-       while (bounce_log_read(bounce_info->log_handle) != 0) {
-           if (bounce_info->log_handle->rcpt.dsn_notify == 0   /* compat */
-           || (bounce_info->log_handle->rcpt.dsn_notify & notify_filter)) {
+       while (bounce_log_read(bounce_info->log_handle, bounce_info->rcpt_buf,
+                              bounce_info->dsn_buf) != 0) {
+           if (rcpt->dsn_notify == 0           /* compat */
+               || (rcpt->dsn_notify & notify_filter)) {
                count++;
                if (bounce_recipient_dsn(bounce, bounce_info) != 0)
                    break;
@@ -752,22 +798,23 @@ int     bounce_original(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
 
 void    bounce_delrcpt(BOUNCE_INFO *bounce_info)
 {
+    RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
+
     if (bounce_info->orig_fp != 0
        && bounce_info->log_handle != 0
        && bounce_log_rewind(bounce_info->log_handle) == 0)
-       while (bounce_log_read(bounce_info->log_handle) != 0)
-           if (bounce_info->log_handle->rcpt.offset > 0)
-               deliver_completed(bounce_info->orig_fp,
-                                 bounce_info->log_handle->rcpt.offset);
+       while (bounce_log_read(bounce_info->log_handle, bounce_info->rcpt_buf,
+                              bounce_info->dsn_buf) != 0)
+           if (rcpt->offset > 0)
+               deliver_completed(bounce_info->orig_fp, rcpt->offset);
 }
 
 /* bounce_delrcpt_one - delete one recipient from original queue file */
 
 void    bounce_delrcpt_one(BOUNCE_INFO *bounce_info)
 {
-    if (bounce_info->orig_fp != 0
-       && bounce_info->log_handle != 0
-       && bounce_info->log_handle->rcpt.offset > 0)
-       deliver_completed(bounce_info->orig_fp,
-                         bounce_info->log_handle->rcpt.offset);
+    RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
+
+    if (bounce_info->orig_fp != 0 && rcpt->offset > 0)
+       deliver_completed(bounce_info->orig_fp, rcpt->offset);
 }
index e1f69dc017047e3b744665628c2c918e85696bd1..9a1913103258c5b4cfa3e6f6cd9431a98ab3f9c6 100644 (file)
@@ -97,7 +97,8 @@ int     bounce_notify_verp(int flags, char *service, char *queue_name,
     int     notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
                                    var_notify_classes);
     char   *postmaster;
-    VSTRING *verp_buf = vstring_alloc(100);
+    VSTRING *verp_buf;
+    VSTRING *new_id;
 
     /*
      * Sanity checks. We must be called only for undeliverable non-bounce
@@ -114,6 +115,27 @@ int     bounce_notify_verp(int flags, char *service, char *queue_name,
     bounce_info = bounce_mail_init(service, queue_name, queue_id,
                                   encoding, dsn_envid, ts->failure);
 
+    /*
+     * If we have no recipient list then we can't send VERP replies. Send
+     * *something* anyway so that the mail is not lost in a black hole.
+     */
+    if (bounce_info->log_handle == 0) {
+       DSN_BUF *dsn_buf = dsb_create();
+       RCPT_BUF *rcpt_buf = rcpb_create();
+
+       dsb_simple(dsn_buf, "5.0.0", "(error report unavailable)");
+       (void) DSN_FROM_DSN_BUF(dsn_buf);
+       vstring_strcpy(rcpt_buf->address, "(recipient address unavailable)");
+       (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf);
+       bounce_status = bounce_one_service(flags, queue_name, queue_id,
+                                          encoding, recipient, dsn_envid,
+                                          dsn_ret, rcpt_buf, dsn_buf, ts);
+       rcpb_free(rcpt_buf);
+       dsb_free(dsn_buf);
+       bounce_mail_free(bounce_info);
+       return (bounce_status);
+    }
+
 #define NULL_SENDER            MAIL_ADDR_EMPTY /* special address */
 #define NULL_TRACE_FLAGS       0
 
@@ -121,20 +143,24 @@ int     bounce_notify_verp(int flags, char *service, char *queue_name,
      * A non-bounce message was returned. Send a single bounce, one per
      * recipient.
      */
-    while (bounce_log_read(bounce_info->log_handle) != 0) {
+    verp_buf = vstring_alloc(100);
+    new_id = vstring_alloc(10);
+    while (bounce_log_read(bounce_info->log_handle, bounce_info->rcpt_buf,
+                          bounce_info->dsn_buf) != 0) {
+       RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
 
        /*
         * Notify the originator, subject to DSN NOTIFY restrictions.
         */
-       if (bounce_info->log_handle->rcpt.dsn_notify != 0       /* compat */
-           && (bounce_info->log_handle->rcpt.dsn_notify & DSN_NOTIFY_FAILURE) == 0) {
+       if (rcpt->dsn_notify != 0               /* compat */
+           && (rcpt->dsn_notify & DSN_NOTIFY_FAILURE) == 0) {
            bounce_status = 0;
        } else {
-           verp_sender(verp_buf, verp_delims, recipient,
-                       bounce_info->log_handle->rcpt.address);
+           verp_sender(verp_buf, verp_delims, recipient, rcpt->address);
            if ((bounce = post_mail_fopen_nowait(NULL_SENDER, STR(verp_buf),
                                                 CLEANUP_FLAG_MASK_INTERNAL,
-                                                NULL_TRACE_FLAGS)) != 0) {
+                                                NULL_TRACE_FLAGS,
+                                                new_id)) != 0) {
 
                /*
                 * Send the bounce message header, some boilerplate text that
@@ -150,6 +176,9 @@ int     bounce_notify_verp(int flags, char *service, char *queue_name,
                    bounce_original(bounce, bounce_info, dsn_ret ?
                                    dsn_ret : DSN_RET_FULL);
                bounce_status = post_mail_fclose(bounce);
+               if (bounce_status == 0)
+                   msg_info("%s: sender non-delivery notification: %s",
+                            queue_id, STR(new_id));
            } else
                bounce_status = 1;
 
@@ -189,7 +218,8 @@ int     bounce_notify_verp(int flags, char *service, char *queue_name,
            if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
                                                 postmaster,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
-                                                NULL_TRACE_FLAGS)) != 0) {
+                                                NULL_TRACE_FLAGS,
+                                                new_id)) != 0) {
                if (bounce_header(bounce, bounce_info, postmaster,
                                  POSTMASTER_COPY) == 0
                    && bounce_recipient_log(bounce, bounce_info) == 0
@@ -197,12 +227,15 @@ int     bounce_notify_verp(int flags, char *service, char *queue_name,
                    && bounce_recipient_dsn(bounce, bounce_info) == 0)
                    bounce_original(bounce, bounce_info, DSN_RET_HDRS);
                postmaster_status = post_mail_fclose(bounce);
+               if (postmaster_status == 0)
+                   msg_info("%s: postmaster non-delivery notification: %s",
+                            queue_id, STR(new_id));
            } else
                postmaster_status = 1;
 
            if (postmaster_status)
-               msg_warn("postmaster notice failed while bouncing to %s",
-                        recipient);
+               msg_warn("%s: postmaster notice failed while bouncing to %s",
+                        queue_id, recipient);
        }
     }
 
@@ -220,6 +253,7 @@ int     bounce_notify_verp(int flags, char *service, char *queue_name,
      */
     bounce_mail_free(bounce_info);
     vstring_free(verp_buf);
+    vstring_free(new_id);
 
     return (bounce_status);
 }
index d6355afba90b8fc2cf21f886847ddffad47cf884..6d6ca629a4d3101dbdc8923b0f15d5885495843d 100644 (file)
@@ -8,7 +8,7 @@
 /*
 /*     int     bounce_one_service(flags, queue_name, queue_id, encoding,
 /*                                     orig_sender, envid, ret,
-/*                                     rcpt, dsn, templates)
+/*                                     rcpt_buf, dsn_buf, templates)
 /*     int     flags;
 /*     char    *queue_name;
 /*     char    *queue_id;
@@ -16,8 +16,8 @@
 /*     char    *orig_sender;
 /*     char    *envid;
 /*     int     ret;
-/*     RECIPIENT *rcpt;
-/*     DSN     *dsn;
+/*     RCPT_BUF *rcpt_buf;
+/*     DSN_BUF *dsn_buf;
 /*     BOUNCE_TEMPLATES *templates;
 /* DESCRIPTION
 /*     This module implements the server side of the bounce_one()
@@ -86,7 +86,7 @@
 int     bounce_one_service(int flags, char *queue_name, char *queue_id,
                                   char *encoding, char *orig_sender,
                                   char *dsn_envid, int dsn_ret,
-                                  RECIPIENT *rcpt, DSN *dsn,
+                                  RCPT_BUF *rcpt_buf, DSN_BUF *dsn_buf,
                                   BOUNCE_TEMPLATES *ts)
 {
     BOUNCE_INFO *bounce_info;
@@ -95,12 +95,14 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
     VSTREAM *bounce;
     int     notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
                                    var_notify_classes);
+    VSTRING *new_id = vstring_alloc(10);
 
     /*
      * Initialize. Open queue file, bounce log, etc.
      */
     bounce_info = bounce_mail_one_init(queue_name, queue_id, encoding,
-                                      dsn_envid, rcpt, dsn, ts->failure);
+                                      dsn_envid, rcpt_buf, dsn_buf,
+                                      ts->failure);
 
 #define NULL_SENDER            MAIL_ADDR_EMPTY /* special address */
 #define NULL_TRACE_FLAGS       0
@@ -146,7 +148,8 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
            if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
                                                 var_2bounce_rcpt,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
-                                                NULL_TRACE_FLAGS)) != 0) {
+                                                NULL_TRACE_FLAGS,
+                                                new_id)) != 0) {
 
                /*
                 * Double bounce to Postmaster. This is the last opportunity
@@ -161,6 +164,9 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
                    && bounce_recipient_dsn(bounce, bounce_info) == 0)
                    bounce_original(bounce, bounce_info, DSN_RET_FULL);
                bounce_status = post_mail_fclose(bounce);
+               if (bounce_status == 0)
+                   msg_info("%s: postmaster non-delivery notification: %s",
+                            queue_id, STR(new_id));
            }
        }
     }
@@ -170,13 +176,16 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
      * restrictions.
      */
     else {
-       if (bounce_info->log_handle->rcpt.dsn_notify != 0       /* compat */
-           && (bounce_info->log_handle->rcpt.dsn_notify & DSN_NOTIFY_FAILURE) == 0) {
+       RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
+
+       if (rcpt->dsn_notify != 0               /* compat */
+           && (rcpt->dsn_notify & DSN_NOTIFY_FAILURE) == 0) {
            bounce_status = 0;
        } else {
            if ((bounce = post_mail_fopen_nowait(NULL_SENDER, orig_sender,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
-                                                NULL_TRACE_FLAGS)) != 0) {
+                                                NULL_TRACE_FLAGS,
+                                                new_id)) != 0) {
 
                /*
                 * Send the bounce message header, some boilerplate text that
@@ -192,6 +201,9 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
                    bounce_original(bounce, bounce_info, dsn_ret ?
                                    dsn_ret : DSN_RET_FULL);
                bounce_status = post_mail_fclose(bounce);
+               if (bounce_status == 0)
+                   msg_info("%s: sender non-delivery notification: %s",
+                            queue_id, STR(new_id));
            }
        }
 
@@ -217,7 +229,8 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
            if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
                                                 var_bounce_rcpt,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
-                                                NULL_TRACE_FLAGS)) != 0) {
+                                                NULL_TRACE_FLAGS,
+                                                new_id)) != 0) {
                if (bounce_header(bounce, bounce_info, var_bounce_rcpt,
                                  POSTMASTER_COPY) == 0
                    && bounce_recipient_log(bounce, bounce_info) == 0
@@ -225,10 +238,13 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
                    && bounce_recipient_dsn(bounce, bounce_info) == 0)
                    bounce_original(bounce, bounce_info, DSN_RET_HDRS);
                postmaster_status = post_mail_fclose(bounce);
+               if (postmaster_status == 0)
+                   msg_info("%s: postmaster non-delivery notification: %s",
+                            queue_id, STR(new_id));
            }
            if (postmaster_status)
-               msg_warn("postmaster notice failed while bouncing to %s",
-                        orig_sender);
+               msg_warn("%s: postmaster notice failed while bouncing to %s",
+                        queue_id, orig_sender);
        }
     }
 
@@ -242,6 +258,7 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
      * Cleanup.
      */
     bounce_mail_free(bounce_info);
+    vstring_free(new_id);
 
     return (bounce_status);
 }
index fb3af89c72c0ccf4e0ab5df4e8d568d8f2c8aad7..0a9bc4d0225d3d0b2cfc5592af17b0841cc08c16 100644 (file)
@@ -26,7 +26,7 @@
  /*
   * bounce_append_service.c
   */
-extern int bounce_append_service(int, char *, char *, RECIPIENT_VAR *, DSN_VAR *);
+extern int bounce_append_service(int, char *, char *, RECIPIENT *, DSN *);
 
  /*
   * bounce_notify_service.c
@@ -51,7 +51,7 @@ extern int bounce_notify_verp(int, char *, char *, char *, char *, char *, char
  /*
   * bounce_one_service.c
   */
-extern int bounce_one_service(int, char *, char *, char *, char *, char *, int, RECIPIENT *, DSN *, BOUNCE_TEMPLATES *);
+extern int bounce_one_service(int, char *, char *, char *, char *, char *, int, RCPT_BUF *, DSN_BUF *, BOUNCE_TEMPLATES *);
 
  /*
   * bounce_cleanup.c
@@ -80,6 +80,8 @@ typedef struct {
     long    orig_offs;                 /* start of content */
     time_t  arrival_time;              /* time of arrival */
     long    message_size;              /* size of content */
+    RCPT_BUF *rcpt_buf;                        /* recipient info */
+    DSN_BUF *dsn_buf;                  /* delivery status info */
     BOUNCE_LOG *log_handle;            /* open logfile */
     char   *mail_name;                 /* $mail_name, cooked */
 } BOUNCE_INFO;
@@ -87,7 +89,7 @@ typedef struct {
  /* */
 
 extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, const char *, const char *, BOUNCE_TEMPLATE *);
-extern BOUNCE_INFO *bounce_mail_one_init(const char *, const char *, const char *, const char *, RECIPIENT *, DSN *, BOUNCE_TEMPLATE *);
+extern BOUNCE_INFO *bounce_mail_one_init(const char *, const char *, const char *, const char *, RCPT_BUF *, DSN_BUF *, BOUNCE_TEMPLATE *);
 extern void bounce_mail_free(BOUNCE_INFO *);
 extern int bounce_header(VSTREAM *, BOUNCE_INFO *, const char *, int);
 extern int bounce_boilerplate(VSTREAM *, BOUNCE_INFO *);
index 381763429edf3b816ab7d70d516e37030073e218..b01f12686c251b2d25377a35eb4c5094f7ada621 100644 (file)
@@ -130,7 +130,7 @@ static const char *def_bounce_delay_body[] = {
     "# THIS IS A WARNING ONLY.  YOU DO NOT NEED TO RESEND YOUR MESSAGE. #",
     "####################################################################",
     "",
-    "Your message could not be delivered for $delay_warning_time_hours hour(s)."
+    "Your message could not be delivered for more than $delay_warning_time_hours hour(s)."
     ,
     "It will be retried until it is $maximal_queue_lifetime_days day(s) old.",
     "",
index 04cf425ce8f1afb7bab1fd6c15a65b49747fa285..747e6f400210ff6ed4faf64da59b3b6ce7c412d6 100644 (file)
@@ -83,6 +83,7 @@ int     bounce_trace_service(int flags, char *service, char *queue_name,
     BOUNCE_INFO *bounce_info;
     int     bounce_status = 1;
     VSTREAM *bounce;
+    VSTRING *new_id = vstring_alloc(10);
     int     count;
 
     /*
@@ -140,7 +141,8 @@ int     bounce_trace_service(int flags, char *service, char *queue_name,
      */
     if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
                                         CLEANUP_FLAG_MASK_INTERNAL,
-                                        NULL_TRACE_FLAGS)) != 0) {
+                                        NULL_TRACE_FLAGS,
+                                        new_id)) != 0) {
        count = -1;
        if (bounce_header(bounce, bounce_info, recipient,
                          NO_POSTMASTER_COPY) == 0
@@ -152,6 +154,9 @@ int     bounce_trace_service(int flags, char *service, char *queue_name,
                                     DSN_NOTIFY_OVERRIDE) > 0) {
            bounce_original(bounce, bounce_info, DSN_RET_HDRS);
            bounce_status = post_mail_fclose(bounce);
+           if (bounce_status == 0)
+               msg_info("%s: sender delivery status notification: %s",
+                        queue_id, STR(new_id));
        } else {
            (void) vstream_fclose(bounce);
            if (count == 0)
@@ -171,6 +176,7 @@ int     bounce_trace_service(int flags, char *service, char *queue_name,
      * Cleanup.
      */
     bounce_mail_free(bounce_info);
+    vstring_free(new_id);
 
     return (bounce_status);
 }
index f446dd6d5f61fd32e1a5fea061c9705852cce57b..98db272ea8fa6a5897f2f26431f41ea85a85aec2 100644 (file)
@@ -92,6 +92,7 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
     VSTREAM *bounce;
     int     notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
                                    var_notify_classes);
+    VSTRING *new_id = vstring_alloc(10);
     char   *postmaster;
     int     count;
 
@@ -164,7 +165,8 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
            if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
                                                 postmaster,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
-                                                NULL_TRACE_FLAGS)) != 0) {
+                                                NULL_TRACE_FLAGS,
+                                                new_id)) != 0) {
 
                /*
                 * Double bounce to Postmaster. This is the last opportunity
@@ -182,6 +184,9 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
                                             DSN_NOTIFY_OVERRIDE) > 0) {
                    bounce_original(bounce, bounce_info, DSN_RET_FULL);
                    bounce_status = post_mail_fclose(bounce);
+                   if (bounce_status == 0)
+                       msg_info("%s: postmaster delay notification: %s",
+                                queue_id, STR(new_id));
                } else {
                    (void) vstream_fclose(bounce);
                    if (count == 0)
@@ -198,7 +203,8 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
     else {
        if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
                                             CLEANUP_FLAG_MASK_INTERNAL,
-                                            NULL_TRACE_FLAGS)) != 0) {
+                                            NULL_TRACE_FLAGS,
+                                            new_id)) != 0) {
 
            /*
             * Send the bounce message header, some boilerplate text that
@@ -216,6 +222,9 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
                                         DSN_NOTIFY_DELAY) > 0) {
                bounce_original(bounce, bounce_info, DSN_RET_HDRS);
                bounce_status = post_mail_fclose(bounce);
+               if (bounce_status == 0)
+                   msg_info("%s: sender delay notification: %s",
+                            queue_id, STR(new_id));
            } else {
                (void) vstream_fclose(bounce);
                if (count == 0)
@@ -244,7 +253,8 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
            if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
                                                 postmaster,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
-                                                NULL_TRACE_FLAGS)) != 0) {
+                                                NULL_TRACE_FLAGS,
+                                                new_id)) != 0) {
                count = -1;
                if (bounce_header(bounce, bounce_info, postmaster,
                                  POSTMASTER_COPY) == 0
@@ -255,6 +265,9 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
                                             DSN_NOTIFY_OVERRIDE) > 0) {
                    bounce_original(bounce, bounce_info, DSN_RET_HDRS);
                    postmaster_status = post_mail_fclose(bounce);
+                   if (postmaster_status == 0)
+                       msg_info("%s: postmaster delay notification: %s",
+                                queue_id, STR(new_id));
                } else {
                    (void) vstream_fclose(bounce);
                    if (count == 0)
@@ -262,8 +275,8 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
                }
            }
            if (postmaster_status)
-               msg_warn("postmaster notice failed while bouncing to %s",
-                        recipient);
+               msg_warn("%s: postmaster notice failed while warning %s",
+                        queue_id, recipient);
        }
     }
 
@@ -271,6 +284,7 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
      * Cleanup.
      */
     bounce_mail_free(bounce_info);
+    vstring_free(new_id);
 
     return (bounce_status);
 }
index 415c4703bc7e1967f65be4460798f24bee2e2850..70562383125a79484af1b7f65a1a0adab5f69c31 100644 (file)
@@ -80,7 +80,7 @@ typedef struct DNS_FIXED {
   * named after the things one can expect to find in a DNS resource record.
   */
 typedef struct DNS_RR {
-    char   *name;                      /* name, mystrdup()ed */
+    char   *qname;                     /* query name, mystrdup()ed */
     char   *rname;                     /* reply name, mystrdup()ed */
     unsigned short type;               /* T_A, T_CNAME, etc. */
     unsigned short class;              /* C_IN, etc. */
index e4dc0f85eaa88fcab6586ce1d35bff008ff49291..e2027ba472b0cb493bcc8efd38396184837c7378 100644 (file)
@@ -6,9 +6,9 @@
 /* SYNOPSIS
 /*     #include <dns.h>
 /*
-/*     DNS_RR  *dns_rr_create(name, rname, type, class, ttl, preference,
+/*     DNS_RR  *dns_rr_create(qname, rname, type, class, ttl, preference,
 /*                             data, data_len)
-/*     const char *name;
+/*     const char *qname;
 /*     const char *rname;
 /*     unsigned short type;
 /*     unsigned short class;
@@ -46,7 +46,7 @@
 /*     information, and maintain lists of DNS resource records.
 /*
 /*     dns_rr_create() creates and initializes one resource record.
-/*     The \fIname\fR field specifies the query name.
+/*     The \fIqname\fR field specifies the query name.
 /*     The \fIrname\fR field specifies the reply name.
 /*     \fIpreference\fR is used for MX records; \fIdata\fR is a null
 /*     pointer or specifies optional resource-specific data;
@@ -59,6 +59,7 @@
 /*
 /*     dns_rr_append() appends a resource record to a (list of) resource
 /*     record(s).
+/*     A null input list is explicitly allowed.
 /*
 /*     dns_rr_sort() sorts a list of resource records into ascending
 /*     order according to a user-specified criterion. The result is the
@@ -71,6 +72,7 @@
 /*
 /*     dns_rr_remove() removes the specified record from the specified list.
 /*     The updated list is the result value.
+/*     The record MUST be a list member.
 /* LICENSE
 /* .ad
 /* .fi
 
 /* dns_rr_create - fill in resource record structure */
 
-DNS_RR *dns_rr_create(const char *name, const char *rname,
+DNS_RR *dns_rr_create(const char *qname, const char *rname,
                              ushort type, ushort class,
                              unsigned int ttl, unsigned pref,
                              const char *data, size_t data_len)
@@ -108,7 +110,7 @@ DNS_RR *dns_rr_create(const char *name, const char *rname,
     DNS_RR *rr;
 
     rr = (DNS_RR *) mymalloc(sizeof(*rr) + data_len - 1);
-    rr->name = mystrdup(name);
+    rr->qname = mystrdup(qname);
     rr->rname = mystrdup(rname);
     rr->type = type;
     rr->class = class;
@@ -128,7 +130,7 @@ void    dns_rr_free(DNS_RR *rr)
     if (rr) {
        if (rr->next)
            dns_rr_free(rr->next);
-       myfree(rr->name);
+       myfree(rr->qname);
        myfree(rr->rname);
        myfree((char *) rr);
     }
@@ -146,7 +148,7 @@ DNS_RR *dns_rr_copy(DNS_RR *src)
      */
     dst = (DNS_RR *) mymalloc(len);
     memcpy((char *) dst, (char *) src, len);
-    dst->name = mystrdup(src->name);
+    dst->qname = mystrdup(src->qname);
     dst->rname = mystrdup(src->rname);
     dst->next = 0;
     return (dst);
index c7be3d6ecd8f5c117438cc6e67a86207255998df..1a13a76138d02051f472066eda82d388c5671440 100644 (file)
@@ -178,8 +178,7 @@ static int deliver_message(DELIVER_REQUEST *request)
        rcpt = request->rcpt_list.info + nrcpt;
        if (rcpt->offset >= 0) {
            status = bounce_append(BOUNCE_FLAGS(request), request->queue_id,
-                                  &request->msg_stats, rcpt, "none",
-                                  &dsn);
+                                  &request->msg_stats, rcpt, "none", &dsn);
            if (status == 0)
                deliver_completed(src, rcpt->offset);
            result |= status;
index e46bf79a671f0cc23f165b92459abe81905bede0..1a6faf28230c56952e4d12845e7350b27adf2d29 100644 (file)
@@ -642,6 +642,7 @@ deliver_pass.o: dsn_buf.h
 deliver_pass.o: mail_params.h
 deliver_pass.o: mail_proto.h
 deliver_pass.o: msg_stats.h
+deliver_pass.o: rcpt_print.h
 deliver_pass.o: recipient_list.h
 deliver_request.o: ../../include/attr.h
 deliver_request.o: ../../include/iostuff.h
@@ -655,12 +656,12 @@ deliver_request.o: ../../include/vstring.h
 deliver_request.o: deliver_request.c
 deliver_request.o: deliver_request.h
 deliver_request.o: dsn.h
-deliver_request.o: dsn_buf.h
 deliver_request.o: dsn_print.h
 deliver_request.o: mail_open_ok.h
 deliver_request.o: mail_proto.h
 deliver_request.o: mail_queue.h
 deliver_request.o: msg_stats.h
+deliver_request.o: rcpt_buf.h
 deliver_request.o: recipient_list.h
 dict_ldap.o: ../../include/argv.h
 dict_ldap.o: ../../include/binhash.h
@@ -763,16 +764,14 @@ dsb_scan.o: ../../include/vstream.h
 dsb_scan.o: ../../include/vstring.h
 dsb_scan.o: dsb_scan.c
 dsb_scan.o: dsb_scan.h
+dsb_scan.o: dsn.h
 dsb_scan.o: dsn_buf.h
 dsb_scan.o: mail_proto.h
 dsn.o: ../../include/msg.h
 dsn.o: ../../include/mymalloc.h
 dsn.o: ../../include/sys_defs.h
-dsn.o: ../../include/vbuf.h
-dsn.o: ../../include/vstring.h
 dsn.o: dsn.c
 dsn.o: dsn.h
-dsn.o: dsn_buf.h
 dsn_attr_map.o: ../../include/attr.h
 dsn_attr_map.o: ../../include/iostuff.h
 dsn_attr_map.o: ../../include/sys_defs.h
@@ -787,6 +786,7 @@ dsn_buf.o: ../../include/mymalloc.h
 dsn_buf.o: ../../include/sys_defs.h
 dsn_buf.o: ../../include/vbuf.h
 dsn_buf.o: ../../include/vstring.h
+dsn_buf.o: dsn.h
 dsn_buf.o: dsn_buf.c
 dsn_buf.o: dsn_buf.h
 dsn_mask.o: ../../include/msg.h
@@ -800,9 +800,7 @@ dsn_print.o: ../../include/iostuff.h
 dsn_print.o: ../../include/sys_defs.h
 dsn_print.o: ../../include/vbuf.h
 dsn_print.o: ../../include/vstream.h
-dsn_print.o: ../../include/vstring.h
 dsn_print.o: dsn.h
-dsn_print.o: dsn_buf.h
 dsn_print.o: dsn_print.c
 dsn_print.o: dsn_print.h
 dsn_print.o: mail_proto.h
@@ -888,7 +886,6 @@ log_adhoc.o: ../../include/vbuf.h
 log_adhoc.o: ../../include/vstream.h
 log_adhoc.o: ../../include/vstring.h
 log_adhoc.o: dsn.h
-log_adhoc.o: dsn_buf.h
 log_adhoc.o: log_adhoc.c
 log_adhoc.o: log_adhoc.h
 log_adhoc.o: mail_params.h
@@ -1041,6 +1038,7 @@ mail_copy.o: ../../include/vbuf.h
 mail_copy.o: ../../include/vstream.h
 mail_copy.o: ../../include/vstring.h
 mail_copy.o: ../../include/vstring_vstream.h
+mail_copy.o: dsn.h
 mail_copy.o: dsn_buf.h
 mail_copy.o: mail_addr.h
 mail_copy.o: mail_copy.c
@@ -1217,7 +1215,6 @@ mark_corrupt.o: ../../include/vstream.h
 mark_corrupt.o: ../../include/vstring.h
 mark_corrupt.o: deliver_request.h
 mark_corrupt.o: dsn.h
-mark_corrupt.o: dsn_buf.h
 mark_corrupt.o: mail_params.h
 mark_corrupt.o: mail_queue.h
 mark_corrupt.o: mark_corrupt.c
@@ -1249,6 +1246,7 @@ mbox_open.o: ../../include/vstream.h
 mbox_open.o: ../../include/vstring.h
 mbox_open.o: deliver_flock.h
 mbox_open.o: dot_lockfile.h
+mbox_open.o: dsn.h
 mbox_open.o: dsn_buf.h
 mbox_open.o: mbox_conf.h
 mbox_open.o: mbox_open.c
@@ -1266,7 +1264,14 @@ mime_state.o: mail_params.h
 mime_state.o: mime_state.c
 mime_state.o: mime_state.h
 mime_state.o: rec_type.h
+mkmap_cdb.o: ../../include/argv.h
+mkmap_cdb.o: ../../include/dict.h
+mkmap_cdb.o: ../../include/dict_cdb.h
+mkmap_cdb.o: ../../include/mymalloc.h
 mkmap_cdb.o: ../../include/sys_defs.h
+mkmap_cdb.o: ../../include/vbuf.h
+mkmap_cdb.o: ../../include/vstream.h
+mkmap_cdb.o: mkmap.h
 mkmap_cdb.o: mkmap_cdb.c
 mkmap_db.o: ../../include/argv.h
 mkmap_db.o: ../../include/dict.h
@@ -1407,6 +1412,7 @@ pipe_command.o: ../../include/timed_wait.h
 pipe_command.o: ../../include/vbuf.h
 pipe_command.o: ../../include/vstream.h
 pipe_command.o: ../../include/vstring.h
+pipe_command.o: dsn.h
 pipe_command.o: dsn_buf.h
 pipe_command.o: dsn_util.h
 pipe_command.o: mail_copy.h
@@ -1453,6 +1459,7 @@ rcpt_buf.o: ../../include/vstring.h
 rcpt_buf.o: mail_proto.h
 rcpt_buf.o: rcpt_buf.c
 rcpt_buf.o: rcpt_buf.h
+rcpt_buf.o: recipient_list.h
 rcpt_print.o: ../../include/attr.h
 rcpt_print.o: ../../include/iostuff.h
 rcpt_print.o: ../../include/sys_defs.h
@@ -1754,7 +1761,6 @@ verify.o: ../../include/vstream.h
 verify.o: ../../include/vstring.h
 verify.o: deliver_request.h
 verify.o: dsn.h
-verify.o: dsn_buf.h
 verify.o: log_adhoc.h
 verify.o: mail_params.h
 verify.o: mail_proto.h
@@ -1773,7 +1779,6 @@ verify_clnt.o: ../../include/vstring.h
 verify_clnt.o: clnt_stream.h
 verify_clnt.o: deliver_request.h
 verify_clnt.o: dsn.h
-verify_clnt.o: dsn_buf.h
 verify_clnt.o: mail_params.h
 verify_clnt.o: mail_proto.h
 verify_clnt.o: msg_stats.h
index bde6451c14d399ee895b61b4f7e1d25a26929ca3..31f7398d24648ed0d70eb969fbcec491ef9cf594 100644 (file)
@@ -20,6 +20,7 @@
   * Global library.
   */
 #include <deliver_request.h>
+#include <dsn_buf.h>
 
  /*
   * Client interface.
index 0fac7f986b0260a396fd39df641c5a6863094890..d93198609ee9a683eb36a6227c5be47e78fb5d21 100644 (file)
@@ -8,9 +8,7 @@
 /*
 /*     typedef struct {
 /* .in +4
-/*         /* Non-null: rcpt.address, dsn.{status,action,text} */
-/*         RECIPIENT   rcpt;
-/*         DSN         dsn;
+/*         /* No public members. */
 /* .in -4
 /*     } BOUNCE_LOG;
 /*
 /*     int     flags;
 /*     mode_t  mode;
 /*
-/*     BOUNCE_LOG *bounce_log_read(bp)
+/*     BOUNCE_LOG *bounce_log_read(bp, rcpt, dsn)
 /*     BOUNCE_LOG *bp;
+/*     RCPT_BUF *rcpt;
+/*     DSN_BUF *dsn;
 /*
 /*     void    bounce_log_rewind(bp)
 /*     BOUNCE_LOG *bp;
 /*
-/*     BOUNCE_LOG *bounce_log_forge(rcpt, dsn)
-/*     RECIPIENT *rcpt;
-/*     DSN     *dsn;
-/*
 /*     void    bounce_log_close(bp)
 /*     BOUNCE_LOG *bp;
 /* DESCRIPTION
 /*     are marked as done). The result is 0 in case of success, -1 in case
 /*     of problems.
 /*
-/*     bounce_log_forge() forges one recipient status record
-/*     without actually accessing a logfile. No copy is made
-/*     of strings with recipient or status information.
-/*     The result cannot be used for any logfile access operation
-/*     and must be disposed of by passing it to bounce_log_close().
-/*
 /*     bounce_log_close() closes an open bounce or defer logfile and
 /*     releases memory for the specified handle. The result is non-zero
 /*     in case of I/O errors.
 /*     File open flags, as with open(2).
 /* .IP mode
 /*     File permissions, as with open(2).
-/* .PP
-/*     Recipient results:
-/* .IP address
-/*     The final recipient address in RFC 822 external form, or <>
-/*     in case of the null recipient address.
-/* .IP dsn_orcpt
-/*     Null pointer or DSN original recipient.
-/* .IP orig_addr
-/*      Null pointer or the original recipient address in RFC 822
-/*     external form.
-/* .IP dsn_notify
-/*     Zero or DSN notify flags.
-/* .IP offset
-/*     Zero or queue file offset of recipient record.
-/* .PP
-/*     Delivery status results:
-/* .IP dsn_status
-/*     RFC 3463-compatible enhanced status code (digit.digits.digits).
-/* .IP dsn_action
-/*     "delivered", "failed", "delayed" and so on.
-/* .IP reason
-/*     The text that explains why the recipient was undeliverable.
-/* .IP dsn_dtype
-/*     Null pointer or RFC 3464-compatible diagnostic type.
-/* .IP dsn_dtext
-/*     Null pointer or RFC 3464-compatible diagnostic text.
-/* .IP dsn_mtype
-/*     Null pointer or RFC 3464-compatible remote MTA type.
-/* .IP dsn_mname
-/*     Null pointer or RFC 3464-compatible remote MTA name.
-/* .PP
-/*     Other fields will be added as the code evolves.
+/* .IP rcpt
+/*     Recipient buffer. The RECIPIENT member is updated.
+/* .IP dsn
+/*     Delivery status information. The DSN member is updated.
 /* LICENSE
 /* .ad
 /* .fi
 #include <mail_proto.h>
 #include <mail_queue.h>
 #include <dsn_mask.h>
-#include <recipient_list.h>
-#include <dsn.h>
 #include <bounce_log.h>
 
 /* Application-specific. */
@@ -160,10 +120,8 @@ BOUNCE_LOG *bounce_log_open(const char *queue_name, const char *queue_id,
 #define STREQ(x,y)     (strcmp((x),(y)) == 0)
 
     /*
-     * TODO: peek at the first byte to see if this is an old-style log
-     * (<recipient>: text) or a new-style extensible log with multiple
-     * attributes per recipient. That would not help during a transition from
-     * old to new style, where one can expect to find mixed format files.
+     * Logfiles may contain a mixture of old-style (<recipient>: text) and
+     * new-style entries with multiple attributes per recipient.
      * 
      * Kluge up default DSN status and action for old-style logfiles.
      */
@@ -173,8 +131,6 @@ BOUNCE_LOG *bounce_log_open(const char *queue_name, const char *queue_id,
        bp = (BOUNCE_LOG *) mymalloc(sizeof(*bp));
        bp->fp = fp;
        bp->buf = vstring_alloc(100);
-       bp->rcpt_buf = rcpb_create();
-       bp->dsn_buf = dsb_create();
        if (STREQ(queue_name, MAIL_QUEUE_DEFER)) {
            bp->compat_status = mystrdup("4.0.0");
            bp->compat_action = mystrdup("delayed");
@@ -188,7 +144,8 @@ BOUNCE_LOG *bounce_log_open(const char *queue_name, const char *queue_id,
 
 /* bounce_log_read - read one record from bounce log file */
 
-BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
+BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf,
+                                   DSN_BUF *dsn_buf)
 {
     char   *recipient;
     char   *text;
@@ -202,24 +159,11 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
 #define FOUND  1                               /* in logfile entry */
 
     /*
-     * Initialize. See also DSN_FROM_DSN_BUF() and bounce_log_forge() for
-     * null and non-null fields.
+     * Initialize.
      */
     state = START;
-    bp->rcpt.address = "(recipient address unavailable)";
-    bp->dsn.status = bp->compat_status;
-    bp->dsn.action = bp->compat_action;
-    bp->dsn.reason = "(description unavailable)";
-
-    bp->rcpt.orig_addr = 0;
-    bp->rcpt.dsn_orcpt = 0;
-    bp->rcpt.dsn_notify = 0;
-    bp->rcpt.offset = 0;
-
-    bp->dsn.dtype = 0;
-    bp->dsn.dtext = 0;
-    bp->dsn.mtype = 0;
-    bp->dsn.mname = 0;
+    rcpb_reset(rcpt_buf);
+    dsb_reset(dsn_buf);
 
     /*
      * Support mixed logfile formats to make migration easier. The same file
@@ -227,7 +171,9 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
      * backwards compatibility, we even have old format followed by new
      * format within the same logfile entry!
      */
-    while ((vstring_get_nonl(bp->buf, bp->fp) != VSTREAM_EOF)) {
+    for (;;) {
+       if ((vstring_get_nonl(bp->buf, bp->fp) == VSTREAM_EOF))
+           return (0);
 
        /*
         * Logfile entries are separated by blank lines. Even the old ad-hoc
@@ -237,7 +183,7 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
         */
        if (STR(bp->buf)[0] == 0) {
            if (state == FOUND)
-               return (bp);
+               break;
            state = START;
            continue;
        }
@@ -259,7 +205,7 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
            char   *name;
            char   *value;
            long    offset;
-           long    notify;
+           int     notify;
 
            /*
             * Split into name and value.
@@ -273,51 +219,33 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
             * Save attribute value.
             */
            if (STREQ(name, MAIL_ATTR_RECIP)) {
-               bp->rcpt.address =
-                   STR(vstring_strcpy(bp->rcpt_buf->address, *value ?
-                                      value : "(MAILER-DAEMON)"));
+               vstring_strcpy(rcpt_buf->address, *value ?
+                              value : "(MAILER-DAEMON)");
            } else if (STREQ(name, MAIL_ATTR_ORCPT)) {
-               bp->rcpt.orig_addr =
-                   STR(vstring_strcpy(bp->rcpt_buf->orig_addr, *value ?
-                                      value : "(MAILER-DAEMON)"));
+               vstring_strcpy(rcpt_buf->orig_addr, *value ?
+                              value : "(MAILER-DAEMON)");
            } else if (STREQ(name, MAIL_ATTR_DSN_ORCPT)) {
-               if (*value)
-                   bp->rcpt.dsn_orcpt =
-                       STR(vstring_strcpy(bp->rcpt_buf->dsn_orcpt, value));
+               vstring_strcpy(rcpt_buf->dsn_orcpt, value);
            } else if (STREQ(name, MAIL_ATTR_DSN_NOTIFY)) {
                if ((notify = atoi(value)) > 0 && DSN_NOTIFY_OK(notify))
-                   bp->rcpt.dsn_notify = notify;
+                   rcpt_buf->dsn_notify = notify;
            } else if (STREQ(name, MAIL_ATTR_OFFSET)) {
                if ((offset = atol(value)) > 0)
-                   bp->rcpt.offset = offset;
+                   rcpt_buf->offset = offset;
            } else if (STREQ(name, MAIL_ATTR_DSN_STATUS)) {
-               if (*value)
-                   bp->dsn.status =
-                       STR(vstring_strcpy(bp->dsn_buf->status, value));
+               vstring_strcpy(dsn_buf->status, value);
            } else if (STREQ(name, MAIL_ATTR_DSN_ACTION)) {
-               if (*value)
-                   bp->dsn.action =
-                       STR(vstring_strcpy(bp->dsn_buf->action, value));
+               vstring_strcpy(dsn_buf->action, value);
            } else if (STREQ(name, MAIL_ATTR_DSN_DTYPE)) {
-               if (*value)
-                   bp->dsn.dtype =
-                       STR(vstring_strcpy(bp->dsn_buf->dtype, value));
+               vstring_strcpy(dsn_buf->dtype, value);
            } else if (STREQ(name, MAIL_ATTR_DSN_DTEXT)) {
-               if (*value)
-                   bp->dsn.dtext =
-                       STR(vstring_strcpy(bp->dsn_buf->dtext, value));
+               vstring_strcpy(dsn_buf->dtext, value);
            } else if (STREQ(name, MAIL_ATTR_DSN_MTYPE)) {
-               if (*value)
-                   bp->dsn.mtype =
-                       STR(vstring_strcpy(bp->dsn_buf->mtype, value));
+               vstring_strcpy(dsn_buf->mtype, value);
            } else if (STREQ(name, MAIL_ATTR_DSN_MNAME)) {
-               if (*value)
-                   bp->dsn.mname =
-                       STR(vstring_strcpy(bp->dsn_buf->mname, value));
+               vstring_strcpy(dsn_buf->mname, value);
            } else if (STREQ(name, MAIL_ATTR_WHY)) {
-               if (*value)
-                   bp->dsn.reason =
-                       STR(vstring_strcpy(bp->dsn_buf->reason, value));
+               vstring_strcpy(dsn_buf->reason, value);
            } else {
                msg_warn("%s: unknown attribute name: %s, ignored",
                         VSTREAM_PATH(bp->fp), name);
@@ -340,9 +268,8 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
            continue;
        }
        *cp = 0;
-       vstring_strcpy(bp->rcpt_buf->address, *recipient ?
+       vstring_strcpy(rcpt_buf->address, *recipient ?
                       recipient : "(MAILER-DAEMON)");
-       bp->rcpt.address = STR(bp->rcpt_buf->address);
 
        /*
         * Find the text that explains why mail was not deliverable.
@@ -350,69 +277,26 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
        text = cp + 2;
        while (*text && ISSPACE(*text))
            text++;
-       vstring_strcpy(bp->dsn_buf->reason, text);
-       if (*text)
-           bp->dsn.reason = STR(bp->dsn_buf->reason);
+       vstring_strcpy(dsn_buf->reason, text);
     }
-    return (0);
-}
-
-/* bounce_log_forge - forge one recipient status record */
-
-BOUNCE_LOG *bounce_log_forge(RECIPIENT *rcpt, DSN *dsn)
-{
-    BOUNCE_LOG *bp;
-
-    /*
-     * Create a partial record. No point copying information that doesn't
-     * need to be.
-     */
-    bp = (BOUNCE_LOG *) mymalloc(sizeof(*bp));
-    bp->fp = 0;
-    bp->buf = 0;
-    bp->rcpt_buf = 0;
-    bp->dsn_buf = 0;
-    bp->compat_status = 0;
-    bp->compat_action = 0;
-
-    bp->rcpt = *rcpt;
-    bp->dsn = *dsn;
-
-    /*
-     * Finalize. See also DSN_FROM_DSN_BUF() and bounce_log_read() for null
-     * and non-null fields.
-     */
-#define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0)
-#define EMPTY_STRING(s)        ((s) != 0 && *(s) == 0)
 
     /*
-     * Replace null pointers and empty strings by place holders.
+     * Specify place holders for missing fields. See also DSN_FROM_DSN_BUF()
+     * and RECIPIENT_FROM_RCPT_BUF() for null and non-null fields.
      */
-    if (bp->rcpt.address == 0)
-       bp->rcpt.address = "(recipient address unavailable)";
-    if (NULL_OR_EMPTY(bp->dsn.status))
-       bp->dsn.status = "(unavailable)";
-    if (NULL_OR_EMPTY(bp->dsn.action))
-       bp->dsn.action = "(unavailable)";
-    if (NULL_OR_EMPTY(bp->dsn.reason))
-       bp->dsn.reason = "(description unavailable)";
-
-    /*
-     * Replace empty strings by null pointers.
-     */
-    if (EMPTY_STRING(bp->rcpt.orig_addr))
-       bp->rcpt.orig_addr = 0;
-    if (EMPTY_STRING(bp->rcpt.dsn_orcpt))
-       bp->rcpt.dsn_orcpt = 0;
-
-    if (EMPTY_STRING(bp->dsn.dtype))
-       bp->dsn.dtype = 0;
-    if (EMPTY_STRING(bp->dsn.dtext))
-       bp->dsn.dtext = 0;
-    if (EMPTY_STRING(bp->dsn.mtype))
-       bp->dsn.mtype = 0;
-    if (EMPTY_STRING(bp->dsn.mname))
-       bp->dsn.mname = 0;
+#define BUF_NODATA(buf)                (STR(buf)[0] == 0)
+#define BUF_ASSIGN(buf, text)  vstring_strcpy((buf), (text))
+
+    if (BUF_NODATA(rcpt_buf->address))
+       BUF_ASSIGN(rcpt_buf->address, "(recipient address unavailable)");
+    if (BUF_NODATA(dsn_buf->status))
+       BUF_ASSIGN(dsn_buf->status, bp->compat_status);
+    if (BUF_NODATA(dsn_buf->action))
+       BUF_ASSIGN(dsn_buf->action, bp->compat_action);
+    if (BUF_NODATA(dsn_buf->reason))
+       BUF_ASSIGN(dsn_buf->reason, "(description unavailable)");
+    (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf);
+    (void) DSN_FROM_DSN_BUF(dsn_buf);
     return (bp);
 }
 
@@ -422,20 +306,10 @@ int     bounce_log_close(BOUNCE_LOG *bp)
 {
     int     ret;
 
-    if (bp->fp)
-       ret = vstream_fclose(bp->fp);
-    else
-       ret = 0;
-    if (bp->buf)
-       vstring_free(bp->buf);
-    if (bp->rcpt_buf)
-       rcpb_free(bp->rcpt_buf);
-    if (bp->dsn_buf)
-       dsb_free(bp->dsn_buf);
-    if (bp->compat_status)
-       myfree(bp->compat_status);
-    if (bp->compat_action)
-       myfree(bp->compat_action);
+    ret = vstream_fclose(bp->fp);
+    vstring_free(bp->buf);
+    myfree(bp->compat_status);
+    myfree(bp->compat_action);
     myfree((char *) bp);
 
     return (ret);
index 235772ed306fcd1d03a16e1568235b1c78073f85..03b78b2c4638aa3b6886ec1c897335b69b3750fa 100644 (file)
 #include <recipient_list.h>
 #include <rcpt_buf.h>
 #include <dsn_buf.h>
-#include <dsn.h>
 
  /*
   * External interface.
   */
 typedef struct {
-    /* Private. */
     VSTREAM *fp;                       /* open file */
     VSTRING *buf;                      /* I/O buffer */
-    RCPT_BUF *rcpt_buf;                        /* recipient info */
-    DSN_BUF *dsn_buf;                  /* delivery status */
     char    *compat_status;            /* old logfile compatibility */
     char    *compat_action;            /* old logfile compatibility */
-    /* Public. */
-    RECIPIENT rcpt;                    /* recipient info */
-    DSN     dsn;                       /* delivery status */
 } BOUNCE_LOG;
 
 extern BOUNCE_LOG *bounce_log_open(const char *, const char *, int, mode_t);
-extern BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *);
+extern BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *, RCPT_BUF *, DSN_BUF *);
 extern BOUNCE_LOG *bounce_log_delrcpt(BOUNCE_LOG *);
-extern BOUNCE_LOG *bounce_log_forge(RECIPIENT *, DSN *);
 extern int bounce_log_close(BOUNCE_LOG *);
 
 #define bounce_log_rewind(bp) vstream_fseek((bp)->fp, 0L, SEEK_SET)
index 91675b495741b43d5e57f3528d1ca2a41ad3abcd..8938e6a884c5e2adf746daf8648c786034c95ccf 100644 (file)
@@ -69,6 +69,7 @@
 #include <deliver_pass.h>
 #include <dsb_scan.h>
 #include <defer.h>
+#include <rcpt_print.h>
 
 #define DELIVER_PASS_DEFER     1
 #define DELIVER_PASS_UNKNOWN   2
@@ -116,12 +117,10 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request,
             ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, request->sasl_username,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, request->sasl_sender,
             ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, request->rewrite_context,
-              ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, rcpt->offset,
-              ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt,
-              ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify,
-              ATTR_TYPE_STR, MAIL_ATTR_ORCPT, rcpt->orig_addr,
-              ATTR_TYPE_STR, MAIL_ATTR_RECIP, rcpt->address,
-              ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0,
+              ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, 1,
+              ATTR_TYPE_END);
+    attr_print(stream, ATTR_FLAG_NONE,
+              ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt,
               ATTR_TYPE_END);
 
     if (vstream_fflush(stream)) {
@@ -192,17 +191,13 @@ int     deliver_pass(const char *class, const char *service,
      */
     if (deliver_pass_initial_reply(stream) != 0
        || deliver_pass_send_request(stream, request, nexthop, rcpt) != 0) {
-       DSN_SMTP(&dsn, "4.3.0",
-                "451 mail transport unavailable",
-                "mail transport unavailable");
+       (void) DSN_SIMPLE(&dsn, "4.3.0", "mail transport unavailable");
        status = defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
                              request->queue_id, &request->msg_stats,
                              rcpt, "none", &dsn);
     } else if ((status = deliver_pass_final_reply(stream, dsb))
               == DELIVER_PASS_UNKNOWN) {
-       DSN_SMTP(&dsn, "4.3.0",
-                "451 unknown mail transport error",
-                "unknown mail transport error");
+       (void) DSN_SIMPLE(&dsn, "4.3.0", "unknown mail transport error");
        status = defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
                              request->queue_id, &request->msg_stats,
                              rcpt, "none", &dsn);
@@ -227,6 +222,11 @@ int     deliver_pass_all(const char *class, const char *service,
     RECIPIENT *rcpt;
     int     status = 0;
 
+    /*
+     * XXX We should find out if the target transport can handle
+     * multi-recipient requests. Unfortunately such code is hard to test,
+     * rarely used, and therefore will be buggy.
+     */
     list = &request->rcpt_list;
     for (rcpt = list->info; rcpt < list->info + list->len; rcpt++)
        status |= deliver_pass(class, service, request, rcpt);
index 1391e5d7c3f1c5299319c2381000e8279a613500..029d2fdeff85c0e743e7446ff5082e6536477781 100644 (file)
 #include "dsn.h"
 #include "dsn_print.h"
 #include "deliver_request.h"
+#include "rcpt_buf.h"
 
 /* deliver_request_initial - send initial status code */
 
@@ -143,13 +144,12 @@ static int deliver_request_final(VSTREAM *stream, DELIVER_REQUEST *request,
 {
     DSN    *hop_status;
     int     err;
+    /* XXX This DSN structure initialization bypasses integrity checks. */
     static DSN dummy_dsn = {"", "", "", "", "", "", ""};
 
     /*
      * Send the status and the optional reason.
      */
-#define STRING_OR_EMPTY(s) ((s) ? (s) : "")
-
     if ((hop_status = request->hop_status) == 0)
        hop_status = &dummy_dsn;
     if (msg_verbose)
@@ -185,8 +185,6 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
     static VSTRING *queue_id;
     static VSTRING *nexthop;
     static VSTRING *encoding;
-    static VSTRING *dsn_orcpt;
-    static VSTRING *orig_addr;
     static VSTRING *address;
     static VSTRING *client_name;
     static VSTRING *client_addr;
@@ -197,9 +195,9 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
     static VSTRING *sasl_sender;
     static VSTRING *rewrite_context;
     static VSTRING *dsn_envid;
-    long    offset;
+    static RCPT_BUF *rcpt_buf;
+    int     rcpt_count;
     int     dsn_ret;
-    int     dsn_notify;
 
     /*
      * Initialize. For some reason I wanted to allow for multiple instances
@@ -211,9 +209,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
        queue_id = vstring_alloc(10);
        nexthop = vstring_alloc(10);
        encoding = vstring_alloc(10);
-       dsn_orcpt = vstring_alloc(10);
-       orig_addr = vstring_alloc(10);
-       address = vstring_alloc(10);
+        address = vstring_alloc(10);
        client_name = vstring_alloc(10);
        client_addr = vstring_alloc(10);
        client_proto = vstring_alloc(10);
@@ -223,13 +219,14 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
        sasl_sender = vstring_alloc(10);
        rewrite_context = vstring_alloc(10);
        dsn_envid = vstring_alloc(10);
+       rcpt_buf = rcpb_create();
     }
 
     /*
      * Extract the queue file name, data offset, and sender address. Abort
      * the conversation when they send bad information.
      */
-    if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
+    if (attr_scan(stream, ATTR_FLAG_STRICT,
                  ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request->flags,
                  ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name,
                  ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
@@ -249,7 +246,8 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
                  ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, sasl_username,
                  ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, sasl_sender,
                  ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, rewrite_context,
-                 ATTR_TYPE_END) != 19) {
+                 ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, &rcpt_count,
+                 ATTR_TYPE_END) != 20) {
        msg_warn("%s: error receiving common attributes", myname);
        return (-1);
     }
@@ -281,28 +279,18 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
      * Extract the recipient offset and address list. Skip over any
      * attributes from the sender that we do not understand.
      */
-    for (;;) {
-       if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
-                     ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &offset,
+    while (rcpt_count-- > 0) {
+       if (attr_scan(stream, ATTR_FLAG_STRICT,
+                     ATTR_TYPE_FUNC, rcpb_scan, (void *) rcpt_buf,
                      ATTR_TYPE_END) != 1) {
-           msg_warn("%s: error receiving offset attribute", myname);
-           return (-1);
-       }
-       if (offset == 0)
-           break;
-       if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
-                     ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, dsn_orcpt,
-                     ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, &dsn_notify,
-                     ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_addr,
-                     ATTR_TYPE_STR, MAIL_ATTR_RECIP, address,
-                     ATTR_TYPE_END) != 4) {
            msg_warn("%s: error receiving recipient attributes", myname);
            return (-1);
        }
-       recipient_list_add(&request->rcpt_list, offset,
-                          vstring_str(dsn_orcpt), dsn_notify,
-                          vstring_str(orig_addr),
-                          vstring_str(address));
+       recipient_list_add(&request->rcpt_list, rcpt_buf->offset,
+                          vstring_str(rcpt_buf->dsn_orcpt),
+                          rcpt_buf->dsn_notify,
+                          vstring_str(rcpt_buf->orig_addr),
+                          vstring_str(rcpt_buf->address));
     }
     if (request->rcpt_list.len <= 0) {
        msg_warn("%s: no recipients in delivery request for destination %s",
index b233f56b0c89f1bcb7896bb20d525b4f859d097c..aa78c3b9c57e44647182535a1e7994ba168dd6d5 100644 (file)
@@ -8,17 +8,17 @@
 /*
 /*     typedef struct {
 /* .in +4
-/*             char *status;   /* RFC 3463 status */
-/*             char *action;   /* null or RFC 3464 action */
-/*             char *reason;   /* human-readable text */
-/*             char *dtype;    /* null or diagnostic type */
-/*             char *dtext;    /* null or diagnostic code */
-/*             char *mtype;    /* null or MTA type */
-/*             char *mname;    /* null or remote MTA */
+/*             const char *status;     /* RFC 3463 status */
+/*             const char *action;     /* null or RFC 3464 action */
+/*             const char *reason;     /* human-readable text */
+/*             const char *dtype;      /* null or diagnostic type */
+/*             const char *dtext;      /* null or diagnostic code */
+/*             const char *mtype;      /* null or MTA type */
+/*             const char *mname;      /* null or remote MTA */
 /* .in -4
 /*     } DSN;
 /*
-/*     DSN *create(status, action, reason, dtype, dtext, mtype, mname)
+/*     DSN     *create(status, action, reason, dtype, dtext, mtype, mname)
 /*     const char *status;
 /*     const char *action;
 /*     const char *reason;
 /*     const char *mtype;
 /*     const char *mname;
 /*
-/*     DSN *copy(dsn)
-/*     DSN *dsn;
+/*     DSN     *DSN_COPY(dsn)
+/*     DSN     *dsn;
 /*
-/*     DSN *DSN_ASSIGN(dsn, status, action, reason, dtype, dtext, mtype, mname)
-/*     DSN *dsn;
+/*     void    dsn_free(dsn)
+/*     DSN     *dsn;
+/*
+/*     DSN     *DSN_ASSIGN(dsn, status, action, reason, dtype, dtext, 
+/*                                             mtype, mname)
+/*     DSN     *dsn;
 /*     const char *status;
 /*     const char *action;
 /*     const char *reason;
 /*     const char *mtype;
 /*     const char *mname;
 /*
-/*     DSN *DSN_SIMPLE(dsn, status, action, reason)
-/*     DSN *dsn;
+/*     DSN     *DSN_SIMPLE(dsn, status, action, reason)
+/*     DSN     *dsn;
 /*     const char *status;
 /*     const char *action;
 /*     const char *reason;
-/*
-/*     DSN *DSN_SMTP(dsn, status, action, smtp_dtext, reason)
-/*     DSN *dsn;
-/*     const char *status;
-/*     const char *action;
-/*     const char *smtp_dtext;
-/*     const char *reason;
-/*
-/*     void    dsn_free(dsn)
-/*     DSN *dsn;
 /* DESCRIPTION
 /*     This module maintains delivery error information. For a
 /*     description of structure field members see "Arguments"
 /*     for stack-based short-lived storage.
 /*
 /*     DSN_SIMPLE() takes the minimally required subset of all the
-/*     parameters and resets the rest to zero.
-/*
-/*     DSN_SMTP() handles the common case of an SMTP-type
-/*     diagnostic code that was generated by the local MTA.
+/*     attributes and sets the rest to empty strings.
+/*     This is a wrapper around the DSN_ASSIGN() macro.
 /*
 /*     Arguments:
 /* .IP reason
@@ -88,8 +80,8 @@
 /* .IP status
 /*     Enhanced status code as specified in RFC 3463.
 /* .IP action
-/*     Action as defined in RFC 3464. If null, a default action
-/*     is chosen.
+/*     DSN_NO_ACTION, empty string, or action as defined in RFC 3464.
+/*     If no action is specified, a default action is chosen.
 /* .IP dtype
 /*     DSN_NO_DTYPE, empty string, or diagnostic code type as
 /*     specified in RFC 3464.
 /*     DSN_NO_MNAME, empty string, or remote MTA as specified in
 /*     RFC 3464.
 /* DIAGNOSTICS
-/*     Panic: null status or reason.
+/*     Panic: null or empty status or reason.
 /*     Fatal: out of memory.
 /* LICENSE
 /* .ad
@@ -140,8 +132,13 @@ DSN    *dsn_create(const char *status, const char *action, const char *reason,
     dsn = (DSN *) mymalloc(sizeof(*dsn));
 
     /*
-     * Status and reason must not be null. Other members may be null pointers
-     * or empty strings. Null/empty members are represented as null pointers.
+     * Status and reason must not be empty. Other members may be empty
+     * strings.
+     * 
+     * Early implementations represented unavailable information with null
+     * pointers. This resulted in code that was difficult to maintain. We now
+     * use empty strings instead. For safety sake we keep the null pointer
+     * test for input, but we always convert to empty string on output.
      */
 #define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0)
 
@@ -151,7 +148,7 @@ DSN    *dsn_create(const char *status, const char *action, const char *reason,
        dsn->status = mystrdup(status);
 
     if (NULL_OR_EMPTY(action))
-       dsn->action = 0;
+       dsn->action = mystrdup("");
     else
        dsn->action = mystrdup(action);
 
@@ -161,15 +158,15 @@ DSN    *dsn_create(const char *status, const char *action, const char *reason,
        dsn->reason = mystrdup(reason);
 
     if (NULL_OR_EMPTY(dtype) || NULL_OR_EMPTY(dtext)) {
-       dsn->dtype = 0;
-       dsn->dtext = 0;
+       dsn->dtype = mystrdup("");
+       dsn->dtext = mystrdup("");
     } else {
        dsn->dtype = mystrdup(dtype);
        dsn->dtext = mystrdup(dtext);
     }
     if (NULL_OR_EMPTY(mtype) || NULL_OR_EMPTY(mname)) {
-       dsn->mtype = 0;
-       dsn->mname = 0;
+       dsn->mtype = mystrdup("");
+       dsn->mname = mystrdup("");
     } else {
        dsn->mtype = mystrdup(mtype);
        dsn->mname = mystrdup(mname);
@@ -182,16 +179,11 @@ DSN    *dsn_create(const char *status, const char *action, const char *reason,
 void    dsn_free(DSN *dsn)
 {
     myfree((char *) dsn->status);
-    if (dsn->action)
-       myfree((char *) dsn->action);
+    myfree((char *) dsn->action);
     myfree((char *) dsn->reason);
-    if (dsn->dtype)
-       myfree((char *) dsn->dtype);
-    if (dsn->dtext)
-       myfree((char *) dsn->dtext);
-    if (dsn->mtype)
-       myfree((char *) dsn->mtype);
-    if (dsn->mname)
-       myfree((char *) dsn->mname);
+    myfree((char *) dsn->dtype);
+    myfree((char *) dsn->dtext);
+    myfree((char *) dsn->mtype);
+    myfree((char *) dsn->mname);
     myfree((char *) dsn);
 }
index 333545f4bd3eb506e893c72ab0d9587519143a1f..bf49dcb166c56295384966146ea790d71915782a 100644 (file)
 /* DESCRIPTION
 /* .nf
 
- /*
-  * Global library.
-  */
-#include <dsn_buf.h>
-
  /*
   * External interface.
   */
@@ -29,19 +24,6 @@ typedef struct {
     const char *mname;                 /* Null / RFC 3464 remote MTA */
 } DSN;
 
- /*
-  * Ditto, without const poisoning.
-  */
-typedef struct {
-    char   *status;                    /* RFC 3463 status */
-    char   *action;                    /* Null / RFC 3464 action */
-    char   *reason;                    /* descriptive reason */
-    char   *dtype;                     /* Null / RFC 3464 diagnostic type */
-    char   *dtext;                     /* Null / RFC 3464 diagnostic code */
-    char   *mtype;                     /* Null / RFC 3464 MTA type */
-    char   *mname;                     /* Null / RFC 3464 remote MTA */
-} DSN_VAR;
-
 extern DSN *dsn_create(const char *, const char *, const char *, const char *,
                               const char *, const char *, const char *);
 extern void dsn_free(DSN *);
@@ -58,55 +40,36 @@ extern void dsn_free(DSN *);
 
 #define DSN_SIMPLE(dsn, _status, _reason) \
     (((dsn)->status = (_status)), \
-     ((dsn)->action = 0), \
+     ((dsn)->action = DSN_NO_ACTION), \
      ((dsn)->reason = (_reason)), \
-     ((dsn)->dtype = 0), \
-     ((dsn)->dtext = 0), \
-     ((dsn)->mtype = 0), \
-     ((dsn)->mname = 0), \
+     ((dsn)->dtype = DSN_NO_DTYPE), \
+     ((dsn)->dtext = DSN_NO_DTEXT), \
+     ((dsn)->mtype = DSN_NO_MTYPE), \
+     ((dsn)->mname = DSN_NO_MNAME), \
      (dsn))
 
-#define DSN_SMTP(dsn, _status, _dtext, _reason) \
-    (((dsn)->status = (_status)), \
-     ((dsn)->action = 0), \
-     ((dsn)->reason = (_reason)), \
-     ((dsn)->dtype = DSB_DTYPE_SMTP), \
-     ((dsn)->dtext = _dtext), \
-     ((dsn)->mtype = 0), \
-     ((dsn)->mname = 0), \
-     (dsn))
-
-#define DSN_NO_DTYPE   0
-#define DSN_NO_DTEXT   0
-#define DSN_NO_MTYPE   0
-#define DSN_NO_MNAME   0
+#define DSN_NO_ACTION  ""
+#define DSN_NO_DTYPE   ""
+#define DSN_NO_DTEXT   ""
+#define DSN_NO_MTYPE   ""
+#define DSN_NO_MNAME   ""
 
  /*
-  * In order to save space in the queue manager, some DSN fields may be null
-  * pointers so that we don't waste memory making copies of empty strings. In
-  * addition, sanity requires that the status and reason are never null or
+  * Early implementations represented unavailable information with null
+  * pointers. This resulted in code that is hard to maintain. We now use
+  * empty strings instead. This does not waste precious memory as long as we
+  * can represent empty strings efficiently by collapsing them.
+  * 
+  * The only restriction left is that the status and reason are never null or
   * empty; this is enforced by dsn_create() which is invoked by DSN_COPY().
-  * This complicates the bounce_log(3) and bounce(8) daemons, as well as the
-  * server reply parsing code in the smtp(8) and lmtp(8) clients. They must
-  * be able to cope with null pointers, and they must never supply empty
-  * strings for the required fields.
+  * This complicates the server reply parsing code in the smtp(8) and lmtp(8)
+  * clients. they must never supply empty strings for these required fields.
   */
 #define DSN_COPY(dsn) \
     dsn_create((dsn)->status, (dsn)->action, (dsn)->reason, \
        (dsn)->dtype, (dsn)->dtext, \
        (dsn)->mtype, (dsn)->mname)
 
-#define DSN_STRING_OR_NULL(s) ((s)[0] ? (s) : 0)
-
-#define DSN_FROM_DSN_BUF(dsn, dsb) \
-    DSN_ASSIGN((dsn), vstring_str((dsb)->status), \
-       DSN_STRING_OR_NULL(vstring_str((dsb)->action)), \
-       vstring_str((dsb)->reason), \
-       DSN_STRING_OR_NULL(vstring_str((dsb)->dtype)), \
-       DSN_STRING_OR_NULL(vstring_str((dsb)->dtext)), \
-       DSN_STRING_OR_NULL(vstring_str((dsb)->mtype)), \
-       DSN_STRING_OR_NULL(vstring_str((dsb)->mname)))
-
 /* LICENSE
 /* .ad
 /* .fi
index c80bc62500197bab700fa03670a35323fc16dcbc..c3c3a7e309c8edd670769ee72ef4325394880fa9 100644 (file)
@@ -1,6 +1,6 @@
 /*++
 /* NAME
-/*     dsbuf 3
+/*     dsn_buf 3
 /* SUMMARY
 /*     delivery status buffer
 /* SYNOPSIS
@@ -8,20 +8,23 @@
 /*
 /*     typedef struct {
 /* .in +4
+/*             /* Convenience member */
+/*             DSN     dsn;            /* light-weight, dsn(3) */
+/*             /* Formal members... */
 /*             VSTRING *status;        /* RFC 3463 */
 /*             VSTRING *action;        /* RFC 3464 */
 /*             VSTRING *mtype;         /* dns */
 /*             VSTRING *mname;         /* host or domain */
 /*             VSTRING *dtype;         /* smtp, x-unix */
-/*             int     dcode;          /* RFC 2821, sysexits.h */
 /*             VSTRING *dtext;         /* RFC 2821, sysexits.h */
+/*             /* Informal members... */
 /*             VSTRING *reason;        /* informal text */
 /* .in -4
 /*     } DSN_BUF;
 /*
 /*     DSN_BUF *dsb_create(void)
 /*
-/*     DSN_BUF *dsb_update(dsb, status, action, mtype, mname, dtype, dcode,
+/*     DSN_BUF *dsb_update(dsb, status, action, mtype, mname, dtype,
 /*                             dtext, reason_fmt, ...)
 /*     DSN_BUF *dsb;
 /*     const char *status;
@@ -29,7 +32,6 @@
 /*     const char *mtype;
 /*     const char *mname;
 /*     const char *dtype;
-/*     int     dcode;
 /*     const char *dtext;
 /*     const char *reason_fmt;
 /*
 /*     const char *status;
 /*     const char *reason_fmt;
 /*
-/*     DSN_BUF *dsb_unix(dsb, status, dcode, dtext, reason_fmt, ...)
+/*     DSN_BUF *dsb_unix(dsb, status, dtext, reason_fmt, ...)
 /*     DSN_BUF *dsb;
 /*     const char *status;
 /*     const char *reason_fmt;
 /*
-/*     DSN_BUF *dsb_smtp(dsb, status, dcode, dtext, reason_fmt, ...)
-/*     DSN_BUF *dsb;
-/*     const char *status;
-/*     const char *reason_fmt;
-/*
-/*     DSN_BUF *dsb_formal(dsb, status, action, mtype, mname, dtype, dcode,
+/*     DSN_BUF *dsb_formal(dsb, status, action, mtype, mname, dtype,
 /*                             dtext)
 /*     DSN_BUF *dsb;
 /*     const char *status;
@@ -56,7 +53,6 @@
 /*     const char *mtype;
 /*     const char *mname;
 /*     const char *dtype;
-/*     int     dcode;
 /*     const char *dtext;
 /*
 /*     DSN_BUF *dsb_status(dsb, status)
 /*     const char *status;
 /*
 /*     void    dsb_reset(dsb)
+/*     DSN_BUF *dsb;
 /*
 /*     void    dsb_free(dsb)
+/*     DSN_BUF *dsb;
+/*
+/*     DSN     *DSN_FROM_DSN_BUF(dsb)
+/*     DSN_BUF *dsb;
 /* DESCRIPTION
 /*     This module implements a simple to update delivery status
-/*     buffer for Postfix-internal use. Typically it is populated
-/*     in course of delivery attempt, and then formatted into a
+/*     buffer for Postfix-internal use. Typically it is filled in
+/*     the course of delivery attempt, and then formatted into a
 /*     DSN structure for external notification.
 /*
 /*     dsb_create() creates initialized storage for formal RFC 3464
@@ -84,8 +85,6 @@
 /*     text, and informal text, sets the diagnostic type to UNIX,
 /*     and resets all other fields to defaults.
 /*
-/*     dsb_smtp() does the same for SMTP style diagnostics.
-/*
 /*     dsb_formal() updates all fields except the informal text.
 /*
 /*     dsb_status() updates the status field, and resets all
 /*     dsb_free() recycles the storage that was allocated by
 /*     dsb_create(), and so on.
 /*
+/*     DSN_FROM_DSN_BUF() populates the DSN member with a shallow
+/*     copy of the contents of the formal and informal fields, and
+/*     returns a pointer to the DSN member. This is typically used
+/*     for external reporting.
+/*
 /*     Arguments:
 /* .IP dsb
 /*     Delivery status buffer.
 /*     matter here are "expanded" and "relayed"; all other values
 /*     are already implied by the context.
 /* .IP mtype
+/*     The remote MTA type.
 /*     The only valid type is DSB_MTYPE_DNS.  The macro DSB_SKIP_RMTA
 /*     conveniently expands into a null argument list for the
 /*     remote MTA type and name.
 /* .IP mname
 /*     Remote MTA name.
 /* .IP dtype
+/*     The reply type.
 /*     DSB_DTYPE_SMTP or DSB_DTYPE_UNIX.  The macro DSB_SKIP_REPLY
 /*     conveniently expands into a null argument list for the reply
-/*     type, code and text.
-/* .IP dcode
-/*     Numerical reply code. The reply code is reset when dtype is
-/*     DSB_SKIP_REPLY.
+/*     type and text.
 /* .IP dtext
 /*     The reply text. The reply text is reset when dtype is
 /*     DSB_SKIP_REPLY.
-/* .IP reply_fmt
-/*     The reply text format. The reply text is reset when type
-/*     is DSB_SKIP_REPLY.
 /* .IP reason_fmt
 /*     The informal reason format.
 /* SEE ALSO
@@ -179,7 +179,6 @@ DSN_BUF *dsb_create(void)
     dsb->mtype = vstring_alloc(10);
     dsb->mname = vstring_alloc(100);
     dsb->dtype = vstring_alloc(10);
-    dsb->dcode = 0;
     dsb->dtext = vstring_alloc(100);
     dsb->reason = vstring_alloc(100);
 
@@ -200,13 +199,22 @@ void    dsb_free(DSN_BUF *dsb)
     myfree((char *) dsb);
 }
 
+ /*
+  * Initial versions of this code represented unavailable inputs with null
+  * pointers, which produced fragile and hard to maintain code. The current
+  * code uses empty strings instead of null pointers.
+  * 
+  * For safety we keep the test for null pointers in input. It's cheap.
+  */
 #define DSB_TRUNCATE(s) (STR(s)[0] = 0)
 
+#define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0)
+
 #define DSB_ACTION(dsb, stat, act) \
-    vstring_strcpy((dsb)->action, (act) && *(act) ? (act) : "")
+    vstring_strcpy((dsb)->action, !NULL_OR_EMPTY(act) ? (act) : "")
 
 #define DSB_MTA(dsb, type, name) do { \
-    if ((type) == 0) { \
+    if (NULL_OR_EMPTY(type) || NULL_OR_EMPTY(name)) { \
        DSB_TRUNCATE((dsb)->mtype); \
        DSB_TRUNCATE((dsb)->mname); \
     } else { \
@@ -215,11 +223,21 @@ void    dsb_free(DSN_BUF *dsb)
     } \
 } while (0)
 
+#define DSB_DIAG(dsb, type, text) do { \
+    if (NULL_OR_EMPTY(type) || NULL_OR_EMPTY(text)) { \
+       DSB_TRUNCATE((dsb)->dtype); \
+       DSB_TRUNCATE((dsb)->dtext); \
+    } else { \
+       vstring_strcpy((dsb)->dtype, (type)); \
+       vstring_strcpy((dsb)->dtext, (text)); \
+    } \
+} while (0)
+
 /* dsb_update - update formal attributes and informal text */
 
 DSN_BUF *dsb_update(DSN_BUF *dsb, const char *status, const char *action,
                            const char *mtype, const char *mname,
-                           const char *dtype, int dcode, const char *dtext,
+                           const char *dtype, const char *dtext,
                            const char *format,...)
 {
     va_list ap;
@@ -227,15 +245,7 @@ DSN_BUF *dsb_update(DSN_BUF *dsb, const char *status, const char *action,
     vstring_strcpy(dsb->status, status);
     DSB_ACTION(dsb, status, action);
     DSB_MTA(dsb, mtype, mname);
-    if (dtype == 0) {
-       DSB_TRUNCATE(dsb->dtype);
-       dsb->dcode = 0;
-       DSB_TRUNCATE(dsb->dtext);
-    } else {
-       vstring_strcpy(dsb->dtype, dtype);
-       dsb->dcode = dcode;
-       vstring_strcpy(dsb->dtext, dtext);
-    }
+    DSB_DIAG(dsb, dtype, dtext);
     va_start(ap, format);
     vstring_vsprintf(dsb->reason, format, ap);
     va_end(ap);
@@ -243,7 +253,7 @@ DSN_BUF *dsb_update(DSN_BUF *dsb, const char *status, const char *action,
     return (dsb);
 }
 
-/* dsb_simple - update status and text */
+/* dsb_simple - update status and informal text */
 
 DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
 {
@@ -254,7 +264,6 @@ DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
     DSB_TRUNCATE(dsb->mtype);
     DSB_TRUNCATE(dsb->mname);
     DSB_TRUNCATE(dsb->dtype);
-    dsb->dcode = 0;
     DSB_TRUNCATE(dsb->dtext);
     va_start(ap, format);
     vstring_vsprintf(dsb->reason, format, ap);
@@ -263,9 +272,9 @@ DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
     return (dsb);
 }
 
-/* dsb_unix - update status, UNIX diagnostic and text */
+/* dsb_unix - update status, UNIX diagnostic and informal text */
 
-DSN_BUF *dsb_unix(DSN_BUF *dsb, const char *status, int dcode,
+DSN_BUF *dsb_unix(DSN_BUF *dsb, const char *status,
                          const char *dtext, const char *format,...)
 {
     va_list ap;
@@ -275,28 +284,6 @@ DSN_BUF *dsb_unix(DSN_BUF *dsb, const char *status, int dcode,
     DSB_TRUNCATE(dsb->mtype);
     DSB_TRUNCATE(dsb->mname);
     vstring_strcpy(dsb->dtype, DSB_DTYPE_UNIX);
-    dsb->dcode = dcode;
-    vstring_strcpy(dsb->dtext, dtext);
-    va_start(ap, format);
-    vstring_vsprintf(dsb->reason, format, ap);
-    va_end(ap);
-
-    return (dsb);
-}
-
-/* dsb_smtp - update status, SMTP diagnostic and text */
-
-DSN_BUF *dsb_smtp(DSN_BUF *dsb, const char *status, int dcode,
-                         const char *dtext, const char *format,...)
-{
-    va_list ap;
-
-    vstring_strcpy(dsb->status, status);
-    DSB_TRUNCATE(dsb->action);
-    DSB_TRUNCATE(dsb->mtype);
-    DSB_TRUNCATE(dsb->mname);
-    vstring_strcpy(dsb->dtype, DSB_DTYPE_SMTP);
-    dsb->dcode = dcode;
     vstring_strcpy(dsb->dtext, dtext);
     va_start(ap, format);
     vstring_vsprintf(dsb->reason, format, ap);
@@ -309,21 +296,12 @@ DSN_BUF *dsb_smtp(DSN_BUF *dsb, const char *status, int dcode,
 
 DSN_BUF *dsb_formal(DSN_BUF *dsb, const char *status, const char *action,
                            const char *mtype, const char *mname,
-                           const char *dtype, int dcode,
-                           const char *dtext)
+                           const char *dtype, const char *dtext)
 {
     vstring_strcpy(dsb->status, status);
     DSB_ACTION(dsb, status, action);
     DSB_MTA(dsb, mtype, mname);
-    if (dtype == 0) {
-       DSB_TRUNCATE(dsb->dtype);
-       dsb->dcode = 0;
-       DSB_TRUNCATE(dsb->dtext);
-    } else {
-       vstring_strcpy(dsb->dtype, dtype);
-       dsb->dcode = dcode;
-       vstring_strcpy(dsb->dtext, dtext);
-    }
+    DSB_DIAG(dsb, dtype, dtext);
     return (dsb);
 }
 
@@ -336,7 +314,6 @@ DSN_BUF *dsb_status(DSN_BUF *dsb, const char *status)
     DSB_TRUNCATE(dsb->mtype);
     DSB_TRUNCATE(dsb->mname);
     DSB_TRUNCATE(dsb->dtype);
-    dsb->dcode = 0;
     DSB_TRUNCATE(dsb->dtext);
     return (dsb);
 }
@@ -350,7 +327,6 @@ void    dsb_reset(DSN_BUF *dsb)
     DSB_TRUNCATE(dsb->mtype);
     DSB_TRUNCATE(dsb->mname);
     DSB_TRUNCATE(dsb->dtype);
-    dsb->dcode = 0;
     DSB_TRUNCATE(dsb->dtext);
     DSB_TRUNCATE(dsb->reason);
 }
index 17dd7fc3843384f5f8e27fcd7ab5f3a04eed8237..b38f46d0da82a1b8514d1fc38983a07d42fcf94c 100644 (file)
@@ -3,9 +3,9 @@
 
 /*++
 /* NAME
-/*     dsbuf 3h
+/*     dsn_buf 3h
 /* SUMMARY
-/*     DSN support routines
+/*     delivery status buffer
 /* SYNOPSIS
 /*     #include <dsn_buf.h>
 /* DESCRIPTION
   */
 #include <vstring.h>
 
+ /*
+  * Global library.
+  */
+#include <dsn.h>
+
  /*
   * Delivery status buffer, Postfix-internal form.
   */
 typedef struct {
+    DSN     dsn;                       /* convenience */
+    /* Formal members. */
     VSTRING *status;                   /* RFC 3463 */
     VSTRING *action;                   /* RFC 3464 */
     VSTRING *mtype;                    /* null or remote MTA type */
     VSTRING *mname;                    /* null or remote MTA name */
-    VSTRING *dtype;                    /* null, smtp, x-unix-command */
-    int     dcode;                     /* null, RFC 2821, sysexits.h */
+    VSTRING *dtype;                    /* null, smtp, x-unix */
     VSTRING *dtext;                    /* null, RFC 2821, sysexits.h */
+    /* Informal free text. */
     VSTRING *reason;                   /* free text */
 } DSN_BUF;
 
@@ -36,23 +43,38 @@ typedef struct {
 #define DSB_MTYPE_NONE ((char *) 0)
 #define DSB_MTYPE_DNS  "dns"           /* RFC 2821 */
 
-#define DSB_SKIP_REPLY (char *) 0, (int) 0, " "        /* XXX Bogus? */
+#define DSB_SKIP_REPLY (char *) 0, " " /* XXX Bogus? */
 #define DSB_DTYPE_NONE ((char *) 0)
 #define DSB_DTYPE_SMTP "smtp"          /* RFC 2821 */
 #define DSB_DTYPE_UNIX "x-unix"        /* sysexits.h */
 #define DSB_DTYPE_SASL "x-sasl"        /* libsasl */
 
 extern DSN_BUF *dsb_create(void);
-extern DSN_BUF *PRINTFLIKE(9, 10) dsb_update(DSN_BUF *, const char *, const char *, const char *, const char *, const char *, int, const char *, const char *,...);
+extern DSN_BUF *PRINTFLIKE(8, 9) dsb_update(DSN_BUF *, const char *, const char *, const char *, const char *, const char *, const char *, const char *,...);
 extern DSN_BUF *PRINTFLIKE(3, 4) dsb_simple(DSN_BUF *, const char *, const char *,...);
-extern DSN_BUF *PRINTFLIKE(5, 6) dsb_smtp(DSN_BUF *, const char *, int, const char *, const char *,...);
-extern DSN_BUF *PRINTFLIKE(5, 6) dsb_unix(DSN_BUF *, const char *, int, const char *, const char *,...);
-extern DSN_BUF *PRINTFLIKE(5, 6) dsb_smtp(DSN_BUF *, const char *, int, const char *, const char *,...);
-extern DSN_BUF *dsb_formal(DSN_BUF *, const char *, const char *, const char *, const char *, const char *, int, const char *);
+extern DSN_BUF *PRINTFLIKE(4, 5) dsb_unix(DSN_BUF *, const char *, const char *, const char *,...);
+extern DSN_BUF *PRINTFLIKE(4, 5) dsb_smtp(DSN_BUF *, const char *, const char *, const char *,...);
+extern DSN_BUF *dsb_formal(DSN_BUF *, const char *, const char *, const char *, const char *, const char *, const char *);
 extern DSN_BUF *dsb_status(DSN_BUF *, const char *);
 extern void dsb_reset(DSN_BUF *);
 extern void dsb_free(DSN_BUF *);
 
+ /*
+  * Early implementations of the DSN structure represented unavailable
+  * information with null pointers. This resulted in hard to maintain code.
+  * We now use empty strings instead, so there is no need anymore to convert
+  * empty strings to null pointers in the macro below.
+  */
+#define DSN_FROM_DSN_BUF(dsb) \
+    DSN_ASSIGN(&(dsb)->dsn, \
+       vstring_str((dsb)->status), \
+        vstring_str((dsb)->action), \
+        vstring_str((dsb)->reason), \
+        vstring_str((dsb)->dtype), \
+        vstring_str((dsb)->dtext), \
+        vstring_str((dsb)->mtype), \
+        vstring_str((dsb)->mname))
+
 /* LICENSE
 /* .ad
 /* .fi
index ea1dc4924ce37d8e9363e75590ad43b9148e025b..9b21a6904a02e57d191c6b4f50fe1e0a1fa8b7b5 100644 (file)
@@ -51,19 +51,17 @@ int     dsn_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
     DSN    *dsn = (DSN *) ptr;
     int     ret;
 
-#define S(s) ((s) ? (s) : "")
-
     /*
      * The attribute order is determined by backwards compatibility. It can
      * be sanitized after all the ad-hoc DSN read/write code is replaced.
      */
     ret = print_fn(fp, flags | ATTR_FLAG_MORE,
                   ATTR_TYPE_STR, MAIL_ATTR_DSN_STATUS, dsn->status,
-                  ATTR_TYPE_STR, MAIL_ATTR_DSN_DTYPE, S(dsn->dtype),
-                  ATTR_TYPE_STR, MAIL_ATTR_DSN_DTEXT, S(dsn->dtext),
-                  ATTR_TYPE_STR, MAIL_ATTR_DSN_MTYPE, S(dsn->mtype),
-                  ATTR_TYPE_STR, MAIL_ATTR_DSN_MNAME, S(dsn->mname),
-                  ATTR_TYPE_STR, MAIL_ATTR_DSN_ACTION, S(dsn->action),
+                  ATTR_TYPE_STR, MAIL_ATTR_DSN_DTYPE, dsn->dtype,
+                  ATTR_TYPE_STR, MAIL_ATTR_DSN_DTEXT, dsn->dtext,
+                  ATTR_TYPE_STR, MAIL_ATTR_DSN_MTYPE, dsn->mtype,
+                  ATTR_TYPE_STR, MAIL_ATTR_DSN_MNAME, dsn->mname,
+                  ATTR_TYPE_STR, MAIL_ATTR_DSN_ACTION, dsn->action,
                   ATTR_TYPE_STR, MAIL_ATTR_WHY, dsn->reason,
                   ATTR_TYPE_END);
     return (ret);
index a4d7ceed5898acb5281d6d6dc9a6a0a60eba9faa..52b997a3320593bc2ab577442d38e7290e11a18f 100644 (file)
@@ -12,7 +12,7 @@
 /*
 /*     typedef struct {
 /* .in +4
-/*             DSN_BUF dsn;            /* RFC 3463 status */
+/*             DSN_STAT dsn;           /* RFC 3463 status */
 /*             const char *text;       /* Free text */
 /* .in -4
 /*     } DSN_SPLIT;
index fbcbfd23102134e43ee68ad322e78345a3ef8f33..8657a3e507323af1021efeee0edc03de0c401d49 100644 (file)
@@ -33,7 +33,7 @@
   */
 typedef struct {
     char    data[DSN_SIZE];            /* NOT a public interface */
-}       DSN_BUFFER;
+} DSN_STAT;
 
 #define DSN_UPDATE(dsn_buf, dsn, len) do { \
        if (len >= sizeof((dsn_buf).data)) \
@@ -51,7 +51,7 @@ typedef struct {
   * Split flat text into detail code and free text.
   */
 typedef struct {
-    DSN_BUFFER dsn;                    /* RFC 3463 status */
+    DSN_STAT dsn;                      /* RFC 3463 status */
     const char *text;                  /* free text */
 } DSN_SPLIT;
 
index 33d41c491810c43c6a53eb388a470b907878d4e1..42753d8542486e7031ea202b3d5f4ed69234503b 100644 (file)
@@ -268,11 +268,11 @@ int     mail_copy(const char *sender,
 
     if (why && read_error)
        dsb_unix(why, TRY_AGAIN_ERROR(errno) ? "4.3.0" : "5.3.0",
-                EX_IOERR, sys_exits_detail(EX_IOERR)->text,
+                sys_exits_detail(EX_IOERR)->text,
                 "error reading message: %m");
     if (why && write_error)
        dsb_unix(why, mbox_dsn(errno, "5.3.0"),
-                EX_IOERR, sys_exits_detail(EX_IOERR)->text,
+                sys_exits_detail(EX_IOERR)->text,
                 "error writing message: %m");
 
     /*
index 97f39f26aaf01415bff9e3cbf5cebcc4db1f2c3a..9a0c60f0eb83828b4be4f40bb56a1683dc78c39f 100644 (file)
@@ -1329,6 +1329,12 @@ extern char *var_smtp_sasl_type;
 #define DEF_LMTP_SASL_TLS_OPTS "$" VAR_LMTP_SASL_OPTS
 extern char *var_smtp_sasl_tls_opts;
 
+#define VAR_SMTP_SASL_TLSV_OPTS        "smtp_sasl_tls_verified_security_options"
+#define DEF_SMTP_SASL_TLSV_OPTS        "$" VAR_SMTP_SASL_TLS_OPTS
+#define VAR_LMTP_SASL_TLSV_OPTS        "lmtp_sasl_tls_verified_security_options"
+#define DEF_LMTP_SASL_TLSV_OPTS        "$" VAR_LMTP_SASL_TLS_OPTS
+extern char *var_smtp_sasl_tlsv_opts;
+
  /*
   * LMTP server. The soft error limit determines how many errors an LMTP
   * client may make before we start to slow down; the hard error limit
@@ -2532,6 +2538,15 @@ extern char *var_bounce_tmpl;
 #define DEF_LMTP_SENDER_AUTH   0
 extern bool var_smtp_sender_auth;
 
+ /*
+  * Allow CNAME lookup result to override the server hostname.
+  */
+#define VAR_SMTP_CNAME_OVERR           "smtp_cname_overrides_servername"
+#define DEF_SMTP_CNAME_OVERR           0
+#define VAR_LMTP_CNAME_OVERR           "lmtp_cname_overrides_servername"
+#define DEF_LMTP_CNAME_OVERR           0
+extern bool var_smtp_cname_overr;
+
 /* LICENSE
 /* .ad
 /* .fi
index 2ffcc128aba597bc0827ffecd11f464acc232ea8..6e585528730159a58554ba14a72bcc0e5cc2e6a4 100644 (file)
@@ -98,6 +98,7 @@ extern char *mail_pathname(const char *, const char *);
 #define MAIL_ATTR_QUEUE                "queue_name"
 #define MAIL_ATTR_QUEUEID      "queue_id"
 #define MAIL_ATTR_SENDER       "sender"
+#define MAIL_ATTR_RCPT_COUNT   "recipient_count"
 #define MAIL_ATTR_ORCPT                "original_recipient"
 #define MAIL_ATTR_RECIP                "recipient"
 #define MAIL_ATTR_WHY          "reason"
index ee8ce66aadca2758df7b7d40349d4aa2f41c0424..f77b11e485b163aef403f3e62fb5506411d9a814 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      "20060103"
+#define MAIL_RELEASE_DATE      "20060112"
 #define MAIL_VERSION_NUMBER    "2.3"
 
 #ifdef SNAPSHOT
index 5765e3e3305c7c704431a718b877ab3a7270d482..98d468dcde9116bbbe9daa30dcec3b00d5b09f76 100644 (file)
@@ -47,7 +47,7 @@
 /* msg_stats_print - write MSG_STATS to stream */
 
 int     msg_stats_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
-                         int flags, void *ptr)
+                               int flags, void *ptr)
 {
     int     ret;
 
index 245e492dcd38153e2c8aa2ddc8f234adebc50773..b0caa5cba5a8a43087228cf6be1e8ef95a133828 100644 (file)
@@ -427,7 +427,7 @@ int     pipe_command(VSTREAM *src, DSN_BUF *why,...)
         */
     case -1:
        msg_warn("fork: %m");
-       dsb_unix(why, "4.3.0", EX_OSERR, sys_exits_detail(EX_OSERR)->text,
+       dsb_unix(why, "4.3.0", sys_exits_detail(EX_OSERR)->text,
                 "Delivery failed: %m");
        return (PIPE_STAT_DEFER);
 
@@ -553,7 +553,7 @@ int     pipe_command(VSTREAM *src, DSN_BUF *why,...)
                                      args.uid, args.gid) < 0)
            msg_fatal("wait: %m");
        if (pipe_command_timeout) {
-           dsb_unix(why, "5.3.0", EX_SOFTWARE, log_len ?
+           dsb_unix(why, "5.3.0", log_len ?
                     log_buf : sys_exits_detail(EX_SOFTWARE)->text,
                     "Command time limit exceeded: \"%s\"%s%s",
                     args.command,
@@ -567,7 +567,7 @@ int     pipe_command(VSTREAM *src, DSN_BUF *why,...)
         */
        if (!NORMAL_EXIT_STATUS(wait_status)) {
            if (WIFSIGNALED(wait_status)) {
-               dsb_unix(why, "5.3.0", EX_SOFTWARE, log_len ?
+               dsb_unix(why, "5.3.0", log_len ?
                         log_buf : sys_exits_detail(EX_SOFTWARE)->text,
                         "Command died with signal %d: \"%s\"%s%s",
                         WTERMSIG(wait_status), args.command,
@@ -577,15 +577,14 @@ int     pipe_command(VSTREAM *src, DSN_BUF *why,...)
            /* Use "D.S.N text" command output. XXX What diagnostic code? */
            else if (dsn_valid(log_buf) > 0) {
                dsn_split(&dp, "5.3.0", log_buf);
-               dsb_unix(why, DSN_STATUS(dp.dsn), DSN_CLASS(dp.dsn) == '4' ?
-                     EX_TEMPFAIL : EX_UNAVAILABLE, dp.text, "%s", dp.text);
+               dsb_unix(why, DSN_STATUS(dp.dsn), dp.text, "%s", dp.text);
                return (DSN_CLASS(dp.dsn) == '4' ?
                        PIPE_STAT_DEFER : PIPE_STAT_BOUNCE);
            }
            /* Use <sysexits.h> compatible exit status. */
            else if (SYS_EXITS_CODE(WEXITSTATUS(wait_status))) {
                sp = sys_exits_detail(WEXITSTATUS(wait_status));
-               dsb_unix(why, sp->dsn, WEXITSTATUS(wait_status),
+               dsb_unix(why, sp->dsn,
                         log_len ? log_buf : sp->text, "%s%s%s", sp->text,
                         log_len ? ". Command output: " : "", log_buf);
                return (sp->dsn[0] == '4' ?
@@ -594,7 +593,7 @@ int     pipe_command(VSTREAM *src, DSN_BUF *why,...)
            /* No "D.S.N text" or <sysexits.h> compatible status. Fake it. */
            else {
                sp = sys_exits_detail(WEXITSTATUS(wait_status));
-               dsb_unix(why, sp->dsn, WEXITSTATUS(wait_status),
+               dsb_unix(why, sp->dsn,
                         log_len ? log_buf : sp->text,
                         "Command died with status %d: \"%s\"%s%s",
                         WEXITSTATUS(wait_status), args.command,
index 0904e6e0caf4bea2710f8d5def9662f21181b190..e1c46796dd661e700b6b0296243de866daa9cd07 100644 (file)
@@ -6,26 +6,30 @@
 /* SYNOPSIS
 /*     #include <post_mail.h>
 /*
-/*     VSTREAM *post_mail_fopen(sender, recipient, cleanup_flags, trace_flags)
+/*     VSTREAM *post_mail_fopen(sender, recipient, cleanup_flags, trace_flags,
+/*             queue_id)
 /*     const char *sender;
 /*     const char *recipient;
 /*     int     cleanup_flags;
 /*     int     trace_flags;
+/*     VSTRING *queue_id;
 /*
 /*     VSTREAM *post_mail_fopen_nowait(sender, recipient,
-/*                                     cleanup_flags, trace_flags)
+/*                                     cleanup_flags, trace_flags, queue_id)
 /*     const char *sender;
 /*     const char *recipient;
 /*     int     cleanup_flags;
 /*     int     trace_flags;
+/*     VSTRING *queue_id;
 /*
 /*     void    post_mail_fopen_async(sender, recipient,
 /*                                     cleanup_flags, trace_flags,
-/*                                     notify, context)
+/*                                     queue_id, notify, context)
 /*     const char *sender;
 /*     const char *recipient;
 /*     int     cleanup_flags;
 /*     int     trace_flags;
+/*     VSTRING *queue_id;
 /*     void    (*notify)(VSTREAM *stream, char *context);
 /*     char    *context;
 /*
 /*     \fB<cleanup_user.h>\fR.
 /* .IP trace_flags
 /*     Message tracing flags as specified in \fB<deliver_request.h>\fR.
-/* .IP via
-/*     The name of the service responsible for posting this message.
+/* .IP queue_id
+/*     Null pointer, or pointer to buffer that receives the queue
+/*     ID of the new message.
 /* .IP stream
 /*     A stream opened by mail_post_fopen().
 /* .IP notify
@@ -169,15 +174,17 @@ typedef struct {
     POST_MAIL_NOTIFY notify;
     void   *context;
     VSTREAM *stream;
+    VSTRING *queue_id;
 } POST_MAIL_STATE;
 
 /* post_mail_init - initial negotiations */
 
 static void post_mail_init(VSTREAM *stream, const char *sender,
                                   const char *recipient,
-                                  int cleanup_flags, int trace_flags)
+                                  int cleanup_flags, int trace_flags,
+                                  VSTRING *queue_id)
 {
-    VSTRING *id = vstring_alloc(100);
+    VSTRING *id = queue_id ? queue_id : vstring_alloc(100);
     struct timeval now;
     const char *date;
 
@@ -217,31 +224,36 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
                      var_myhostname, var_mail_name);
     post_mail_fprintf(stream, "\tid %s; %s", vstring_str(id), date);
     post_mail_fprintf(stream, "Date: %s", date);
-    vstring_free(id);
+    if (queue_id == 0)
+       vstring_free(id);
 }
 
 /* post_mail_fopen - prepare for posting a message */
 
 VSTREAM *post_mail_fopen(const char *sender, const char *recipient,
-                                int cleanup_flags, int trace_flags)
+                                int cleanup_flags, int trace_flags,
+                                VSTRING *queue_id)
 {
     VSTREAM *stream;
 
     stream = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service);
-    post_mail_init(stream, sender, recipient, cleanup_flags, trace_flags);
+    post_mail_init(stream, sender, recipient, cleanup_flags, trace_flags,
+                  queue_id);
     return (stream);
 }
 
 /* post_mail_fopen_nowait - prepare for posting a message */
 
 VSTREAM *post_mail_fopen_nowait(const char *sender, const char *recipient,
-                                       int cleanup_flags, int trace_flags)
+                                       int cleanup_flags, int trace_flags,
+                                       VSTRING *queue_id)
 {
     VSTREAM *stream;
 
     if ((stream = mail_connect(MAIL_CLASS_PUBLIC, var_cleanup_service,
                               BLOCKING)) != 0)
-       post_mail_init(stream, sender, recipient, cleanup_flags, trace_flags);
+       post_mail_init(stream, sender, recipient, cleanup_flags, trace_flags,
+                      queue_id);
     return (stream);
 }
 
@@ -281,7 +293,7 @@ static void post_mail_open_event(int event, char *context)
        event_disable_readwrite(vstream_fileno(state->stream));
        post_mail_init(state->stream, state->sender,
                       state->recipient, state->cleanup_flags,
-                      state->trace_flags);
+                      state->trace_flags, state->queue_id);
        myfree(state->sender);
        myfree(state->recipient);
        state->notify(state->stream, state->context);
@@ -332,6 +344,7 @@ static void post_mail_open_event(int event, char *context)
 
 void    post_mail_fopen_async(const char *sender, const char *recipient,
                                      int cleanup_flags, int trace_flags,
+                                     VSTRING *queue_id,
                                      void (*notify) (VSTREAM *, void *),
                                      void *context)
 {
@@ -347,6 +360,7 @@ void    post_mail_fopen_async(const char *sender, const char *recipient,
     state->notify = notify;
     state->context = context;
     state->stream = stream;
+    state->queue_id = queue_id;
 
     /*
      * To keep interfaces as simple as possible we report all errors via the
index d0a0aceccde0faaf35db2d93701c97a8980e617d..e55a8d1662b76cb734b7047a8df968f38eb3d9e9 100644 (file)
@@ -15,6 +15,7 @@
   * Utility library.
   */
 #include <vstream.h>
+#include <vstring.h>
 
  /*
   * Global library.
@@ -25,9 +26,9 @@
   * External interface.
   */
 typedef void (*POST_MAIL_NOTIFY)(VSTREAM *, void *);
-extern VSTREAM *post_mail_fopen(const char *, const char *, int, int);
-extern VSTREAM *post_mail_fopen_nowait(const char *, const char *, int, int);
-extern void post_mail_fopen_async(const char *, const char *, int, int, POST_MAIL_NOTIFY, void *);
+extern VSTREAM *post_mail_fopen(const char *, const char *, int, int, VSTRING *);
+extern VSTREAM *post_mail_fopen_nowait(const char *, const char *, int, int, VSTRING *);
+extern void post_mail_fopen_async(const char *, const char *, int, int, VSTRING *, POST_MAIL_NOTIFY, void *);
 extern int PRINTFLIKE(2, 3) post_mail_fprintf(VSTREAM *, const char *,...);
 extern int post_mail_fputs(VSTREAM *, const char *);
 extern int post_mail_buffer(VSTREAM *, const char *, int);
index 2417a5cb1f62108f166d3b53ee22c8565d7b3ff5..cfb1b41784a77fde66499950e8bfeb2a893a9ee7 100644 (file)
@@ -7,6 +7,7 @@
 /*     #include <rcpt_buf.h>
 /*
 /*     typedef struct {
+/*             RECIPIENT rcpt;         /* convenience */
 /* .in +4
 /*             VSTRING *address;       /* final recipient */
 /*             VSTRING *orig_addr;     /* original recipient */
 /* .in -4
 /*     } RCPT_BUF;
 /*
+/*     RECIPIENT *RECIPIENT_FROM_RCPT_BUF(rcpb)
+/*     RCPT_BUF *rcpb;
+/*
 /*     RCPT_BUF *rcpb_create(void)
 /*
-/*     void    rcpb_free(rcpt)
-/*     RCPT_BUF *rcpt;
+/*     void    rcpb_reset(rcpb)
+/*     RCPT_BUF *rcpb;
+/*
+/*     void    rcpb_free(rcpb)
+/*     RCPT_BUF *rcpb;
 /*
 /*     int     rcpb_scan(scan_fn, stream, flags, ptr)
 /*     ATTR_SCAN_MASTER_FN scan_fn;
 /*     int     flags;
 /*     void    *ptr;
 /* DESCRIPTION
+/*     RECIPIENT_FROM_RCPT_BUF() populates the rcpt member with
+/*     a shallow copy of the contents of the other fields.
+/*
 /*     rcpb_scan() reads a recipient buffer from the named stream
 /*     using the specified attribute scan routine. rcpb_scan()
 /*     is meant to be passed as a call-back to attr_scan(), thusly:
 /*
 /*     ... ATTR_SCAN_FUNC, rcpb_scan, (void *) rcpt_buf, ...
 /*
-/*     rcpb_create() and rcpb_free() create and destroy
-/*     recipient buffer instances.
+/*     rcpb_create(), rcpb_reset() and rcpb_free() create, wipe
+/*     and destroy recipient buffer instances.
 /* DIAGNOSTICS
 /*     Fatal: out of memory.
 /* LICENSE
@@ -80,6 +90,19 @@ RCPT_BUF *rcpb_create(void)
     return (rcpt);
 }
 
+/* rcpb_reset - reset recipient buffer */
+
+void    rcpb_reset(RCPT_BUF *rcpt)
+{
+#define BUF_TRUNCATE(s) (vstring_str(s)[0] = 0)
+
+    rcpt->offset = 0;
+    BUF_TRUNCATE(rcpt->dsn_orcpt);
+    rcpt->dsn_notify = 0;
+    BUF_TRUNCATE(rcpt->orig_addr);
+    BUF_TRUNCATE(rcpt->address);
+}
+
 /* rcpb_free - destroy recipient buffer */
 
 void    rcpb_free(RCPT_BUF *rcpt)
index 0dbee35c8b467dfb0bf19c5eb3af8ba16e22d166..9b2994c0ac28dae2e1c5e7e1dc3e1dc912a86a14 100644 (file)
 #include <vstring.h>
 #include <attr.h>
 
+ /*
+  * Global library.
+  */
+#include <recipient_list.h>
+
  /*
   * External interface.
   */
 typedef struct {
+    RECIPIENT rcpt;                    /* convenience */
     VSTRING *address;                  /* final recipient */
     VSTRING *orig_addr;                        /* original recipient */
     VSTRING *dsn_orcpt;                        /* dsn original recipient */
@@ -30,16 +36,17 @@ typedef struct {
 } RCPT_BUF;
 
 extern RCPT_BUF *rcpb_create(void);
+extern void rcpb_reset(RCPT_BUF *);
 extern void rcpb_free(RCPT_BUF *);
 extern int rcpb_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
 
-#define RECIPIENT_FROM_RCPT_BUF(rcpt, buf) \
-    ((rcpt)->address = vstring_str((buf)->address), \
-     (rcpt)->orig_addr = vstring_str((buf)->orig_addr), \
-     (rcpt)->dsn_orcpt = vstring_str((buf)->dsn_orcpt), \
-     (rcpt)->dsn_notify = (buf)->dsn_notify, \
-     (rcpt)->offset = (buf)->offset, \
-     (rcpt))
+#define RECIPIENT_FROM_RCPT_BUF(buf) \
+    ((buf)->rcpt.address = vstring_str((buf)->address), \
+     (buf)->rcpt.orig_addr = vstring_str((buf)->orig_addr), \
+     (buf)->rcpt.dsn_orcpt = vstring_str((buf)->dsn_orcpt), \
+     (buf)->rcpt.dsn_notify = (buf)->dsn_notify, \
+     (buf)->rcpt.offset = (buf)->offset, \
+     &(buf)->rcpt)
 
 /* LICENSE
 /* .ad
index 47af4703277b1f2e82e9977a7e99795089d7a7f7..1c3b723f887d40081362896589118e15e8132d03 100644 (file)
@@ -52,8 +52,6 @@ int     rcpt_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
     RECIPIENT *rcpt = (RECIPIENT *) ptr;
     int     ret;
 
-#define S(s) ((s) ? (s) : "")
-
     /*
      * The attribute order is determined by backwards compatibility. It can
      * be sanitized after all the ad-hoc recipient read/write code is
@@ -61,10 +59,10 @@ int     rcpt_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
      */
     ret =
        print_fn(fp, flags | ATTR_FLAG_MORE,
-                ATTR_TYPE_STR, MAIL_ATTR_ORCPT, S(rcpt->orig_addr),
+                ATTR_TYPE_STR, MAIL_ATTR_ORCPT, rcpt->orig_addr,
                 ATTR_TYPE_STR, MAIL_ATTR_RECIP, rcpt->address,
                 ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, rcpt->offset,
-                ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, S(rcpt->dsn_orcpt),
+                ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt,
                 ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify,
                 ATTR_TYPE_END);
     return (ret);
index 8d2c964f9447ec56d1306ecbf896ddb0d2f5cfc8..a399792410011d54e6c1a6549f9931a145a99ec9 100644 (file)
@@ -15,9 +15,9 @@
 /*             char   *address;
 /*             union {
 /* .in +4
-/*             int     status;
-/*             struct QMGR_QUEUE *queue;
-/*             char    *addr_type;
+/*                     int     status;
+/*                     struct QMGR_QUEUE *queue;
+/*                     char    *addr_type;
 /* .in -4
 /*             }
 /* .in -4
index e617b42122d51c04f2454480a717df503d87fff9..6e9617218b9e500be9fe28dd94089a6182fa00ea 100644 (file)
@@ -46,22 +46,6 @@ typedef struct RECIPIENT {
     myfree((char *) (ptr)); (ptr) = mystrdup(new); \
 } while (0)
 
- /*
-  * Same without const poisning.
-  */
-typedef struct RECIPIENT_VAR {
-    long    offset;                    /* REC_TYPE_RCPT byte */
-    char   *dsn_orcpt;                 /* DSN original recipient */
-    int     dsn_notify;                        /* DSN notify flags */
-    char   *orig_addr;                 /* null or original recipient */
-    char   *address;                   /* complete address */
-    union {                            /* Application specific. */
-       int     status;                 /* SMTP client */
-       struct QMGR_QUEUE *queue;       /* Queue manager */
-       char   *addr_type;              /* DSN */
-    } u;
-} RECIPIENT_VAR;
-
 typedef struct RECIPIENT_LIST {
     RECIPIENT *info;
     int     len;
index 5b3d6e04052182403bc1b2d99ea904935e11d9ee..24507d5ee6b530b751abd5ab4b6311f47bb36a9e 100644 (file)
 /*     An I/O error happened, or the peer has disconnected unexpectedly.
 /* .IP SMTP_ERR_TIME
 /*     The time limit specified to smtp_timeout_setup() was exceeded.
-/* .IP SMTP_ERR_PROTO
-/*     A protocol error happened.
-/*     This error is never generated by the smtp_stream(3) module, but
-/*     is defined for application-specific use.
 /* .IP SMTP_ERR_QUIET
 /*     Perform silent cleanup; the error was already reported by
 /*     the application.
index 190baf50d3dd81e2fc2621fc3ac673dfac5e1817..a09a13f898a869b164b69cc1a94c112227c8952e 100644 (file)
@@ -28,7 +28,6 @@
   */
 #define SMTP_ERR_EOF   1               /* unexpected client disconnect */
 #define SMTP_ERR_TIME  2               /* time out */
-#define SMTP_ERR_PROTO 3               /* protocol (application) */
 #define SMTP_ERR_QUIET 4               /* silent cleanup (application) */
 
 extern void smtp_timeout_setup(VSTREAM *, int);
index 2e3d79359d72ee528c1bc1ea56e59fafd07c11be..67c3a94037bf33d55c931b95eb7fffa0b0c825a2 100644 (file)
@@ -88,7 +88,6 @@ typedef struct DELIVER_ATTR {
     char   *exp_from;                  /* expanded_from */
     DELIVER_REQUEST *request;          /* the kitchen sink */
     DSN_BUF *why;                      /* delivery status */
-    DSN     dsn;                       /* delivery status */
 } DELIVER_ATTR;
 
 extern void deliver_attr_init(DELIVER_ATTR *);
@@ -132,15 +131,15 @@ typedef struct LOCAL_STATE {
 
 #define BOUNCE_ATTR(attr) \
        attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \
-       DSN_FROM_DSN_BUF(&attr.dsn, attr.why)
+       DSN_FROM_DSN_BUF(attr.why)
 #define BOUNCE_ONE_ATTR(attr) \
        attr.queue_name, attr.queue_id, attr.encoding, \
        attr.sender, attr.dsn_envid, attr.dsn_ret, \
        &attr.msg_stats, &attr.rcpt, attr.relay, \
-       DSN_FROM_DSN_BUF(&attr.dsn, attr.why)
+       DSN_FROM_DSN_BUF(attr.why)
 #define SENT_ATTR(attr) \
        attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \
-       DSN_FROM_DSN_BUF(&attr.dsn, attr.why)
+       DSN_FROM_DSN_BUF(attr.why)
 #define OPENED_ATTR(attr) \
        attr.queue_id, attr.sender
 #define COPY_ATTR(attr) \
index cc0a07458d05deb06e5d091e254877feeaef768f..c6d7ed9f0795160bda0dc442ac147a3cdf441a04 100644 (file)
@@ -152,8 +152,8 @@ int     deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr)
     /*
      * Bounce the message when no luser relay is specified.
      */
-    dsb_smtp(state.msg_attr.why, "5.1.1", 550, "550 user unknown",
-            "unknown user: \"%s\"", state.msg_attr.local);
+    dsb_simple(state.msg_attr.why, "5.1.1",
+              "unknown user: \"%s\"", state.msg_attr.local);
     return (bounce_append(BOUNCE_FLAGS(state.request),
                          BOUNCE_ATTR(state.msg_attr)));
 }
index 36cfa45cda2971c4760aa6405b51624f4f28a8c7..c7e70f939f4e2dd9a3834f59388afaaaaadee3b5 100644 (file)
@@ -135,6 +135,7 @@ master_ent.o: ../../include/myaddrinfo.h
 master_ent.o: ../../include/mymalloc.h
 master_ent.o: ../../include/own_inet_addr.h
 master_ent.o: ../../include/readlline.h
+master_ent.o: ../../include/sock_addr.h
 master_ent.o: ../../include/stringops.h
 master_ent.o: ../../include/sys_defs.h
 master_ent.o: ../../include/vbuf.h
index 1815ddbcb67925d3187600f1308af414abdeb42b..accc7a2ed649ef502d93e8c551c476700cdaaf64 100644 (file)
@@ -64,7 +64,6 @@ qmgr.o: ../../include/argv.h
 qmgr.o: ../../include/attr.h
 qmgr.o: ../../include/dict.h
 qmgr.o: ../../include/dsn.h
-qmgr.o: ../../include/dsn_buf.h
 qmgr.o: ../../include/events.h
 qmgr.o: ../../include/flush_clnt.h
 qmgr.o: ../../include/iostuff.h
@@ -74,7 +73,6 @@ qmgr.o: ../../include/mail_params.h
 qmgr.o: ../../include/mail_proto.h
 qmgr.o: ../../include/mail_queue.h
 qmgr.o: ../../include/mail_server.h
-qmgr.o: ../../include/maps.h
 qmgr.o: ../../include/master_proto.h
 qmgr.o: ../../include/msg.h
 qmgr.o: ../../include/recipient_list.h
@@ -86,12 +84,10 @@ qmgr.o: ../../include/vstring.h
 qmgr.o: qmgr.c
 qmgr.o: qmgr.h
 qmgr_active.o: ../../include/abounce.h
-qmgr_active.o: ../../include/argv.h
 qmgr_active.o: ../../include/attr.h
 qmgr_active.o: ../../include/bounce.h
 qmgr_active.o: ../../include/defer.h
 qmgr_active.o: ../../include/deliver_request.h
-qmgr_active.o: ../../include/dict.h
 qmgr_active.o: ../../include/dsn.h
 qmgr_active.o: ../../include/dsn_buf.h
 qmgr_active.o: ../../include/dsn_mask.h
@@ -99,7 +95,6 @@ qmgr_active.o: ../../include/events.h
 qmgr_active.o: ../../include/mail_open_ok.h
 qmgr_active.o: ../../include/mail_params.h
 qmgr_active.o: ../../include/mail_queue.h
-qmgr_active.o: ../../include/maps.h
 qmgr_active.o: ../../include/msg.h
 qmgr_active.o: ../../include/msg_stats.h
 qmgr_active.o: ../../include/mymalloc.h
@@ -114,15 +109,12 @@ qmgr_active.o: ../../include/vstream.h
 qmgr_active.o: ../../include/vstring.h
 qmgr_active.o: qmgr.h
 qmgr_active.o: qmgr_active.c
-qmgr_bounce.o: ../../include/argv.h
 qmgr_bounce.o: ../../include/attr.h
 qmgr_bounce.o: ../../include/bounce.h
 qmgr_bounce.o: ../../include/deliver_completed.h
 qmgr_bounce.o: ../../include/deliver_request.h
-qmgr_bounce.o: ../../include/dict.h
 qmgr_bounce.o: ../../include/dsn.h
 qmgr_bounce.o: ../../include/dsn_buf.h
-qmgr_bounce.o: ../../include/maps.h
 qmgr_bounce.o: ../../include/msg_stats.h
 qmgr_bounce.o: ../../include/recipient_list.h
 qmgr_bounce.o: ../../include/scan_dir.h
@@ -132,15 +124,12 @@ qmgr_bounce.o: ../../include/vstream.h
 qmgr_bounce.o: ../../include/vstring.h
 qmgr_bounce.o: qmgr.h
 qmgr_bounce.o: qmgr_bounce.c
-qmgr_defer.o: ../../include/argv.h
 qmgr_defer.o: ../../include/attr.h
 qmgr_defer.o: ../../include/bounce.h
 qmgr_defer.o: ../../include/defer.h
 qmgr_defer.o: ../../include/deliver_request.h
-qmgr_defer.o: ../../include/dict.h
 qmgr_defer.o: ../../include/dsn.h
 qmgr_defer.o: ../../include/dsn_buf.h
-qmgr_defer.o: ../../include/maps.h
 qmgr_defer.o: ../../include/msg.h
 qmgr_defer.o: ../../include/msg_stats.h
 qmgr_defer.o: ../../include/recipient_list.h
@@ -151,10 +140,8 @@ qmgr_defer.o: ../../include/vstream.h
 qmgr_defer.o: ../../include/vstring.h
 qmgr_defer.o: qmgr.h
 qmgr_defer.o: qmgr_defer.c
-qmgr_deliver.o: ../../include/argv.h
 qmgr_deliver.o: ../../include/attr.h
 qmgr_deliver.o: ../../include/deliver_request.h
-qmgr_deliver.o: ../../include/dict.h
 qmgr_deliver.o: ../../include/dsb_scan.h
 qmgr_deliver.o: ../../include/dsn.h
 qmgr_deliver.o: ../../include/dsn_buf.h
@@ -164,9 +151,9 @@ qmgr_deliver.o: ../../include/iostuff.h
 qmgr_deliver.o: ../../include/mail_params.h
 qmgr_deliver.o: ../../include/mail_proto.h
 qmgr_deliver.o: ../../include/mail_queue.h
-qmgr_deliver.o: ../../include/maps.h
 qmgr_deliver.o: ../../include/msg.h
 qmgr_deliver.o: ../../include/msg_stats.h
+qmgr_deliver.o: ../../include/rcpt_print.h
 qmgr_deliver.o: ../../include/recipient_list.h
 qmgr_deliver.o: ../../include/scan_dir.h
 qmgr_deliver.o: ../../include/stringops.h
@@ -178,29 +165,20 @@ qmgr_deliver.o: ../../include/vstring.h
 qmgr_deliver.o: ../../include/vstring_vstream.h
 qmgr_deliver.o: qmgr.h
 qmgr_deliver.o: qmgr_deliver.c
-qmgr_enable.o: ../../include/argv.h
-qmgr_enable.o: ../../include/dict.h
 qmgr_enable.o: ../../include/dsn.h
-qmgr_enable.o: ../../include/dsn_buf.h
-qmgr_enable.o: ../../include/maps.h
 qmgr_enable.o: ../../include/msg.h
 qmgr_enable.o: ../../include/recipient_list.h
 qmgr_enable.o: ../../include/scan_dir.h
 qmgr_enable.o: ../../include/sys_defs.h
 qmgr_enable.o: ../../include/vbuf.h
 qmgr_enable.o: ../../include/vstream.h
-qmgr_enable.o: ../../include/vstring.h
 qmgr_enable.o: qmgr.h
 qmgr_enable.o: qmgr_enable.c
-qmgr_entry.o: ../../include/argv.h
 qmgr_entry.o: ../../include/attr.h
 qmgr_entry.o: ../../include/deliver_request.h
-qmgr_entry.o: ../../include/dict.h
 qmgr_entry.o: ../../include/dsn.h
-qmgr_entry.o: ../../include/dsn_buf.h
 qmgr_entry.o: ../../include/events.h
 qmgr_entry.o: ../../include/mail_params.h
-qmgr_entry.o: ../../include/maps.h
 qmgr_entry.o: ../../include/msg.h
 qmgr_entry.o: ../../include/msg_stats.h
 qmgr_entry.o: ../../include/mymalloc.h
@@ -224,11 +202,9 @@ qmgr_message.o: ../../include/dsn_attr_map.h
 qmgr_message.o: ../../include/dsn_buf.h
 qmgr_message.o: ../../include/dsn_mask.h
 qmgr_message.o: ../../include/iostuff.h
-qmgr_message.o: ../../include/mail_addr_find.h
 qmgr_message.o: ../../include/mail_params.h
 qmgr_message.o: ../../include/mail_proto.h
 qmgr_message.o: ../../include/mail_queue.h
-qmgr_message.o: ../../include/maps.h
 qmgr_message.o: ../../include/msg.h
 qmgr_message.o: ../../include/msg_stats.h
 qmgr_message.o: ../../include/myflock.h
@@ -253,13 +229,9 @@ qmgr_message.o: ../../include/vstream.h
 qmgr_message.o: ../../include/vstring.h
 qmgr_message.o: qmgr.h
 qmgr_message.o: qmgr_message.c
-qmgr_move.o: ../../include/argv.h
-qmgr_move.o: ../../include/dict.h
 qmgr_move.o: ../../include/dsn.h
-qmgr_move.o: ../../include/dsn_buf.h
 qmgr_move.o: ../../include/mail_queue.h
 qmgr_move.o: ../../include/mail_scan_dir.h
-qmgr_move.o: ../../include/maps.h
 qmgr_move.o: ../../include/msg.h
 qmgr_move.o: ../../include/recipient_list.h
 qmgr_move.o: ../../include/scan_dir.h
@@ -269,14 +241,10 @@ qmgr_move.o: ../../include/vstream.h
 qmgr_move.o: ../../include/vstring.h
 qmgr_move.o: qmgr.h
 qmgr_move.o: qmgr_move.c
-qmgr_queue.o: ../../include/argv.h
-qmgr_queue.o: ../../include/dict.h
 qmgr_queue.o: ../../include/dsn.h
-qmgr_queue.o: ../../include/dsn_buf.h
 qmgr_queue.o: ../../include/events.h
 qmgr_queue.o: ../../include/htable.h
 qmgr_queue.o: ../../include/mail_params.h
-qmgr_queue.o: ../../include/maps.h
 qmgr_queue.o: ../../include/msg.h
 qmgr_queue.o: ../../include/mymalloc.h
 qmgr_queue.o: ../../include/recipient_list.h
@@ -284,15 +252,10 @@ qmgr_queue.o: ../../include/scan_dir.h
 qmgr_queue.o: ../../include/sys_defs.h
 qmgr_queue.o: ../../include/vbuf.h
 qmgr_queue.o: ../../include/vstream.h
-qmgr_queue.o: ../../include/vstring.h
 qmgr_queue.o: qmgr.h
 qmgr_queue.o: qmgr_queue.c
-qmgr_scan.o: ../../include/argv.h
-qmgr_scan.o: ../../include/dict.h
 qmgr_scan.o: ../../include/dsn.h
-qmgr_scan.o: ../../include/dsn_buf.h
 qmgr_scan.o: ../../include/mail_scan_dir.h
-qmgr_scan.o: ../../include/maps.h
 qmgr_scan.o: ../../include/msg.h
 qmgr_scan.o: ../../include/mymalloc.h
 qmgr_scan.o: ../../include/recipient_list.h
@@ -300,21 +263,16 @@ qmgr_scan.o: ../../include/scan_dir.h
 qmgr_scan.o: ../../include/sys_defs.h
 qmgr_scan.o: ../../include/vbuf.h
 qmgr_scan.o: ../../include/vstream.h
-qmgr_scan.o: ../../include/vstring.h
 qmgr_scan.o: qmgr.h
 qmgr_scan.o: qmgr_scan.c
-qmgr_transport.o: ../../include/argv.h
 qmgr_transport.o: ../../include/attr.h
-qmgr_transport.o: ../../include/dict.h
 qmgr_transport.o: ../../include/dsn.h
-qmgr_transport.o: ../../include/dsn_buf.h
 qmgr_transport.o: ../../include/events.h
 qmgr_transport.o: ../../include/htable.h
 qmgr_transport.o: ../../include/iostuff.h
 qmgr_transport.o: ../../include/mail_conf.h
 qmgr_transport.o: ../../include/mail_params.h
 qmgr_transport.o: ../../include/mail_proto.h
-qmgr_transport.o: ../../include/maps.h
 qmgr_transport.o: ../../include/msg.h
 qmgr_transport.o: ../../include/mymalloc.h
 qmgr_transport.o: ../../include/recipient_list.h
@@ -322,6 +280,5 @@ qmgr_transport.o: ../../include/scan_dir.h
 qmgr_transport.o: ../../include/sys_defs.h
 qmgr_transport.o: ../../include/vbuf.h
 qmgr_transport.o: ../../include/vstream.h
-qmgr_transport.o: ../../include/vstring.h
 qmgr_transport.o: qmgr.h
 qmgr_transport.o: qmgr_transport.c
index 7f392d319f00c5af06b5fcb5ef9d8dd584953ffb..1f813ce4d482b108bfe3ab82953a1149a0e6c15c 100644 (file)
@@ -68,6 +68,7 @@
 #include <dsn_util.h>
 #include <dsn_buf.h>
 #include <dsb_scan.h>
+#include <rcpt_print.h>
 
 /* Application-specific. */
 
@@ -150,8 +151,8 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
     flags = message->tflags
        | entry->queue->dflags
        | (message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT);
-    QMGR_MSG_STATS(&stats, message);
-    attr_print(stream, ATTR_FLAG_MORE,
+    (void) QMGR_MSG_STATS(&stats, message);
+    attr_print(stream, ATTR_FLAG_NONE,
               ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
               ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name,
               ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id,
@@ -171,20 +172,14 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
             ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
             ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context,
+              ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, list.len,
               ATTR_TYPE_END);
     if (sender_buf != 0)
        vstring_free(sender_buf);
     for (recipient = list.info; recipient < list.info + list.len; recipient++)
-       attr_print(stream, ATTR_FLAG_MORE,
-                  ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, recipient->offset,
-                  ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, recipient->dsn_orcpt,
-                ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, recipient->dsn_notify,
-                  ATTR_TYPE_STR, MAIL_ATTR_ORCPT, recipient->orig_addr,
-                  ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient->address,
+       attr_print(stream, ATTR_FLAG_NONE,
+                  ATTR_TYPE_FUNC, rcpt_print, (void *) recipient,
                   ATTR_TYPE_END);
-    attr_print(stream, ATTR_FLAG_NONE,
-              ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0,
-              ATTR_TYPE_END);
     if (vstream_fflush(stream) != 0) {
        msg_warn("write to process (%s): %m", entry->queue->transport->name);
        return (-1);
@@ -218,7 +213,6 @@ static void qmgr_deliver_update(int unused_event, char *context)
     QMGR_MESSAGE *message = entry->message;
     static DSN_BUF *dsb;
     int     status;
-    DSN     dsn;
     RECIPIENT *recipient;
     int     nrcpt;
 
@@ -251,9 +245,8 @@ static void qmgr_deliver_update(int unused_event, char *context)
     if (status == DELIVER_STAT_CRASH) {
        message->flags |= DELIVER_STAT_DEFER;
        qmgr_transport_throttle(transport,
-                               DSN_SMTP(&dsn, "4.3.0",
-                                        "451 unknown mail transport error",
-                                        "unknown mail transport error"));
+                               DSN_SIMPLE(&dsb->dsn, "4.3.0",
+                                          "unknown mail transport error"));
        msg_warn("transport %s failure -- see a previous warning/fatal/panic logfile record for the problem description",
                 transport->name);
 
@@ -269,9 +262,9 @@ static void qmgr_deliver_update(int unused_event, char *context)
         */
        for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) {
            recipient = entry->rcpt_list.info + nrcpt;
-           qmgr_defer_recipient(message, recipient, &dsn);
+           qmgr_defer_recipient(message, recipient, &dsb->dsn);
        }
-       qmgr_defer_transport(transport, &dsn);
+       qmgr_defer_transport(transport, &dsb->dsn);
     }
 
     /*
@@ -282,21 +275,23 @@ static void qmgr_deliver_update(int unused_event, char *context)
      * (the todo list); stay away from queue entries that have been selected
      * (the busy list), or we would have dangling pointers. The queue itself
      * won't go away before we dispose of the current queue entry.
+     *
+     * XXX Caution: DSN_COPY() will panic on empty status or reason.
      */
 #define SUSPENDED      "delivery temporarily suspended: "
 
     if (status == DELIVER_STAT_DEFER) {
        message->flags |= DELIVER_STAT_DEFER;
        if (VSTRING_LEN(dsb->status)) {
-           /* Sanitize the DSN status from the delivery agent. */
+           /* Sanitize the DSN status/reason from the delivery agent. */
            if (!dsn_valid(vstring_str(dsb->status)))
                vstring_strcpy(dsb->status, "4.0.0");
            if (VSTRING_LEN(dsb->reason) == 0)
                vstring_strcpy(dsb->reason, "unknown error");
            vstring_prepend(dsb->reason, SUSPENDED, sizeof(SUSPENDED) - 1);
-           qmgr_queue_throttle(queue, DSN_FROM_DSN_BUF(&dsn, dsb));
+           qmgr_queue_throttle(queue, DSN_FROM_DSN_BUF(dsb));
            if (queue->window == 0)
-               qmgr_defer_todo(queue, &dsn);
+               qmgr_defer_todo(queue, &dsb->dsn);
        }
     }
 
@@ -339,9 +334,8 @@ void    qmgr_deliver(QMGR_TRANSPORT *transport, VSTREAM *stream)
      */
     if (qmgr_deliver_initial_reply(stream) != 0) {
        qmgr_transport_throttle(transport,
-                               DSN_SMTP(&dsn, "4.3.0",
-                                        "451 mail transport unavailable",
-                                        "mail transport unavailable"));
+                               DSN_SIMPLE(&dsn, "4.3.0",
+                                          "mail transport unavailable"));
        qmgr_defer_transport(transport, &dsn);
        (void) vstream_fclose(stream);
        return;
@@ -369,9 +363,8 @@ void    qmgr_deliver(QMGR_TRANSPORT *transport, VSTREAM *stream)
     if (qmgr_deliver_send_request(entry, stream) < 0) {
        qmgr_entry_unselect(queue, entry);
        qmgr_transport_throttle(transport,
-                               DSN_SMTP(&dsn, "4.3.0",
-                                        "451 mail transport unavailable",
-                                        "mail transport unavailable"));
+                               DSN_SIMPLE(&dsn, "4.3.0",
+                                          "mail transport unavailable"));
        qmgr_defer_transport(transport, &dsn);
        /* warning: entry and queue may be dangling pointers here */
        (void) vstream_fclose(stream);
index a973ffa65bb95afea9c010de0c91d59e2e82d422..146c7c678a2db828e3c382e6d3dcefc6a96393b8 100644 (file)
@@ -854,15 +854,13 @@ static int qmgr_resolve_one(QMGR_MESSAGE *message, RECIPIENT *recipient,
        resolve_clnt_verify_from(message->sender, addr, reply);
     if (reply->flags & RESOLVE_FLAG_FAIL) {
        qmgr_defer_recipient(message, recipient,
-                            DSN_SMTP(&dsn, "4.3.0",
-                                     "451 address resolver failure",
-                                     "address resolver failure"));
+                            DSN_SIMPLE(&dsn, "4.3.0",
+                                       "address resolver failure"));
        return (-1);
     } else if (reply->flags & RESOLVE_FLAG_ERROR) {
        qmgr_bounce_recipient(message, recipient,
-                             DSN_SMTP(&dsn, "5.1.3",
-                                      "553 bad address syntax",
-                                      "bad address syntax"));
+                             DSN_SIMPLE(&dsn, "5.1.3",
+                                        "bad address syntax"));
        return (-1);
     } else {
        return (0);
@@ -948,9 +946,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
         */
        if (recipient->address[0] == 0) {
            qmgr_bounce_recipient(message, recipient,
-                                 DSN_SMTP(&dsn, "5.1.3",
-                                          "553 null recipient address",
-                                          "null recipient address"));
+                                 DSN_SIMPLE(&dsn, "5.1.3",
+                                            "null recipient address"));
            continue;
        }
 
@@ -967,9 +964,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
         */
        if (var_allow_min_user == 0 && recipient->address[0] == '-') {
            qmgr_bounce_recipient(message, recipient,
-                                 DSN_SMTP(&dsn, "5.1.3",
-                                          "553 bad address syntax",
-                                          "bad address syntax"));
+                                 DSN_SIMPLE(&dsn, "5.1.3",
+                                            "bad address syntax"));
            continue;
        }
 
@@ -1015,9 +1011,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
                    break;
            if (*cpp) {
                qmgr_defer_recipient(message, recipient,
-                                    DSN_SMTP(&dsn, "4.3.2",
-                                             "450 delivery suspended",
-                                             "deferred transport"));
+                                    DSN_SIMPLE(&dsn, "4.3.2",
+                                               "deferred transport"));
                continue;
            }
        }
index 756dd48095a37917c8938ae67d87eeb4333480fb..d31f7bd390b0cdab552d5787ec1af7bac1cfe1d0 100644 (file)
@@ -289,9 +289,8 @@ void    qmgr_transport_alloc(QMGR_TRANSPORT *transport, QMGR_TRANSPORT_ALLOC_NOT
     if ((stream = mail_connect(MAIL_CLASS_PRIVATE, transport->name, BLOCK_MODE)) == 0) {
        msg_warn("connect to transport %s: %m", transport->name);
        qmgr_transport_throttle(transport,
-                               DSN_SMTP(&dsn, "4.3.0",
-                                        "451 mail transport unavailable",
-                                        "mail transport unavailable"));
+                               DSN_SIMPLE(&dsn, "4.3.0",
+                                          "mail transport unavailable"));
        return;
     }
     alloc = (QMGR_TRANSPORT_ALLOC *) mymalloc(sizeof(*alloc));
index e365a3e9d1a90d34724839e1e31a9e2889e6f5ab..967d9fb5afcb48f6738e30233283d51a07ea4380 100644 (file)
@@ -24,8 +24,8 @@
 /* .ad
 /* .fi
 /*     Some external commands cannot handle more than one recipient
-/*     per delivery request. Examples of such transports are pagers,
-/*     fax machines, and so on.
+/*     per delivery request. Examples of such transports are pagers
+/*     or fax machines.
 /*
 /*     To prevent Postfix from sending multiple recipients per delivery
 /*     request, specify
@@ -882,7 +882,6 @@ static int eval_command_status(int command_status, char *service,
     int     status;
     int     result = 0;
     int     n;
-    DSN     dsn;
 
     /*
      * Depending on the result, bounce or defer the message, and mark the
@@ -892,12 +891,12 @@ static int eval_command_status(int command_status, char *service,
     case PIPE_STAT_OK:
        dsb_update(why, "2.0.0", "relayed", DSB_SKIP_RMTA, DSB_SKIP_REPLY,
                   "delivered via %s service", service);
-       (void) DSN_FROM_DSN_BUF(&dsn, why);
+       (void) DSN_FROM_DSN_BUF(why);
        for (n = 0; n < request->rcpt_list.len; n++) {
            rcpt = request->rcpt_list.info + n;
            status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
                          request->queue_id, &request->msg_stats, rcpt,
-                         service, &dsn);
+                         service, &why->dsn);
            if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
                deliver_completed(src, rcpt->offset);
            result |= status;
@@ -905,14 +904,14 @@ static int eval_command_status(int command_status, char *service,
        break;
     case PIPE_STAT_BOUNCE:
     case PIPE_STAT_DEFER:
-       (void) DSN_FROM_DSN_BUF(&dsn, why);
+       (void) DSN_FROM_DSN_BUF(why);
        if (STR(why->status)[0] != '4') {
            for (n = 0; n < request->rcpt_list.len; n++) {
                rcpt = request->rcpt_list.info + n;
                status = bounce_append(DEL_REQ_TRACE_FLAGS(request->flags),
                                       request->queue_id,
                                       &request->msg_stats, rcpt,
-                                      service, &dsn);
+                                      service, &why->dsn);
                if (status == 0)
                    deliver_completed(src, rcpt->offset);
                result |= status;
@@ -923,7 +922,7 @@ static int eval_command_status(int command_status, char *service,
                result |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
                                       request->queue_id,
                                       &request->msg_stats, rcpt,
-                                      service, &dsn);
+                                      service, &why->dsn);
            }
        }
        break;
@@ -948,7 +947,6 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
     static PIPE_ATTR attr;
     RECIPIENT_LIST *rcpt_list = &request->rcpt_list;
     DSN_BUF *why = dsb_create();
-    DSN     dsn;
     VSTRING *buf;
     ARGV   *expanded_argv = 0;
     int     deliver_status;
@@ -1029,11 +1027,12 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
 
        deliver_status = 0;
        dsb_simple(why, "2.0.0", "delivers to command: %s", attr.command[0]);
+       (void) DSN_FROM_DSN_BUF(why);
        for (n = 0; n < request->rcpt_list.len; n++) {
            rcpt = request->rcpt_list.info + n;
            status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
                          request->queue_id, &request->msg_stats,
-                         rcpt, service, DSN_FROM_DSN_BUF(&dsn, why));
+                         rcpt, service, &why->dsn);
            if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
                deliver_completed(request->fp, rcpt->offset);
            deliver_status |= status;
index dffba604f51a25b46725bebf5c20c0ed47213e93..284f7c6866a7ece1aa39b1478f388dfe8bca042a 100644 (file)
@@ -58,6 +58,7 @@ depend: $(MAKES)
 postlock.o: ../../include/argv.h
 postlock.o: ../../include/deliver_flock.h
 postlock.o: ../../include/dot_lockfile.h
+postlock.o: ../../include/dsn.h
 postlock.o: ../../include/dsn_buf.h
 postlock.o: ../../include/dsn_util.h
 postlock.o: ../../include/iostuff.h
index dde0e834f553da80802e93190f391632bff6d6d0..d7d52652c74e3e4c8e1e0db46e57293dd7e03095 100644 (file)
@@ -66,7 +66,6 @@ qmgr.o: ../../include/argv.h
 qmgr.o: ../../include/attr.h
 qmgr.o: ../../include/dict.h
 qmgr.o: ../../include/dsn.h
-qmgr.o: ../../include/dsn_buf.h
 qmgr.o: ../../include/events.h
 qmgr.o: ../../include/flush_clnt.h
 qmgr.o: ../../include/iostuff.h
@@ -76,7 +75,6 @@ qmgr.o: ../../include/mail_params.h
 qmgr.o: ../../include/mail_proto.h
 qmgr.o: ../../include/mail_queue.h
 qmgr.o: ../../include/mail_server.h
-qmgr.o: ../../include/maps.h
 qmgr.o: ../../include/master_proto.h
 qmgr.o: ../../include/msg.h
 qmgr.o: ../../include/recipient_list.h
@@ -88,12 +86,10 @@ qmgr.o: ../../include/vstring.h
 qmgr.o: qmgr.c
 qmgr.o: qmgr.h
 qmgr_active.o: ../../include/abounce.h
-qmgr_active.o: ../../include/argv.h
 qmgr_active.o: ../../include/attr.h
 qmgr_active.o: ../../include/bounce.h
 qmgr_active.o: ../../include/defer.h
 qmgr_active.o: ../../include/deliver_request.h
-qmgr_active.o: ../../include/dict.h
 qmgr_active.o: ../../include/dsn.h
 qmgr_active.o: ../../include/dsn_buf.h
 qmgr_active.o: ../../include/dsn_mask.h
@@ -101,7 +97,6 @@ qmgr_active.o: ../../include/events.h
 qmgr_active.o: ../../include/mail_open_ok.h
 qmgr_active.o: ../../include/mail_params.h
 qmgr_active.o: ../../include/mail_queue.h
-qmgr_active.o: ../../include/maps.h
 qmgr_active.o: ../../include/msg.h
 qmgr_active.o: ../../include/msg_stats.h
 qmgr_active.o: ../../include/mymalloc.h
@@ -116,15 +111,12 @@ qmgr_active.o: ../../include/vstream.h
 qmgr_active.o: ../../include/vstring.h
 qmgr_active.o: qmgr.h
 qmgr_active.o: qmgr_active.c
-qmgr_bounce.o: ../../include/argv.h
 qmgr_bounce.o: ../../include/attr.h
 qmgr_bounce.o: ../../include/bounce.h
 qmgr_bounce.o: ../../include/deliver_completed.h
 qmgr_bounce.o: ../../include/deliver_request.h
-qmgr_bounce.o: ../../include/dict.h
 qmgr_bounce.o: ../../include/dsn.h
 qmgr_bounce.o: ../../include/dsn_buf.h
-qmgr_bounce.o: ../../include/maps.h
 qmgr_bounce.o: ../../include/msg_stats.h
 qmgr_bounce.o: ../../include/recipient_list.h
 qmgr_bounce.o: ../../include/scan_dir.h
@@ -134,15 +126,12 @@ qmgr_bounce.o: ../../include/vstream.h
 qmgr_bounce.o: ../../include/vstring.h
 qmgr_bounce.o: qmgr.h
 qmgr_bounce.o: qmgr_bounce.c
-qmgr_defer.o: ../../include/argv.h
 qmgr_defer.o: ../../include/attr.h
 qmgr_defer.o: ../../include/bounce.h
 qmgr_defer.o: ../../include/defer.h
 qmgr_defer.o: ../../include/deliver_request.h
-qmgr_defer.o: ../../include/dict.h
 qmgr_defer.o: ../../include/dsn.h
 qmgr_defer.o: ../../include/dsn_buf.h
-qmgr_defer.o: ../../include/maps.h
 qmgr_defer.o: ../../include/msg.h
 qmgr_defer.o: ../../include/msg_stats.h
 qmgr_defer.o: ../../include/recipient_list.h
@@ -153,10 +142,8 @@ qmgr_defer.o: ../../include/vstream.h
 qmgr_defer.o: ../../include/vstring.h
 qmgr_defer.o: qmgr.h
 qmgr_defer.o: qmgr_defer.c
-qmgr_deliver.o: ../../include/argv.h
 qmgr_deliver.o: ../../include/attr.h
 qmgr_deliver.o: ../../include/deliver_request.h
-qmgr_deliver.o: ../../include/dict.h
 qmgr_deliver.o: ../../include/dsb_scan.h
 qmgr_deliver.o: ../../include/dsn.h
 qmgr_deliver.o: ../../include/dsn_buf.h
@@ -166,9 +153,9 @@ qmgr_deliver.o: ../../include/iostuff.h
 qmgr_deliver.o: ../../include/mail_params.h
 qmgr_deliver.o: ../../include/mail_proto.h
 qmgr_deliver.o: ../../include/mail_queue.h
-qmgr_deliver.o: ../../include/maps.h
 qmgr_deliver.o: ../../include/msg.h
 qmgr_deliver.o: ../../include/msg_stats.h
+qmgr_deliver.o: ../../include/rcpt_print.h
 qmgr_deliver.o: ../../include/recipient_list.h
 qmgr_deliver.o: ../../include/scan_dir.h
 qmgr_deliver.o: ../../include/stringops.h
@@ -180,29 +167,20 @@ qmgr_deliver.o: ../../include/vstring.h
 qmgr_deliver.o: ../../include/vstring_vstream.h
 qmgr_deliver.o: qmgr.h
 qmgr_deliver.o: qmgr_deliver.c
-qmgr_enable.o: ../../include/argv.h
-qmgr_enable.o: ../../include/dict.h
 qmgr_enable.o: ../../include/dsn.h
-qmgr_enable.o: ../../include/dsn_buf.h
-qmgr_enable.o: ../../include/maps.h
 qmgr_enable.o: ../../include/msg.h
 qmgr_enable.o: ../../include/recipient_list.h
 qmgr_enable.o: ../../include/scan_dir.h
 qmgr_enable.o: ../../include/sys_defs.h
 qmgr_enable.o: ../../include/vbuf.h
 qmgr_enable.o: ../../include/vstream.h
-qmgr_enable.o: ../../include/vstring.h
 qmgr_enable.o: qmgr.h
 qmgr_enable.o: qmgr_enable.c
-qmgr_entry.o: ../../include/argv.h
 qmgr_entry.o: ../../include/attr.h
 qmgr_entry.o: ../../include/deliver_request.h
-qmgr_entry.o: ../../include/dict.h
 qmgr_entry.o: ../../include/dsn.h
-qmgr_entry.o: ../../include/dsn_buf.h
 qmgr_entry.o: ../../include/events.h
 qmgr_entry.o: ../../include/mail_params.h
-qmgr_entry.o: ../../include/maps.h
 qmgr_entry.o: ../../include/msg.h
 qmgr_entry.o: ../../include/msg_stats.h
 qmgr_entry.o: ../../include/mymalloc.h
@@ -214,12 +192,8 @@ qmgr_entry.o: ../../include/vstream.h
 qmgr_entry.o: ../../include/vstring.h
 qmgr_entry.o: qmgr.h
 qmgr_entry.o: qmgr_entry.c
-qmgr_job.o: ../../include/argv.h
-qmgr_job.o: ../../include/dict.h
 qmgr_job.o: ../../include/dsn.h
-qmgr_job.o: ../../include/dsn_buf.h
 qmgr_job.o: ../../include/htable.h
-qmgr_job.o: ../../include/maps.h
 qmgr_job.o: ../../include/msg.h
 qmgr_job.o: ../../include/mymalloc.h
 qmgr_job.o: ../../include/recipient_list.h
@@ -228,7 +202,6 @@ qmgr_job.o: ../../include/scan_dir.h
 qmgr_job.o: ../../include/sys_defs.h
 qmgr_job.o: ../../include/vbuf.h
 qmgr_job.o: ../../include/vstream.h
-qmgr_job.o: ../../include/vstring.h
 qmgr_job.o: qmgr.h
 qmgr_job.o: qmgr_job.c
 qmgr_message.o: ../../include/argv.h
@@ -243,11 +216,9 @@ qmgr_message.o: ../../include/dsn_attr_map.h
 qmgr_message.o: ../../include/dsn_buf.h
 qmgr_message.o: ../../include/dsn_mask.h
 qmgr_message.o: ../../include/iostuff.h
-qmgr_message.o: ../../include/mail_addr_find.h
 qmgr_message.o: ../../include/mail_params.h
 qmgr_message.o: ../../include/mail_proto.h
 qmgr_message.o: ../../include/mail_queue.h
-qmgr_message.o: ../../include/maps.h
 qmgr_message.o: ../../include/msg.h
 qmgr_message.o: ../../include/msg_stats.h
 qmgr_message.o: ../../include/myflock.h
@@ -273,13 +244,9 @@ qmgr_message.o: ../../include/vstream.h
 qmgr_message.o: ../../include/vstring.h
 qmgr_message.o: qmgr.h
 qmgr_message.o: qmgr_message.c
-qmgr_move.o: ../../include/argv.h
-qmgr_move.o: ../../include/dict.h
 qmgr_move.o: ../../include/dsn.h
-qmgr_move.o: ../../include/dsn_buf.h
 qmgr_move.o: ../../include/mail_queue.h
 qmgr_move.o: ../../include/mail_scan_dir.h
-qmgr_move.o: ../../include/maps.h
 qmgr_move.o: ../../include/msg.h
 qmgr_move.o: ../../include/recipient_list.h
 qmgr_move.o: ../../include/scan_dir.h
@@ -289,12 +256,8 @@ qmgr_move.o: ../../include/vstream.h
 qmgr_move.o: ../../include/vstring.h
 qmgr_move.o: qmgr.h
 qmgr_move.o: qmgr_move.c
-qmgr_peer.o: ../../include/argv.h
-qmgr_peer.o: ../../include/dict.h
 qmgr_peer.o: ../../include/dsn.h
-qmgr_peer.o: ../../include/dsn_buf.h
 qmgr_peer.o: ../../include/htable.h
-qmgr_peer.o: ../../include/maps.h
 qmgr_peer.o: ../../include/msg.h
 qmgr_peer.o: ../../include/mymalloc.h
 qmgr_peer.o: ../../include/recipient_list.h
@@ -302,17 +265,12 @@ qmgr_peer.o: ../../include/scan_dir.h
 qmgr_peer.o: ../../include/sys_defs.h
 qmgr_peer.o: ../../include/vbuf.h
 qmgr_peer.o: ../../include/vstream.h
-qmgr_peer.o: ../../include/vstring.h
 qmgr_peer.o: qmgr.h
 qmgr_peer.o: qmgr_peer.c
-qmgr_queue.o: ../../include/argv.h
-qmgr_queue.o: ../../include/dict.h
 qmgr_queue.o: ../../include/dsn.h
-qmgr_queue.o: ../../include/dsn_buf.h
 qmgr_queue.o: ../../include/events.h
 qmgr_queue.o: ../../include/htable.h
 qmgr_queue.o: ../../include/mail_params.h
-qmgr_queue.o: ../../include/maps.h
 qmgr_queue.o: ../../include/msg.h
 qmgr_queue.o: ../../include/mymalloc.h
 qmgr_queue.o: ../../include/recipient_list.h
@@ -320,15 +278,10 @@ qmgr_queue.o: ../../include/scan_dir.h
 qmgr_queue.o: ../../include/sys_defs.h
 qmgr_queue.o: ../../include/vbuf.h
 qmgr_queue.o: ../../include/vstream.h
-qmgr_queue.o: ../../include/vstring.h
 qmgr_queue.o: qmgr.h
 qmgr_queue.o: qmgr_queue.c
-qmgr_scan.o: ../../include/argv.h
-qmgr_scan.o: ../../include/dict.h
 qmgr_scan.o: ../../include/dsn.h
-qmgr_scan.o: ../../include/dsn_buf.h
 qmgr_scan.o: ../../include/mail_scan_dir.h
-qmgr_scan.o: ../../include/maps.h
 qmgr_scan.o: ../../include/msg.h
 qmgr_scan.o: ../../include/mymalloc.h
 qmgr_scan.o: ../../include/recipient_list.h
@@ -336,21 +289,16 @@ qmgr_scan.o: ../../include/scan_dir.h
 qmgr_scan.o: ../../include/sys_defs.h
 qmgr_scan.o: ../../include/vbuf.h
 qmgr_scan.o: ../../include/vstream.h
-qmgr_scan.o: ../../include/vstring.h
 qmgr_scan.o: qmgr.h
 qmgr_scan.o: qmgr_scan.c
-qmgr_transport.o: ../../include/argv.h
 qmgr_transport.o: ../../include/attr.h
-qmgr_transport.o: ../../include/dict.h
 qmgr_transport.o: ../../include/dsn.h
-qmgr_transport.o: ../../include/dsn_buf.h
 qmgr_transport.o: ../../include/events.h
 qmgr_transport.o: ../../include/htable.h
 qmgr_transport.o: ../../include/iostuff.h
 qmgr_transport.o: ../../include/mail_conf.h
 qmgr_transport.o: ../../include/mail_params.h
 qmgr_transport.o: ../../include/mail_proto.h
-qmgr_transport.o: ../../include/maps.h
 qmgr_transport.o: ../../include/msg.h
 qmgr_transport.o: ../../include/mymalloc.h
 qmgr_transport.o: ../../include/recipient_list.h
@@ -358,6 +306,5 @@ qmgr_transport.o: ../../include/scan_dir.h
 qmgr_transport.o: ../../include/sys_defs.h
 qmgr_transport.o: ../../include/vbuf.h
 qmgr_transport.o: ../../include/vstream.h
-qmgr_transport.o: ../../include/vstring.h
 qmgr_transport.o: qmgr.h
 qmgr_transport.o: qmgr_transport.c
index a2d96f511eccdf5bdcff7aa0e32fd58314c19a1b..9dc54c2f58815b8783e1483d68bd14b7428faa54 100644 (file)
@@ -73,6 +73,7 @@
 #include <dsn_util.h>
 #include <dsn_buf.h>
 #include <dsb_scan.h>
+#include <rcpt_print.h>
 
 /* Application-specific. */
 
@@ -155,8 +156,8 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
     flags = message->tflags
        | entry->queue->dflags
        | (message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT);
-    QMGR_MSG_STATS(&stats, message);
-    attr_print(stream, ATTR_FLAG_MORE,
+    (void) QMGR_MSG_STATS(&stats, message);
+    attr_print(stream, ATTR_FLAG_NONE,
               ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
               ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name,
               ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id,
@@ -176,20 +177,14 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
             ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
               ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
             ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context,
+              ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, list.len,
               ATTR_TYPE_END);
     if (sender_buf != 0)
        vstring_free(sender_buf);
     for (recipient = list.info; recipient < list.info + list.len; recipient++)
-       attr_print(stream, ATTR_FLAG_MORE,
-                  ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, recipient->offset,
-                  ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, recipient->dsn_orcpt,
-                ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, recipient->dsn_notify,
-                  ATTR_TYPE_STR, MAIL_ATTR_ORCPT, recipient->orig_addr,
-                  ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient->address,
+       attr_print(stream, ATTR_FLAG_NONE,
+                  ATTR_TYPE_FUNC, rcpt_print, (void *) recipient,
                   ATTR_TYPE_END);
-    attr_print(stream, ATTR_FLAG_NONE,
-              ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0,
-              ATTR_TYPE_END);
     if (vstream_fflush(stream) != 0) {
        msg_warn("write to process (%s): %m", entry->queue->transport->name);
        return (-1);
@@ -223,7 +218,6 @@ static void qmgr_deliver_update(int unused_event, char *context)
     QMGR_MESSAGE *message = entry->message;
     static DSN_BUF *dsb;
     int     status;
-    DSN     dsn;
     RECIPIENT *recipient;
     int     nrcpt;
 
@@ -256,9 +250,8 @@ static void qmgr_deliver_update(int unused_event, char *context)
     if (status == DELIVER_STAT_CRASH) {
        message->flags |= DELIVER_STAT_DEFER;
        qmgr_transport_throttle(transport,
-                               DSN_SMTP(&dsn, "4.3.0",
-                                        "451 unknown mail transport error",
-                                        "unknown mail transport error"));
+                               DSN_SIMPLE(&dsb->dsn, "4.3.0",
+                                          "unknown mail transport error"));
        msg_warn("transport %s failure -- see a previous warning/fatal/panic logfile record for the problem description",
                 transport->name);
 
@@ -274,9 +267,9 @@ static void qmgr_deliver_update(int unused_event, char *context)
         */
        for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) {
            recipient = entry->rcpt_list.info + nrcpt;
-           qmgr_defer_recipient(message, recipient, &dsn);
+           qmgr_defer_recipient(message, recipient, &dsb->dsn);
        }
-       qmgr_defer_transport(transport, &dsn);
+       qmgr_defer_transport(transport, &dsb->dsn);
     }
 
     /*
@@ -287,21 +280,23 @@ static void qmgr_deliver_update(int unused_event, char *context)
      * (the todo list); stay away from queue entries that have been selected
      * (the busy list), or we would have dangling pointers. The queue itself
      * won't go away before we dispose of the current queue entry.
+     *
+     * XXX Caution: DSN_COPY() will panic on empty status or reason.
      */
 #define SUSPENDED      "delivery temporarily suspended: "
 
     if (status == DELIVER_STAT_DEFER) {
        message->flags |= DELIVER_STAT_DEFER;
        if (VSTRING_LEN(dsb->status)) {
-           /* Sanitize the DSN status from the delivery agent. */
+           /* Sanitize the DSN status/reason from the delivery agent. */
            if (!dsn_valid(vstring_str(dsb->status)))
                vstring_strcpy(dsb->status, "4.0.0");
            if (VSTRING_LEN(dsb->reason) == 0)
                vstring_strcpy(dsb->reason, "unknown error");
            vstring_prepend(dsb->reason, SUSPENDED, sizeof(SUSPENDED) - 1);
-           qmgr_queue_throttle(queue, DSN_FROM_DSN_BUF(&dsn, dsb));
+           qmgr_queue_throttle(queue, DSN_FROM_DSN_BUF(dsb));
            if (queue->window == 0)
-               qmgr_defer_todo(queue, &dsn);
+               qmgr_defer_todo(queue, &dsb->dsn);
        }
     }
 
@@ -343,9 +338,8 @@ void    qmgr_deliver(QMGR_TRANSPORT *transport, VSTREAM *stream)
      */
     if (qmgr_deliver_initial_reply(stream) != 0) {
        qmgr_transport_throttle(transport,
-                               DSN_SMTP(&dsn, "4.3.0",
-                                        "451 mail transport unavailable",
-                                        "mail transport unavailable"));
+                               DSN_SIMPLE(&dsn, "4.3.0",
+                                          "mail transport unavailable"));
        qmgr_defer_transport(transport, &dsn);
        (void) vstream_fclose(stream);
        return;
@@ -372,9 +366,8 @@ void    qmgr_deliver(QMGR_TRANSPORT *transport, VSTREAM *stream)
     if (qmgr_deliver_send_request(entry, stream) < 0) {
        qmgr_entry_unselect(entry);
        qmgr_transport_throttle(transport,
-                               DSN_SMTP(&dsn, "4.3.0",
-                                        "451 mail transport unavailable",
-                                        "mail transport unavailable"));
+                               DSN_SIMPLE(&dsn, "4.3.0",
+                                          "mail transport unavailable"));
        qmgr_defer_transport(transport, &dsn);
        /* warning: entry may be a dangling pointer here */
        (void) vstream_fclose(stream);
index bd4ab56e2cccf55ee847b0c1c69395498c641b94..fdef95bcef6da4a9706eca8866fce3681be62bd8 100644 (file)
@@ -896,15 +896,13 @@ static int qmgr_resolve_one(QMGR_MESSAGE *message, RECIPIENT *recipient,
        resolve_clnt_verify_from(message->sender, addr, reply);
     if (reply->flags & RESOLVE_FLAG_FAIL) {
        qmgr_defer_recipient(message, recipient,
-                            DSN_SMTP(&dsn, "4.3.0",
-                                     "451 address resolver failure",
-                                     "address resolver failure"));
+                            DSN_SIMPLE(&dsn, "4.3.0",
+                                       "address resolver failure"));
        return (-1);
     } else if (reply->flags & RESOLVE_FLAG_ERROR) {
        qmgr_bounce_recipient(message, recipient,
-                             DSN_SMTP(&dsn, "5.1.3",
-                                      "553 bad address syntax",
-                                      "bad address syntax"));
+                             DSN_SIMPLE(&dsn, "5.1.3",
+                                        "bad address syntax"));
        return (-1);
     } else {
        return (0);
@@ -990,9 +988,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
         */
        if (recipient->address[0] == 0) {
            qmgr_bounce_recipient(message, recipient,
-                                 DSN_SMTP(&dsn, "5.1.3",
-                                          "553 null recipient address",
-                                          "null recipient address"));
+                                 DSN_SIMPLE(&dsn, "5.1.3",
+                                            "null recipient address"));
            continue;
        }
 
@@ -1009,9 +1006,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
         */
        if (var_allow_min_user == 0 && recipient->address[0] == '-') {
            qmgr_bounce_recipient(message, recipient,
-                                 DSN_SMTP(&dsn, "5.1.3",
-                                          "553 bad address syntax",
-                                          "bad address syntax"));
+                                 DSN_SIMPLE(&dsn, "5.1.3",
+                                            "bad address syntax"));
            continue;
        }
 
@@ -1057,9 +1053,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
                    break;
            if (*cpp) {
                qmgr_defer_recipient(message, recipient,
-                                    DSN_SMTP(&dsn, "4.3.2",
-                                             "450 delivery suspended",
-                                             "deferred transport"));
+                                    DSN_SIMPLE(&dsn, "4.3.2",
+                                               "deferred transport"));
                continue;
            }
        }
index 036d15b20a96d321954472d91da0df9ed047a2d4..14a4593ac238bcdfb855357bc219fc146cb8c45a 100644 (file)
@@ -294,9 +294,8 @@ void    qmgr_transport_alloc(QMGR_TRANSPORT *transport, QMGR_TRANSPORT_ALLOC_NOT
     if ((stream = mail_connect(MAIL_CLASS_PRIVATE, transport->name, BLOCK_MODE)) == 0) {
        msg_warn("connect to transport %s: %m", transport->name);
        qmgr_transport_throttle(transport,
-                               DSN_SMTP(&dsn, "4.3.0",
-                                        "451 mail transport unavailable",
-                                        "mail transport unavailable"));
+                               DSN_SIMPLE(&dsn, "4.3.0",
+                                          "mail transport unavailable"));
        return;
     }
     alloc = (QMGR_TRANSPORT_ALLOC *) mymalloc(sizeof(*alloc));
index aaf91d5e30223ffc304a9a9a1e16385b2451fa84..1ba772ef38cd1bf4649f98b3acf322290d6a53cb 100644 (file)
@@ -91,6 +91,7 @@ qmqpd.o: qmqpd.h
 qmqpd_peer.o: ../../include/attr.h
 qmqpd_peer.o: ../../include/inet_proto.h
 qmqpd_peer.o: ../../include/iostuff.h
+qmqpd_peer.o: ../../include/mail_params.h
 qmqpd_peer.o: ../../include/mail_proto.h
 qmqpd_peer.o: ../../include/mail_stream.h
 qmqpd_peer.o: ../../include/msg.h
index 45f39128188bb00973d92527cebfe9403cf60104..a2ce8a62e882e8fb7a2c46701bf373716579db48 100644 (file)
@@ -62,7 +62,6 @@ sendmail.o: ../../include/connect.h
 sendmail.o: ../../include/debug_process.h
 sendmail.o: ../../include/deliver_request.h
 sendmail.o: ../../include/dsn.h
-sendmail.o: ../../include/dsn_buf.h
 sendmail.o: ../../include/dsn_mask.h
 sendmail.o: ../../include/fullname.h
 sendmail.o: ../../include/header_opts.h
index 806f0279550b56d43a975b981acf4434c5f4befe..ef7e2a38f21b3f222b3635267777094c001b647f 100644 (file)
@@ -143,7 +143,8 @@ char   *var_empty_addr;
 #define SENDER_FORMAT  "%-11s%8ld %20.20s %s\n"
 #define DROP_FORMAT    "%-10s%c%8ld %20.20s (maildrop queue, sender UID %u)\n"
 
-static void showq_reasons(VSTREAM *, BOUNCE_LOG *, HTABLE *);
+static void showq_reasons(VSTREAM *, BOUNCE_LOG *, RCPT_BUF *, DSN_BUF *, 
+HTABLE *);
 
 #define STR(x) vstring_str(x)
 
@@ -160,6 +161,8 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
     long    msg_size = 0;
     BOUNCE_LOG *logfile;
     HTABLE *dup_filter = 0;
+    RCPT_BUF *rcpt_buf = 0;
+    DSN_BUF *dsn_buf = 0;
     char    status = (strcmp(queue, MAIL_QUEUE_ACTIVE) == 0 ? '*' :
                      strcmp(queue, MAIL_QUEUE_HOLD) == 0 ? '!' : ' ');
     int     msg_size_ok = 0;
@@ -236,47 +239,58 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
            && dup_filter == 0
            && (logfile = bounce_log_open(MAIL_QUEUE_DEFER, id, O_RDONLY, 0)) != 0) {
            dup_filter = htable_create(var_dup_filter_limit);
-           showq_reasons(client, logfile, dup_filter);
+           if (rcpt_buf == 0)
+               rcpt_buf = rcpb_create();
+           if (dsn_buf == 0)
+               dsn_buf = dsb_create();
+           showq_reasons(client, logfile, rcpt_buf, dsn_buf, dup_filter);
            if (bounce_log_close(logfile))
                msg_warn("close %s %s: %m", MAIL_QUEUE_DEFER, id);
        }
     }
     vstring_free(buf);
     vstring_free(printable_quoted_addr);
+    if (rcpt_buf)
+       rcpb_free(rcpt_buf);
+    if (dsn_buf)
+       dsb_free(dsn_buf);
     if (dup_filter)
        htable_free(dup_filter, (void (*) (char *)) 0);
 }
 
 /* showq_reasons - show deferral reasons */
 
-static void showq_reasons(VSTREAM *client, BOUNCE_LOG *bp, HTABLE *dup_filter)
+static void showq_reasons(VSTREAM *client, BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf, 
+DSN_BUF *dsn_buf, HTABLE *dup_filter)
 {
     char   *saved_reason = 0;
     int     padding;
+    RECIPIENT *rcpt = &rcpt_buf->rcpt;
+    DSN    *dsn = &dsn_buf->dsn;
 
-    while (bounce_log_read(bp) != 0) {
+    while (bounce_log_read(bp, rcpt_buf, dsn_buf) != 0) {
 
        /*
         * Update the duplicate filter.
         */
        if (var_dup_filter_limit == 0
            || dup_filter->used < var_dup_filter_limit)
-           if (htable_locate(dup_filter, bp->rcpt.address) == 0)
-               htable_enter(dup_filter, bp->rcpt.address, (char *) 0);
+           if (htable_locate(dup_filter, rcpt->address) == 0)
+               htable_enter(dup_filter, rcpt->address, (char *) 0);
 
        /*
         * Don't print the reason when the previous recipient had the same
         * problem.
         */
-       if (saved_reason == 0 || strcmp(saved_reason, bp->dsn.reason) != 0) {
+       if (saved_reason == 0 || strcmp(saved_reason, dsn->reason) != 0) {
            if (saved_reason)
                myfree(saved_reason);
-           saved_reason = mystrdup(bp->dsn.reason);
+           saved_reason = mystrdup(dsn->reason);
            if ((padding = 76 - strlen(saved_reason)) < 0)
                padding = 0;
            vstream_fprintf(client, "%*s(%s)\n", padding, "", saved_reason);
        }
-       vstream_fprintf(client, STRING_FORMAT, "", "", "", bp->rcpt.address);
+       vstream_fprintf(client, STRING_FORMAT, "", "", "", rcpt->address);
     }
     if (saved_reason)
        myfree(saved_reason);
index 00a4ed30b264fcb6fc29e7cf236bf9d430646f2f..668daea677727181e4b922f4adcdeffe18da3c35 100644 (file)
@@ -1,12 +1,10 @@
 SHELL  = /bin/sh
 SRCS   = smtp.c smtp_connect.c smtp_proto.c smtp_chat.c smtp_session.c \
        smtp_addr.c smtp_trouble.c smtp_state.c smtp_rcpt.c \
-       smtp_sasl_proto.c smtp_sasl_glue.c smtp_reuse.c smtp_map11.c \
-       smtp_dsn.c
+       smtp_sasl_proto.c smtp_sasl_glue.c smtp_reuse.c smtp_map11.c
 OBJS   = smtp.o smtp_connect.o smtp_proto.o smtp_chat.o smtp_session.o \
        smtp_addr.o smtp_trouble.o smtp_state.o smtp_rcpt.o \
-       smtp_sasl_proto.o smtp_sasl_glue.o smtp_reuse.o smtp_map11.o \
-       smtp_dsn.o
+       smtp_sasl_proto.o smtp_sasl_glue.o smtp_reuse.o smtp_map11.o
 HDRS   = smtp.h smtp_sasl.h smtp_addr.h smtp_reuse.h
 TESTSRC        = 
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
@@ -234,30 +232,6 @@ smtp_connect.o: smtp.h
 smtp_connect.o: smtp_addr.h
 smtp_connect.o: smtp_connect.c
 smtp_connect.o: smtp_reuse.h
-smtp_dsn.o: ../../include/argv.h
-smtp_dsn.o: ../../include/attr.h
-smtp_dsn.o: ../../include/deliver_request.h
-smtp_dsn.o: ../../include/dict.h
-smtp_dsn.o: ../../include/dsn.h
-smtp_dsn.o: ../../include/dsn_buf.h
-smtp_dsn.o: ../../include/htable.h
-smtp_dsn.o: ../../include/mail_params.h
-smtp_dsn.o: ../../include/maps.h
-smtp_dsn.o: ../../include/match_list.h
-smtp_dsn.o: ../../include/match_ops.h
-smtp_dsn.o: ../../include/msg_stats.h
-smtp_dsn.o: ../../include/recipient_list.h
-smtp_dsn.o: ../../include/resolve_clnt.h
-smtp_dsn.o: ../../include/scache.h
-smtp_dsn.o: ../../include/string_list.h
-smtp_dsn.o: ../../include/sys_defs.h
-smtp_dsn.o: ../../include/tls.h
-smtp_dsn.o: ../../include/tok822.h
-smtp_dsn.o: ../../include/vbuf.h
-smtp_dsn.o: ../../include/vstream.h
-smtp_dsn.o: ../../include/vstring.h
-smtp_dsn.o: smtp.h
-smtp_dsn.o: smtp_dsn.c
 smtp_map11.o: ../../include/argv.h
 smtp_map11.o: ../../include/attr.h
 smtp_map11.o: ../../include/deliver_request.h
index efb85e3e624594e2917c9c78b2a3e9a29f6cf7ee..980b4fd0eba8694d4ec5cb561345c157945fbc95 100644 (file)
@@ -7,6 +7,7 @@
        VAR_LMTP_SASL_PATH, DEF_LMTP_SASL_PATH, &var_smtp_sasl_path, 0, 0,
 #ifdef USE_TLS
        VAR_LMTP_SASL_TLS_OPTS, DEF_LMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0,
+       VAR_LMTP_SASL_TLSV_OPTS, DEF_LMTP_SASL_TLSV_OPTS, &var_smtp_sasl_tlsv_opts, 0, 0,
 #endif
        VAR_LMTP_SASL_MECHS, DEF_LMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0,
        VAR_LMTP_SASL_TYPE, DEF_LMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0,
@@ -70,5 +71,6 @@
        VAR_LMTP_TLS_NOTEOFFER, DEF_LMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer,
 #endif
        VAR_LMTP_SENDER_AUTH, DEF_LMTP_SENDER_AUTH, &var_smtp_sender_auth,
+       VAR_LMTP_CNAME_OVERR, DEF_LMTP_CNAME_OVERR, &var_smtp_cname_overr,
        0,
     };
index cc1199d4a4e4a8538298fa7b8fc0bb3c2c9f4b4c..a05bc8ae2e462ef28d1a10c5982bf0d8dc9aeb8c 100644 (file)
@@ -85,7 +85,6 @@
 /*     RFC 1652 (8bit-MIME transport)
 /*     RFC 1870 (Message Size Declaration)
 /*     RFC 2033 (LMTP protocol)
-/*     RFC 2034 (Enhanced Status Codes)
 /*     RFC 2045 (MIME: Format of Internet Message Bodies)
 /*     RFC 2046 (MIME: Media Types)
 /*     RFC 2554 (AUTH command)
 /*     SMTP client, typically to transform a locally valid address into
 /*     a globally valid address when sending mail across the Internet.
 /* .PP
+/*     Available in Postfix version 2.2.9 and later:
+/* .IP "\fBsmtp_cname_overrides_servername (version dependent)\fR"
+/*     Allow DNS CNAME records to override the servername that the
+/*     Postfix SMTP client uses for logging, SASL password lookup, TLS
+/*     policy decisions, or TLS certificate verification.
+/* .PP
 /*     Available in Postfix version 2.3 and later:
 /* .IP "\fBlmtp_discard_lhlo_keyword_address_maps (empty)\fR"
 /*     Lookup tables, indexed by the remote LMTP server address, with
 /*     The number of pseudo-random bytes that an \fBsmtp\fR(8) or \fBsmtpd\fR(8)
 /*     process requests from the \fBtlsmgr\fR(8) server in order to seed its
 /*     internal pseudo random number generator (PRNG).
+/* .PP
+/*     Available in Postfix version 2.3 and later:
+/* .IP "\fBsmtp_sasl_tls_verified_security_options ($smtp_sasl_tls_security_options)\fR"
+/*     The SASL authentication security options that the Postfix SMTP
+/*     client uses for TLS encrypted SMTP sessions with a verified server
+/*     certificate.
 /* RESOURCE AND RATE CONTROLS
 /* .ad
 /* .fi
@@ -606,6 +617,7 @@ char   *var_smtp_tls_per_site;
 #ifdef USE_TLS
 int     var_smtp_starttls_tmout;
 char   *var_smtp_sasl_tls_opts;
+char   *var_smtp_sasl_tlsv_opts;
 bool    var_smtp_tls_enforce_peername;
 int     var_smtp_tls_scert_vd;
 bool    var_smtp_tls_note_starttls_offer;
@@ -617,12 +629,11 @@ char   *var_prop_extension;
 bool    var_smtp_sender_auth;
 char   *var_lmtp_tcp_port;
 int     var_scache_proto_tmout;
+bool    var_smtp_cname_overr;
 
  /*
-  * Global variables. smtp_errno is set by the address lookup routines and by
-  * the connection management routines.
+  * Global variables.
   */
-int     smtp_errno;
 int     smtp_host_lookup_mask;
 STRING_LIST *smtp_cache_dest;
 SCACHE *smtp_scache;
index 9e4e5c8edd111e70254d3ac7f7151f7bd6eefbad..e79832fb0866a26af6bd4512220c29b0dd46c983 100644 (file)
@@ -8,6 +8,11 @@
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * System library.
+  */
+#include <string.h>
+
  /*
   * Utility library.
   */
@@ -77,7 +82,7 @@ typedef struct SMTP_STATE {
     /*
      * DSN Support introduced major bloat in error processing.
      */
-    VSTRING *dsn_reason;               /* on-the-fly formatting buffer */
+    DSN_BUF *why;                      /* on-the-fly formatting buffer */
 } SMTP_STATE;
 
 #define SET_NEXTHOP_STATE(state, lookup_mx, domain, port) { \
@@ -140,12 +145,14 @@ typedef struct SMTP_STATE {
  /*
   * smtp.c
   */
-extern int smtp_errno;                 /* XXX can we get rid of this? */
+#define SMTP_HAS_DSN(why)      (STR((why)->status)[0] != 0)
+#define SMTP_HAS_SOFT_DSN(why) (STR((why)->status)[0] == '4')
+#define SMTP_HAS_HARD_DSN(why) (STR((why)->status)[0] == '5')
+#define SMTP_HAS_LOOP_DSN(why) \
+    (SMTP_HAS_DSN(why) && strcmp(STR((why)->status) + 1, ".4.6") == 0)
 
-#define SMTP_ERR_NONE  0               /* no error */
-#define SMTP_ERR_FAIL  1               /* permanent error */
-#define SMTP_ERR_RETRY 2               /* temporary error */
-#define SMTP_ERR_LOOP  3               /* mailer loop */
+#define SMTP_SET_SOFT_DSN(why) (STR((why)->status)[0] = '4')
+#define SMTP_SET_HARD_DSN(why) (STR((why)->status)[0] = '5')
 
 extern int smtp_host_lookup_mask;      /* host lookup methods to use */
 
@@ -228,6 +235,11 @@ extern void smtp_tls_list_init(void);
 
 #endif
 
+ /*
+  * What's in a name?
+  */
+#define SMTP_HNAME(rr) (var_smtp_cname_overr ? (rr)->rname : (rr)->qname)
+
  /*
   * smtp_connect.c
   */
@@ -320,12 +332,14 @@ extern void smtp_chat_init(SMTP_SESSION *);
 extern void smtp_chat_reset(SMTP_SESSION *);
 extern void smtp_chat_notify(SMTP_SESSION *);
 
-#define SMTP_RESP_FAKE(resp, _code, _dsn, _str) \
-    ((resp)->code = (_code), \
+#define SMTP_RESP_FAKE(resp, _dsn) \
+    ((resp)->code = 0, \
      (resp)->dsn = (_dsn), \
-     (resp)->str = (_str), \
+     (resp)->str = DSN_BY_LOCAL_MTA, \
      (resp))
 
+#define DSN_BY_LOCAL_MTA       ((char *) 0)    /* DSN issued by local MTA */
+
  /*
   * These operations implement a redundant mark-and-sweep algorithm that
   * explicitly accounts for the fate of every recipient. The interface is
@@ -370,7 +384,7 @@ extern void smtp_rcpt_done(SMTP_STATE *, SMTP_RESP *, RECIPIENT *);
  /*
   * smtp_trouble.c
   */
-extern int smtp_sess_fail(SMTP_STATE *, DSN_BUF *);
+extern int smtp_sess_fail(SMTP_STATE *);
 extern int PRINTFLIKE(4, 5) smtp_site_fail(SMTP_STATE *, const char *,
                                             SMTP_RESP *, const char *,...);
 extern int PRINTFLIKE(4, 5) smtp_mesg_fail(SMTP_STATE *, const char *,
@@ -399,26 +413,6 @@ extern int smtp_map11_external(VSTRING *, MAPS *, int);
 extern int smtp_map11_tree(TOK822 *, MAPS *, int);
 extern int smtp_map11_internal(VSTRING *, MAPS *, int);
 
- /*
-  * smtp_dsn.c
-  */
-extern void PRINTFLIKE(6, 7) smtp_dsn_update(DSN_BUF *, const char *,
-                                                    const char *,
-                                                    int,
-                                                    const char *,
-                                                    const char *,...);
-extern void vsmtp_dsn_update(DSN_BUF *, const char *, const char *,
-                                    int, const char *,
-                                    const char *, va_list);
-extern void smtp_dsn_formal(DSN_BUF *, const char *, const char *, int,
-                                   const char *);
-
-#define SMTP_DSN_ASSIGN(dsn, mta, stat, resp, why) \
-    DSN_ASSIGN((dsn), (stat), DSB_DEF_ACTION, (why), DSB_DTYPE_SMTP, (resp), \
-       (mta) ? DSB_MTYPE_DNS : DSB_MTYPE_NONE, (mta))
-
-#define DSN_BY_LOCAL_MTA       ((char *) 0)    /* DSN issued by local MTA */
-
  /*
   * Silly little macros.
   */
index ddc06c87eea03c2f6a7a3c6e7a46e8adefa32398..bb9f0d147cb24e6daa8eda6c9ac4682943e87504 100644 (file)
 /*     when DNS lookups are explicitly disabled.
 /*
 /*     All routines either return a DNS_RR pointer, or return a null
-/*     pointer and set the \fIsmtp_errno\fR global variable accordingly:
-/* .IP SMTP_ERR_RETRY
-/*     The request failed due to a soft error, and should be retried later.
-/* .IP SMTP_ERR_FAIL
-/*     The request attempt failed due to a hard error.
-/* .IP SMTP_ERR_LOOP
-/*     The local machine is the best mail exchanger.
-/* .PP
-/*     In addition, a description of the problem is made available
-/*     via the \fIwhy\fR argument.
+/*     pointer and update the \fIwhy\fR argument accordingly.
 /* LICENSE
 /* .ad
 /* .fi
@@ -120,7 +111,7 @@ static void smtp_print_addr(char *what, DNS_RR *addr_list)
            msg_warn("skipping record type %s: %m", dns_strtype(addr->type));
        } else {
            msg_info("pref %4d host %s/%s",
-                    addr->pref, addr->name,
+                    addr->pref, SMTP_HNAME(addr),
                     hostaddr.buf);
        }
     }
@@ -170,22 +161,14 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
            addr_list = dns_rr_append(addr_list, addr);
            return (addr_list);
        default:
-           smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
-                           "4.4.3", 450, "450 Host not found");
-           smtp_errno = SMTP_ERR_RETRY;
+           dsb_status(why, "4.4.3");
            return (addr_list);
        case DNS_FAIL:
-           smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
-                           "5.4.3", 550, "550 Name server failure");
-           if (smtp_errno != SMTP_ERR_RETRY)
-               smtp_errno = SMTP_ERR_FAIL;
+           dsb_status(why, SMTP_HAS_SOFT_DSN(why) ? "4.4.3" : "5.4.3");
            return (addr_list);
        case DNS_INVAL:
        case DNS_NOTFOUND:
-           smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
-                           "5.4.4", 550, "550 Host not found");
-           if (smtp_errno != SMTP_ERR_RETRY)
-               smtp_errno = SMTP_ERR_FAIL;
+           dsb_status(why, SMTP_HAS_SOFT_DSN(why) ? "4.4.4" : "5.4.4");
            /* maybe native naming service will succeed */
            break;
        }
@@ -206,14 +189,11 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
 
     if (smtp_host_lookup_mask & SMTP_HOST_FLAG_NATIVE) {
        if ((aierr = hostname_to_sockaddr(host, (char *) 0, 0, &res0)) != 0) {
-           smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
-                           DSN_NOHOST(aierr) ? "4.4.4" : "4.3.0",
-                           450, "450 Host not found",
-                           "unable to look up host %s: %s",
-                           host, MAI_STRERROR(aierr));
-           if (smtp_errno != SMTP_ERR_RETRY)
-               smtp_errno =
-                   (RETRY_AI_ERROR(aierr) ? SMTP_ERR_RETRY : SMTP_ERR_FAIL);
+           dsb_simple(why, (SMTP_HAS_SOFT_DSN(why) || RETRY_AI_ERROR(aierr)) ?
+                      (DSN_NOHOST(aierr) ? "4.4.4" : "4.3.0") :
+                      (DSN_NOHOST(aierr) ? "5.4.4" : "5.3.0"),
+                      "unable to look up host %s: %s",
+                      host, MAI_STRERROR(aierr));
        } else {
            for (found = 0, res = res0; res != 0; res = res->ai_next) {
                if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
@@ -229,11 +209,8 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
            }
            freeaddrinfo(res0);
            if (found == 0) {
-               smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
-                               "5.4.4", 550, "550 Host not found",
-                               "%s: host not found", host);
-               if (smtp_errno != SMTP_ERR_RETRY)
-                   smtp_errno = SMTP_ERR_FAIL;
+               dsb_simple(why, SMTP_HAS_SOFT_DSN(why) ? "4.4.4" : "5.4.4",
+                          "%s: host not found", host);
            }
            return (addr_list);
        }
@@ -257,10 +234,11 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, DSN_BUF *why)
      * with DNS lookups (except if we're backup MX, and all the better MX
      * hosts can't be found).
      * 
-     * XXX 2821: update smtp_errno (0->FAIL upon unrecoverable lookup error,
-     * any->RETRY upon temporary lookup error) so that we can correctly
-     * handle the case of no resolvable MX host. Currently this is always
-     * treated as a soft error. RFC 2821 wants a more precise response.
+     * XXX 2821: update the error status (0->FAIL upon unrecoverable lookup
+     * error, any->RETRY upon temporary lookup error) so that we can
+     * correctly handle the case of no resolvable MX host. Currently this is
+     * always treated as a soft error. RFC 2821 wants a more precise
+     * response.
      */
     for (rr = mx_names; rr; rr = rr->next) {
        if (rr->type != T_MX)
@@ -349,7 +327,7 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
     unsigned best_pref;
     unsigned best_found;
 
-    smtp_errno = SMTP_ERR_NONE;                        /* Paranoia */
+    dsb_reset(why);                            /* Paranoia */
 
     /*
      * Preferences from DNS use 0..32767, fall-backs use 32768+.
@@ -406,16 +384,12 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
      */
     switch (dns_lookup(name, T_MX, 0, &mx_names, (VSTRING *) 0, why->reason)) {
     default:
-       smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
-                       "4.4.3", 450, "450 Host not found");
-       smtp_errno = SMTP_ERR_RETRY;
+       dsb_status(why, "4.4.3");
        if (var_ign_mx_lookup_err)
            addr_list = smtp_host_addr(name, misc_flags, why);
        break;
     case DNS_FAIL:
-       smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
-                       "5.4.3", 550, "550 Name server failure");
-       smtp_errno = SMTP_ERR_FAIL;
+       dsb_status(why, "5.4.3");
        if (var_ign_mx_lookup_err)
            addr_list = smtp_host_addr(name, misc_flags, why);
        break;
@@ -425,9 +399,15 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
        addr_list = smtp_addr_list(mx_names, why);
        dns_rr_free(mx_names);
        if (addr_list == 0) {
-           /* DSN and text does not change. */
-           if (var_smtp_defer_mxaddr)
-               smtp_errno = SMTP_ERR_RETRY;
+           /* Text does not change. */
+           if (var_smtp_defer_mxaddr) {
+               /* Don't clobber the null terminator. */
+               if (SMTP_HAS_HARD_DSN(why))
+                   SMTP_SET_SOFT_DSN(why);     /* XXX */
+               /* Require some error status. */
+               else if (!SMTP_HAS_SOFT_DSN(why))
+                   msg_panic("smtp_domain_addr: bad status");
+           }
            msg_warn("no MX host for %s has a valid address record", name);
            break;
        }
@@ -439,17 +419,11 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
            addr_list = smtp_truncate_self(addr_list, self->pref);
            if (addr_list == 0) {
                if (best_pref != best_found) {
-                   smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
-                                   "4.4.4", 450, "450 Host not found",
-                                   "unable to find primary relay for %s",
-                                   name);
-                   smtp_errno = SMTP_ERR_RETRY;
+                   dsb_simple(why, "4.4.4",
+                              "unable to find primary relay for %s", name);
                } else {
-                   smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
-                                   "5.4.6", 550, "550 Mailer loop",
-                                   "mail for %s loops back to myself",
-                                   name);
-                   smtp_errno = SMTP_ERR_LOOP;
+                   dsb_simple(why, "5.4.6", "mail for %s loops back to myself",
+                              name);
                }
            }
        }
@@ -459,9 +433,7 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
        }
        break;
     case DNS_INVAL:
-       smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
-                       "5.4.4", 550, "550 Host not found");
-       smtp_errno = SMTP_ERR_FAIL;
+       dsb_status(why, "5.4.4");
        break;
     case DNS_NOTFOUND:
        addr_list = smtp_host_addr(name, misc_flags, why);
@@ -481,7 +453,7 @@ DNS_RR *smtp_host_addr(char *host, int misc_flags, DSN_BUF *why)
 {
     DNS_RR *addr_list;
 
-    smtp_errno = SMTP_ERR_NONE;                        /* Paranoia */
+    dsb_reset(why);                            /* Paranoia */
 
     /*
      * If the host is specified by numerical address, just convert the
@@ -493,10 +465,7 @@ DNS_RR *smtp_host_addr(char *host, int misc_flags, DSN_BUF *why)
        && (misc_flags & SMTP_MISC_FLAG_LOOP_DETECT)
        && smtp_find_self(addr_list) != 0) {
        dns_rr_free(addr_list);
-       smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
-                       "5.4.6", 550, "550 Mailer loop",
-                       "mail for %s loops back to myself", host);
-       smtp_errno = SMTP_ERR_LOOP;
+       dsb_simple(why, "5.4.6", "mail for %s loops back to myself", host);
        return (0);
     }
     if (addr_list && addr_list->next) {
index 0b645dc473829f9d4c9e0137b15b13fef2bb56b6..7b68b157cbab9788c30035308909b6413004fd99 100644 (file)
@@ -400,13 +400,14 @@ void    smtp_chat_notify(SMTP_SESSION *session)
      * generate from untrusted data.
      */
 #define NULL_TRACE_FLAGS       0
+#define NO_QUEUE_ID            ((VSTRING *) 0)
 #define LENGTH 78
 #define INDENT 4
 
     notice = post_mail_fopen_nowait(mail_addr_double_bounce(),
                                    var_error_rcpt,
                                    CLEANUP_FLAG_MASK_INTERNAL,
-                                   NULL_TRACE_FLAGS);
+                                   NULL_TRACE_FLAGS, NO_QUEUE_ID);
     if (notice == 0) {
        msg_warn("postmaster notify: %m");
        return;
index 6e883116d27092c916e359dcce35210000b7de5f..8142cc47a3c29266ef70189f50554e46769e1533 100644 (file)
@@ -126,17 +126,14 @@ static SMTP_SESSION *smtp_connect_unix(const char *addr,
     int     len = strlen(addr);
     int     sock;
 
-    smtp_errno = SMTP_ERR_NONE;                        /* Paranoia */
+    dsb_reset(why);                            /* Paranoia */
 
     /*
      * Sanity checks.
      */
     if (len >= (int) sizeof(sock_un.sun_path)) {
        msg_warn("unix-domain name too long: %s", addr);
-       smtp_dsn_update(why, DSN_BY_LOCAL_MTA, "4.3.5",
-                       450, "450 Mail server configuration error",
-                       "Server configuration error");
-       smtp_errno = SMTP_ERR_RETRY;
+       dsb_simple(why, "4.3.5", "Server configuration error");
        return (0);
     }
 
@@ -182,7 +179,7 @@ static SMTP_SESSION *smtp_connect_addr(const char *destination, DNS_RR *addr,
     char   *bind_addr;
     char   *bind_var;
 
-    smtp_errno = SMTP_ERR_NONE;                        /* Paranoia */
+    dsb_reset(why);                            /* Paranoia */
 
     /*
      * Sanity checks.
@@ -190,10 +187,7 @@ static SMTP_SESSION *smtp_connect_addr(const char *destination, DNS_RR *addr,
     if (dns_rr_to_sa(addr, port, sa, &salen) != 0) {
        msg_warn("%s: skip address type %s: %m",
                 myname, dns_strtype(addr->type));
-       smtp_dsn_update(why, DSN_BY_LOCAL_MTA, "4.4.0",
-                       451, "451 network address conversion failed",
-                       "network address conversion failed: %m");
-       smtp_errno = SMTP_ERR_RETRY;
+       dsb_simple(why, "4.4.0", "network address conversion failed: %m");
        return (0);
     }
 
@@ -271,9 +265,9 @@ static SMTP_SESSION *smtp_connect_addr(const char *destination, DNS_RR *addr,
     SOCKADDR_TO_HOSTADDR(sa, salen, &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
     if (msg_verbose)
        msg_info("%s: trying: %s[%s] port %d...",
-                myname, addr->name, hostaddr.buf, ntohs(port));
+                myname, SMTP_HNAME(addr), hostaddr.buf, ntohs(port));
 
-    return (smtp_connect_sock(sock, sa, salen, addr->name, hostaddr.buf,
+    return (smtp_connect_sock(sock, sa, salen, SMTP_HNAME(addr), hostaddr.buf,
                              port, destination, why, sess_flags));
 }
 
@@ -290,7 +284,6 @@ static SMTP_SESSION *smtp_connect_sock(int sock, struct sockaddr * sa,
     int     conn_stat;
     int     saved_errno;
     VSTREAM *stream;
-    int     ch;
     time_t  start_time;
 
     start_time = time((time_t *) 0);
@@ -303,54 +296,12 @@ static SMTP_SESSION *smtp_connect_sock(int sock, struct sockaddr * sa,
     } else {
        conn_stat = sane_connect(sock, sa, salen);
     }
-    /* XXX 42X Means connection error, but only 421 is defined. */
     if (conn_stat < 0) {
-       smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
-                       "4.4.1", 420, "420 Unable to connect to server",
-                       "connect to %s[%s]: %m", name, addr);
-       smtp_errno = SMTP_ERR_RETRY;
+       dsb_simple(why, "4.4.1", "connect to %s[%s]: %m", name, addr);
        close(sock);
        return (0);
     }
-
-    /*
-     * Following code is obsolete now that the SMTP client will connect to
-     * alternate hosts when a session fails before "MAIL FROM".
-     */
-#if 1
     stream = vstream_fdopen(sock, O_RDWR);
-#else
-
-    /*
-     * Skip this host if it takes no action within some time limit. XXX Some
-     * MTAs use 426 to indicate a timeout error.
-     */
-    if (read_wait(sock, var_smtp_helo_tmout) < 0) {
-       smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
-                       "4.4.2", 426, "426 No response from server",
-                       "connect to %s[%s]: read timeout",
-                       addr->name, hostaddr.buf);
-       smtp_errno = SMTP_ERR_RETRY;
-       close(sock);
-       return (0);
-    }
-
-    /*
-     * Skip this host if it disconnects without talking to us.
-     */
-    stream = vstream_fdopen(sock, O_RDWR);
-    if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
-       smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
-                       "4.4.0", 421, "421 Lost connection",
-                       "connect to %s[%s]: server dropped connection"
-                       " without sending the initial greeting",
-                       addr->name, hostaddr.buf);
-       smtp_errno = SMTP_ERR_RETRY;
-       vstream_fclose(stream);
-       return (0);
-    }
-    vstream_ungetc(stream, ch);
-#endif
 
     /*
      * Bundle up what we have into a nice SMTP_SESSION object.
@@ -473,11 +424,11 @@ static void smtp_cleanup_session(SMTP_STATE *state)
 
 /* smtp_connect_local - connect to local server */
 
-static void smtp_connect_local(SMTP_STATE *state, const char *path,
-                                      DSN_BUF *why)
+static void smtp_connect_local(SMTP_STATE *state, const char *path)
 {
     DELIVER_REQUEST *request = state->request;
     SMTP_SESSION *session;
+    DSN_BUF *why = state->why;
 
     /*
      * It's too painful to weave this code into the SMTP connection
@@ -660,13 +611,14 @@ static int smtp_reuse_session(SMTP_STATE *state, int lookup_mx,
 /* smtp_connect_remote - establish remote connection */
 
 static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
-                                       char *def_service, DSN_BUF *why)
+                                       char *def_service)
 {
     DELIVER_REQUEST *request = state->request;
     ARGV   *sites;
     char   *dest;
     char  **cpp;
     int     non_fallback_sites;
+    DSN_BUF *why = state->why;
 
     /*
      * First try to deliver to the indicated destination, then try to deliver
@@ -759,7 +711,7 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
         * Don't try fall-back hosts if mail loops to myself. That would just
         * make the problem worse.
         */
-       if (addr_list == 0 && smtp_errno == SMTP_ERR_LOOP)
+       if (addr_list == 0 && SMTP_HAS_LOOP_DSN(why))
            state->misc_flags |= SMTP_MISC_FLAG_FINAL_NEXTHOP;
 
        /*
@@ -885,23 +837,22 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
     if (SMTP_RCPT_LEFT(state) > 0) {
 
        /*
-        * In case of a "no error" indication we make up an excuse; this can
-        * happen when the fall-back relay was already tried via a cached
-        * connection, so that the address list scrubber left behind an empty
-        * list.
+        * In case of a "no error" indication we make up an excuse: we did
+        * find the host address, but we did not attempt to connect to it.
+        * This can happen when the fall-back relay was already tried via a
+        * cached connection, so that the address list scrubber left behind
+        * an empty list.
         */
-       if (smtp_errno == SMTP_ERR_NONE) {
-           smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
-                           "4.3.0", 450, "450 Server unavailable",
-                           "server unavailable or unable to receive mail");
-           smtp_errno = SMTP_ERR_RETRY;
+       if (!SMTP_HAS_DSN(why)) {
+           dsb_simple(why, "4.3.0",
+                      "server unavailable or unable to receive mail");
        }
 
        /*
         * Pay attention to what could be configuration problems, and pretend
         * that these are recoverable rather than bouncing the mail.
         */
-       else if (smtp_errno != SMTP_ERR_RETRY
+       else if (!SMTP_HAS_SOFT_DSN(why)
                 && (state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) == 0) {
 
            /*
@@ -912,7 +863,6 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
                msg_warn("%s configuration problem", VAR_SMTP_FALLBACK);
                vstring_strcpy(why->status, "4.3.5");
                /* XXX Keep the diagnostic code and MTA. */
-               smtp_errno = SMTP_ERR_RETRY;
            }
 
            /*
@@ -923,18 +873,17 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
                msg_warn("%s configuration problem", VAR_RELAYHOST);
                vstring_strcpy(why->status, "4.3.5");
                /* XXX Keep the diagnostic code and MTA. */
-               smtp_errno = SMTP_ERR_RETRY;
            }
 
            /*
             * Mail for the next-hop destination loops back to myself. Pass
             * the mail to the best_mx_transport or bounce it.
             */
-           else if (smtp_errno == SMTP_ERR_LOOP && *var_bestmx_transp) {
+           else if (SMTP_HAS_LOOP_DSN(why) && *var_bestmx_transp) {
+               dsb_reset(why);                 /* XXX */
                state->status = deliver_pass_all(MAIL_CLASS_PRIVATE,
                                                 var_bestmx_transp,
                                                 request);
-               smtp_errno = 0;                 /* XXX */
                SMTP_RCPT_LEFT(state) = 0;      /* XXX */
            }
        }
@@ -953,7 +902,6 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
 int     smtp_connect(SMTP_STATE *state)
 {
     DELIVER_REQUEST *request = state->request;
-    DSN_BUF *why = dsb_create();
     char   *destination = request->nexthop;
 
     /*
@@ -975,11 +923,11 @@ int     smtp_connect(SMTP_STATE *state)
      */
     if (state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) {
        if (strncmp(destination, "unix:", 5) == 0) {
-           smtp_connect_local(state, destination + 5, why);
+           smtp_connect_local(state, destination + 5);
        } else {
            if (strncmp(destination, "inet:", 5) == 0)
                destination += 5;
-           smtp_connect_remote(state, destination, DEF_LMTP_SERVICE, why);
+           smtp_connect_remote(state, destination, DEF_LMTP_SERVICE);
        }
     }
 
@@ -992,7 +940,7 @@ int     smtp_connect(SMTP_STATE *state)
      * Postfix configurations that have a host with such a name.
      */
     else {
-       smtp_connect_remote(state, destination, DEF_SMTP_SERVICE, why);
+       smtp_connect_remote(state, destination, DEF_SMTP_SERVICE);
     }
 
     /*
@@ -1005,20 +953,10 @@ int     smtp_connect(SMTP_STATE *state)
      * deferred recipients at the end. We'd probably still want to bounce
      * recipients immediately, so we'd end up with another chunk of code for
      * defer logging only.
-     * 
-     * XXX Unlike enhanced status codes, changing a 4xx into 5xx SMTP code is
-     * not simply a matter of changing the initial digit. What we're doing
-     * here is correct only under specific conditions, such as changing 450
-     * into 550 or vice versa.
      */
     if (SMTP_RCPT_LEFT(state) > 0) {
        state->misc_flags |= SMTP_MISC_FLAG_FINAL_SERVER;       /* XXX */
-       if (smtp_errno == SMTP_ERR_RETRY)
-           STR(why->status)[0] = STR(why->dtext)[0] = '4';     /* XXX */
-       else
-           STR(why->status)[0] = STR(why->dtext)[0] = '5';     /* XXX */
-       why->dcode = atoi(STR(why->dtext));     /* XXX */
-       smtp_sess_fail(state, why);
+       smtp_sess_fail(state);
 
        /*
         * Sanity check. Don't silently lose recipients.
@@ -1027,6 +965,5 @@ int     smtp_connect(SMTP_STATE *state)
        if (SMTP_RCPT_LEFT(state) > 0)
            msg_panic("smtp_connect: left-over recipients");
     }
-    dsb_free(why);
     return (state->status);
 }
diff --git a/postfix/src/smtp/smtp_dsn.c b/postfix/src/smtp/smtp_dsn.c
deleted file mode 100644 (file)
index a48701e..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*++
-/* NAME
-/*     smtp_dsn 3
-/* SUMMARY
-/*     application-specific DSN wrappers
-/* SYNOPSIS
-/*     #include <smtp.h>
-/*
-/*     void    smtp_dsn_update(dsb, mta_name, status, code, reply,
-/*                             reason_fmt, ...)
-/*     SMTP_DSN        *dsb;
-/*     const char *mta_name;
-/*     const char *status;
-/*     int     code;
-/*     const char *reply;
-/*     const char *reason_fmt;
-/*
-/*     void    vsmtp_dsn_update(dsb, mta_name, status, code, reply,
-/*                             reason_fmt, ap)
-/*     SMTP_DSN        *dsb;
-/*     const char *mta_name;
-/*     const char *status;
-/*     int     code;
-/*     const char *reply;
-/*     const char *reason_fmt;
-/*     va_list ap;
-/*
-/*     void    smtp_dsn_formal(dsb, mta_name, status, code, reply)
-/*     DSN_BUF *dsb;
-/*     const char *mta_name;
-/*     const char *status;
-/*     int     code;
-/*     const char *reply;
-/*
-/*     DSN     *SMTP_DSN_ASSIGN(dsn, mta_name, status, action, reply, reason)
-/*     DSN     *dsn;
-/*     const char *mta_name;
-/*     const char *status;
-/*     const char *action;
-/*     const char *reply;
-/*     const char *reason;
-/* DESCRIPTION
-/*     This module implements application-specific wrappers for
-/*     the dsbuf(3) delivery status information module. The purpose
-/*     of the wrappers is to eliminate clutter from the code.
-/*
-/*     smtp_dsn_update() updates the formal and informal delivery
-/*     status attributes.
-/*
-/*     vsmtp_dsn_update() implements an alternative interface.
-/*
-/*     smtp_dsn_formal() updates the formal delivery status
-/*     attributes and leaves the informal reason attribute unmodified.
-/*
-/*     SMTP_DSN_ASSIGN() is a wrapper around the DSN_ASSIGN macro.
-/*
-/*     Arguments:
-/* .IP dsb
-/*     Delivery status information. See dsbuf(3).
-/* .IP mta_name
-/*     The name of the MTA that issued the response given with the
-/*     status and reply arguments. Specify DSN_BY_LOCAL_MTA for
-/*     status and "reply" information that was issued by the local
-/*     MTA.
-/* .IP status
-/*     RFC 3463 status code.
-/* .IP code
-/*     SMTP reply code.
-/* .IP reply
-/*     SMTP reply code followed by text. The bounce(8) server
-/*     replaces non-printable characters by '?', so it is a good
-/*     idea to replace embedded newline characters by spaces
-/*     before using this module.
-/* .IP reason_fmt
-/*     Format string for the informal reason attribute.
-/* .IP DIAGNOSTICS
-/*     Fatal: out of memory. Panic: invalid arguments.
-/* BUGS
-/*     It seems wasteful to copy mostly-constant information into
-/*     VSTRING buffers, but it's unavoidable if one needs to
-/*     delegate work to a subordinate routine, and report the error
-/*     after the subordinate has terminated.
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/*     Wietse Venema
-/*     IBM T.J. Watson Research
-/*     P.O. Box 704
-/*     Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-#include <stdlib.h>                    /* 44BSD stdarg.h uses abort() */
-#include <stdarg.h>
-
-/* Utility library. */
-
-#include <vstring.h>
-
-/* Global library. */
-
-#include <dsn_buf.h>
-#include <mail_params.h>
-
-/* Application-specific. */
-
-#include <smtp.h>
-
-/* smtp_dsn_update - update formal and informal DSN attributes */
-
-void    smtp_dsn_update(DSN_BUF *why, const char *mta_name,
-                               const char *status, int code,
-                               const char *reply,
-                               const char *format,...)
-{
-    va_list ap;
-
-    va_start(ap, format);
-    vsmtp_dsn_update(why, mta_name, status, code, reply, format, ap);
-    va_end(ap);
-}
-
-/* vsmtp_dsn_update - update formal and informal DSN attributes */
-
-void    vsmtp_dsn_update(DSN_BUF *why, const char *mta_name,
-                                const char *status, int code,
-                                const char *reply,
-                                const char *format, va_list ap)
-{
-    dsb_formal(why, status, DSB_DEF_ACTION,
-              mta_name ? DSB_MTYPE_DNS : DSB_MTYPE_NONE,
-              mta_name, var_procname, code, reply);
-    vstring_vsprintf(why->reason, format, ap);
-}
-
-/* smtp_dsn_formal - update formal DSN attributes only */
-
-void    smtp_dsn_formal(DSN_BUF *why, const char *mta_name,
-                               const char *status, int code,
-                               const char *reply)
-{
-    dsb_formal(why, status, DSB_DEF_ACTION,
-              mta_name ? DSB_MTYPE_DNS : DSB_MTYPE_NONE,
-              mta_name, var_procname, code, reply);
-}
index f3a1494b1428618627b434111aa4acd4b68654d0..2aed9efa14208e496ff68688d083f51dca01488e 100644 (file)
@@ -8,6 +8,7 @@
        VAR_SMTP_SASL_PATH, DEF_SMTP_SASL_PATH, &var_smtp_sasl_path, 0, 0,
 #ifdef USE_TLS
        VAR_SMTP_SASL_TLS_OPTS, DEF_SMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0,
+       VAR_SMTP_SASL_TLSV_OPTS, DEF_SMTP_SASL_TLSV_OPTS, &var_smtp_sasl_tlsv_opts, 0, 0,
 #endif
        VAR_SMTP_SASL_MECHS, DEF_SMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0,
        VAR_SMTP_SASL_TYPE, DEF_SMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0,
@@ -74,5 +75,6 @@
        VAR_SMTP_TLS_NOTEOFFER, DEF_SMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer,
 #endif
        VAR_SMTP_SENDER_AUTH, DEF_SMTP_SENDER_AUTH, &var_smtp_sender_auth,
+       VAR_SMTP_CNAME_OVERR, DEF_SMTP_CNAME_OVERR, &var_smtp_cname_overr,
        0,
     };
index 337fda0a0df881ca51346b874ed3be483a92bbc4..5cee7ff284e90a250d6d726a3bde88573da3113d 100644 (file)
@@ -405,14 +405,12 @@ int     smtp_helo(SMTP_STATE *state)
                             session->namaddrport, var_myhostname);
                    if (session->features & SMTP_FEATURE_BEST_MX)
                        return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
-                                        SMTP_RESP_FAKE(&fake, 554, "5.4.6",
-                                                       "554 Mailer loop"),
+                                            SMTP_RESP_FAKE(&fake, "5.4.6"),
                                         "mail for %s loops back to myself",
                                               request->nexthop));
                    else
                        return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
-                                        SMTP_RESP_FAKE(&fake, 450, "4.4.6",
-                                                       "450 Mailer loop"),
+                                            SMTP_RESP_FAKE(&fake, "4.4.6"),
                                         "mail for %s loops back to myself",
                                               request->nexthop));
                }
@@ -542,10 +540,8 @@ int     smtp_helo(SMTP_STATE *state)
            smtp_chat_cmd(session, "STARTTLS");
            if ((resp = smtp_chat_resp(session))->code / 100 == 2) {
 #ifdef USE_SASL_AUTH
-               if (session->sasl_mechanism_list) {
-                   myfree(session->sasl_mechanism_list);
-                   session->sasl_mechanism_list = 0;
-               }
+               if (session->features & SMTP_FEATURE_AUTH)
+                   smtp_sasl_cleanup(session);
 #endif
                session->features = saved_features;
                /* XXX Mix-up of per-session and per-request flags. */
@@ -578,39 +574,26 @@ int     smtp_helo(SMTP_STATE *state)
        if (session->tls_enforce_tls) {
            if (!(session->features & SMTP_FEATURE_STARTTLS)) {
                return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
-                                      SMTP_RESP_FAKE(&fake, 421, "4.7.4",
-                                   "421 TLS is required, but unavailable"),
+                                      SMTP_RESP_FAKE(&fake, "4.7.4"),
                          "TLS is required, but was not offered by host %s",
                                       session->namaddr));
            } else if (smtp_tls_ctx == 0) {
                return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
-                                      SMTP_RESP_FAKE(&fake, 421, "4.7.5",
-                                   "421 TLS is required, but unavailable"),
+                                      SMTP_RESP_FAKE(&fake, "4.7.5"),
                     "TLS is required, but our TLS engine is unavailable"));
            } else {
                msg_warn("%s: TLS is required but unavailable, don't know why",
                         myname);
                return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
-                                      SMTP_RESP_FAKE(&fake, 421, "4.7.0",
-                                   "421 TLS is required, but unavailable"),
+                                      SMTP_RESP_FAKE(&fake, "4.7.0"),
                                       "TLS is required, but unavailable"));
            }
        }
     }
 #endif
 #ifdef USE_SASL_AUTH
-    if (var_smtp_sasl_enable && (session->features & SMTP_FEATURE_AUTH)) {
-       if (session->sasl_mechanism_list != 0)
-           return (smtp_sasl_helo_login(state));
-       else
-           return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
-                                  SMTP_RESP_FAKE(&fake, 421, "4.7.0",
-                                         "421 SASL authentication failed: "
-                 "server offered no compatible authentication mechanisms"),
-                                  "SASL authentication failed: "
-               "server %s offered no compatible authentication mechanisms",
-                                  session->namaddr));
-    }
+    if (var_smtp_sasl_enable && (session->features & SMTP_FEATURE_AUTH))
+       return (smtp_sasl_helo_login(state));
 #endif
 
     return (0);
@@ -669,8 +652,7 @@ static int smtp_start_tls(SMTP_STATE *state)
     vstring_free(serverid);
     if (session->tls_context == 0)
        return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
-                              SMTP_RESP_FAKE(&fake, 421, "4.7.5",
-                                             "421 TLS handshake failure"),
+                              SMTP_RESP_FAKE(&fake, "4.7.5"),
                               "Cannot start TLS: handshake failure"));
 
     /*
@@ -860,14 +842,11 @@ static void smtp_mime_fail(SMTP_STATE *state, int mime_errs)
 {
     MIME_STATE_DETAIL *detail;
     SMTP_RESP fake;
-    char   *text;
 
     detail = mime_state_detail(mime_errs);
-    text = concatenate("554 ", detail->text, (char *) 0);
     smtp_mesg_fail(state, DSN_BY_LOCAL_MTA,
-                  SMTP_RESP_FAKE(&fake, 554, detail->dsn, text),
+                  SMTP_RESP_FAKE(&fake, detail->dsn),
                   "%s", detail->text);
-    myfree(text);
 }
 
 /* smtp_loop - exercise the SMTP protocol engine */
@@ -1638,8 +1617,7 @@ int     smtp_xfer(SMTP_STATE *state)
      */
     if (session->size_limit > 0 && session->size_limit < request->data_size) {
        smtp_mesg_fail(state, DSN_BY_LOCAL_MTA,
-                      SMTP_RESP_FAKE(&fake, 552, "5.3.4",
-                                     "552 message too large"),
+                      SMTP_RESP_FAKE(&fake, "5.3.4"),
                    "message size %lu exceeds size limit %.0f of server %s",
                       request->data_size, (double) session->size_limit,
                       session->namaddr);
index 1b64f6b06e6c368fdc60ec5827e8954b2cefe74f..31599464b2edb52baab59e8cb696029c01289bb5 100644 (file)
@@ -131,7 +131,7 @@ void    smtp_rcpt_done(SMTP_STATE *state, SMTP_RESP *resp, RECIPIENT *rcpt)
 {
     DELIVER_REQUEST *request = state->request;
     SMTP_SESSION *session = state->session;
-    DSN     dsn;
+    DSN_BUF *why = state->why;
     int     status;
 
     /*
@@ -144,13 +144,12 @@ void    smtp_rcpt_done(SMTP_STATE *state, SMTP_RESP *resp, RECIPIENT *rcpt)
     if (session->features & SMTP_FEATURE_DSN)
        rcpt->dsn_notify &= ~DSN_NOTIFY_SUCCESS;
 
-    (void) SMTP_DSN_ASSIGN(&dsn, session->host, resp->dsn,
-                          resp->str, resp->str);
-    dsn.action = "relayed";
+    dsb_update(why, resp->dsn, "relayed", DSB_MTYPE_DNS, session->host,
+              DSB_DTYPE_SMTP, resp->str, "%s", resp->str);
 
     status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
                  request->queue_id, &request->msg_stats, rcpt,
-                 session->namaddrport, &dsn);
+                 session->namaddrport, DSN_FROM_DSN_BUF(why));
     if (status == 0)
        if (request->flags & DEL_REQ_FLAG_SUCCESS)
            deliver_completed(state->src, rcpt->offset);
index b08ed135c12d21274c19ab7337ff52d9b883d2bd..38e78ddccb4cd7ad452867511dd18dd650d4fa31 100644 (file)
@@ -283,8 +283,9 @@ int     smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why)
                                session->sasl_passwd,
                                &mechanism, session->sasl_reply);
     if (result != XSASL_AUTH_OK) {
-       dsb_update(why, "4.7.0", DSB_DEF_ACTION, DSB_SKIP_RMTA, DSB_DTYPE_SASL,
-                  421, STR(session->sasl_reply),
+       dsb_update(why, "4.7.0", DSB_DEF_ACTION, DSB_SKIP_RMTA,
+                  DSB_DTYPE_SASL, STR(session->sasl_reply),
+                  "SASL authentication failed; "
                   "cannot authenticate to server %s: %s",
                   session->namaddr, STR(session->sasl_reply));
        return (-1);
@@ -317,8 +318,8 @@ int     smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why)
                                   session->sasl_reply);
        if (result != XSASL_AUTH_OK) {
            dsb_update(why, "4.7.0", DSB_DEF_ACTION,    /* Fix 200512 */
-                      DSB_SKIP_RMTA, DSB_DTYPE_SASL,
-                      421, STR(session->sasl_reply),
+                   DSB_SKIP_RMTA, DSB_DTYPE_SASL, STR(session->sasl_reply),
+                      "SASL authentication failed; "
                       "cannot authenticate to server %s: %s",
                       session->namaddr, STR(session->sasl_reply));
            return (-1);                        /* Fix 200512 */
@@ -334,9 +335,11 @@ int     smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why)
      * We completed the authentication protocol.
      */
     if (resp->code / 100 != 2) {
-       smtp_dsn_update(why, session->host, resp->dsn, resp->code, resp->str,
-                       "SASL authentication failed; server %s said: %s",
-                       session->namaddr, resp->str);
+       dsb_update(why, resp->dsn, DSB_DEF_ACTION,
+                  DSB_MTYPE_DNS, session->host,
+                  var_procname, resp->str,
+                  "SASL authentication failed; server %s said: %s",
+                  session->namaddr, resp->str);
        return (0);
     }
     return (1);
index 699f163d2c5724211cc460f932ecbf3df501c857..0799d2c441edbe724cb2a711f154a94cab69a194 100644 (file)
@@ -149,7 +149,7 @@ void    smtp_sasl_helo_auth(SMTP_SESSION *session, const char *words)
 int     smtp_sasl_helo_login(SMTP_STATE *state)
 {
     SMTP_SESSION *session = state->session;
-    DSN_BUF *why;
+    DSN_BUF *why = state->why;
     int     ret;
 
     /*
@@ -168,16 +168,28 @@ int     smtp_sasl_helo_login(SMTP_STATE *state)
      * error is unrecoverable from a session point of view - the session will
      * not be reused.
      */
-    why = dsb_create();
     ret = 0;
-    smtp_sasl_start(session, VAR_SMTP_SASL_OPTS, var_smtp_sasl_opts);
-    if (smtp_sasl_authenticate(session, why) <= 0) {
-       vstring_prepend(why->reason, "Authentication failed: ",
-                       sizeof("Authentication failed: ") - 1);
-       ret = smtp_sess_fail(state, why);
+    if (session->sasl_mechanism_list == 0) {
+       dsb_simple(why, "4.7.0", "SASL authentication failed: "
+               "server %s offered no compatible authentication mechanisms for this type of connection security",
+                  session->namaddr);
+       ret = smtp_sess_fail(state);
        /* Session reuse is disabled. */
+    } else {
+       if (session->tls_context == 0)
+           smtp_sasl_start(session, VAR_SMTP_SASL_OPTS, 
+               var_smtp_sasl_opts);
+       else if (session->tls_context->peer_verified == 0)
+           smtp_sasl_start(session, VAR_SMTP_SASL_TLS_OPTS, 
+               var_smtp_sasl_tls_opts);
+       else
+           smtp_sasl_start(session, VAR_SMTP_SASL_TLSV_OPTS, 
+               var_smtp_sasl_tlsv_opts);
+       if (smtp_sasl_authenticate(session, why) <= 0) {
+           ret = smtp_sess_fail(state);
+           /* Session reuse is disabled. */
+       }
     }
-    dsb_free(why);
     return (ret);
 }
 
index 9f364b6710582c958e126c3b8fa55a30543153c2..b396397a1ae0c86e6b7a6c356289ee239c247307 100644 (file)
@@ -76,7 +76,7 @@ SMTP_STATE *smtp_state_alloc(void)
        state->endp_prop = 0;
        state->cache_used = 0;
     }
-    state->dsn_reason = 0;
+    state->why = dsb_create();
 
     /*
      * The process name, "smtp" or "lmtp", is also used as the DSN server
@@ -112,8 +112,8 @@ void    smtp_state_free(SMTP_STATE *state)
        vstring_free(state->endp_prop);
     if (state->cache_used)
        htable_free(state->cache_used, (void (*) (char *)) 0);
-    if (state->dsn_reason)
-       vstring_free(state->dsn_reason);
+    if (state->why)
+       dsb_free(state->why);
 
     myfree((char *) state);
 }
index 4ddef7dcc33b081a9c4a00b4ccc9052a5b7f0d48..761aee970d16690536bdd319e565ff861474f1c3 100644 (file)
@@ -6,9 +6,8 @@
 /* SYNOPSIS
 /*     #include "smtp.h"
 /*
-/*     int     smtp_sess_fail(state, why)
+/*     int     smtp_sess_fail(state)
 /*     SMTP_STATE *state;
-/*     DSN_BUF *why;
 /*
 /*     int     smtp_site_fail(state, mta_name, resp, format, ...)
 /*     SMTP_STATE *state;
@@ -183,13 +182,14 @@ static void smtp_check_code(SMTP_SESSION *session, int code)
 
 /* smtp_bulk_fail - skip, defer or bounce recipients, maybe throttle queue */
 
-static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
+static int smtp_bulk_fail(SMTP_STATE *state, int throttle_queue)
 {
     DELIVER_REQUEST *request = state->request;
     SMTP_SESSION *session = state->session;
+    DSN_BUF *why = state->why;
     RECIPIENT *rcpt;
     int     status;
-    int     soft_error = (dsn->status[0] == '4');
+    int     soft_error = (STR(why->status)[0] == '4');
     int     nrcpt;
 
     /*
@@ -198,7 +198,7 @@ static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
      * why we're skipping this host.
      */
     if (soft_error && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) {
-       msg_info("%s: %s", request->queue_id, dsn->reason);
+       msg_info("%s: %s", request->queue_id, STR(why->reason));
        for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
            rcpt = request->rcpt_list.info + nrcpt;
            if (SMTP_RCPT_ISMARKED(rcpt))
@@ -230,6 +230,7 @@ static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
        } else
            GETTIMEOFDAY(&request->msg_stats.deliver_done);
 
+       (void) DSN_FROM_DSN_BUF(why);
        for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
            rcpt = request->rcpt_list.info + nrcpt;
            if (SMTP_RCPT_ISMARKED(rcpt))
@@ -237,14 +238,14 @@ static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
            status = (soft_error ? defer_append : bounce_append)
                (DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
                 &request->msg_stats, rcpt,
-                session ? session->namaddrport : "none", dsn);
+                session ? session->namaddrport : "none", &why->dsn);
            if (status == 0)
                deliver_completed(state->src, rcpt->offset);
            SMTP_RCPT_DROP(state, rcpt);
            state->status |= status;
        }
        if (throttle_queue && soft_error && request->hop_status == 0)
-           request->hop_status = DSN_COPY(dsn);
+           request->hop_status = DSN_COPY(&why->dsn);
     }
 
     /*
@@ -258,57 +259,42 @@ static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
 
 /* smtp_sess_fail - skip site, defer or bounce all recipients */
 
-int     smtp_sess_fail(SMTP_STATE *state, DSN_BUF *why)
+int     smtp_sess_fail(SMTP_STATE *state)
 {
-    DSN     dsn;
 
     /*
-     * We need to incur the expense of copying lots of strings into VSTRING
-     * buffers when the error information is collected by a routine that
-     * terminates BEFORE the error is reported. If no copies were made, the
-     * information would not be frozen in time.
+     * We can't avoid copying copying lots of strings into VSTRING buffers,
+     * because this error information is collected by a routine that
+     * terminates BEFORE the error is reported.
      */
-    return (smtp_bulk_fail(state, DSN_FROM_DSN_BUF(&dsn, why), SMTP_THROTTLE));
+    return (smtp_bulk_fail(state, SMTP_THROTTLE));
 }
 
 /* vsmtp_fill_dsn - fill in temporary DSN structure */
 
-static void vsmtp_fill_dsn(SMTP_STATE *state, DSN *dsn, const char *mta_name,
+static void vsmtp_fill_dsn(SMTP_STATE *state, const char *mta_name,
                                   const char *status, const char *reply,
                                   const char *format, va_list ap)
 {
+    DSN_BUF *why = state->why;
 
     /*
-     * We can avoid the cost of copying lots of strings into VSTRING buffers
-     * when the error information is collected by the routine that terminates
-     * AFTER the error is reported. In this case, the information is already
-     * frozen in time, so we don't need to make copies.
+     * We could avoid copying lots of strings into VSTRING buffers, because
+     * this error information is given to us by a routine that terminates
+     * AFTER the error is reported. However, this results in ugly kludges
+     * when informal text needs to be formatted. So we maintain consistency
+     * with other error reporting in the SMTP client even if we waste a few
+     * cycles.
      */
-    if (state->dsn_reason == 0)
-       state->dsn_reason = vstring_alloc(100);
-    else
-       VSTRING_RESET(state->dsn_reason);
-    if (mta_name && reply[0] != '4' && reply[0] != '5') {
-       vstring_strcpy(state->dsn_reason, "Protocol error: ");
-       mta_name = DSN_BY_LOCAL_MTA;
+    VSTRING_RESET(why->reason);
+    if (mta_name && reply && reply[0] != '4' && reply[0] != '5') {
+       vstring_strcpy(why->reason, "Protocol error: ");
        status = "5.5.0";
-       reply = "501 Protocol error in server reply";
     }
-    vstring_vsprintf_append(state->dsn_reason, format, ap);
-    SMTP_DSN_ASSIGN(dsn, mta_name, status, reply, STR(state->dsn_reason));
-}
-
-/* smtp_fill_dsn - fill in temporary DSN structure */
-
-static void smtp_fill_dsn(SMTP_STATE *state, DSN *dsn, const char *mta_name,
-                                 const char *status, const char *reply,
-                                 const char *format,...)
-{
-    va_list ap;
-
-    va_start(ap, format);
-    vsmtp_fill_dsn(state, dsn, mta_name, status, reply, format, ap);
-    va_end(ap);
+    vstring_vsprintf_append(why->reason, format, ap);
+    dsb_formal(why, status, DSB_DEF_ACTION,
+              mta_name ? DSB_MTYPE_DNS : DSB_MTYPE_NONE, mta_name,
+              reply ? DSB_DTYPE_SMTP : DSB_DTYPE_NONE, reply);
 }
 
 /* smtp_site_fail - throttle this queue; skip, defer or bounce all recipients */
@@ -316,14 +302,13 @@ static void smtp_fill_dsn(SMTP_STATE *state, DSN *dsn, const char *mta_name,
 int     smtp_site_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
                               const char *format,...)
 {
-    DSN     dsn;
     va_list ap;
 
     /*
      * Initialize.
      */
     va_start(ap, format);
-    vsmtp_fill_dsn(state, &dsn, mta_name, resp->dsn, resp->str, format, ap);
+    vsmtp_fill_dsn(state, mta_name, resp->dsn, resp->str, format, ap);
     va_end(ap);
 
     if (state->session && mta_name)
@@ -332,7 +317,7 @@ int     smtp_site_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
     /*
      * Skip, defer or bounce recipients, and throttle this queue.
      */
-    return (smtp_bulk_fail(state, &dsn, SMTP_THROTTLE));
+    return (smtp_bulk_fail(state, SMTP_THROTTLE));
 }
 
 /* smtp_mesg_fail - skip, defer or bounce all recipients; no queue throttle */
@@ -341,13 +326,12 @@ int     smtp_mesg_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
                               const char *format,...)
 {
     va_list ap;
-    DSN     dsn;
 
     /*
      * Initialize.
      */
     va_start(ap, format);
-    vsmtp_fill_dsn(state, &dsn, mta_name, resp->dsn, resp->str, format, ap);
+    vsmtp_fill_dsn(state, mta_name, resp->dsn, resp->str, format, ap);
     va_end(ap);
 
     if (state->session && mta_name)
@@ -356,7 +340,7 @@ int     smtp_mesg_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
     /*
      * Skip, defer or bounce recipients, but don't throttle this queue.
      */
-    return (smtp_bulk_fail(state, &dsn, SMTP_NOTHROTTLE));
+    return (smtp_bulk_fail(state, SMTP_NOTHROTTLE));
 }
 
 /* smtp_rcpt_fail - skip, defer, or bounce recipient */
@@ -366,7 +350,7 @@ void    smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
 {
     DELIVER_REQUEST *request = state->request;
     SMTP_SESSION *session = state->session;
-    DSN     dsn;
+    DSN_BUF *why = state->why;
     int     status;
     int     soft_error;
     va_list ap;
@@ -381,9 +365,9 @@ void    smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
      * Initialize.
      */
     va_start(ap, format);
-    vsmtp_fill_dsn(state, &dsn, mta_name, resp->dsn, resp->str, format, ap);
+    vsmtp_fill_dsn(state, mta_name, resp->dsn, resp->str, format, ap);
     va_end(ap);
-    soft_error = dsn.status[0] == '4';
+    soft_error = STR(why->status)[0] == '4';
 
     if (state->session && mta_name)
        smtp_check_code(state->session, resp->code);
@@ -394,7 +378,7 @@ void    smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
      * why we're skipping this recipient now.
      */
     if (soft_error && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) {
-       msg_info("%s: %s", request->queue_id, dsn.reason);
+       msg_info("%s: %s", request->queue_id, STR(why->reason));
        SMTP_RCPT_KEEP(state, rcpt);
     }
 
@@ -407,10 +391,11 @@ void    smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
      * that did qualify for delivery to a backup server.
      */
     else {
+       (void) DSN_FROM_DSN_BUF(state->why);
        status = (soft_error ? defer_append : bounce_append)
            (DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
             &request->msg_stats, rcpt,
-            session ? session->namaddrport : "none", &dsn);
+            session ? session->namaddrport : "none", &why->dsn);
        if (status == 0)
            deliver_completed(state->src, rcpt->offset);
        SMTP_RCPT_DROP(state, rcpt);
@@ -423,7 +408,7 @@ void    smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
 int     smtp_stream_except(SMTP_STATE *state, int code, const char *description)
 {
     SMTP_SESSION *session = state->session;
-    DSN     dsn;
+    DSN_BUF *why = state->why;
 
     /*
      * Sanity check.
@@ -438,23 +423,13 @@ int     smtp_stream_except(SMTP_STATE *state, int code, const char *description)
     default:
        msg_panic("smtp_stream_except: unknown exception %d", code);
     case SMTP_ERR_EOF:
-       smtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
-                     "4.4.2", "421 lost connection",
-                     "lost connection with %s while %s",
-                     session->namaddr, description);
+       dsb_simple(why, "4.4.2", "lost connection with %s while %s",
+                  session->namaddr, description);
        break;
     case SMTP_ERR_TIME:
-       smtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
-                     "4.4.2", "426 conversation timed out",
-                     "conversation with %s timed out while %s",
-                     session->namaddr, description);
-       break;
-    case SMTP_ERR_PROTO:
-       smtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
-                     "4.5.0", "403 remote protocol error",
-                     "remote protocol error in reply from %s while %s",
-                     session->namaddr, description);
+       dsb_simple(why, "4.4.2", "conversation with %s timed out while %s",
+                  session->namaddr, description);
        break;
     }
-    return (smtp_bulk_fail(state, &dsn, SMTP_THROTTLE));
+    return (smtp_bulk_fail(state, SMTP_THROTTLE));
 }
index da78675d01a07494d5b6f03f583d1fe1a2278dfd..2776c4c91923c7bc5b81abf8ba46df33e13f3cfd 100644 (file)
@@ -215,7 +215,6 @@ smtpd_check.o: ../../include/dict.h
 smtpd_check.o: ../../include/dns.h
 smtpd_check.o: ../../include/domain_list.h
 smtpd_check.o: ../../include/dsn.h
-smtpd_check.o: ../../include/dsn_buf.h
 smtpd_check.o: ../../include/dsn_util.h
 smtpd_check.o: ../../include/fsspace.h
 smtpd_check.o: ../../include/htable.h
index 9457a150530d17055c38f6ad22dea336acd0c18b..664f3ddd81302e6affd0a22733a5f17aa812ccf5 100644 (file)
@@ -40,7 +40,6 @@
 /*     RFC 1869 (SMTP service extensions)
 /*     RFC 1870 (Message Size Declaration)
 /*     RFC 1985 (ETRN command)
-/*     RFC 2034 (Enhanced Status Codes)
 /*     RFC 2554 (AUTH command)
 /*     RFC 2821 (SMTP protocol)
 /*     RFC 2920 (SMTP Pipelining)
@@ -98,9 +97,9 @@
 /*     Available in Postfix version 2.2 and later:
 /* .IP "\fBsmtpd_discard_ehlo_keyword_address_maps (empty)\fR"
 /*     Lookup tables, indexed by the remote SMTP client address, with
-/*     case insensitive lists of EHLO keywords (pipelining, starttls,
-/*     auth, etc.) that the SMTP server will not send in the EHLO response
-/*     to a remote SMTP client.
+/*     case insensitive lists of EHLO keywords (pipelining, starttls, auth,
+/*     etc.) that the SMTP server will not send in the EHLO response to a
+/*     remote SMTP client.
 /* .IP "\fBsmtpd_discard_ehlo_keywords (empty)\fR"
 /*     A case insensitive list of EHLO keywords (pipelining, starttls,
 /*     auth, etc.) that the SMTP server will not send in the EHLO response
index 2962b1efbe43f07de9966596faa6d4510c7f4386..d91b8131a306af00e4aaf8ecb22da577d07a5673 100644 (file)
@@ -214,13 +214,14 @@ void    smtpd_chat_notify(SMTPD_STATE *state)
      * generate from untrusted data.
      */
 #define NULL_TRACE_FLAGS       0
+#define NO_QUEUE_ID            ((VSTRING *) 0)
 #define LENGTH 78
 #define INDENT 4
 
     notice = post_mail_fopen_nowait(mail_addr_double_bounce(),
                                    var_error_rcpt,
                                    CLEANUP_FLAG_MASK_INTERNAL,
-                                   NULL_TRACE_FLAGS);
+                                   NULL_TRACE_FLAGS, NO_QUEUE_ID);
     if (notice == 0) {
        msg_warn("postmaster notify: %m");
        return;
index 91b4af2818955f14096b624df80f96ff1dfa7eb5..1c8165da7db8242c5b76b69b3bf8f0b82ff5d5a6 100644 (file)
 /*     handling. A call of these functions either succeeds or it does
 /*     not return at all.
 /*
+/*     To save memory, zero-length strings are shared and read-only.
+/*     The caller must not attempt to modify the null terminator.
+/*     This code is enabled unless NO_SHARED_EMPTY_STRINGS is
+/*     defined at compile time (for example, you have an sscanf()
+/*     routine that pushes characters back into its input).
+/*
 /*     mymalloc() allocates the requested amount of memory. The memory
 /*     is not set to zero.
 /*
@@ -118,6 +124,22 @@ typedef struct MBLOCK {
 
 #define SPACE_FOR(len) (offsetof(MBLOCK, u.payload[0]) + len)
 
+ /*
+  * Optimization for short strings. We share one copy with multiple callers.
+  * This differs from normal heap memory in two ways, because the memory is
+  * shared:
+  * 
+  * -  It must be read-only to avoid horrible bugs. This is OK because there is
+  * no legitimate reason to modify the null terminator.
+  * 
+  * - myfree() cannot overwrite the memory with a filler pattern like it can do
+  * with heap memory. Therefore, some dangling pointer bugs will be masked.
+  */
+#ifndef NO_SHARED_EMPTY_STRINGS
+static const char empty_string[] = "";
+
+#endif
+
 /* mymalloc - allocate memory or bust */
 
 char   *mymalloc(ssize_t len)
@@ -141,6 +163,11 @@ char   *myrealloc(char *ptr, ssize_t len)
     MBLOCK *real_ptr;
     ssize_t old_len;
 
+#ifndef NO_SHARED_EMPTY_STRINGS
+    if (ptr == empty_string)
+       return (mymalloc(len));
+#endif
+
     if (len < 1)
        msg_panic("myrealloc: requested length %ld", (long) len);
     CHECK_IN_PTR(ptr, real_ptr, old_len, "myrealloc");
@@ -159,9 +186,15 @@ void    myfree(char *ptr)
     MBLOCK *real_ptr;
     ssize_t len;
 
-    CHECK_IN_PTR(ptr, real_ptr, len, "myfree");
-    memset((char *) real_ptr, FILLER, SPACE_FOR(len));
-    free((char *) real_ptr);
+#ifndef NO_SHARED_EMPTY_STRINGS
+    if (ptr != empty_string) {
+#endif
+       CHECK_IN_PTR(ptr, real_ptr, len, "myfree");
+       memset((char *) real_ptr, FILLER, SPACE_FOR(len));
+       free((char *) real_ptr);
+#ifndef NO_SHARED_EMPTY_STRINGS
+    }
+#endif
 }
 
 /* mystrdup - save string to heap */
@@ -170,6 +203,10 @@ char   *mystrdup(const char *str)
 {
     if (str == 0)
        msg_panic("mystrdup: null pointer argument");
+#ifndef NO_SHARED_EMPTY_STRINGS
+    if (*str == 0)
+       return ((char *) empty_string);
+#endif
     return (strcpy(mymalloc(strlen(str) + 1), str));
 }
 
@@ -184,6 +221,10 @@ char   *mystrndup(const char *str, ssize_t len)
        msg_panic("mystrndup: null pointer argument");
     if (len < 0)
        msg_panic("mystrndup: requested length %ld", (long) len);
+#ifndef NO_SHARED_EMPTY_STRINGS
+    if (*str == 0)
+       return ((char *) empty_string);
+#endif
     if ((cp = memchr(str, 0, len)) != 0)
        len = cp - str;
     result = memcpy(mymalloc(len + 1), str, len);
index 7dfee0a34ce6d35a7e436f4dea6ea11641afdfbb..54c793321a907cea557b6317d6f787acb9499e9e 100644 (file)
@@ -204,6 +204,9 @@ ssize_t netstring_get_length(VSTREAM *stream)
            if (!ISDIGIT(ch))
                netstring_except(stream, NETSTRING_ERR_FORMAT);
            len = len * 10 + ch - '0';
+           /* vstream_fread() would read zero bytes. Reject input anyway. */
+           if (len < 0)
+               netstring_except(stream, NETSTRING_ERR_SIZE);
            break;
        }
     }
index c050f6381f712dc55925965a08629f54112b27ae..df65a69bca62e7e06b7b2c558c595f59218f2a6d 100644 (file)
@@ -491,7 +491,6 @@ char   *vstring_memchr(VSTRING *vp, int ch)
 
 VSTRING *vstring_insert(VSTRING *vp, ssize_t start, const char *buf, ssize_t len)
 {
-    const char *myname = "vstring_insert";
     ssize_t new_len;
 
     /*
index 3592ffaa9eefb1ef08416afbc73a5f93fd686d3f..b5a1a2884b421236ec26e602193d71a95b2c62bd 100644 (file)
@@ -62,7 +62,6 @@ verify.o: ../../include/deliver_request.h
 verify.o: ../../include/dict.h
 verify.o: ../../include/dict_ht.h
 verify.o: ../../include/dsn.h
-verify.o: ../../include/dsn_buf.h
 verify.o: ../../include/htable.h
 verify.o: ../../include/iostuff.h
 verify.o: ../../include/mail_conf.h
index 0ae579b973f3cc5be36b127e3f6a0277bd8df6c7..ecc0d5f39d49ed0429d1738079d47dc07fcd6a0b 100644 (file)
@@ -454,6 +454,7 @@ static void verify_query_service(VSTREAM *client_stream)
                                  "" : var_verify_sender, STR(addr),
                                  CLEANUP_FLAG_MASK_INTERNAL,
                                  DEL_REQ_FLAG_MTA_VRFY,
+                                 (VSTRING *) 0,
                                  verify_post_mail_action,
                                  (void *) 0);
            if (updated != 0 || var_verify_neg_cache != 0) {
index 54208df1439f437ee7672bfde512767d67391f47..d789a471e17980ae0827065e2871960ee3b721dd 100644 (file)
@@ -58,8 +58,8 @@ int     deliver_unknown(LOCAL_STATE state)
     if (msg_verbose)
        MSG_LOG_STATE(myname, state);
 
-    dsb_smtp(state.msg_attr.why, "5.1.1", 550, "550 user unknown",
-            "unknown user: \"%s\"", state.msg_attr.user);
+    dsb_simple(state.msg_attr.why, "5.1.1",
+              "unknown user: \"%s\"", state.msg_attr.user);
     return (bounce_append(BOUNCE_FLAGS(state.request),
                          BOUNCE_ATTR(state.msg_attr)));
 }
index b7493606763d7c44a10a3eec425c593bdb7f1d56..75dd6cd2ede1d41d12022a8b0ef3c5cd39d86735 100644 (file)
@@ -76,7 +76,6 @@ typedef struct DELIVER_ATTR {
     char   *relay;                     /* relay host */
     MSG_STATS msg_stats;               /* time profile */
     DSN_BUF *why;                      /* delivery status */
-    DSN     dsn;                       /* delivery status */
 } DELIVER_ATTR;
 
 extern void deliver_attr_init(DELIVER_ATTR *);
@@ -103,10 +102,10 @@ typedef struct LOCAL_STATE {
 
 #define BOUNCE_ATTR(attr) \
        attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \
-       DSN_FROM_DSN_BUF(&attr.dsn, attr.why)
+       DSN_FROM_DSN_BUF(attr.why)
 #define SENT_ATTR(attr) \
        attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \
-       DSN_FROM_DSN_BUF(&attr.dsn, attr.why)
+       DSN_FROM_DSN_BUF(attr.why)
 #define COPY_ATTR(attr) \
        attr.sender, attr.rcpt.orig_addr, attr.delivered, attr.fp