]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.5-20070422
authorWietse Venema <wietse@porcupine.org>
Sun, 22 Apr 2007 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:33:06 +0000 (06:33 +0000)
40 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/SMTPD_POLICY_README
postfix/RELEASE_NOTES
postfix/conf/access
postfix/conf/master.cf
postfix/conf/postfix-script
postfix/html/SMTPD_POLICY_README.html
postfix/html/access.5.html
postfix/html/pcre_table.5.html
postfix/html/pipe.8.html
postfix/html/regexp_table.5.html
postfix/man/man5/access.5
postfix/man/man5/pcre_table.5
postfix/man/man5/regexp_table.5
postfix/man/man8/pipe.8
postfix/proto/SMTPD_POLICY_README.html
postfix/proto/access
postfix/proto/pcre_table
postfix/proto/regexp_table
postfix/src/global/Makefile.in
postfix/src/global/delivered_hdr.c [new file with mode: 0644]
postfix/src/global/delivered_hdr.h [new file with mode: 0644]
postfix/src/global/mail_version.h
postfix/src/global/resolve_clnt.c
postfix/src/global/rewrite_clnt.c
postfix/src/local/Makefile.in
postfix/src/local/delivered.c [deleted file]
postfix/src/local/local.c
postfix/src/local/local.h
postfix/src/local/recipient.c
postfix/src/pipe/Makefile.in
postfix/src/pipe/pipe.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_state.c
postfix/src/trivial-rewrite/Makefile.in
postfix/src/trivial-rewrite/transport.c
postfix/src/trivial-rewrite/transport.h

index ea48c48d4296ac71ea39c815aca933f22f282bda..fc69659c20057a99da19c873a6e3aae2ae9a4ff0 100644 (file)
@@ -46,6 +46,7 @@
 -TCRYPTO_EX_DATA
 -TCTABLE
 -TCTABLE_ENTRY
+-TDELIVERED_HDR_INFO
 -TDELIVER_ATTR
 -TDELIVER_REQUEST
 -TDELTA_TIME
index 37f27edab184b1d5c49ead6538fd7d061b0f596f..e2494e3714647b9e2680108509cdb4f24e909ce8 100644 (file)
@@ -13400,8 +13400,8 @@ Apologies for any names omitted.
 20070331 
 
        Bugfix (introduced Postfix 2.3): segfault with HOLD action
-       in header/body_checks on 64-bit platforms. File:
-       cleanup/cleanup_api.c.
+       in access/header_checks/body_checks on 64-bit platforms.
+       File: cleanup/cleanup_api.c.
 
 20070402
 
@@ -13416,14 +13416,58 @@ Apologies for any names omitted.
        broke with "fcntl F_DUPFD: Invalid argument" on 64-bit
        Solaris.  Files: master/multi_server.c, *qmgr/qmgr_transport.c.
 
+20070405
+
+       Feature: BCC access/policy action, to demonstrate that this
+       is not a good feature. The action's behavior is non-intuitive
+       and requires too much documentation to explain.  It's
+       therefore snapshot only.  File: smtpd/smtpd_check.c.
+
+20070414
+
+       Cleanup: expire cached results from addres rewriting, address
+       resolution, and from transport map lookups.  Results expire
+       after 30 seconds; short enough that it doesn't freak out
+       people who run the same test repeatedly, and long enough
+       that it doesn't upset other people with continuous streams
+       of "*" transport map lookups.  Files: global/rewrite_clnt.c,
+       global/resolve_clnt.c, trivial-rewrite/transport.c.
+
+20070421
+
+       Cleanup: on (Linux) platforms that cripple signal handlers
+       with deadlock, "postfix stop" now forcefully stops all the
+       processes in the master's process group, not just the master
+       process alone.  File: conf/postfix-script.
+
+20070422
+
+       Cleanup: the "Delivered-To:" loop detection implementation
+       was moved from the local(8) delivery agent to the library,
+       where it can also be used by other delivery agents. Files:
+       global/delivered_hdr.[hc].
+
+       Safety: the "Delivered-To:" loop detection implementation
+       keeps state for no more than 1000 "Delivered-To:" headers.
+
+       Feature: $domain command-line macro support, to get access
+       to the recipient address domain portion.  Based on code by
+       Koen Vermeer. File: pipe/pipe.c.
+
+       Cleanup: suport for "Delivered-To:" loop detection in the
+       pipe(8) delivery agent. This follows a general principle:
+       if a program creates the "Delivered-To:" header, then it
+       is also responsible for "Delivered-To:" loop detection.
+       File pipe/pipe.c.
+
 Wish list:
 
        Remove defer(8) and trace(8) references and man pages. These
        are services not program names.
 
        Bind all deliveries to the same local delivery process,
-       making Postfix perform as poorly as monolithic mailers,
-       but giving a possibility to eliminate duplicate deliveries.
+       making Postfix perform as poorly as monolithic mailers, but
+       giving a possibility to eliminate duplicate deliveries.
 
        Maybe declare loop when resolve_local(mxhost) is true?
 
index 68e04db0cb6da13010ba2074a9ad0f7380758380..bbcb28ef487f1a9975f44c014a0b10a9c9c07cb0 100644 (file)
@@ -43,6 +43,7 @@ terminated by an empty line.
 Here is an example of all the attributes that the Postfix SMTP server sends in
 a delegated SMTPD access policy request:
 
+    P\bPo\bos\bst\btf\bfi\bix\bx v\bve\ber\brs\bsi\bio\bon\bn 2\b2.\b.1\b1 a\ban\bnd\bd l\bla\bat\bte\ber\br:\b:
     request=smtpd_access_policy
     protocol_state=RCPT
     protocol_name=SMTP
index 2ae10b5507bd911eb11a7bd5d6b6fe6d6337f5ce..78b49996cbc77891df0e3f41476f554c16f640e0 100644 (file)
@@ -16,3 +16,12 @@ Incompatibility with Postfix 2.3 and earlier
 
 If you upgrade from Postfix 2.3 or earlier, read RELEASE_NOTES-2.4
 before proceeding.
+
+Incompatibility with Postfix snapshot 20070422
+==============================================
+
+When the pipe(8) delivery agent is configured to create the optional
+Delivered-To: header, it first checks if that same header is already
+present. If so, the mail is returned as undeliverable. This test
+should have been included with Postfix 2.0 when Delivered-To: support
+was added to the pipe(8) delivery agent.
index 6026a80f4a133181bbcdf9a5f53f2f71c6680f4d..9d396594e94ac36b5f25172a4669192a44683df1 100644 (file)
 #               Apply the named UCE restriction(s) (permit, reject,
 #               reject_unauth_destination, and so on).
 # 
+#        BCC user@domain
+#               Send  one  copy  of  the  message  to the specified
+#               recipient.
+# 
+#               If multiple BCC actions are  specified  within  the
+#               same  SMTP  MAIL  transaction, only the last action
+#               will be used.
+# 
+#               This feature is not  part  of  the  stable  Postfix
+#               release.
+# 
 #        DISCARD optional text...
 #               Claim  successful delivery and silently discard the
 #               message.  Log the optional text if specified,  oth-
index 29ea1a0436e093d8616fd0bbab0b19421da3ebbf..1bdc00c1b1a7ea11e9726215ba337d22451afe2f 100644 (file)
@@ -2,6 +2,8 @@
 # Postfix master process configuration file.  For details on the format
 # of the file, see the master(5) manual page (command: "man 5 master").
 #
+# Do not forget to execute "postfix reload" after editing this file.
+#
 # ==========================================================================
 # service type  private unpriv  chroot  wakeup  maxproc command + args
 #               (yes)   (yes)   (yes)   (never) (100)
index 33b408cf4017c122f58abd9de49ea788eb8d1ae0..e5a5169183b38dd7733cf475c68ab3dedde9ad15 100644 (file)
@@ -136,7 +136,8 @@ stop)
            sleep 1
        done
        $WARN stopping the Postfix mail system with force
-       kill -9 `sed 1q pid/master.pid`
+       pid=`awk '{ print $1; exit 0 } END { exit 1 }' pid/master.pid` && 
+               kill -9 -$pid
        ;;
 
 abort)
index 9962eae6fa0fe53612d5347ad65b407f031d1cc0..05ff6ff5db84adbf4935c9701ba5fcbd50ff292b 100644 (file)
@@ -74,6 +74,7 @@ server sends in a delegated SMTPD access policy request: </p>
 
 <blockquote>
 <pre>
+<b>Postfix version 2.1 and later:</b>
 request=smtpd_access_policy
 protocol_state=RCPT
 protocol_name=SMTP
index f73bc3bef2d8cea1cf36c8449f22fce1f630e2cc..1eb182bbcb8f8ea82a25ea91680cffc807fc5349 100644 (file)
@@ -225,6 +225,17 @@ ACCESS(5)                                                            ACCESS(5)
               Apply the named UCE restriction(s) (<b>permit</b>, <b>reject</b>,
               <b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a></b>, and so on).
 
+       <b>BCC</b> <i>user@domain</i>
+              Send  one  copy  of  the  message  to the specified
+              recipient.
+
+              If multiple BCC actions are  specified  within  the
+              same  SMTP  MAIL  transaction, only the last action
+              will be used.
+
+              This feature is not  part  of  the  stable  Postfix
+              release.
+
        <b>DISCARD</b> <i>optional text...</i>
               Claim  successful delivery and silently discard the
               message.  Log the optional text if specified,  oth-
index 7a68ce8a5b7b4ac27c8e1d2579f9403eaa7fe03d..a80d3108e17ba2c8414aaee99b7d2d80684b1a07 100644 (file)
@@ -50,8 +50,8 @@ PCRE_TABLE(5)                                                    PCRE_TABLE(5)
        <b>if /</b><i>pattern</i><b>/</b><i>flags</i>
 
        <b>endif</b>  Match the input string against the patterns between
-              <b>if</b> and <b>endif</b>, if and only if the input string  also
-              matches <i>pattern</i>. The <b>if</b>..<b>endif</b> can nest.
+              <b>if</b> and <b>endif</b>, if and only if that same input string
+              also matches <i>pattern</i>. The <b>if</b>..<b>endif</b> can nest.
 
               Note:  do not prepend whitespace to patterns inside
               <b>if</b>..<b>endif</b>.
@@ -61,8 +61,8 @@ PCRE_TABLE(5)                                                    PCRE_TABLE(5)
        <b>if !/</b><i>pattern</i><b>/</b><i>flags</i>
 
        <b>endif</b>  Match the input string against the patterns between
-              <b>if</b> and <b>endif</b>, if and only if the input string  does
-              <b>not</b> match <i>pattern</i>. The <b>if</b>..<b>endif</b> can nest.
+              <b>if</b> and <b>endif</b>, if and only if that same input string
+              does <b>not</b> match <i>pattern</i>. The <b>if</b>..<b>endif</b> can nest.
 
               Note:  do not prepend whitespace to patterns inside
               <b>if</b>..<b>endif</b>.
index a6abe8188f8d2145b7d837965d1056c050292dee..cf1210a0ca68f4e2f5a81bbe4641bb4dcb7c7846 100644 (file)
@@ -30,9 +30,11 @@ PIPE(8)                                                                PIPE(8)
        <a href="trace.8.html"><b>trace</b>(8)</a> daemon as appropriate.
 
 <b>SINGLE-RECIPIENT DELIVERY</b>
-       Some external commands cannot handle more than one recipi-
-       ent per delivery request. Examples of such transports  are
-       pagers or fax machines.
+       Some  destinations  cannot  handle more than one recipient
+       per delivery request. Examples are pagers or fax machines.
+       In  addition, multi-recipient delivery is undesirable when
+       prepending  a  <b>Delivered-to:</b>  or  <b>X-Original-To:</b>   message
+       header.
 
        To  prevent  Postfix  from sending multiple recipients per
        delivery request, specify
@@ -86,89 +88,99 @@ PIPE(8)                                                                PIPE(8)
               <b>D</b>      Prepend  a "<b>Delivered-To:</b> <i>recipient</i>" message
                      header with the envelope recipient  address.
                      Note: for this to work, the <i>transport</i><b>_desti-</b>
-                     <b>nation_recipient_limit</b> must be 1.
+                     <b>nation_recipient_limit</b> must be 1  (see  SIN-
+                     GLE-RECIPIENT DELIVERY above for details).
+
+                     This   code  also  enforces  loop  detection
+                     (Postfix  2.5  and  later).   If  a  message
+                     already contains a <b>Delivered-To:</b> header with
+                     the same recipient address, then the message
+                     is returned as undeliverable.
 
                      This feature is available as of Postfix 2.0.
 
-              <b>F</b>      Prepend  a "<b>From</b> <i>sender time</i><b>_</b><i>stamp</i>" envelope
-                     header to  the  message  content.   This  is
+              <b>F</b>      Prepend a "<b>From</b> <i>sender time</i><b>_</b><i>stamp</i>"  envelope
+                     header  to  the  message  content.   This is
                      expected by, for example, <b>UUCP</b> software.
 
-              <b>O</b>      Prepend  an  "<b>X-Original-To:</b> <i>recipient</i>" mes-
-                     sage header with the  recipient  address  as
-                     given  to  Postfix.  Note: for this to work,
+              <b>O</b>      Prepend an "<b>X-Original-To:</b>  <i>recipient</i>"  mes-
+                     sage  header  with  the recipient address as
+                     given to Postfix. Note: for  this  to  work,
                      the    <i>transport</i><b>_destination_recipient_limit</b>
-                     must be 1.
+                     must be  1  (see  SINGLE-RECIPIENT  DELIVERY
+                     above for details).
 
                      This feature is available as of Postfix 2.0.
 
               <b>R</b>      Prepend a <b>Return-Path:</b> message  header  with
                      the envelope sender address.
 
-              <b>h</b>      Fold the command-line <b>$recipient</b> domain name
-                     and <b>$nexthop</b> host name to lower case.   This
-                     is recommended for delivery via <b>UUCP</b>.
+              <b>h</b>      Fold  the  command-line  <b>$recipient</b>  address
+                     domain part (text to the right of the right-
+                     most  <b>@</b>  character)  to lower case; fold the
+                     entire  command-line  <b>$domain</b>  and  <b>$nexthop</b>
+                     host  or  domain  information to lower case.
+                     This is recommended for delivery via <b>UUCP</b>.
 
-              <b>q</b>      Quote  white space and other special charac-
+              <b>q</b>      Quote white space and other special  charac-
                      ters in the command-line <b>$sender</b> and <b>$recip-</b>
                      <b>ient</b> address localparts (text to the left of
                      the right-most <b>@</b> character), according to an
-                     8-bit  transparent version of <a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a>.  This
-                     is recommended  for  delivery  via  <b>UUCP</b>  or
+                     8-bit transparent version of <a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a>.   This
+                     is  recommended  for  delivery  via  <b>UUCP</b> or
                      <b>BSMTP</b>.
 
-                     The  result  is  compatible with the address
-                     parsing of command-line  recipients  by  the
+                     The result is compatible  with  the  address
+                     parsing  of  command-line  recipients by the
                      Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> mail submission command.
 
-                     The <b>q</b> flag affects  only  entire  addresses,
+                     The  <b>q</b>  flag  affects only entire addresses,
                      not the partial address information from the
-                     <b>$user</b>, <b>$extension</b> or  <b>$mailbox</b>  command-line
+                     <b>$user</b>,  <b>$extension</b>  or <b>$mailbox</b> command-line
                      macros.
 
               <b>u</b>      Fold  the  command-line  <b>$recipient</b>  address
-                     localpart (text to the left  of  the  right-
-                     most  <b>@</b>  character)  to lower case.  This is
+                     localpart  (text  to  the left of the right-
+                     most <b>@</b> character) to lower  case.   This  is
                      recommended for delivery via <b>UUCP</b>.
 
               <b>.</b>      Prepend "<b>.</b>" to lines starting with "<b>.</b>". This
                      is needed by, for example, <b>BSMTP</b> software.
 
-              &gt;      Prepend  "&gt;" to lines starting with "<b>From</b> ".
+              &gt;      Prepend "&gt;" to lines starting with "<b>From</b>  ".
                      This is expected by, for example, <b>UUCP</b> soft-
                      ware.
 
        <b>null_sender</b>=<i>replacement</i> (default: MAILER-DAEMON)
               Replace the null sender address (typically used for
-              delivery status notifications) with  the  specified
+              delivery  status  notifications) with the specified
               text when expanding the <b>$sender</b> command-line macro,
               and when generating a From_ or Return-Path: message
               header.
 
-              If  the null sender replacement text is a non-empty
-              string then it  is  affected  by  the  <b>q</b>  flag  for
+              If the null sender replacement text is a  non-empty
+              string  then  it  is  affected  by  the  <b>q</b> flag for
               address quoting in command-line arguments.
 
               The null sender replacement text may be empty; this
-              form is recommended for content filters  that  feed
+              form  is  recommended for content filters that feed
               mail back into Postfix. The empty sender address is
-              not affected by the <b>q</b> flag for address  quoting  in
+              not  affected  by the <b>q</b> flag for address quoting in
               command-line arguments.
 
               Caution: a null sender address is easily mis-parsed
-              by naive software. For example,  when  the  <a href="pipe.8.html"><b>pipe</b>(8)</a>
+              by  naive  software.  For example, when the <a href="pipe.8.html"><b>pipe</b>(8)</a>
               daemon executes a command such as:
 
                   command -f$sender -- $recipient (<i>bad</i>)
 
               the command will mis-parse the -f option value when
-              the sender address is a null string.   For  correct
+              the  sender  address is a null string.  For correct
               parsing, specify <b>$sender</b> as an argument by itself:
 
                   command -f $sender -- $recipient (<i>good</i>)
 
-              This  feature  is  available  with  Postfix 2.3 and
-              later.
+              This feature is available as of Postfix 2.3.
 
        <b>size</b>=<i>size</i><b>_</b><i>limit</i> (optional)
               Messages greater in size than this limit (in bytes)
@@ -224,176 +236,187 @@ PIPE(8)                                                                PIPE(8)
 
                      This is available in Postfix 2.2 and  later.
 
+              <b>${domain</b>}
+                     This  macro expands to the domain portion of
+                     the recipient address.  For example, with an
+                     address   <i>user+foo@domain</i>   the   domain  is
+                     <i>domain</i>.
+
+                     This information is modified by the  <b>h</b>  flag
+                     for case folding.
+
+                     This  is available in Postfix 2.5 and later.
+
               <b>${extension</b>}
-                     This  macro expands to the extension part of
-                     a recipient address.  For example,  with  an
+                     This macro expands to the extension part  of
+                     a  recipient  address.  For example, with an
                      address  <i>user+foo@domain</i>  the  extension  is
                      <i>foo</i>.
 
-                     A  command-line   argument   that   contains
-                     <b>${extension</b>}  expands  into as many command-
+                     A   command-line   argument   that  contains
+                     <b>${extension</b>} expands into as  many  command-
                      line arguments as there are recipients.
 
-                     This information is modified by the  <b>u</b>  flag
+                     This  information  is modified by the <b>u</b> flag
                      for case folding.
 
               <b>${mailbox</b>}
-                     This  macro  expands  to  the complete local
-                     part of a recipient address.   For  example,
-                     with  an address <i>user+foo@domain</i> the mailbox
+                     This macro expands  to  the  complete  local
+                     part  of  a recipient address.  For example,
+                     with an address <i>user+foo@domain</i> the  mailbox
                      is <i>user+foo</i>.
 
-                     A  command-line   argument   that   contains
-                     <b>${mailbox</b>}  expands  to as many command-line
+                     A   command-line   argument   that  contains
+                     <b>${mailbox</b>} expands to as  many  command-line
                      arguments as there are recipients.
 
-                     This information is modified by the  <b>u</b>  flag
+                     This  information  is modified by the <b>u</b> flag
                      for case folding.
 
               <b>${nexthop</b>}
                      This macro expands to the next-hop hostname.
 
-                     This information is modified by the  <b>h</b>  flag
+                     This  information  is modified by the <b>h</b> flag
                      for case folding.
 
               <b>${recipient</b>}
                      This macro expands to the complete recipient
                      address.
 
-                     A  command-line   argument   that   contains
+                     A   command-line   argument   that  contains
                      <b>${recipient</b>} expands to as many command-line
                      arguments as there are recipients.
 
-                     This information  is  modified  by  the  <b>hqu</b>
+                     This  information  is  modified  by  the <b>hqu</b>
                      flags for quoting and case folding.
 
               <b>${sasl_method</b>}
-                     This  macro  expands to the SASL authentica-
-                     tion mechanism used during the reception  of
-                     the  message.  An  empty string is passed if
-                     the message has been received  without  SASL
+                     This macro expands to the  SASL  authentica-
+                     tion  mechanism used during the reception of
+                     the message. An empty string  is  passed  if
+                     the  message  has been received without SASL
                      authentication.
 
-                     This  is available in Postfix 2.2 and later.
+                     This is available in Postfix 2.2 and  later.
 
               <b>${sasl_sender</b>}
-                     This macro expands to the SASL  sender  name
-                     (i.e.  the  original  submitter  as  per <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC</a>
-                     <a href="http://www.faqs.org/rfcs/rfc2554.html">2554</a>) used during the reception of the  mes-
+                     This  macro  expands to the SASL sender name
+                     (i.e. the  original  submitter  as  per  <a href="http://www.faqs.org/rfcs/rfc2554.html">RFC</a>
+                     <a href="http://www.faqs.org/rfcs/rfc2554.html">2554</a>)  used during the reception of the mes-
                      sage.
 
-                     This  is available in Postfix 2.2 and later.
+                     This is available in Postfix 2.2 and  later.
 
               <b>${sasl_username</b>}
-                     This macro expands to  the  SASL  user  name
+                     This  macro  expands  to  the SASL user name
                      used during the reception of the message. An
-                     empty string is passed if  the  message  has
+                     empty  string  is  passed if the message has
                      been received without SASL authentication.
 
-                     This  is available in Postfix 2.2 and later.
+                     This is available in Postfix 2.2 and  later.
 
               <b>${sender</b>}
-                     This macro expands to  the  envelope  sender
+                     This  macro  expands  to the envelope sender
                      address. By default, the null sender address
-                     expands  to  MAILER-DAEMON;  this   can   be
-                     changed  with  the <b>null_sender</b> attribute, as
+                     expands   to   MAILER-DAEMON;  this  can  be
+                     changed with the <b>null_sender</b>  attribute,  as
                      described above.
 
-                     This information is modified by the  <b>q</b>  flag
+                     This  information  is modified by the <b>q</b> flag
                      for quoting.
 
               <b>${size</b>}
-                     This  macro expands to Postfix's idea of the
-                     message size, which is an  approximation  of
+                     This macro expands to Postfix's idea of  the
+                     message  size,  which is an approximation of
                      the size of the message as delivered.
 
               <b>${user</b>}
                      This macro expands to the username part of a
-                     recipient address.   For  example,  with  an
+                     recipient  address.   For  example,  with an
                      address <i>user+foo@domain</i> the username part is
                      <i>user</i>.
 
-                     A  command-line   argument   that   contains
-                     <b>${user</b>}  expands  into  as many command-line
+                     A   command-line   argument   that  contains
+                     <b>${user</b>} expands into  as  many  command-line
                      arguments as there are recipients.
 
-                     This information is modified by the  <b>u</b>  flag
+                     This  information  is modified by the <b>u</b> flag
                      for case folding.
 
 <b>STANDARDS</b>
        <a href="http://www.faqs.org/rfcs/rfc3463.html">RFC 3463</a> (Enhanced status codes)
 
 <b>DIAGNOSTICS</b>
-       Command  exit status codes are expected to follow the con-
-       ventions defined in &lt;<b>sysexits.h</b>&gt;.   Exit  status  0  means
+       Command exit status codes are expected to follow the  con-
+       ventions  defined  in  &lt;<b>sysexits.h</b>&gt;.   Exit status 0 means
        normal successful completion.
 
-       Postfix  version  2.3  and  later  support  <a href="http://www.faqs.org/rfcs/rfc3463.html">RFC 3463</a>-style
-       enhanced status codes.  If a  command  terminates  with  a
-       non-zero  exit  status, and the command output begins with
+       Postfix version  2.3  and  later  support  <a href="http://www.faqs.org/rfcs/rfc3463.html">RFC  3463</a>-style
+       enhanced  status  codes.   If  a command terminates with a
+       non-zero exit status, and the command output  begins  with
        an enhanced status code, this status code takes precedence
        over the non-zero exit status.
 
-       Problems  and transactions are logged to <b>syslogd</b>(8).  Cor-
-       rupted message files are marked so that the queue  manager
+       Problems and transactions are logged to <b>syslogd</b>(8).   Cor-
+       rupted  message files are marked so that the queue manager
        can move them to the <b>corrupt</b> queue for further inspection.
 
 <b>SECURITY</b>
-       This program needs a dual personality  1)  to  access  the
-       private  Postfix  queue and IPC mechanisms, and 2) to exe-
+       This  program  needs  a  dual personality 1) to access the
+       private Postfix queue and IPC mechanisms, and 2)  to  exe-
        cute external commands as the specified user. It is there-
        fore security sensitive.
 
 <b>CONFIGURATION PARAMETERS</b>
-       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
+       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.
 
-       The  text  below  provides  only  a parameter summary. See
+       The text below provides  only  a  parameter  summary.  See
        <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
 
 <b>RESOURCE AND RATE CONTROLS</b>
-       In the text below, <i>transport</i> is the first field in a  <b>mas-</b>
+       In  the text below, <i>transport</i> is the first field in a <b>mas-</b>
        <b>ter.cf</b> entry.
 
        <i>transport</i><b>_destination_concurrency_limit ($<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>
               Limit the number of parallel deliveries to the same
-              destination, for delivery via the named  <i>transport</i>.
+              destination,  for delivery via the named <i>transport</i>.
               The limit is enforced by the Postfix queue manager.
 
        <i>transport</i><b>_destination_recipient_limit   ($<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>
-              Limit the number of recipients per  message  deliv-
-              ery,  for  delivery  via  the named <i>transport</i>.  The
+              Limit  the  number of recipients per message deliv-
+              ery, for delivery via  the  named  <i>transport</i>.   The
               limit is enforced by the Postfix queue manager.
 
        <i>transport</i><b>_time_limit ($<a href="postconf.5.html#command_time_limit">command_time_limit</a>)</b>
-              Limit the time for delivery  to  external  command,
+              Limit  the  time  for delivery to external command,
               for delivery via the named <i>transport</i>.  The limit is
               enforced by the pipe delivery agent.
 
-              Postfix 2.4 and later support a suffix that  speci-
-              fies  the  time  unit:  s (seconds), m (minutes), h
+              Postfix  2.4 and later support a suffix that speci-
+              fies the time unit: s  (seconds),  m  (minutes),  h
               (hours), d (days), w (weeks). The default time unit
               is seconds.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The  default  location  of  the Postfix <a href="postconf.5.html">main.cf</a> and
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
               <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
-              How much time a Postfix daemon process may take  to
-              handle  a  request  before  it  is  terminated by a
+              How  much time a Postfix daemon process may take to
+              handle a request  before  it  is  terminated  by  a
               built-in watchdog timer.
 
        <b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
-              The maximal number  of  digits  after  the  decimal
+              The  maximal  number  of  digits  after the decimal
               point when logging sub-second delay values.
 
        <b><a href="postconf.5.html#export_environment">export_environment</a> (see 'postconf -d' output)</b>
-              The  list  of  environment variables that a Postfix
+              The list of environment variables  that  a  Postfix
               process will export to non-Postfix processes.
 
        <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
@@ -405,25 +428,25 @@ PIPE(8)                                                                PIPE(8)
               and most Postfix daemon processes.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The maximum amount of time  that  an  idle  Postfix
-              daemon  process  waits  for  an incoming connection
+              The  maximum  amount  of  time that an idle Postfix
+              daemon process waits  for  an  incoming  connection
               before terminating voluntarily.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The maximal number of incoming connections  that  a
-              Postfix  daemon  process will service before termi-
+              The  maximal  number of incoming connections that a
+              Postfix daemon process will service  before  termi-
               nating voluntarily.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The process ID  of  a  Postfix  command  or  daemon
+              The  process  ID  of  a  Postfix  command or daemon
               process.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The  process  name  of  a Postfix command or daemon
+              The process name of a  Postfix  command  or  daemon
               process.
 
        <b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
-              The location of the Postfix top-level queue  direc-
+              The  location of the Postfix top-level queue direc-
               tory.
 
        <b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
@@ -434,8 +457,8 @@ PIPE(8)                                                                PIPE(8)
               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".
 
 <b>SEE ALSO</b>
@@ -447,7 +470,7 @@ PIPE(8)                                                                PIPE(8)
        syslogd(8), system logging
 
 <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 ac0646f7a29e7f52207fe29f74c7221519d7aead..5ec01696fca57f568a2a578ef53b7fc20c7fa2d7 100644 (file)
@@ -62,77 +62,76 @@ REGEXP_TABLE(5)                                                REGEXP_TABLE(5)
 
        <b>endif</b>  Match the input string against the patterns between
               <b>if</b> and <b>endif</b>, if and only if that same input string
-              does  <b>not</b>  match  <i>pattern</i>.  The <b>if</b>..<b>endif</b> can nest.
-              matches <i>pattern</i>. The <b>if</b>..<b>endif</b> can nest.
+              does <b>not</b> match <i>pattern</i>. The <b>if</b>..<b>endif</b> can nest.
 
-              Note: do not prepend whitespace to patterns  inside
+              Note:  do not prepend whitespace to patterns inside
               <b>if</b>..<b>endif</b>.
 
               This feature is available in Postfix 2.1 and later.
 
        blank lines and comments
-              Empty lines and whitespace-only lines are  ignored,
-              as  are  lines whose first non-whitespace character
+              Empty  lines and whitespace-only lines are ignored,
+              as are lines whose first  non-whitespace  character
               is a `#'.
 
        multi-line text
-              A logical line starts with non-whitespace  text.  A
-              line  that starts with whitespace continues a logi-
+              A  logical  line starts with non-whitespace text. A
+              line that starts with whitespace continues a  logi-
               cal line.
 
-       Each pattern is a POSIX regular expression enclosed  by  a
+       Each  pattern  is a POSIX regular expression enclosed by a
        pair of delimiters. The regular expression syntax is docu-
-       mented in  <b>re_format</b>(7)  with  4.4BSD,  in  <b>regex</b>(5)  with
+       mented  in  <b>re_format</b>(7)  with  4.4BSD,  in  <b>regex</b>(5) with
        Solaris, and in <b>regex</b>(7) with Linux. Other systems may use
        other document names.
 
-       The expression delimiter  can  be  any  character,  except
+       The  expression  delimiter  can  be  any character, except
        whitespace or characters that have special meaning (tradi-
-       tionally the forward slash is used). The  regular  expres-
+       tionally  the  forward slash is used). The regular expres-
        sion can contain whitespace.
 
        By default, matching is case-insensitive, and newlines are
-       not treated as special characters. The  behavior  is  con-
-       trolled  by  flags,  which are toggled by appending one or
+       not  treated  as  special characters. The behavior is con-
+       trolled by flags, which are toggled by  appending  one  or
        more of the following characters after the pattern:
 
        <b>i</b> (default: on)
-              Toggles the  case  sensitivity  flag.  By  default,
+              Toggles  the  case  sensitivity  flag.  By default,
               matching is case insensitive.
 
        <b>x</b> (default: on)
-              Toggles  the  extended  expression  syntax flag. By
-              default, support for extended expression syntax  is
+              Toggles the extended  expression  syntax  flag.  By
+              default,  support for extended expression syntax is
               enabled.
 
        <b>m</b> (default: off)
-              Toggle  the multi-line mode flag. When this flag is
-              on, the <b>^</b> and <b>$</b>  metacharacters  match  immediately
-              after  and  immediately before a newline character,
-              respectively, in addition to matching at the  start
+              Toggle the multi-line mode flag. When this flag  is
+              on,  the  <b>^</b>  and <b>$</b> metacharacters match immediately
+              after and immediately before a  newline  character,
+              respectively,  in addition to matching at the start
               and end of the input string.
 
 <b>TABLE SEARCH ORDER</b>
-       Patterns  are applied in the order as specified in the ta-
-       ble, until a pattern  is  found  that  matches  the  input
+       Patterns are applied in the order as specified in the  ta-
+       ble,  until  a  pattern  is  found  that matches the input
        string.
 
-       Each  pattern  is  applied  to  the  entire  input string.
-       Depending on the application, that  string  is  an  entire
+       Each pattern  is  applied  to  the  entire  input  string.
+       Depending  on  the  application,  that string is an entire
        client hostname, an entire client IP address, or an entire
-       mail address.  Thus, no parent domain  or  parent  network
-       search  is  done,  and  <i>user@domain</i> mail addresses are not
-       broken up into their <i>user</i> and  <i>domain</i>  constituent  parts,
+       mail  address.   Thus,  no parent domain or parent network
+       search is done, and <i>user@domain</i>  mail  addresses  are  not
+       broken  up  into  their <i>user</i> and <i>domain</i> constituent parts,
        nor is <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
 
 <b>TEXT SUBSTITUTION</b>
-       Substitution  of  substrings  from  the matched expression
-       into the result string is possible  using  $1,  $2,  etc.;
+       Substitution of substrings  from  the  matched  expression
+       into  the  result  string  is possible using $1, $2, etc.;
        specify $$ to produce a $ character as output.  The macros
-       in the result string may need to be  written  as  ${n}  or
+       in  the  result  string  may need to be written as ${n} or
        $(n) if they aren't followed by whitespace.
 
-       Note:  since negated patterns (those preceded by <b>!</b>) return
+       Note: since negated patterns (those preceded by <b>!</b>)  return
        a result when the expression does not match, substitutions
        are not available for negated patterns.
 
index 63485b9f5d34714bdfd37a0d0c3f84c24fa48a30..e96f4ad3b6a0a79daece466f0a711f123d0aca51 100644 (file)
@@ -216,6 +216,13 @@ This feature is available in Postfix 2.1 and later.
 .IP \fIrestriction...\fR
 Apply the named UCE restriction(s) (\fBpermit\fR, \fBreject\fR,
 \fBreject_unauth_destination\fR, and so on).
+.IP "\fBBCC \fIuser@domain\fR"
+Send one copy of the message to the specified recipient.
+.sp
+If multiple BCC actions are specified within the same SMTP
+MAIL transaction, only the last action will be used.
+.sp
+This feature is not part of the stable Postfix release.
 .IP "\fBDISCARD \fIoptional text...\fR
 Claim successful delivery and silently discard the message.
 Log the optional text if specified, otherwise log a generic
index 8cb6abf5d36cbb7cb6f82f6d5b5b8063ca650215..c3c008fb1d157612233010232e477eb3c0f9710e 100644 (file)
@@ -51,7 +51,7 @@ the corresponding \fIresult\fR value.
 .IP "\fBif /\fIpattern\fB/\fIflags\fR"
 .IP "\fBendif\fR"
 Match the input string against the patterns between \fBif\fR
-and \fBendif\fR, if and only if the input string also matches
+and \fBendif\fR, if and only if that same input string also matches
 \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
 .sp
 Note: do not prepend whitespace to patterns inside
@@ -61,7 +61,7 @@ This feature is available in Postfix 2.1 and later.
 .IP "\fBif !/\fIpattern\fB/\fIflags\fR"
 .IP "\fBendif\fR"
 Match the input string against the patterns between \fBif\fR
-and \fBendif\fR, if and only if the input string does \fBnot\fR
+and \fBendif\fR, if and only if that same input string does \fBnot\fR
 match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
 .sp
 Note: do not prepend whitespace to patterns inside
index 5113c1a1fde5956df41d1e4ac6b962c7ba7cbefd..4b4d98231af7178338eb01533fcf1476cba994b3 100644 (file)
@@ -63,7 +63,6 @@ This feature is available in Postfix 2.1 and later.
 Match the input string against the patterns between \fBif\fR
 and \fBendif\fR, if and only if that same input string does
 \fBnot\fR match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
-matches \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
 .sp
 Note: do not prepend whitespace to patterns inside
 \fBif\fR..\fBendif\fR.
index 4c27e7bb017f007ba255b9e901e13579600e973d..7b5a2c6758f09d5e028282a99118830b02ad6cb3 100644 (file)
@@ -31,9 +31,11 @@ appropriate.
 .nf
 .ad
 .fi
-Some external commands cannot handle more than one recipient
-per delivery request. Examples of such transports are pagers
-or fax machines.
+Some destinations cannot handle more than one recipient per
+delivery request. Examples are pagers or fax machines.
+In addition, multi-recipient delivery is undesirable when
+prepending a \fBDelivered-to:\fR or \fBX-Original-To:\fR
+message header.
 
 To prevent Postfix from sending multiple recipients per delivery
 request, specify
@@ -84,7 +86,13 @@ when preceded by a blank line.
 .IP \fBD\fR
 Prepend a "\fBDelivered-To: \fIrecipient\fR" message header with the
 envelope recipient address. Note: for this to work, the
-\fItransport\fB_destination_recipient_limit\fR must be 1.
+\fItransport\fB_destination_recipient_limit\fR must be 1
+(see SINGLE-RECIPIENT DELIVERY above for details).
+.sp
+This code also enforces loop detection (Postfix 2.5 and later).
+If a message already contains a \fBDelivered-To:\fR header
+with the same recipient address, then the message is
+returned as undeliverable.
 .sp
 This feature is available as of Postfix 2.0.
 .IP \fBF\fR
@@ -94,15 +102,18 @@ This is expected by, for example, \fBUUCP\fR software.
 .IP \fBO\fR
 Prepend an "\fBX-Original-To: \fIrecipient\fR" message header
 with the recipient address as given to Postfix. Note: for this to
-work, the \fItransport\fB_destination_recipient_limit\fR must be 1.
+work, the \fItransport\fB_destination_recipient_limit\fR must be 1
+(see SINGLE-RECIPIENT DELIVERY above for details).
 .sp
 This feature is available as of Postfix 2.0.
 .IP \fBR\fR
 Prepend a \fBReturn-Path:\fR message header with the envelope sender
 address.
 .IP \fBh\fR
-Fold the command-line \fB$recipient\fR domain name and \fB$nexthop\fR
-host name to lower case.
+Fold the command-line \fB$recipient\fR address domain part
+(text to the right of the right-most \fB@\fR character) to
+lower case; fold the entire command-line \fB$domain\fR and
+\fB$nexthop\fR host or domain information to lower case.
 This is recommended for delivery via \fBUUCP\fR.
 .IP \fBq\fR
 Quote white space and other special characters in the command-line
@@ -159,7 +170,7 @@ specify \fB$sender\fR as an argument by itself:
     command -f $sender -- $recipient (\fIgood\fR)
 .fi
 .IP
-This feature is available with Postfix 2.3 and later.
+This feature is available as of Postfix 2.3.
 .IP "\fBsize\fR=\fIsize_limit\fR (optional)"
 Messages greater in size than this limit (in bytes) will
 be returned to the sender as undeliverable.
@@ -201,6 +212,14 @@ This is available in Postfix 2.2 and later.
 This macro expands to the remote client protocol.
 .sp
 This is available in Postfix 2.2 and later.
+.IP \fB${\fBdomain\fR}\fR
+This macro expands to the domain portion of the recipient
+address.  For example, with an address \fIuser+foo@domain\fR
+the domain is \fIdomain\fR.
+.sp
+This information is modified by the \fBh\fR flag for case folding.
+.sp
+This is available in Postfix 2.5 and later.
 .IP \fB${\fBextension\fR}\fR
 This macro expands to the extension part of a recipient address.
 For example, with an address \fIuser+foo@domain\fR the extension is
index b0fc39ee30546e44398052fc564b02d6c27e4103..1854a6f001e1cde21ea2fee6ef1291f196d35559 100644 (file)
@@ -74,6 +74,7 @@ server sends in a delegated SMTPD access policy request: </p>
 
 <blockquote>
 <pre>
+<b>Postfix version 2.1 and later:</b>
 request=smtpd_access_policy
 protocol_state=RCPT
 protocol_name=SMTP
index 6ebee10ad68342f290728ea01fa3e8c6b90cb035..665cc9e8f7ebaaf00000537e0091c94db8a40d9b 100644 (file)
 # .IP \fIrestriction...\fR
 #      Apply the named UCE restriction(s) (\fBpermit\fR, \fBreject\fR,
 #      \fBreject_unauth_destination\fR, and so on).
+# .IP "\fBBCC \fIuser@domain\fR"
+#      Send one copy of the message to the specified recipient.
+# .sp
+#      If multiple BCC actions are specified within the same SMTP
+#      MAIL transaction, only the last action will be used.
+# .sp
+#      This feature is not part of the stable Postfix release.
 # \" .IP "\fBDELAY \fItime\fR"
 # \"   Place the message into the deferred queue, and delay the
 # \"   initial delivery attempt by \fItime\fR. The time value may
index c0ab8f3eb69a8e9d5a4d2fadaf227ae4cba7bbb7..679e67ef7ae26aa9558d27ccd2d047d4a4fe4a1e 100644 (file)
@@ -41,7 +41,7 @@
 # .IP "\fBif /\fIpattern\fB/\fIflags\fR"
 # .IP "\fBendif\fR"
 #      Match the input string against the patterns between \fBif\fR
-#      and \fBendif\fR, if and only if the input string also matches
+#      and \fBendif\fR, if and only if that same input string also matches
 #      \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
 # .sp
 #      Note: do not prepend whitespace to patterns inside
@@ -51,7 +51,7 @@
 # .IP "\fBif !/\fIpattern\fB/\fIflags\fR"
 # .IP "\fBendif\fR"
 #      Match the input string against the patterns between \fBif\fR
-#      and \fBendif\fR, if and only if the input string does \fBnot\fR
+#      and \fBendif\fR, if and only if that same input string does \fBnot\fR
 #      match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
 # .sp
 #      Note: do not prepend whitespace to patterns inside
index 3a15f46a912c9b22d02acfbc528044a54f3b1e68..6e225b33cb6c9f448b32b3a7105a9b643dae6f0d 100644 (file)
@@ -53,7 +53,6 @@
 #       Match the input string against the patterns between \fBif\fR
 #      and \fBendif\fR, if and only if that same input string does
 #      \fBnot\fR match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
-#      matches \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
 # .sp
 #       Note: do not prepend whitespace to patterns inside
 #      \fBif\fR..\fBendif\fR.
index b6c602f0b928f35849106b1239587e222f70b689..1e2aa89a272bf6c6d32d09c0997cc5b832d3fc77 100644 (file)
@@ -27,7 +27,7 @@ SRCS  = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
        sys_exits.c timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
        tok822_resolve.c tok822_rewrite.c tok822_tree.c trace.c \
        user_acl.c valid_mailhost_addr.c verify.c verify_clnt.c \
-       verp_sender.c wildcard_inet_addr.c xtext.c
+       verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c
 OBJS   = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
        canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
        clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
@@ -56,7 +56,7 @@ OBJS  = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
        sys_exits.o timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
        tok822_resolve.o tok822_rewrite.o tok822_tree.o trace.o \
        user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o \
-       verp_sender.o wildcard_inet_addr.o xtext.o
+       verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o
 HDRS   = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
        canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
        conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
@@ -79,7 +79,7 @@ HDRS  = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
        rewrite_clnt.h scache.h sent.h smtp_stream.h split_addr.h \
        string_list.h strip_addr.h sys_exits.h timed_ipc.h tok822.h \
        trace.h user_acl.h valid_mailhost_addr.h verify.h verify_clnt.h \
-       verp_sender.h wildcard_inet_addr.h xtext.h
+       verp_sender.h wildcard_inet_addr.h xtext.h delivered_hdr.h
 TESTSRC        = rec2stream.c stream2rec.c recdump.c
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
@@ -688,6 +688,23 @@ deliver_request.o: mail_queue.h
 deliver_request.o: msg_stats.h
 deliver_request.o: rcpt_buf.h
 deliver_request.o: recipient_list.h
+delivered_hdr.o: ../../include/htable.h
+delivered_hdr.o: ../../include/msg.h
+delivered_hdr.o: ../../include/mymalloc.h
+delivered_hdr.o: ../../include/stringops.h
+delivered_hdr.o: ../../include/sys_defs.h
+delivered_hdr.o: ../../include/vbuf.h
+delivered_hdr.o: ../../include/vstream.h
+delivered_hdr.o: ../../include/vstring.h
+delivered_hdr.o: ../../include/vstring_vstream.h
+delivered_hdr.o: delivered_hdr.c
+delivered_hdr.o: delivered_hdr.h
+delivered_hdr.o: header_opts.h
+delivered_hdr.o: is_header.h
+delivered_hdr.o: quote_822_local.h
+delivered_hdr.o: quote_flags.h
+delivered_hdr.o: rec_type.h
+delivered_hdr.o: record.h
 dict_ldap.o: ../../include/argv.h
 dict_ldap.o: ../../include/binhash.h
 dict_ldap.o: ../../include/dict.h
diff --git a/postfix/src/global/delivered_hdr.c b/postfix/src/global/delivered_hdr.c
new file mode 100644 (file)
index 0000000..f3dc2c4
--- /dev/null
@@ -0,0 +1,167 @@
+/*++
+/* NAME
+/*     delivered_hdr 3
+/* SUMMARY
+/*     process Delivered-To: headers
+/* SYNOPSIS
+/*     #include <delivered_hdr.h>
+/*
+/*     DELIVERED_HDR_INFO *delivered_hdr_init(stream, offset)
+/*     VSTREAM *stream;
+/*     off_t   offset;
+/*
+/*     int     delivered_hdr_find(info, address)
+/*     DELIVERED_HDR_INFO *info;
+/*     const char *address;
+/*
+/*     void    delivered_hdr_free(info)
+/*     DELIVERED_HDR_INFO *info;
+/* DESCRIPTION
+/*     This module processes addresses in Delivered-To: headers.
+/*     These headers are added by some mail delivery systems, for the
+/*     purpose of breaking mail forwarding loops. N.B. This solves
+/*     a different problem than the Received: hop count limit. Hop
+/*     counts are used to limit the impact of mail routing problems.
+/*
+/*     delivered_hdr_init() extracts Delivered-To: header addresses
+/*     from the specified message, and returns a table with the
+/*     result. The file seek pointer is changed.
+/*
+/*     delivered_hdr_find() looks up the address in the lookup table,
+/*     and returns non-zero when the address was found. The
+/*     address argument must be in internalized form.
+/*
+/*     delivered_hdr_free() releases storage that was allocated by
+/*     delivered_hdr_init().
+/*
+/*     Arguments:
+/* .IP stream
+/*     The open queue file.
+/* .IP offset
+/*     Offset of the first message content record.
+/* .IP info
+/*     Extracted Delivered-To: addresses information.
+/* .IP address
+/*     A recipient address, internal form.
+/* DIAGNOSTICS
+/*     Fatal errors: out of memory.
+/* SEE ALSO
+/*     mail_copy(3), producer of Delivered-To: and other headers.
+/* 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 <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <htable.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <vstring_vstream.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include <record.h>
+#include <rec_type.h>
+#include <is_header.h>
+#include <quote_822_local.h>
+#include <header_opts.h>
+#include <delivered_hdr.h>
+
+ /*
+  * Application-specific.
+  */
+struct DELIVERED_HDR_INFO {
+    VSTRING *buf;
+    HTABLE *table;
+};
+
+#define STR(x) vstring_str(x)
+
+/* delivered_hdr_init - extract delivered-to information from the message */
+
+DELIVERED_HDR_INFO *delivered_hdr_init(VSTREAM *fp, off_t offset)
+{
+    char   *cp;
+    DELIVERED_HDR_INFO *info;
+    HEADER_OPTS *hdr;
+
+    info = (DELIVERED_HDR_INFO *) mymalloc(sizeof(*info));
+    info->buf = vstring_alloc(10);
+    info->table = htable_create(0);
+
+    if (vstream_fseek(fp, offset, SEEK_SET) < 0)
+       msg_fatal("seek queue file %s: %m", VSTREAM_PATH(fp));
+
+    /*
+     * XXX Assume that mail_copy() produces delivered-to headers that fit in
+     * a REC_TYPE_NORM record. Lowercase the delivered-to addresses for
+     * consistency.
+     * 
+     * XXX Don't get bogged down by gazillions of delivered-to headers.
+     */
+#define DELIVERED_HDR_LIMIT    1000
+
+    while (rec_get(fp, info->buf, 0) == REC_TYPE_NORM
+          && info->table->used < DELIVERED_HDR_LIMIT) {
+       if (is_header(STR(info->buf))) {
+           if ((hdr = header_opts_find(STR(info->buf))) != 0
+               && hdr->type == HDR_DELIVERED_TO) {
+               cp = STR(info->buf) + strlen(hdr->name) + 1;
+               while (ISSPACE(*cp))
+                   cp++;
+               lowercase(cp);
+               if (msg_verbose)
+                   msg_info("delivered_hdr_init: %s", cp);
+               htable_enter(info->table, cp, (char *) 0);
+           }
+       } else if (ISSPACE(STR(info->buf)[0])) {
+           continue;
+       } else {
+           break;
+       }
+    }
+    return (info);
+}
+
+/* delivered_hdr_find - look up recipient in delivered table */
+
+int     delivered_hdr_find(DELIVERED_HDR_INFO *info, const char *address)
+{
+    HTABLE_INFO *ht;
+
+    /*
+     * mail_copy() uses quote_822_local() when writing the Delivered-To:
+     * header. We must therefore apply the same transformation when looking
+     * up the recipient. Lowercase the delivered-to address for consistency.
+     */
+    quote_822_local(info->buf, address);
+    lowercase(STR(info->buf));
+    ht = htable_locate(info->table, STR(info->buf));
+    return (ht != 0);
+}
+
+/* delivered_hdr_free - destructor */
+
+void    delivered_hdr_free(DELIVERED_HDR_INFO *info)
+{
+    vstring_free(info->buf);
+    htable_free(info->table, (void (*) (char *)) 0);
+    myfree((char *) info);
+}
diff --git a/postfix/src/global/delivered_hdr.h b/postfix/src/global/delivered_hdr.h
new file mode 100644 (file)
index 0000000..4a7ca25
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _DELIVERED_HDR_H_INCLUDED_
+#define _DELIVERED_HDR_H_INCLUDED_
+
+/*++
+/* NAME
+/*     delivered_hdr 3h
+/* SUMMARY
+/*     process Delivered-To: headers
+/* SYNOPSIS
+/*     #include <delivered_hdr.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <vstream.h>
+
+ /*
+  * External interface.
+  */
+typedef struct DELIVERED_HDR_INFO DELIVERED_HDR_INFO;
+extern DELIVERED_HDR_INFO *delivered_hdr_init(VSTREAM *, off_t);
+extern int delivered_hdr_find(DELIVERED_HDR_INFO *, const char *);
+extern void delivered_hdr_free(DELIVERED_HDR_INFO *);
+
+/* 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
+/*--*/
+
+#endif
index da7a1f3d3ee198d84517a864a67867130c7f1968..b5f4ec0d85275f16b9a5a845e10232a6fdc73ed8 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      "20070402"
+#define MAIL_RELEASE_DATE      "20070422"
 #define MAIL_VERSION_NUMBER    "2.5"
 
 #ifdef SNAPSHOT
index b96f0a736bfbf575803ce3c98c216ddf6a34b340..4668deadda97c782da4e9d28bbe043ff57e5a212 100644 (file)
   */
 extern CLNT_STREAM *rewrite_clnt_stream;
 
+static time_t last_expire;
 static VSTRING *last_class;
 static VSTRING *last_sender;
 static VSTRING *last_addr;
@@ -190,7 +191,8 @@ void    resolve_clnt(const char *class, const char *sender,
      */
 #define IFSET(flag, text) ((reply->flags & (flag)) ? (text) : "")
 
-    if (*addr && strcmp(addr, STR(last_addr)) == 0
+    if (event_time() < last_expire
+       && *addr && strcmp(addr, STR(last_addr)) == 0
        && strcmp(class, STR(last_class)) == 0
        && strcmp(sender, STR(last_sender)) == 0) {
        vstring_strcpy(reply->transport, STR(last_reply.transport));
@@ -282,6 +284,7 @@ void    resolve_clnt(const char *class, const char *sender,
     vstring_strcpy(last_reply.nexthop, STR(reply->nexthop));
     vstring_strcpy(last_reply.recipient, STR(reply->recipient));
     last_reply.flags = reply->flags;
+    last_expire = event_time() + 30;           /* XXX make configurable */
 }
 
 /* resolve_clnt_free - destroy reply */
index 8bb3f0a5247967432349fed7cbf7bf851772c3af..6d110bf5986af02b7d3d5a945d9fe61cbd4bd39f 100644 (file)
@@ -72,6 +72,7 @@
   */
 CLNT_STREAM *rewrite_clnt_stream = 0;
 
+static time_t last_expire;
 static VSTRING *last_rule;
 static VSTRING *last_addr;
 static VSTRING *last_result;
@@ -107,7 +108,8 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
     /*
      * Peek at the cache.
      */
-    if (strcmp(addr, STR(last_addr)) == 0
+    if (event_time() < last_expire
+       && strcmp(addr, STR(last_addr)) == 0
        && strcmp(rule, STR(last_rule)) == 0) {
        vstring_strcpy(result, STR(last_result));
        if (msg_verbose)
@@ -163,6 +165,7 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
     vstring_strcpy(last_rule, rule);
     vstring_strcpy(last_addr, addr);
     vstring_strcpy(last_result, STR(result));
+    last_expire = event_time() + 30;           /* XXX make configurable */
 
     return (result);
 }
index f22a5646e0c3b72e8344063ebc8fb1812328d91e..10962b5ccfba650eb14c528803fde693ff384e31 100644 (file)
@@ -1,9 +1,9 @@
 SHELL  = /bin/sh
-SRCS   = alias.c command.c delivered.c dotforward.c file.c forward.c \
+SRCS   = alias.c command.c dotforward.c file.c forward.c \
        include.c indirect.c local.c mailbox.c recipient.c resolve.c token.c \
        deliver_attr.c maildir.c biff_notify.c unknown.c \
        local_expand.c
-OBJS   = alias.o command.o delivered.o dotforward.o file.o forward.o \
+OBJS   = alias.o command.o dotforward.o file.o forward.o \
        include.o indirect.o local.o mailbox.o recipient.o resolve.o token.o \
        deliver_attr.o maildir.o biff_notify.o unknown.o \
        local_expand.o
@@ -71,6 +71,7 @@ alias.o: ../../include/bounce.h
 alias.o: ../../include/canon_addr.h
 alias.o: ../../include/defer.h
 alias.o: ../../include/deliver_request.h
+alias.o: ../../include/delivered_hdr.h
 alias.o: ../../include/dict.h
 alias.o: ../../include/dsn.h
 alias.o: ../../include/dsn_buf.h
@@ -105,6 +106,7 @@ command.o: ../../include/been_here.h
 command.o: ../../include/bounce.h
 command.o: ../../include/defer.h
 command.o: ../../include/deliver_request.h
+command.o: ../../include/delivered_hdr.h
 command.o: ../../include/dict.h
 command.o: ../../include/dsn.h
 command.o: ../../include/dsn_buf.h
@@ -132,6 +134,7 @@ deliver_attr.o: ../../include/argv.h
 deliver_attr.o: ../../include/attr.h
 deliver_attr.o: ../../include/been_here.h
 deliver_attr.o: ../../include/deliver_request.h
+deliver_attr.o: ../../include/delivered_hdr.h
 deliver_attr.o: ../../include/dict.h
 deliver_attr.o: ../../include/dsn.h
 deliver_attr.o: ../../include/dsn_buf.h
@@ -149,40 +152,12 @@ deliver_attr.o: ../../include/vstream.h
 deliver_attr.o: ../../include/vstring.h
 deliver_attr.o: deliver_attr.c
 deliver_attr.o: local.h
-delivered.o: ../../include/argv.h
-delivered.o: ../../include/attr.h
-delivered.o: ../../include/been_here.h
-delivered.o: ../../include/deliver_request.h
-delivered.o: ../../include/dict.h
-delivered.o: ../../include/dsn.h
-delivered.o: ../../include/dsn_buf.h
-delivered.o: ../../include/header_opts.h
-delivered.o: ../../include/htable.h
-delivered.o: ../../include/is_header.h
-delivered.o: ../../include/maps.h
-delivered.o: ../../include/mbox_conf.h
-delivered.o: ../../include/msg.h
-delivered.o: ../../include/msg_stats.h
-delivered.o: ../../include/quote_822_local.h
-delivered.o: ../../include/quote_flags.h
-delivered.o: ../../include/rec_type.h
-delivered.o: ../../include/recipient_list.h
-delivered.o: ../../include/record.h
-delivered.o: ../../include/resolve_clnt.h
-delivered.o: ../../include/stringops.h
-delivered.o: ../../include/sys_defs.h
-delivered.o: ../../include/tok822.h
-delivered.o: ../../include/vbuf.h
-delivered.o: ../../include/vstream.h
-delivered.o: ../../include/vstring.h
-delivered.o: ../../include/vstring_vstream.h
-delivered.o: delivered.c
-delivered.o: local.h
 dotforward.o: ../../include/argv.h
 dotforward.o: ../../include/attr.h
 dotforward.o: ../../include/been_here.h
 dotforward.o: ../../include/bounce.h
 dotforward.o: ../../include/deliver_request.h
+dotforward.o: ../../include/delivered_hdr.h
 dotforward.o: ../../include/dict.h
 dotforward.o: ../../include/dsn.h
 dotforward.o: ../../include/dsn_buf.h
@@ -221,6 +196,7 @@ file.o: ../../include/bounce.h
 file.o: ../../include/defer.h
 file.o: ../../include/deliver_flock.h
 file.o: ../../include/deliver_request.h
+file.o: ../../include/delivered_hdr.h
 file.o: ../../include/dict.h
 file.o: ../../include/dsn.h
 file.o: ../../include/dsn_buf.h
@@ -252,6 +228,7 @@ forward.o: ../../include/been_here.h
 forward.o: ../../include/bounce.h
 forward.o: ../../include/cleanup_user.h
 forward.o: ../../include/deliver_request.h
+forward.o: ../../include/delivered_hdr.h
 forward.o: ../../include/dict.h
 forward.o: ../../include/dsn.h
 forward.o: ../../include/dsn_buf.h
@@ -287,6 +264,7 @@ include.o: ../../include/been_here.h
 include.o: ../../include/bounce.h
 include.o: ../../include/defer.h
 include.o: ../../include/deliver_request.h
+include.o: ../../include/delivered_hdr.h
 include.o: ../../include/dict.h
 include.o: ../../include/dsn.h
 include.o: ../../include/dsn_buf.h
@@ -318,6 +296,7 @@ indirect.o: ../../include/been_here.h
 indirect.o: ../../include/bounce.h
 indirect.o: ../../include/defer.h
 indirect.o: ../../include/deliver_request.h
+indirect.o: ../../include/delivered_hdr.h
 indirect.o: ../../include/dict.h
 indirect.o: ../../include/dsn.h
 indirect.o: ../../include/dsn_buf.h
@@ -342,6 +321,7 @@ local.o: ../../include/attr.h
 local.o: ../../include/been_here.h
 local.o: ../../include/deliver_completed.h
 local.o: ../../include/deliver_request.h
+local.o: ../../include/delivered_hdr.h
 local.o: ../../include/dict.h
 local.o: ../../include/dsn.h
 local.o: ../../include/dsn_buf.h
@@ -374,6 +354,7 @@ local_expand.o: ../../include/argv.h
 local_expand.o: ../../include/attr.h
 local_expand.o: ../../include/been_here.h
 local_expand.o: ../../include/deliver_request.h
+local_expand.o: ../../include/delivered_hdr.h
 local_expand.o: ../../include/dict.h
 local_expand.o: ../../include/dsn.h
 local_expand.o: ../../include/dsn_buf.h
@@ -400,6 +381,7 @@ mailbox.o: ../../include/bounce.h
 mailbox.o: ../../include/defer.h
 mailbox.o: ../../include/deliver_pass.h
 mailbox.o: ../../include/deliver_request.h
+mailbox.o: ../../include/delivered_hdr.h
 mailbox.o: ../../include/dict.h
 mailbox.o: ../../include/dsn.h
 mailbox.o: ../../include/dsn_buf.h
@@ -436,6 +418,7 @@ maildir.o: ../../include/been_here.h
 maildir.o: ../../include/bounce.h
 maildir.o: ../../include/defer.h
 maildir.o: ../../include/deliver_request.h
+maildir.o: ../../include/delivered_hdr.h
 maildir.o: ../../include/dict.h
 maildir.o: ../../include/dsn.h
 maildir.o: ../../include/dsn_buf.h
@@ -472,6 +455,7 @@ recipient.o: ../../include/bounce.h
 recipient.o: ../../include/canon_addr.h
 recipient.o: ../../include/defer.h
 recipient.o: ../../include/deliver_request.h
+recipient.o: ../../include/delivered_hdr.h
 recipient.o: ../../include/dict.h
 recipient.o: ../../include/dsn.h
 recipient.o: ../../include/dsn_buf.h
@@ -504,6 +488,7 @@ resolve.o: ../../include/been_here.h
 resolve.o: ../../include/bounce.h
 resolve.o: ../../include/defer.h
 resolve.o: ../../include/deliver_request.h
+resolve.o: ../../include/delivered_hdr.h
 resolve.o: ../../include/dict.h
 resolve.o: ../../include/dsn.h
 resolve.o: ../../include/dsn_buf.h
@@ -531,6 +516,7 @@ token.o: ../../include/been_here.h
 token.o: ../../include/bounce.h
 token.o: ../../include/defer.h
 token.o: ../../include/deliver_request.h
+token.o: ../../include/delivered_hdr.h
 token.o: ../../include/dict.h
 token.o: ../../include/dsn.h
 token.o: ../../include/dsn_buf.h
@@ -559,6 +545,7 @@ unknown.o: ../../include/been_here.h
 unknown.o: ../../include/bounce.h
 unknown.o: ../../include/deliver_pass.h
 unknown.o: ../../include/deliver_request.h
+unknown.o: ../../include/delivered_hdr.h
 unknown.o: ../../include/dict.h
 unknown.o: ../../include/dsn.h
 unknown.o: ../../include/dsn_buf.h
diff --git a/postfix/src/local/delivered.c b/postfix/src/local/delivered.c
deleted file mode 100644 (file)
index 20156ce..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*++
-/* NAME
-/*     delivered 3
-/* SUMMARY
-/*     process Delivered-To: headers
-/* SYNOPSIS
-/*     #include "local.h"
-/*
-/*     HTABLE  *delivered_init(attr)
-/*     DELIVER_ATTR attr;
-/*
-/*     int     delivered_find(table, address)
-/*     HTABLE  *table;
-/*     const char *address;
-/*
-/*     void    delivered_free(table)
-/*     HTABLE  *table;
-/* DESCRIPTION
-/*     This module processes addresses in Delivered-To: headers.
-/*     These headers are added by some mail delivery systems, for the
-/*     purpose of breaking mail forwarding loops. N.B. This solves
-/*     a different problem than the Received: hop count limit. Hop
-/*     counts are used to limit the impact of mail routing problems.
-/*
-/*     delivered_init() extracts Delivered-To: header addresses
-/*     from the specified message, and returns a table with the
-/*     result.
-/*
-/*     delivered_find() looks up the address in the lookup table,
-/*     and returns non-zero when the address was found. The
-/*     address argument must be in internalized form.
-/*
-/*     delivered_free() releases storage that was allocated by
-/*     delivered_init().
-/*
-/*     Arguments:
-/* .IP state
-/*     The attributes that specify the message, recipient and more.
-/* .IP table
-/*     A table with extracted Delivered-To: addresses.
-/* .IP address
-/*     A recipient address, internal form.
-/* DIAGNOSTICS
-/*     Fatal errors: out of memory.
-/* SEE ALSO
-/* 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 <unistd.h>
-#include <string.h>
-#include <ctype.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <htable.h>
-#include <vstring.h>
-#include <vstream.h>
-#include <vstring_vstream.h>
-#include <stringops.h>
-
-/* Global library. */
-
-#include <record.h>
-#include <rec_type.h>
-#include <is_header.h>
-#include <quote_822_local.h>
-#include <header_opts.h>
-
-/* Application-specific. */
-
-#include "local.h"
-
-static VSTRING *buf;
-
-/* delivered_init - extract delivered-to information from the message */
-
-HTABLE *delivered_init(DELIVER_ATTR attr)
-{
-    char   *cp;
-    HTABLE *table = htable_create(0);
-    HEADER_OPTS *hdr;
-
-    if (buf == 0)
-       buf = vstring_alloc(10);
-
-    if (vstream_fseek(attr.fp, attr.offset, SEEK_SET) < 0)
-       msg_fatal("seek queue file %s: %m", VSTREAM_PATH(attr.fp));
-
-    /*
-     * XXX Assume that normal mail systems produce headers that fit in a
-     * REC_TYPE_NORM record. Lowercase the delivered-to addresses for
-     * consistency.
-     */
-    while (rec_get(attr.fp, buf, 0) == REC_TYPE_NORM) {
-       if (is_header(STR(buf))) {
-           if ((hdr = header_opts_find(STR(buf))) != 0
-               && hdr->type == HDR_DELIVERED_TO) {
-               cp = STR(buf) + strlen(hdr->name) + 1;
-               while (ISSPACE(*cp))
-                   cp++;
-               lowercase(cp);
-               if (msg_verbose)
-                   msg_info("delivered_init: %s", cp);
-               htable_enter(table, cp, (char *) 0);
-           }
-       } else if (ISSPACE(STR(buf)[0])) {
-           continue;
-       } else {
-           break;
-       }
-    }
-    return (table);
-}
-
-/* delivered_find - look up recipient in delivered table */
-
-int     delivered_find(HTABLE *table, const char *address)
-{
-    HTABLE_INFO *ht;
-
-    /*
-     * mail_copy() uses quote_822_local() when writing the Delivered-To:
-     * header. We must therefore apply the same transformation when looking
-     * up the recipient. Lowercase the delivered-to address for consistency.
-     */
-    quote_822_local(buf, address);
-    lowercase(STR(buf));
-    ht = htable_locate(table, STR(buf));
-    return (ht != 0);
-}
index 557be6f4d0a5eae37c6a6b386b4f1813e487bfd4..f46ed71b3a6a891164e80b68a647c8b21b1cd6f2 100644 (file)
@@ -693,7 +693,7 @@ static int local_deliver(DELIVER_REQUEST *rqst, char *service)
     state.msg_attr.request = rqst;
     RESET_OWNER_ATTR(state.msg_attr, state.level);
     RESET_USER_ATTR(usr_attr, state.level);
-    state.loop_info = delivered_init(state.msg_attr);  /* delivered-to */
+    state.loop_info = delivered_hdr_init(rqst->fp, rqst->data_offset);
     state.request = rqst;
 
     /*
@@ -717,7 +717,7 @@ static int local_deliver(DELIVER_REQUEST *rqst, char *service)
     /*
      * Clean up.
      */
-    delivered_free(state.loop_info);
+    delivered_hdr_free(state.loop_info);
     deliver_attr_free(&state.msg_attr);
 
     return (msg_stat);
index 67c3a94037bf33d55c931b95eb7fffa0b0c825a2..d63c99a65f5dbd2f750366f4393fa2650228ca7b 100644 (file)
@@ -25,6 +25,7 @@
 #include <maps.h>
 #include <dsn_buf.h>
 #include <dsn.h>
+#include <delivered_hdr.h>
 
  /*
   * User attributes: these control the privileges for delivery to external
@@ -107,7 +108,7 @@ typedef struct LOCAL_STATE {
     int     level;                     /* nesting level, for logging */
     DELIVER_ATTR msg_attr;             /* message attributes */
     BH_TABLE *dup_filter;              /* internal duplicate filter */
-    HTABLE *loop_info;                 /* external loop filter */
+    DELIVERED_HDR_INFO *loop_info;     /* external loop filter */
     DELIVER_REQUEST *request;          /* as from queue manager */
 } LOCAL_STATE;
 
@@ -203,14 +204,6 @@ extern int local_mbox_lock_mask;
 
 extern int local_deliver_hdr_mask;
 
- /*
-  * delivered.c
-  */
-extern HTABLE *delivered_init(DELIVER_ATTR);
-extern int delivered_find(HTABLE *, const char *);
-
-#define delivered_free(t) htable_free((t), (void (*) (char *)) 0)
-
  /*
   * forward.c
   */
index e3bab10d0924489967c2029cc48ae914a26cce5e..e279eef0e2b8ec43d6d8dd9798f911cea0ca6949 100644 (file)
@@ -229,7 +229,7 @@ int     deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr)
      * need for VERP specific bouncing code, at the cost of complicating the
      * normal bounce sending procedure, but would simplify the code below.
      */
-    if (delivered_find(state.loop_info, state.msg_attr.rcpt.address)) {
+    if (delivered_hdr_find(state.loop_info, state.msg_attr.rcpt.address)) {
        VSTRING *canon_owner = 0;
 
        if (var_ownreq_special) {
index c661d74201fa9f925e79cd7331b9c9691647fcb8..b9f534fbd7176bdb764d2c7698adf25c8c2dba98 100644 (file)
@@ -64,6 +64,7 @@ pipe.o: ../../include/canon_addr.h
 pipe.o: ../../include/defer.h
 pipe.o: ../../include/deliver_completed.h
 pipe.o: ../../include/deliver_request.h
+pipe.o: ../../include/delivered_hdr.h
 pipe.o: ../../include/dict.h
 pipe.o: ../../include/dsn.h
 pipe.o: ../../include/dsn_buf.h
index d56584ca7b077e0c12f4d8927ff7319a746a515e..ec163e15de9b2cd0e2f7c317a7ab6ec12323df25 100644 (file)
 /* SINGLE-RECIPIENT DELIVERY
 /* .ad
 /* .fi
-/*     Some external commands cannot handle more than one recipient
-/*     per delivery request. Examples of such transports are pagers
-/*     or fax machines.
+/*     Some destinations cannot handle more than one recipient per
+/*     delivery request. Examples are pagers or fax machines.
+/*     In addition, multi-recipient delivery is undesirable when
+/*     prepending a \fBDelivered-to:\fR or \fBX-Original-To:\fR
+/*     message header.
 /*
 /*     To prevent Postfix from sending multiple recipients per delivery
 /*     request, specify
 /* .IP \fBD\fR
 /*     Prepend a "\fBDelivered-To: \fIrecipient\fR" message header with the
 /*     envelope recipient address. Note: for this to work, the
-/*     \fItransport\fB_destination_recipient_limit\fR must be 1.
+/*     \fItransport\fB_destination_recipient_limit\fR must be 1
+/*     (see SINGLE-RECIPIENT DELIVERY above for details).
+/* .sp
+/*     This code also enforces loop detection (Postfix 2.5 and later).
+/*     If a message already contains a \fBDelivered-To:\fR header
+/*     with the same recipient address, then the message is
+/*     returned as undeliverable.
 /* .sp
 /*     This feature is available as of Postfix 2.0.
 /* .IP \fBF\fR
 /* .IP \fBO\fR
 /*     Prepend an "\fBX-Original-To: \fIrecipient\fR" message header
 /*     with the recipient address as given to Postfix. Note: for this to
-/*     work, the \fItransport\fB_destination_recipient_limit\fR must be 1.
+/*     work, the \fItransport\fB_destination_recipient_limit\fR must be 1
+/*     (see SINGLE-RECIPIENT DELIVERY above for details).
 /* .sp
 /*     This feature is available as of Postfix 2.0.
 /* .IP \fBR\fR
 /*     Prepend a \fBReturn-Path:\fR message header with the envelope sender
 /*     address.
 /* .IP \fBh\fR
-/*     Fold the command-line \fB$recipient\fR domain name and \fB$nexthop\fR
-/*     host name to lower case.
+/*     Fold the command-line \fB$recipient\fR address domain part
+/*     (text to the right of the right-most \fB@\fR character) to
+/*     lower case; fold the entire command-line \fB$domain\fR and
+/*     \fB$nexthop\fR host or domain information to lower case.
 /*     This is recommended for delivery via \fBUUCP\fR.
 /* .IP \fBq\fR
 /*     Quote white space and other special characters in the command-line
 /*         command -f $sender -- $recipient (\fIgood\fR)
 /* .fi
 /* .IP
-/*     This feature is available with Postfix 2.3 and later.
+/*     This feature is available as of Postfix 2.3.
 /* .IP "\fBsize\fR=\fIsize_limit\fR (optional)"
 /*     Messages greater in size than this limit (in bytes) will
 /*     be returned to the sender as undeliverable.
 /*     This macro expands to the remote client protocol.
 /* .sp
 /*     This is available in Postfix 2.2 and later.
+/* .IP \fB${\fBdomain\fR}\fR
+/*     This macro expands to the domain portion of the recipient
+/*     address.  For example, with an address \fIuser+foo@domain\fR
+/*     the domain is \fIdomain\fR.
+/* .sp
+/*     This information is modified by the \fBh\fR flag for case folding.
+/* .sp
+/*     This is available in Postfix 2.5 and later.
 /* .IP \fB${\fBextension\fR}\fR
 /*     This macro expands to the extension part of a recipient address.
 /*     For example, with an address \fIuser+foo@domain\fR the extension is
 #include <dsn_util.h>
 #include <dsn_buf.h>
 #include <sys_exits.h>
+#include <delivered_hdr.h>
 
 /* Single server skeleton. */
 
 #define PIPE_DICT_USER         "user"  /* key */
 #define PIPE_DICT_EXTENSION    "extension"     /* key */
 #define PIPE_DICT_MAILBOX      "mailbox"       /* key */
+#define PIPE_DICT_DOMAIN       "domain"/* key */
 #define PIPE_DICT_SIZE         "size"  /* key */
 #define PIPE_DICT_CLIENT_ADDR  "client_address"        /* key */
 #define PIPE_DICT_CLIENT_NAME  "client_hostname"       /* key */
 #define PIPE_FLAG_USER         (1<<1)
 #define PIPE_FLAG_EXTENSION    (1<<2)
 #define PIPE_FLAG_MAILBOX      (1<<3)
+#define PIPE_FLAG_DOMAIN       (1<<4)
 
  /*
   * Additional flags. These are colocated with mail_copy() flags. Allow some
@@ -531,6 +553,7 @@ static int parse_callback(int type, VSTRING *buf, char *context)
        PIPE_DICT_USER, PIPE_FLAG_USER,
        PIPE_DICT_EXTENSION, PIPE_FLAG_EXTENSION,
        PIPE_DICT_MAILBOX, PIPE_FLAG_MAILBOX,
+       PIPE_DICT_DOMAIN, PIPE_FLAG_DOMAIN,
        PIPE_DICT_SIZE, 0,
        PIPE_DICT_CLIENT_ADDR, 0,
        PIPE_DICT_CLIENT_NAME, 0,
@@ -609,6 +632,7 @@ static ARGV *expand_argv(const char *service, char **argv,
     PIPE_STATE state;
     int     i;
     char   *ext;
+    char   *dom;
 
     /*
      * This appears to be simple operation (replace $name by its expansion).
@@ -700,6 +724,22 @@ static ARGV *expand_argv(const char *service, char **argv,
                    dict_update(PIPE_DICT_TABLE, PIPE_DICT_MAILBOX, STR(buf));
                }
 
+               /*
+                * This argument contains $domain. Extract the domain name:
+                * anything to the right of the rightmost @.
+                */
+               if (state.expand_flag & PIPE_FLAG_DOMAIN) {
+                   morph_recipient(buf, rcpt_list->info[i].address,
+                                   flags & PIPE_OPT_FOLD_FLAGS);
+                   dom = split_at_right(STR(buf), '@');
+                   if (dom == 0) {
+                       msg_warn("no @ in recipient address: %s",
+                                rcpt_list->info[i].address);
+                       dom = "";               /* insert null arg */
+                   }
+                   dict_update(PIPE_DICT_TABLE, PIPE_DICT_DOMAIN, dom);
+               }
+
                /*
                 * Done.
                 */
@@ -1073,6 +1113,32 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
        return (deliver_status);
     }
 
+    /*
+     * Report mail delivery loops. By definition, this requires
+     * single-recipient delivery. Don't silently lose recipients.
+     */
+    if (attr.flags & MAIL_COPY_DELIVERED) {
+       DELIVERED_HDR_INFO *info;
+       RECIPIENT *rcpt;
+       int     loop_found;
+
+       if (request->rcpt_list.len > 1)
+           msg_panic("%s: delivered-to enabled with multi-recipient request",
+                     myname);
+       info = delivered_hdr_init(request->fp, request->data_offset);
+       rcpt = request->rcpt_list.info;
+       loop_found = delivered_hdr_find(info, rcpt->address);
+       delivered_hdr_free(info);
+       if (loop_found) {
+           dsb_simple(why, "5.4.6", "mail forwarding loop for %s",
+                      rcpt->address);
+           deliver_status = eval_command_status(PIPE_STAT_BOUNCE, service,
+                                                request, request->fp, why);
+           DELIVER_MSG_CLEANUP();
+           return (deliver_status);
+       }
+    }
+
     /*
      * Deliver. Set the nexthop and sender variables, and expand the command
      * argument vector. Recipients will be expanded on the fly. XXX Rewrite
index 601a1f53887f1c13af026783d26b6cbfcc098f77..70522679ff714def5b763ca5152aeaab5ef48ec2 100644 (file)
@@ -2131,6 +2131,10 @@ static void mail_reset(SMTPD_STATE *state)
        myfree(state->saved_redirect);
        state->saved_redirect = 0;
     }
+    if (state->saved_bcc) {
+       myfree(state->saved_bcc);
+       state->saved_bcc = 0;
+    }
     state->saved_flags = 0;
 #ifdef DELAY_ACTION
     state->saved_delay = 0;
@@ -2712,6 +2716,12 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
            if (state->saved_redirect)
                rec_fprintf(state->cleanup, REC_TYPE_RDR, "%s",
                            state->saved_redirect);
+           if (state->saved_bcc) {
+               rec_fprintf(state->cleanup, REC_TYPE_RCPT, "%s",
+                           state->saved_bcc);
+               rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%d",
+                           MAIL_ATTR_DSN_NOTIFY, DSN_NOTIFY_NEVER);
+           }
            if (state->saved_flags)
                rec_fprintf(state->cleanup, REC_TYPE_FLGS, "%d",
                            state->saved_flags);
index 44478605c69d655600ede3cbc59a3e8a0f63d8c3..d44978050dda8876e44333482794c655bce5ea58 100644 (file)
@@ -133,6 +133,7 @@ typedef struct SMTPD_STATE {
     int     discard;                   /* discard message */
     char   *saved_filter;              /* postponed filter action */
     char   *saved_redirect;            /* postponed redirect action */
+    char   *saved_bcc;                 /* postponed bcc action */
     int     saved_flags;               /* postponed hold/discard */
 #ifdef DELAY_ACTION
     int     saved_delay;               /* postponed deferred delay */
index dde16082822291715287dcbf0cde5cd2a89e4b32..6a3e143517143813a8744bbf41a1c34cfb9525e2 100644 (file)
@@ -2099,6 +2099,32 @@ static int check_table_result(SMTPD_STATE *state, const char *table,
        }
     }
 
+    /*
+     * BCC means deliver to designated recipient. But we may still
+     * change our mind, and reject/discard the message for other reasons.
+     */
+#ifdef SNAPSHOT
+    if (STREQUAL(value, "BCC", cmd_len)) {
+#ifndef TEST
+       if (can_delegate_action(state, table, "BCC", reply_class) == 0)
+           return (SMTPD_CHECK_DUNNO);
+#endif
+       if (strchr(cmd_text, '@') == 0) {
+           msg_warn("access table %s entry \"%s\" requires user@domain target",
+                    table, datum);
+           return (SMTPD_CHECK_DUNNO);
+       } else {
+           vstring_sprintf(error_text, "<%s>: %s triggers BCC %s",
+                           reply_name, reply_class, cmd_text);
+           log_whatsup(state, "bcc", STR(error_text));
+#ifndef TEST
+           UPDATE_STRING(state->saved_bcc, cmd_text);
+#endif
+           return (SMTPD_CHECK_DUNNO);
+       }
+    }
+#endif
+
     /*
      * DEFER_IF_PERMIT changes "permit" into "maybe". Use optional text or
      * generate a generic error response.
index 1f8092dbfcea7deca414b559edd274acf65d16d0..a104a117424c5c1dfcc7a09e4388c76df3bd6138 100644 (file)
@@ -123,6 +123,7 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
     state->proxy_xforward_features = 0;
     state->saved_filter = 0;
     state->saved_redirect = 0;
+    state->saved_bcc = 0;
     state->saved_flags = 0;
 #ifdef DELAY_ACTION
     state->saved_delay = 0;
index 6b3ae51a31d2d6c1654ef6bbe7df77516b559f97..6f4e24e8f95d61f983af482f4b02e5223b9ddc4b 100644 (file)
@@ -119,6 +119,7 @@ rewrite.o: trivial-rewrite.h
 transport.o: ../../include/argv.h
 transport.o: ../../include/attr.h
 transport.o: ../../include/dict.h
+transport.o: ../../include/events.h
 transport.o: ../../include/iostuff.h
 transport.o: ../../include/mail_params.h
 transport.o: ../../include/mail_proto.h
index 8905177461866e57db678c2623d1bf13b066427e..7750a372bb30e317980059b188e4b89a538f3d97 100644 (file)
@@ -69,6 +69,7 @@
 #include <vstring.h>
 #include <split_at.h>
 #include <dict.h>
+#include <events.h>
 
 /* Global library. */
 
@@ -99,8 +100,10 @@ TRANSPORT_INFO *transport_pre_init(const char *transport_maps_name,
     tp->transport_path = maps_create(transport_maps_name, transport_maps,
                                     DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
                                     | DICT_FLAG_NO_REGSUB);
-    tp->wildcard_channel = tp->wildcard_nexthop = 0;
+    tp->wildcard_channel = vstring_alloc(10);
+    tp->wildcard_nexthop = vstring_alloc(10);
     tp->transport_errno = 0;
+    tp->expire = 0;
     return (tp);
 }
 
@@ -204,8 +207,6 @@ static int find_transport_entry(TRANSPORT_INFO *tp, const char *key,
 
 static void transport_wildcard_init(TRANSPORT_INFO *tp)
 {
-    VSTRING *channel = vstring_alloc(10);
-    VSTRING *nexthop = vstring_alloc(10);
 
     /*
      * Technically, the wildcard lookup pattern is redundant. A static map
@@ -221,22 +222,20 @@ static void transport_wildcard_init(TRANSPORT_INFO *tp)
 #define FULL           0
 #define PARTIAL                DICT_FLAG_FIXED
 
-    if (find_transport_entry(tp, WILDCARD, "", FULL, channel, nexthop)) {
+    if (find_transport_entry(tp, WILDCARD, "", FULL,
+                            tp->wildcard_channel,
+                            tp->wildcard_nexthop)) {
        tp->transport_errno = 0;
-       if (tp->wildcard_channel)
-           vstring_free(tp->wildcard_channel);
-       tp->wildcard_channel = channel;
-       if (tp->wildcard_nexthop)
-           vstring_free(tp->wildcard_nexthop);
-       tp->wildcard_nexthop = nexthop;
        if (msg_verbose)
            msg_info("wildcard_{chan:hop}={%s:%s}",
-                    vstring_str(channel), vstring_str(nexthop));
+                    vstring_str(tp->wildcard_channel),
+                    vstring_str(tp->wildcard_nexthop));
     } else {
        tp->transport_errno = dict_errno;
-       vstring_free(channel);
-       vstring_free(nexthop);
+       VSTRING_RESET(tp->wildcard_channel);
+       VSTRING_RESET(tp->wildcard_nexthop);
     }
+    tp->expire = event_time() + 30;            /* XXX make configurable */
 }
 
 /* transport_lookup - map a transport domain */
@@ -321,12 +320,12 @@ int     transport_lookup(TRANSPORT_INFO *tp, const char *addr,
     /*
      * Fall back to the wild-card entry.
      */
-    if (tp->transport_errno)
+    if (tp->transport_errno || event_time() > tp->expire)
        transport_wildcard_init(tp);
     if (tp->transport_errno) {
        dict_errno = tp->transport_errno;
        return (NOTFOUND);
-    } else if (tp->wildcard_channel) {
+    } else if (tp->wildcard_channel && VSTRING_LEN(tp->wildcard_channel)) {
        update_entry(STR(tp->wildcard_channel), STR(tp->wildcard_nexthop),
                     rcpt_domain, channel, nexthop);
        return (FOUND);
index 27912d821e81a9f92d08e10aacbdbc0229684376..0660f97b58997f5173b497294172525e42ce4358 100644 (file)
@@ -8,6 +8,11 @@
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * System library.
+  */
+#include <time.h>
+
  /*
   * Utility library.
   */
@@ -26,6 +31,7 @@ typedef struct TRANSPORT_INFO {
     VSTRING *wildcard_channel;
     VSTRING *wildcard_nexthop;
     int     transport_errno;
+    time_t  expire;
 } TRANSPORT_INFO;
 
 extern TRANSPORT_INFO *transport_pre_init(const char *, const char *);