]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.4-20061217
authorWietse Venema <wietse@porcupine.org>
Sun, 17 Dec 2006 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:32:43 +0000 (06:32 +0000)
36 files changed:
postfix/HISTORY
postfix/README_FILES/BACKSCATTER_README
postfix/RELEASE_NOTES
postfix/html/BACKSCATTER_README.html
postfix/html/flush.8.html
postfix/html/postconf.5.html
postfix/html/postqueue.1.html
postfix/html/sendmail.1.html
postfix/man/man1/postqueue.1
postfix/man/man1/sendmail.1
postfix/man/man5/postconf.5
postfix/man/man8/flush.8
postfix/proto/BACKSCATTER_README.html
postfix/proto/postconf.proto
postfix/src/flush/Makefile.in
postfix/src/flush/flush.c
postfix/src/global/flush_clnt.c
postfix/src/global/flush_clnt.h
postfix/src/global/mail_queue.h
postfix/src/global/mail_version.h
postfix/src/oqmgr/qmgr.c
postfix/src/oqmgr/qmgr.h
postfix/src/oqmgr/qmgr_active.c
postfix/src/oqmgr/qmgr_message.c
postfix/src/oqmgr/qmgr_scan.c
postfix/src/postconf/postconf.c
postfix/src/postqueue/Makefile.in
postfix/src/postqueue/postqueue.c
postfix/src/qmgr/qmgr.c
postfix/src/qmgr/qmgr.h
postfix/src/qmgr/qmgr_active.c
postfix/src/qmgr/qmgr_message.c
postfix/src/qmgr/qmgr_scan.c
postfix/src/sendmail/sendmail.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_check.c

index 952176f91ebca1c608560bacc0ad0ec207f5680e..8c1e6ede69dd03989da57596ebf255ac5b3bd7f2 100644 (file)
@@ -12935,7 +12935,8 @@ Apologies for any names omitted.
        after-the-fact consistency of the thread that was interrupted.
        File: util/msg_output.c.
 
-       Robustness: replace exit() calls by _exit(). File: util/msg.c.
+       Robustness: replace exit() calls by _exit(). File: util/msg.c,
+       bounce/bounce_cleanup.c.
 
 20061207
 
@@ -12982,7 +12983,47 @@ Apologies for any names omitted.
        Cleanup: streamline the signal handler reentrancy protections,
        and document under what conditions these protections work,
        with REENTRANCY sections in the relevant man pages. Files:
-       util/vbuf.c.  util/msg.c, util/msg_output.c.
+       util/vbuf_print.c.  util/msg.c, util/msg_output.c.
+
+20061211
+
+       When doing server access control by the TLS client fingerprint,
+       do not require client certificate verification.  Victor
+       Duchovni.  File: smtpd/smtpd_check.c.
+
+       When the remote SMTP client certificate isn't verified,
+       don't send ccert_subject and ccert_issuer attributes in
+       check_policy_service requests. Victor Duchovni. File:
+       smtpd/smtpd_check.c.
+
+       Bugfix: the postconf command still complained about an
+       unqualified machine name, because it was not updated with
+       the 20050513 change that introduced a default "mydomain =
+       localdomain".  File: postconf/postconf.c.
+
+20061213
+
+       Bugfix: race condition in "ETRN site", "sendmail -qRsite"
+       and "postqueue -s site". When the command arrived while an
+       incoming queue scan was already in progress, mail could
+       stay deferred instead of being flushed. The fix was to
+       unthrottle the queue manager before moving files from the
+       deferred queue to the incoming queue.  Files: flush/flush.c,
+       qmgr/qmgr_scan.c.
+
+       Feature: "sendmail -qIqueueid" and "postqueue -i queueid"
+       to flush a specific queue file. Files: sendmail/sendmail.c,
+       postqueue/postqueue.c, global/flush_clnt.c, flush/flush.c.
+
+20061214
+
+       Performance: "sendmail -qIqueueid" and "postqueue -i queueid"
+       unthrottle only the necessary message delivery transports
+       and queues. The unthrottle request now is propagated to the
+       queue manager via queue file group read permission bits.
+       Based on initial implementation by Victor Duchovni.  Files:
+       flush/flush.c, *qmgr/qmgr.c, *qmgr/qmgr_scan.c,
+       *qmgr/qmgr_active.c, *qmgr/qmgr_message.c.
 
 Wish list:
 
@@ -13037,9 +13078,6 @@ Wish list:
        Are transport:nexthop null fields the same as in the case
        of default_transport etc. parameters?
 
-       Introduce structured API for tls_server_mumble() just like
-       with smtp(8): this eliminates ever-growing lists of arguments.
-
        Don't lose bits when converting st_dev into maildir file
        name. It's 64 bits on Linux. Found with the BEAM source
        code analyzer. Is this really a problem, or are they just
@@ -13054,9 +13092,6 @@ Wish list:
        while it is configured in an SMTP server that runs before
        the smtpd_proxy filter.
 
-       The sendmail command should not return non-std exit status
-       after fatal error in some internal library routine.
-
        Log DSN original recipient when rejecting mail.
 
        Keep whitespace between label and ":"?
@@ -13190,20 +13225,13 @@ Wish list:
        would allow correlation of rejected RCPT TO requests with
        accepted requests for the same mail transaction.
 
-       Med: silly queue file bit so that the queue manager doesn't
-       skip files when fast flush is requested while a queue scan
-       is in progress. The bit is set by the flush server and is
-       reset when the mail is deferred, so that it survives queue
-       manager restart. It's not clear, however, how one would
-       unthrottle disabled transports or queues.
-
        Med: postsuper -r should do something with recipients in
        bounce logfiles, to make sure the sender will be notified.
        To be perfectly safe, no process other than the queue manager
        should move a queue file away from the active queue.
 
        This could involve tagging a queue file, and use up another
-       permission bit.
+       permission bit (postsuper tags a "hot" file, qmgr requeues it).
 
        Low: postsuper re-run after renaming files, but only a
        limited number of times.
@@ -13222,7 +13250,7 @@ Wish list:
 
        Low: have a configurable list of errno values for mailbox
        or maildir delivery that result in deferral rather than
-       bouncing mail.
+       bouncing mail. What about "killed by signal" exits?
 
        Low: after reorganizing configuration parameters, add flags
        to all parameters whose value can be read from file.
index e5dc8f9f3813359698dcef1edecc95b9a27c9c94..a7a82c02a7dedff5f4214fdbf7e14540c444af9c 100644 (file)
@@ -110,6 +110,7 @@ this:
         /^Received:.* +by +(porcupine\.org)[[:>:]]/
             reject forged mail server name in Received: header: $1
         endif
+        /^Message-ID:.* <!&!/ DUNNO
         /^Message-ID:.*@(porcupine\.org)/
        reject forged domain name in Message-ID: header: $1
 
@@ -123,6 +124,7 @@ this:
         /^[> ]*Received:.* +by +(porcupine\.org)[[:>:]]/
             reject forged mail server name in Received: header: $1
         endif
+        /^[> ]*Message-ID:.* <!&!/ DUNNO
         /^[> ]*Message-ID:.*@(porcupine\.org)/
        reject forged domain name in Message-ID: header: $1
 
@@ -143,30 +145,54 @@ Notes:
   * The "if /pattern/" and "endif" eliminate unnecessary matching attempts. DO
     NOT indent lines starting with /pattern/ between the "if" and "endif"!
 
+  * The two "Message-ID:.* <!&!" rules are workarounds for some versions of
+    Outlook express, as described in the caveats section below.
+
 C\bCa\bav\bve\bea\bat\bts\bs
 
-Netscape Messenger (and reportedly, Mozilla) sends a HELO name that is
-identical to the sender address domain part. If you have such clients then the
-above patterns would block legitimate email.
+  * Netscape Messenger (and reportedly, Mozilla) sends a HELO name that is
+    identical to the sender address domain part. If you have such clients then
+    the above patterns would block legitimate email.
 
-My network has only one such machine, and to prevent its mail from being
-blocked I have configured it to send mail as user@hostname.porcupine.org. On
-the Postfix server, a canonical mapping translates this temporary address into
-user@porcupine.org.
+    My network has only one such machine, and to prevent its mail from being
+    blocked I have configured it to send mail as user@hostname.porcupine.org.
+    On the Postfix server, a canonical mapping translates this temporary
+    address into user@porcupine.org.
 
-    /etc/postfix/main.cf:
-        canonical_maps = hash:/etc/postfix/canonical
+        /etc/postfix/main.cf:
+            canonical_maps = hash:/etc/postfix/canonical
+
+        /etc/postfix/canonical:
+            @hostname.porcupine.org @porcupine.org
+
+    This is of course practical only when you have very few systems that send
+    HELO commands like this, and when you never have to send mail to a user on
+    such a host.
+
+    An alternative would be to remove the hostname from
+    "hostname.porcupine.org" with address masquerading, as described in the
+    ADDRESS_REWRITING_README document.
+
+  * Reportedly, Outlook 2003 (perhaps Outlook Express, and other versions as
+    well) present substantially different Message-ID headers depending upon
+    whether or not a DSN is requested (via Options "Request a delivery receipt
+    for this message").
+
+    When a DSN is requested, Outlook 2003 uses a Message-ID string that ends in
+    the sender's domain name:
 
-    /etc/postfix/canonical:
-        @hostname.porcupine.org @porcupine.org
+        Message-ID: <!&! ...very long string... ==@example.com>
 
-This is of course practical only when you have very few systems that send HELO
-commands like this, and when you never have to send mail to a user on such a
-host.
+    where example.com is the domain name part of the email address specified in
+    Outlook's account settings for the user. Since many users configure their
+    email addresses as username@example.com, messages with DSN turned on will
+    trigger the REJECT action in the previous section.
 
-An alternative would be to remove the hostname from "hostname.porcupine.org"
-with address masquerading, as described in the ADDRESS_REWRITING_README
-document.
+    If you have such clients then you can to exclude their Message-ID strings
+    with the two "Message-ID:.* <!&!" patterns that are shown in the previous
+    section. Otherwise you will not be able to use the two backscatter rules to
+    stop forged Message ID strings. Of course this workaround may break the
+    next time Outlook is changed.
 
 B\bBl\blo\boc\bck\bki\bin\bng\bg b\bba\bac\bck\bks\bsc\bca\bat\btt\bte\ber\br m\bma\bai\bil\bl w\bwi\bit\bth\bh f\bfo\bor\brg\bge\bed\bd s\bse\ben\bnd\bde\ber\br i\bin\bnf\bfo\bor\brm\bma\bat\bti\bio\bon\bn
 
index 68e759d86339f2039fd044821be139b09b2e2e1b..c10dd823e0a665506016f52509de816f5dd1ebae 100644 (file)
@@ -17,6 +17,14 @@ Incompatibility with Postfix 2.2 and earlier
 If you upgrade from Postfix 2.2 or earlier, read RELEASE_NOTES-2.3
 before proceeding.
 
+Incompatible changes with Postfix snapshot 20061217
+===================================================
+
+Postfix no longer requires a domain name. It uses "localdomain" as
+the default Internet domain name when no domain is specified in
+main.cf, and when the machine hostname does not include domain name
+information.
+
 Incompatible changes with Postfix snapshot 20061209
 ===================================================
 
index 240f2d0538c1f840c6a09f5093faf88c32534b57..2c757bffc2bd9c4224353c3457be494f3a459306 100644 (file)
@@ -186,6 +186,7 @@ patterns like this: </p>
     /^Received:.* +by +(porcupine\.org)[[:&gt;:]]/
         reject forged mail server name in Received: header: $1
     endif
+    /^Message-ID:.* &lt;!&amp;!/ DUNNO
     /^Message-ID:.*@(porcupine\.org)/
        reject forged domain name in Message-ID: header: $1
 
@@ -198,6 +199,7 @@ patterns like this: </p>
     /^[&gt; ]*Received:.* +by +(porcupine\.org)[[:&gt;:]]/
         reject forged mail server name in Received: header: $1
     endif
+    /^[&gt; ]*Message-ID:.* &lt;!&amp;!/ DUNNO
     /^[&gt; ]*Message-ID:.*@(porcupine\.org)/
        reject forged domain name in Message-ID: header: $1
 </pre>
@@ -226,10 +228,18 @@ see your system documentation. </p>
 matching attempts. DO NOT indent lines starting with /pattern/
 between the "if" and "endif"! </p>
 
+<li> <p> The two "<tt>Message-ID:.* &lt;!&amp;!</tt>" rules are
+workarounds for some versions of Outlook express, as described in
+the <a href="#caveats"> caveats </a> section below.
+
 </ul>
 
 <p><a name="caveats"><strong>Caveats</strong></a></p>
 
+<ul>
+
+<li>
+
 <p> Netscape Messenger (and reportedly, Mozilla) sends a HELO name
 that is identical to the sender address domain part. If you have
 such clients then the above patterns would block legitimate email.
@@ -260,6 +270,35 @@ mail to a user on such a host. </p>
 masquerading, as described in the <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a> document.
 </p>
 
+<li> <p> Reportedly, Outlook 2003 (perhaps Outlook Express, and
+other versions as well) present substantially different Message-ID
+headers depending upon whether or not a DSN is requested (via Options
+"Request a delivery receipt for this message"). </p>
+
+<p> When a DSN is requested, Outlook 2003 uses a Message-ID string
+that ends in the sender's domain name: </p>
+
+<blockquote>
+<pre>
+Message-ID: &lt;!&amp;! ...very long string... ==@example.com&gt;
+</pre>
+</blockquote>
+
+<p> where <i>example.com</i> is the domain name part of the email
+address specified in Outlook's account settings for the user.  Since
+many users configure their email addresses as <i>username@example.com</i>,
+messages with DSN turned on will trigger the REJECT action in the
+previous section. </p>
+
+<p> If you have such clients then you can to exclude their Message-ID
+strings with the two "<tt>Message-ID:.* &lt;!&amp;!</tt>" patterns
+that are shown in the previous section.  Otherwise you will not be
+able to use the two backscatter rules to stop forged Message ID
+strings.  Of course this workaround may break the next time Outlook
+is changed.  </p>
+
+</ul>
+
 <h3><a name="forged_sender">Blocking backscatter mail with forged
 sender information</a></h3>
 
index 5a81f41615baa2f4753bc1841af4307c5a1add3a..cba373e9edc45f03f5516e68c8b13e8be63624e9 100644 (file)
@@ -38,10 +38,13 @@ FLUSH(8)                                                              FLUSH(8)
               the  specified queue ID is queued for the specified
               destination.
 
-       <b>send</b> <i>sitename</i>
+       <b>send_site</b> <i>sitename</i>
               Request delivery of mail that  is  queued  for  the
               specified destination.
 
+       <b>send_file</b> <i>queueid</i>
+              Request delivery of the specified deferred message.
+
        <b>refresh</b>
               Refresh  non-empty  per-destination  logfiles  that
               were not read in <b>$<a href="postconf.5.html#fast_flush_refresh_time">fast_flush_refresh_time</a></b> hours, by
@@ -57,7 +60,7 @@ FLUSH(8)                                                              FLUSH(8)
 
 <b>SECURITY</b>
        The <a href="flush.8.html"><b>flush</b>(8)</a> server is not security-sensitive. It does not
-       talk to the network, and it does not talk to local  users.
+       talk  to the network, and it does not talk to local users.
        The fast flush server can run chrooted at fixed low privi-
        lege.
 
@@ -65,46 +68,46 @@ FLUSH(8)                                                              FLUSH(8)
        Problems and transactions are logged to <b>syslogd</b>(8).
 
 <b>BUGS</b>
-       Fast flush logfiles are  truncated  only  after  a  "send"
-       request,  not  when mail is actually delivered, and there-
-       fore can accumulate outdated or redundant data.  In  order
-       to  maintain  sanity,  "refresh" must be executed periodi-
-       cally. This can be automated with a suitable wakeup  timer
+       Fast  flush  logfiles  are  truncated  only after a "send"
+       request, not when mail is actually delivered,  and  there-
+       fore  can  accumulate outdated or redundant data. In order
+       to maintain sanity, "refresh" must  be  executed  periodi-
+       cally.  This can be automated with a suitable wakeup timer
        setting in the <a href="master.5.html"><b>master.cf</b></a> configuration file.
 
-       Upon  receipt of a request to deliver mail for an eligible
-       destination, the <a href="flush.8.html"><b>flush</b>(8)</a> server requests delivery of  all
-       messages  that  are  listed in that destination's logfile,
-       regardless of the recipients of those  messages.  This  is
+       Upon receipt of a request to deliver mail for an  eligible
+       destination,  the <a href="flush.8.html"><b>flush</b>(8)</a> server requests delivery of all
+       messages that are listed in  that  destination's  logfile,
+       regardless  of  the  recipients of those messages. This is
        not an issue for mail that is sent to a <b><a href="postconf.5.html#relay_domains">relay_domains</a></b> des-
-       tination because such mail typically only  has  recipients
+       tination  because  such mail typically only has recipients
        in one domain.
 
 <b>CONFIGURATION PARAMETERS</b>
        Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically as <a href="flush.8.html"><b>flush</b>(8)</a>
-       processes run for only a limited amount of time.  Use  the
+       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><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#fast_flush_domains">fast_flush_domains</a> ($<a href="postconf.5.html#relay_domains">relay_domains</a>)</b>
               Optional list of destinations that are eligible for
-              per-destination logfiles with mail that  is  queued
+              per-destination  logfiles  with mail that is queued
               to those destinations.
 
        <b><a href="postconf.5.html#fast_flush_refresh_time">fast_flush_refresh_time</a> (12h)</b>
-              The  time  after  which a non-empty but unread per-
-              destination  "fast  flush"  logfile  needs  to   be
+              The time after which a non-empty  but  unread  per-
+              destination   "fast  flush"  logfile  needs  to  be
               refreshed.
 
        <b><a href="postconf.5.html#fast_flush_purge_time">fast_flush_purge_time</a> (7d)</b>
@@ -116,38 +119,38 @@ FLUSH(8)                                                              FLUSH(8)
               over an internal communication channel.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The  maximum  amount  of  time that an idle Postfix
-              daemon process waits for 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#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf  -d'  out-</b>
+       <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a>  (see  'postconf -d' out-</b>
        <b>put)</b>
               What   Postfix   features   match   subdomains   of
               "domain.tld" automatically, instead of requiring an
               explicit ".domain.tld" pattern.
 
        <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#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".
 
 <b>FILES</b>
@@ -165,7 +168,7 @@ FLUSH(8)                                                              FLUSH(8)
        <a href="ETRN_README.html">ETRN_README</a>, Postfix ETRN howto
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>HISTORY</b>
index 0468636f94ffaa98272f237145d869787307c42b..c1e0f2b4c97a9b2ab4b44c3089a27e159339a9d1 100644 (file)
@@ -9190,9 +9190,10 @@ client network address information.
 
 <dt><b><a name="check_ccert_access">check_ccert_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
 
-<dd>When the remote SMTP client certificate is verified successfully,
-use the client certificate fingerprint as lookup key for the specified
-<a href="access.5.html">access(5)</a> database. This feature is available with Postfix version 2.2.</dd>
+<dd> Use the client certificate fingerprint as lookup key for the
+specified <a href="access.5.html">access(5)</a> database; with Postfix version 2.2, also require
+that the SMTP client certificate is verified successfully. This
+feature is available with Postfix version 2.2 and later.</dd>
 
 <dt><b><a name="check_client_access">check_client_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
 
index b1885010062db06bbd352f7dd4cf39aa3d056a01..0a96c5486cc8eb5fcbcaaea51f25433e60e37551 100644 (file)
@@ -11,6 +11,7 @@ POSTQUEUE(1)                                                      POSTQUEUE(1)
 
 <b>SYNOPSIS</b>
        <b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-f</b>
+       <b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-i</b> <i>queue</i><b>_</b><i>id</i>
        <b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-p</b>
        <b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-s</b> <i>site</i>
 
@@ -41,115 +42,121 @@ POSTQUEUE(1)                                                      POSTQUEUE(1)
               will  result  in  poor  delivery performance of all
               other mail.
 
+       <b>-i</b> <i>queue</i><b>_</b><i>id</i>
+              Schedule immediate delivery of mail with the speci-
+              fied  queue  ID.   This  feature  uses the <a href="flush.8.html"><b>flush</b>(8)</a>
+              server, and  is  available  with  Postfix  2.4  and
+              later.
+
        <b>-p</b>     Produce a traditional sendmail-style queue listing.
-              This  option  implements the traditional <b>mailq</b> com-
+              This option implements the traditional  <b>mailq</b>  com-
               mand, by contacting the Postfix <a href="showq.8.html"><b>showq</b>(8)</a> daemon.
 
-              Each queue entry shows the queue file  ID,  message
+              Each  queue  entry shows the queue file ID, message
               size, arrival time, sender, and the recipients that
-              still need to be delivered.  If mail could  not  be
-              delivered  upon  the  last  attempt, the reason for
-              failure is shown. This mode of operation is  imple-
-              mented  by  executing the <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command. The
-              queue ID string is followed by an  optional  status
+              still  need  to be delivered.  If mail could not be
+              delivered upon the last  attempt,  the  reason  for
+              failure  is shown. This mode of operation is imple-
+              mented by executing the <a href="postqueue.1.html"><b>postqueue</b>(1)</a>  command.  The
+              queue  ID  string is followed by an optional status
               character:
 
               <b>*</b>      The message is in the <b>active</b> queue, i.e. the
                      message is selected for delivery.
 
-              <b>!</b>      The message is in the <b>hold</b>  queue,  i.e.  no
-                     further  delivery attempt will be made until
+              <b>!</b>      The  message  is  in the <b>hold</b> queue, i.e. no
+                     further delivery attempt will be made  until
                      the mail is taken off hold.
 
        <b>-s</b> <i>site</i>
-              Schedule immediate delivery of  all  mail  that  is
+              Schedule  immediate  delivery  of  all mail that is
               queued for the named <i>site</i>. A numerical site must be
-              specified as  a  valid  <a href="http://www.faqs.org/rfcs/rfc2821.html">RFC  2821</a>  address  literal
-              enclosed  in [], just like in email addresses.  The
+              specified  as  a  valid  <a href="http://www.faqs.org/rfcs/rfc2821.html">RFC  2821</a>  address literal
+              enclosed in [], just like in email addresses.   The
               site must be eligible for the "fast flush" service.
-              See  <a href="flush.8.html"><b>flush</b>(8)</a>  for more information about the "fast
+              See <a href="flush.8.html"><b>flush</b>(8)</a> for more information about  the  "fast
               flush" service.
 
-              This option implements  the  traditional  "<b>sendmail</b>
-              <b>-qR</b><i>site</i>"   command,   by   contacting  the  Postfix
+              This  option  implements  the traditional "<b>sendmail</b>
+              <b>-qR</b><i>site</i>"  command,  by   contacting   the   Postfix
               <a href="flush.8.html"><b>flush</b>(8)</a> daemon.
 
        <b>-v</b>     Enable verbose logging for debugging purposes. Mul-
-              tiple  <b>-v</b>  options  make  the software increasingly
-              verbose. As of Postfix 2.3, this option  is  avail-
+              tiple <b>-v</b> options  make  the  software  increasingly
+              verbose.  As  of Postfix 2.3, this option is avail-
               able for the super-user only.
 
 <b>SECURITY</b>
-       This  program  is designed to run with set-group ID privi-
+       This program is designed to run with set-group  ID  privi-
        leges, so that it can connect to Postfix daemon processes.
 
 <b>DIAGNOSTICS</b>
-       Problems  are  logged  to  <b>syslogd</b>(8)  and to the standard
+       Problems are logged to  <b>syslogd</b>(8)  and  to  the  standard
        error stream.
 
 <b>ENVIRONMENT</b>
        MAIL_CONFIG
-              Directory with the <a href="postconf.5.html"><b>main.cf</b></a> file. In order to  avoid
-              exploitation  of  set-group  ID  privileges, a non-
+              Directory  with the <a href="postconf.5.html"><b>main.cf</b></a> file. In order to avoid
+              exploitation of set-group  ID  privileges,  a  non-
               standard directory is allowed only if:
 
-              <b>o</b>      The name is listed in the  standard  <a href="postconf.5.html"><b>main.cf</b></a>
-                     file  with  the <b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a></b>
+              <b>o</b>      The  name  is listed in the standard <a href="postconf.5.html"><b>main.cf</b></a>
+                     file with  the  <b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a></b>
                      configuration parameter.
 
               <b>o</b>      The command is invoked by the super-user.
 
 <b>CONFIGURATION PARAMETERS</b>
-       The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are  especially  relevant
+       The  following  <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
        to this program.  The text below provides only a parameter
-       summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including  exam-
+       summary.  See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including exam-
        ples.
 
        <b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a> (empty)</b>
-              A  list of non-default Postfix configuration direc-
+              A list of non-default Postfix configuration  direc-
               tories that may be specified with "-c <a href="postconf.5.html#config_directory">config_direc</a>-
-              <a href="postconf.5.html#config_directory">tory</a>"  on  the command line, or via the MAIL_CONFIG
+              <a href="postconf.5.html#config_directory">tory</a>" on the command line, or via  the  MAIL_CONFIG
               environment parameter.
 
        <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#command_directory">command_directory</a> (see 'postconf -d' output)</b>
-              The  location  of  all  postfix administrative com-
+              The location of  all  postfix  administrative  com-
               mands.
 
        <b><a href="postconf.5.html#fast_flush_domains">fast_flush_domains</a> ($<a href="postconf.5.html#relay_domains">relay_domains</a>)</b>
               Optional list of destinations that are eligible for
-              per-destination  logfiles  with mail that is queued
+              per-destination logfiles with mail that  is  queued
               to those destinations.
 
        <b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
-              The list of environment parameters that  a  Postfix
+              The  list  of environment parameters that a Postfix
               process  will  import  from  a  non-Postfix  parent
               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#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".
 
        <b><a href="postconf.5.html#trigger_timeout">trigger_timeout</a> (10s)</b>
-              The  time  limit for sending a trigger to a Postfix
-              daemon (for example, the <a href="pickup.8.html"><b>pickup</b>(8)</a> or <a href="qmgr.8.html"><b>qmgr</b>(8)</a>  dae-
+              The time limit for sending a trigger to  a  Postfix
+              daemon  (for example, the <a href="pickup.8.html"><b>pickup</b>(8)</a> or <a href="qmgr.8.html"><b>qmgr</b>(8)</a> dae-
               mon).
 
        Available in Postfix version 2.2 and later:
 
        <b><a href="postconf.5.html#authorized_flush_users">authorized_flush_users</a> (static:anyone)</b>
-              List  of  users  who  are  authorized  to flush the
+              List of users  who  are  authorized  to  flush  the
               queue.
 
        <b><a href="postconf.5.html#authorized_mailq_users">authorized_mailq_users</a> (static:anyone)</b>
@@ -169,11 +176,11 @@ POSTQUEUE(1)                                                      POSTQUEUE(1)
        <a href="ETRN_README.html">ETRN_README</a>, Postfix ETRN howto
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>HISTORY</b>
-       The  postqueue command was introduced with Postfix version
+       The postqueue command was introduced with Postfix  version
        1.1.
 
 <b>AUTHOR(S)</b>
index c79578d8e744669cbf9cb46fe7849b74924ce59c..527edee80f03c2ff070846940b9c60ac3a228d15 100644 (file)
@@ -217,24 +217,30 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               The   interval   between   queue   runs.   Use  the
               <b><a href="postconf.5.html#queue_run_delay">queue_run_delay</a></b> configuration parameter instead.
 
+       <b>-qI</b><i>queueid</i>
+              Schedule immediate delivery of mail with the speci-
+              fied  queue ID.  This option is implemented by exe-
+              cuting the <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command, and  is  available
+              with Postfix version 2.4 and later.
+
        <b>-qR</b><i>site</i>
-              Schedule immediate delivery of  all  mail  that  is
+              Schedule  immediate  delivery  of  all mail that is
               queued for the named <i>site</i>. This option accepts only
-              <i>site</i> names that are eligible for the  "fast  flush"
-              service,   and  is  implemented  by  executing  the
+              <i>site</i>  names  that are eligible for the "fast flush"
+              service,  and  is  implemented  by  executing   the
               <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command.  See <a href="flush.8.html"><b>flush</b>(8)</a> for more infor-
               mation about the "fast flush" service.
 
        <b>-qS</b><i>site</i>
-              This  command  is  not  implemented. Use the slower
+              This command is not  implemented.  Use  the  slower
               "<b>sendmail -q</b>" command instead.
 
-       <b>-t</b>     Extract recipients from message headers. These  are
-              added  to  any  recipients specified on the command
+       <b>-t</b>     Extract  recipients from message headers. These are
+              added to any recipients specified  on  the  command
               line.
 
-              With Postfix versions prior  to  2.1,  this  option
-              requires  that no recipient addresses are specified
+              With  Postfix  versions  prior  to 2.1, this option
+              requires that no recipient addresses are  specified
               on the command line.
 
        <b>-U</b> (ignored)
@@ -247,41 +253,41 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               This feature is available in Postfix 2.3 and later.
 
        <b>-XV</b> (Postfix 2.2 and earlier: <b>-V</b>)
-              Variable Envelope Return Path.  Given  an  envelope
-              sender  address  of the form <i>owner-listname</i>@<i>origin</i>,
-              each recipient <i>user</i>@<i>domain</i>  receives  mail  with  a
+              Variable  Envelope  Return  Path. Given an envelope
+              sender address of the  form  <i>owner-listname</i>@<i>origin</i>,
+              each  recipient  <i>user</i>@<i>domain</i>  receives  mail with a
               personalized envelope sender address.
 
-              By   default,   the  personalized  envelope  sender
-              address is  <i>owner-listname</i><b>+</b><i>user</i><b>=</b><i>domain</i>@<i>origin</i>.  The
-              default  <b>+</b>  and  <b>=</b> characters are configurable with
-              the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b>  configuration  parame-
+              By  default,  the  personalized   envelope   sender
+              address  is  <i>owner-listname</i><b>+</b><i>user</i><b>=</b><i>domain</i>@<i>origin</i>. The
+              default <b>+</b> and <b>=</b> characters  are  configurable  with
+              the  <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b>  configuration parame-
               ter.
 
        <b>-XV</b><i>xy</i> (Postfix 2.2 and earlier: <b>-V</b><i>xy</i>)
-              As  <b>-XV</b>,  but  uses  <i>x</i>  and <i>y</i> as the VERP delimiter
-              characters, instead  of  the  characters  specified
-              with   the   <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b>  configuration
+              As <b>-XV</b>, but uses <i>x</i> and  <i>y</i>  as  the  VERP  delimiter
+              characters,  instead  of  the  characters specified
+              with  the   <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b>   configuration
               parameter.
 
-       <b>-v</b>     Send an email report of the first delivery  attempt
-              (Postfix  versions  2.1  and  later). Mail delivery
-              always happens in the background. When multiple  <b>-v</b>
+       <b>-v</b>     Send  an email report of the first delivery attempt
+              (Postfix versions 2.1  and  later).  Mail  delivery
+              always  happens in the background. When multiple <b>-v</b>
               options  are  given,  enable  verbose  logging  for
               debugging purposes.
 
        <b>-X</b> <i>log</i><b>_</b><i>file</i> (ignored)
-              Log mailer traffic.  Use  the  <b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a></b>  and
-              <b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a></b>  configuration parameters instead.
+              Log  mailer  traffic.  Use  the <b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a></b> and
+              <b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a></b> configuration parameters  instead.
 
 <b>SECURITY</b>
-       By design, this program is not  set-user  (or  group)  id.
-       However,  it  must  handle  data  from  untrusted users or
-       untrusted machines.  Thus, the usual precautions  need  to
+       By  design,  this  program  is not set-user (or group) id.
+       However, it must  handle  data  from  untrusted  users  or
+       untrusted  machines.   Thus, the usual precautions need to
        be taken against malicious inputs.
 
 <b>DIAGNOSTICS</b>
-       Problems  are  logged  to  <b>syslogd</b>(8)  and to the standard
+       Problems are logged to  <b>syslogd</b>(8)  and  to  the  standard
        error stream.
 
 <b>ENVIRONMENT</b>
@@ -293,21 +299,21 @@ SENDMAIL(1)                                                        SENDMAIL(1)
 
        <b>MAIL_DEBUG</b> (value does not matter)
               Enable debugging with an external command, as spec-
-              ified   with   the  <b><a href="postconf.5.html#debugger_command">debugger_command</a></b>  configuration
+              ified  with  the   <b><a href="postconf.5.html#debugger_command">debugger_command</a></b>   configuration
               parameter.
 
-       <b>NAME</b>   The sender full name. This is used only  with  mes-
-              sages  that  have no <b>From:</b> message header. See also
+       <b>NAME</b>   The  sender  full name. This is used only with mes-
+              sages that have no <b>From:</b> message header.  See  also
               the <b>-F</b> option above.
 
 <b>CONFIGURATION PARAMETERS</b>
-       The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are  especially  relevant
+       The  following  <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
        to this program.  The text below provides only a parameter
-       summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including  exam-
+       summary.  See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including exam-
        ples.
 
 <b>TROUBLE SHOOTING CONTROLS</b>
-       The  <a href="DEBUG_README.html">DEBUG_README</a>  file  gives  examples of how to trouble
+       The <a href="DEBUG_README.html">DEBUG_README</a> file gives examples  of  how  to  trouble
        shoot a Postfix system.
 
        <b><a href="postconf.5.html#debugger_command">debugger_command</a> (empty)</b>
@@ -315,29 +321,29 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               mon program is invoked with the -D option.
 
        <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>ACCESS CONTROLS</b>
        Available in Postfix version 2.2 and later:
 
        <b><a href="postconf.5.html#authorized_flush_users">authorized_flush_users</a> (static:anyone)</b>
-              List of users  who  are  authorized  to  flush  the
+              List  of  users  who  are  authorized  to flush the
               queue.
 
        <b><a href="postconf.5.html#authorized_mailq_users">authorized_mailq_users</a> (static:anyone)</b>
               List of users who are authorized to view the queue.
 
        <b><a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> (static:anyone)</b>
-              List of users who are  authorized  to  submit  mail
-              with  the  <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command (and with the privi-
+              List  of  users  who  are authorized to submit mail
+              with the <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command (and with  the  privi-
               leged <a href="postdrop.1.html"><b>postdrop</b>(1)</a> helper command).
 
 <b>RESOURCE AND RATE CONTROLS</b>
@@ -346,7 +352,7 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               sent in a non-delivery notification.
 
        <b><a href="postconf.5.html#fork_attempts">fork_attempts</a> (5)</b>
-              The  maximal  number  of attempts to fork() a child
+              The maximal number of attempts to  fork()  a  child
               process.
 
        <b><a href="postconf.5.html#fork_delay">fork_delay</a> (1s)</b>
@@ -354,11 +360,11 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               process.
 
        <b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b>
-              The  maximal  number  of Received:  message headers
+              The maximal number of  Received:   message  headers
               that is allowed in the primary message headers.
 
        <b><a href="postconf.5.html#queue_run_delay">queue_run_delay</a> (1000s)</b>
-              The time between <a href="QSHAPE_README.html#deferred_queue">deferred queue</a> scans by the  queue
+              The  time between <a href="QSHAPE_README.html#deferred_queue">deferred queue</a> scans by the queue
               manager.
 
 <b>FAST FLUSH CONTROLS</b>
@@ -367,37 +373,37 @@ SENDMAIL(1)                                                        SENDMAIL(1)
 
        <b><a href="postconf.5.html#fast_flush_domains">fast_flush_domains</a> ($<a href="postconf.5.html#relay_domains">relay_domains</a>)</b>
               Optional list of destinations that are eligible for
-              per-destination  logfiles  with mail that is queued
+              per-destination logfiles with mail that  is  queued
               to those destinations.
 
 <b>VERP CONTROLS</b>
        The <a href="VERP_README.html">VERP_README</a> file describes configuration and operation
-       details  of  Postfix  support for variable envelope return
+       details of Postfix support for  variable  envelope  return
        path addresses.
 
        <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a> (+=)</b>
               The two default VERP delimiter characters.
 
        <b><a href="postconf.5.html#verp_delimiter_filter">verp_delimiter_filter</a> (-=+)</b>
-              The characters Postfix accepts  as  VERP  delimiter
-              characters  on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
+              The  characters  Postfix  accepts as VERP delimiter
+              characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command  line
               and in SMTP commands.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#alias_database">alias_database</a> (see 'postconf -d' output)</b>
-              The alias databases for <a href="local.8.html"><b>local</b>(8)</a> delivery that  are
+              The  alias databases for <a href="local.8.html"><b>local</b>(8)</a> delivery that are
               updated with "<b>newaliases</b>" or with "<b>sendmail -bi</b>".
 
        <b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
-              The  location  of  all  postfix administrative com-
+              The location of  all  postfix  administrative  com-
               mands.
 
        <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_directory">daemon_directory</a> (see 'postconf -d' output)</b>
-              The  directory  with  Postfix  support programs and
+              The directory with  Postfix  support  programs  and
               daemon programs.
 
        <b><a href="postconf.5.html#default_database_type">default_database_type</a> (see 'postconf -d' output)</b>
@@ -405,16 +411,16 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               <a href="postalias.1.html"><b>postalias</b>(1)</a> and <a href="postmap.1.html"><b>postmap</b>(1)</a> commands.
 
        <b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b>
-              The  time  after which the sender receives the mes-
+              The time after which the sender receives  the  mes-
               sage headers of mail that is still queued.
 
        <b><a href="postconf.5.html#enable_errors_to">enable_errors_to</a> (no)</b>
-              Report mail delivery errors to the  address  speci-
-              fied   with  the  non-standard  Errors-To:  message
-              header, instead  of  the  envelope  sender  address
-              (this  feature is removed with Postfix version 2.2,
-              is turned off by default with Postfix version  2.1,
-              and  is  always  turned  on with older Postfix ver-
+              Report  mail  delivery errors to the address speci-
+              fied  with  the  non-standard  Errors-To:   message
+              header,  instead  of  the  envelope  sender address
+              (this feature is removed with Postfix version  2.2,
+              is  turned off by default with Postfix version 2.1,
+              and is always turned on  with  older  Postfix  ver-
               sions).
 
        <b><a href="postconf.5.html#mail_owner">mail_owner</a> (postfix)</b>
@@ -422,21 +428,21 @@ SENDMAIL(1)                                                        SENDMAIL(1)
               and most Postfix daemon processes.
 
        <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#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
-              Don't rewrite message headers from  remote  clients
+              Don't  rewrite  message headers from remote clients
               at all when this parameter is empty; otherwise, re-
-              write message  headers  and  append  the  specified
+              write  message  headers  and  append  the specified
               domain name to incomplete addresses.
 
        <b><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".
 
 <b>FILES</b>
@@ -461,7 +467,7 @@ SENDMAIL(1)                                                        SENDMAIL(1)
        <a href="VERP_README.html">VERP_README</a>, Postfix VERP howto
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index b3a126c7358a91624ab4cfcd1a64e93c4ac5cf60..79a49f6afe0af452c07ed0748d5f23130d13bd11 100644 (file)
@@ -10,6 +10,8 @@ Postfix queue control
 .nf
 \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-f\fR
 .br
+\fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-i \fIqueue_id\fR
+.br
 \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-p\fR
 .br
 \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
@@ -36,6 +38,10 @@ by contacting the Postfix \fBqmgr\fR(8) daemon.
 
 Warning: flushing undeliverable mail frequently will result in
 poor delivery performance of all other mail.
+.IP "\fB-i \fIqueue_id\fR"
+Schedule immediate delivery of mail with the specified queue ID.
+This feature uses the \fBflush\fR(8) server, and is available
+with Postfix 2.4 and later.
 .IP \fB-p\fR
 Produce a traditional sendmail-style queue listing.
 This option implements the traditional \fBmailq\fR command,
index a4e99359df11ca08277177b784ed9a682b3e3cad..43f34a0f38e1310064b43fdb04bed13adb5cc1bf 100644 (file)
@@ -174,6 +174,11 @@ poor delivery performance of all other mail.
 .IP "\fB-q\fIinterval\fR (ignored)"
 The interval between queue runs. Use the \fBqueue_run_delay\fR
 configuration parameter instead.
+.IP \fB-qI\fIqueueid\fR
+Schedule immediate delivery of mail with the specified queue
+ID.  This option is implemented by executing the
+\fBpostqueue\fR(1) command, and is available with Postfix
+version 2.4 and later.
 .IP \fB-qR\fIsite\fR
 Schedule immediate delivery of all mail that is queued for the named
 \fIsite\fR. This option accepts only \fIsite\fR names that are
index 4ae39dea1698e38c48d20ef957049f8d057a5b96..22a49f1bbac5b7e58e60615c8f8312d0bf01e1fe 100644 (file)
@@ -5408,9 +5408,10 @@ restriction that matches wins.
 The following restrictions are specific to client hostname or
 client network address information.
 .IP "\fBcheck_ccert_access \fItype:table\fR\fR"
-When the remote SMTP client certificate is verified successfully,
-use the client certificate fingerprint as lookup key for the specified
-\fBaccess\fR(5) database. This feature is available with Postfix version 2.2.
+Use the client certificate fingerprint as lookup key for the
+specified \fBaccess\fR(5) database; with Postfix version 2.2, also require
+that the SMTP client certificate is verified successfully. This
+feature is available with Postfix version 2.2 and later.
 .IP "\fBcheck_client_access \fItype:table\fR\fR"
 Search the specified access database for the client hostname,
 parent domains, client IP address, or networks obtained by stripping
index c71950cdfc76e2d747f6314a7fc3628c2fc0a7bb..c85d6eb4436c3fab9d5615993f2732c28e63d971 100644 (file)
@@ -36,9 +36,11 @@ This server implements the following requests:
 .IP "\fBadd\fI sitename queueid\fR"
 Inform the \fBflush\fR(8) server that the message with the specified
 queue ID is queued for the specified destination.
-.IP "\fBsend\fI sitename\fR"
+.IP "\fBsend_site\fI sitename\fR"
 Request delivery of mail that is queued for the specified
 destination.
+.IP "\fBsend_file\fI queueid\fR"
+Request delivery of the specified deferred message.
 .IP \fBrefresh\fR
 Refresh non-empty per-destination logfiles that were not read in
 \fB$fast_flush_refresh_time\fR hours, by simulating
index af7659d240a47c0ea9c1304c1e46783eb0ca41f0..c93add454dfc48844a709df82d3013191b500bf8 100644 (file)
@@ -186,6 +186,7 @@ patterns like this: </p>
     /^Received:.* +by +(porcupine\.org)[[:&gt;:]]/
         reject forged mail server name in Received: header: $1
     endif
+    /^Message-ID:.* &lt;!&amp;!/ DUNNO
     /^Message-ID:.*@(porcupine\.org)/
        reject forged domain name in Message-ID: header: $1
 
@@ -198,6 +199,7 @@ patterns like this: </p>
     /^[&gt; ]*Received:.* +by +(porcupine\.org)[[:&gt;:]]/
         reject forged mail server name in Received: header: $1
     endif
+    /^[&gt; ]*Message-ID:.* &lt;!&amp;!/ DUNNO
     /^[&gt; ]*Message-ID:.*@(porcupine\.org)/
        reject forged domain name in Message-ID: header: $1
 </pre>
@@ -226,10 +228,18 @@ see your system documentation. </p>
 matching attempts. DO NOT indent lines starting with /pattern/
 between the "if" and "endif"! </p>
 
+<li> <p> The two "<tt>Message-ID:.* &lt;!&amp;!</tt>" rules are
+workarounds for some versions of Outlook express, as described in
+the <a href="#caveats"> caveats </a> section below.
+
 </ul>
 
 <p><a name="caveats"><strong>Caveats</strong></a></p>
 
+<ul>
+
+<li>
+
 <p> Netscape Messenger (and reportedly, Mozilla) sends a HELO name
 that is identical to the sender address domain part. If you have
 such clients then the above patterns would block legitimate email.
@@ -260,6 +270,35 @@ mail to a user on such a host. </p>
 masquerading, as described in the ADDRESS_REWRITING_README document.
 </p>
 
+<li> <p> Reportedly, Outlook 2003 (perhaps Outlook Express, and
+other versions as well) present substantially different Message-ID
+headers depending upon whether or not a DSN is requested (via Options
+"Request a delivery receipt for this message"). </p>
+
+<p> When a DSN is requested, Outlook 2003 uses a Message-ID string
+that ends in the sender's domain name: </p>
+
+<blockquote>
+<pre>
+Message-ID: &lt;!&amp;! ...very long string... ==@example.com&gt;
+</pre>
+</blockquote>
+
+<p> where <i>example.com</i> is the domain name part of the email
+address specified in Outlook's account settings for the user.  Since
+many users configure their email addresses as <i>username@example.com</i>,
+messages with DSN turned on will trigger the REJECT action in the
+previous section. </p>
+
+<p> If you have such clients then you can to exclude their Message-ID
+strings with the two "<tt>Message-ID:.* &lt;!&amp;!</tt>" patterns
+that are shown in the previous section.  Otherwise you will not be
+able to use the two backscatter rules to stop forged Message ID
+strings.  Of course this workaround may break the next time Outlook
+is changed.  </p>
+
+</ul>
+
 <h3><a name="forged_sender">Blocking backscatter mail with forged
 sender information</a></h3>
 
index 3d395e3f0d1bb0a58e604936c49e9f31cd4ac830..e73e498477a94197dd93c0fed27ca40be97c73d5 100644 (file)
@@ -4577,9 +4577,10 @@ client network address information.
 
 <dt><b><a name="check_ccert_access">check_ccert_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
 
-<dd>When the remote SMTP client certificate is verified successfully,
-use the client certificate fingerprint as lookup key for the specified
-access(5) database. This feature is available with Postfix version 2.2.</dd>
+<dd> Use the client certificate fingerprint as lookup key for the
+specified access(5) database; with Postfix version 2.2, also require
+that the SMTP client certificate is verified successfully. This
+feature is available with Postfix version 2.2 and later.</dd>
 
 <dt><b><a name="check_client_access">check_client_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
 
index b83c38529315c6355764fdacba0eff71b0ffb4dc..8144eabbfd582cef1ebdc42ba25bcd9b5b94f038 100644 (file)
@@ -78,6 +78,7 @@ flush.o: ../../include/match_ops.h
 flush.o: ../../include/match_parent_style.h
 flush.o: ../../include/msg.h
 flush.o: ../../include/myflock.h
+flush.o: ../../include/safe_open.h
 flush.o: ../../include/scan_dir.h
 flush.o: ../../include/stringops.h
 flush.o: ../../include/sys_defs.h
index 4b47e30a75634a81645863784eab2e44f06b5ace..06f19f15b7666e4d85f688f5daf4ba73631b1fc6 100644 (file)
 /* .IP "\fBadd\fI sitename queueid\fR"
 /*     Inform the \fBflush\fR(8) server that the message with the specified
 /*     queue ID is queued for the specified destination.
-/* .IP "\fBsend\fI sitename\fR"
+/* .IP "\fBsend_site\fI sitename\fR"
 /*     Request delivery of mail that is queued for the specified
 /*     destination.
+/* .IP "\fBsend_file\fI queueid\fR"
+/*     Request delivery of the specified deferred message.
 /* .IP \fBrefresh\fR
 /*     Refresh non-empty per-destination logfiles that were not read in
 /*     \fB$fast_flush_refresh_time\fR hours, by simulating
 #include <dict.h>
 #include <scan_dir.h>
 #include <stringops.h>
+#include <safe_open.h>
 
 /* Global library. */
 
@@ -210,7 +213,7 @@ static DOMAIN_LIST *flush_domains;
   * Silly little macros.
   */
 #define STR(x)                 vstring_str(x)
-#define STREQ(x,y)             (strcmp(x,y) == 0)
+#define STREQ(x,y)             ((x) == (y) || strcmp(x,y) == 0)
 
  /*
   * Forward declarations resulting from breaking up routines according to
@@ -223,9 +226,24 @@ static int flush_send_path(const char *, int);
   * Do we only refresh the per-destination logfile, or do we really request
   * mail delivery as if someone sent ETRN? If the latter, we must override
   * information about unavailable hosts or unavailable transports.
+  * 
+  * When selectively flushing deferred mail, we need to override the queue
+  * manager's "dead destination" information and unthrottle transports and
+  * queues. There are two options:
+  * 
+  * - Unthrottle all transports and queues before we move mail to the incoming
+  * queue. This is less accurate, but has the advantage when flushing lots of
+  * mail, because Postfix can skip delivery of flushed messages after it
+  * discovers that a destination is (still) unavailable.
+  * 
+  * - Unthrottle some transports and queues after the queue manager moves mail
+  * to the active queue. This is more accurate, but has the disadvantage when
+  * flushing lots of mail, because Postfix cannot skip delivery of flushed
+  * messages after it discovers that a destination is (still) unavailable.
   */
 #define REFRESH_ONLY           0
-#define REFRESH_AND_DELIVER    1
+#define UNTHROTTLE_BEFORE      (1<<0)
+#define UNTHROTTLE_AFTER       (1<<1)
 
 /* flush_site_to_path - convert domain or [addr] to harmless string */
 
@@ -366,6 +384,86 @@ static int flush_send_service(const char *site, int how)
     return (status);
 }
 
+/* flush_one_file - move one queue file to incoming queue */
+
+static int flush_one_file(const char *queue_id, VSTRING *queue_file,
+                                   struct utimbuf * tbuf, int how)
+{
+    const char *myname = "flush_one_file";
+    const char *queue_name;
+    const char *path;
+
+    /*
+     * Some other instance of this program may flush some logfile and may
+     * just have moved this queue file to the incoming queue.
+     */
+    for (queue_name = MAIL_QUEUE_DEFERRED; /* see below */ ;
+        queue_name = MAIL_QUEUE_INCOMING) {
+       path = mail_queue_path(queue_file, queue_name, queue_id);
+       if (utime(path, tbuf) == 0)
+           break;
+       if (errno != ENOENT)
+           msg_warn("%s: update %s time stamps: %m", myname, path);
+       if (STREQ(queue_name, MAIL_QUEUE_INCOMING))
+           return (0);
+    }
+
+    /*
+     * With the UNTHROTTLE_AFTER strategy, we leave it up to the queue
+     * manager to unthrottle transports and queues as it reads recipients
+     * from a queue file. We request this unthrottle operation by setting the
+     * group read permission bit.
+     * 
+     * Note: we must avoid using chmod(). It is not only slower than fchmod()
+     * but it is also less secure. With chmod(), an attacker could repeatedly
+     * send requests to the flush server and trick it into changing
+     * permissions of non-queue files, by exploiting a race condition.
+     * 
+     * We use safe_open() because we don't validate the file content before
+     * modifying the file status.
+     */
+    if (how & UNTHROTTLE_AFTER) {
+       VSTRING *why;
+       struct stat st;
+       VSTREAM *fp;
+
+       for (why = vstring_alloc(1); /* see below */ ;
+            queue_name = MAIL_QUEUE_INCOMING,
+            path = mail_queue_path(queue_file, queue_name, queue_id)) {
+           if ((fp = safe_open(path, O_RDWR, 0, &st, -1, -1, why)) != 0)
+               break;
+           if (errno != ENOENT)
+               msg_warn("%s: open %s: %s", myname, path, STR(why));
+           if (errno != ENOENT || STREQ(queue_name, MAIL_QUEUE_INCOMING)) {
+               vstring_free(why);
+               return (0);
+           }
+       }
+       vstring_free(why);
+       if ((st.st_mode & MAIL_QUEUE_STAT_READY) != MAIL_QUEUE_STAT_READY) {
+           (void) vstream_fclose(fp);
+           return (0);
+       }
+       if (fchmod(vstream_fileno(fp), st.st_mode | MAIL_QUEUE_STAT_UNTHROTTLE) < 0)
+           msg_warn("%s: fchmod %s: %m", myname, path);
+       (void) vstream_fclose(fp);
+    }
+
+    /*
+     * Move the file to the incoming queue, if it isn't already there.
+     */
+    if (STREQ(queue_name, MAIL_QUEUE_INCOMING) == 0
+       && mail_queue_rename(queue_id, queue_name, MAIL_QUEUE_INCOMING) < 0
+       && errno != ENOENT)
+       msg_warn("%s: rename from %s to %s: %m",
+                path, queue_name, MAIL_QUEUE_INCOMING);
+
+    /*
+     * If we got here, we achieved something, so let's claim succes.
+     */
+    return (1);
+}
+
 /* flush_send_path - flush logfile file */
 
 static int flush_send_path(const char *path, int how)
@@ -375,11 +473,10 @@ static int flush_send_path(const char *path, int how)
     VSTRING *queue_file;
     VSTREAM *log;
     struct utimbuf tbuf;
-    static char qmgr_deliver_trigger[] = {
-       QMGR_REQ_SCAN_INCOMING,         /* scan incoming queue */
+    static char qmgr_flush_trigger[] = {
        QMGR_REQ_FLUSH_DEAD,            /* flush dead site/transport cache */
     };
-    static char qmgr_refresh_trigger[] = {
+    static char qmgr_scan_trigger[] = {
        QMGR_REQ_SCAN_INCOMING,         /* scan incoming queue */
     };
     HTABLE *dup_filter;
@@ -410,6 +507,23 @@ static int flush_send_path(const char *path, int how)
     if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
        msg_fatal("%s: lock fast flush logfile %s: %m", myname, path);
 
+    /*
+     * With the UNTHROTTLE_BEFORE strategy, we ask the queue manager to
+     * unthrottle all transports and queues before we move a deferred queue
+     * file to the incoming queue. This minimizes a race condition where the
+     * queue manager seizes a queue file before it knows that we want to
+     * flush that message.
+     * 
+     * This reduces the race condition time window to a very small amount (the
+     * flush server does not really know when the queue manager reads its
+     * command fifo). But there is a worse race, where the queue manager
+     * moves a deferred queue file to the active queue before we have a
+     * chance to expedite its delivery.
+     */
+    if (how & UNTHROTTLE_BEFORE)
+       mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service,
+                    qmgr_flush_trigger, sizeof(qmgr_flush_trigger));
+
     /*
      * This is the part that dominates running time: schedule the listed
      * queue files for delivery by updating their file time stamps and by
@@ -444,25 +558,7 @@ static int flush_send_path(const char *path, int how)
                         myname, path, STR(queue_id));
            if (dup_filter->used <= FLUSH_DUP_FILTER_SIZE)
                htable_enter(dup_filter, STR(queue_id), 0);
-
-           mail_queue_path(queue_file, MAIL_QUEUE_DEFERRED, STR(queue_id));
-           if (utime(STR(queue_file), &tbuf) < 0) {
-               if (errno != ENOENT)
-                   msg_warn("%s: update %s time stamps: %m",
-                            myname, STR(queue_file));
-               /* XXX Wart... */
-               mail_queue_path(queue_file, MAIL_QUEUE_INCOMING, STR(queue_id));
-               if (utime(STR(queue_file), &tbuf) < 0)
-                   if (errno != ENOENT)
-                       msg_warn("%s: update %s time stamps: %m",
-                                myname, STR(queue_file));
-           } else if (mail_queue_rename(STR(queue_id), MAIL_QUEUE_DEFERRED,
-                                        MAIL_QUEUE_INCOMING) < 0) {
-               if (errno != ENOENT)
-                   msg_warn("%s: rename from %s to %s: %m",
-                            STR(queue_file), MAIL_QUEUE_DEFERRED,
-                            MAIL_QUEUE_INCOMING);
-           }
+           count += flush_one_file(STR(queue_id), queue_file, &tbuf, how);
        } else {
            if (msg_verbose)
                msg_info("%s: logfile %s: skip queue file %s as duplicate",
@@ -489,16 +585,42 @@ static int flush_send_path(const char *path, int how)
     if (count > 0) {
        if (msg_verbose)
            msg_info("%s: requesting delivery for logfile %s", myname, path);
-       if (how == REFRESH_ONLY)
-           mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service,
-                        qmgr_refresh_trigger, sizeof(qmgr_refresh_trigger));
-       else
-           mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service,
-                        qmgr_deliver_trigger, sizeof(qmgr_deliver_trigger));
+       mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service,
+                    qmgr_scan_trigger, sizeof(qmgr_scan_trigger));
     }
     return (FLUSH_STAT_OK);
 }
 
+/* flush_send_file_service - flush one queue file */
+
+static int flush_send_file_service(const char *queue_id)
+{
+    const char *myname = "flush_send_file_service";
+    VSTRING *queue_file;
+    struct utimbuf tbuf;
+    static char qmgr_scan_trigger[] = {
+       QMGR_REQ_SCAN_INCOMING,         /* scan incoming queue */
+    };
+
+    /*
+     * Sanity check.
+     */
+    if (!mail_queue_id_ok(queue_id))
+       return (FLUSH_STAT_BAD);
+
+    if (msg_verbose)
+       msg_info("%s: requesting delivery for queue_id %s", myname, queue_id);
+
+    queue_file = vstring_alloc(30);
+    tbuf.actime = tbuf.modtime = event_time();
+    if (flush_one_file(queue_id, queue_file, &tbuf, UNTHROTTLE_AFTER) > 0)
+       mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service,
+                    qmgr_scan_trigger, sizeof(qmgr_scan_trigger));
+    vstring_free(queue_file);
+
+    return (FLUSH_STAT_OK);
+}
+
 /* flush_refresh_service - refresh logfiles beyond some age */
 
 static int flush_refresh_service(int max_age)
@@ -633,13 +755,22 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
            attr_print(client_stream, ATTR_FLAG_NONE,
                       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
                       ATTR_TYPE_END);
-       } else if (STREQ(STR(request), FLUSH_REQ_SEND)) {
+       } else if (STREQ(STR(request), FLUSH_REQ_SEND_SITE)) {
            site = vstring_alloc(10);
            if (attr_scan(client_stream, ATTR_FLAG_STRICT,
                          ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
                          ATTR_TYPE_END) == 1)
                status = flush_send_service(lowercase(STR(site)),
-                                           REFRESH_AND_DELIVER);
+                                           UNTHROTTLE_BEFORE);
+           attr_print(client_stream, ATTR_FLAG_NONE,
+                      ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
+                      ATTR_TYPE_END);
+       } else if (STREQ(STR(request), FLUSH_REQ_SEND_FILE)) {
+           queue_id = vstring_alloc(10);
+           if (attr_scan(client_stream, ATTR_FLAG_STRICT,
+                         ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
+                         ATTR_TYPE_END) == 1)
+               status = flush_send_file_service(STR(queue_id));
            attr_print(client_stream, ATTR_FLAG_NONE,
                       ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
                       ATTR_TYPE_END);
index 7f7e65d36f3632ae5b2bf5a4d99d4eca49b28fd1..043754f9b5667d4fcc9e1aee9140020931bda418 100644 (file)
 /*     const char *site;
 /*     const char *queue_id;
 /*
-/*     int     flush_send(site)
+/*     int     flush_send_site(site)
 /*     const char *site;
 /*
+/*     int     flush_send_file(queue_id)
+/*     const char *queue_id;
+/*
 /*     int     flush_refresh()
 /*
 /*     int     flush_purge()
 /*     flush_add() informs the "fast flush" cache manager that mail is
 /*     queued for the specified site with the specified queue ID.
 /*
-/*     flush_send() requests delivery of all mail that is queued for
+/*     flush_send_site() requests delivery of all mail that is queued for
 /*     the specified destination.
 /*
+/*     flush_send_file() requests delivery of mail with the specified
+/*     queue ID.
+/*
 /*     flush_refresh() requests the "fast flush" cache manager to refresh
 /*     cached information that was not used for some configurable amount
 /*     time.
@@ -153,11 +159,11 @@ int     flush_refresh(void)
     return (status);
 }
 
-/* flush_send - deliver mail queued for site */
+/* flush_send_site - deliver mail queued for site */
 
-int     flush_send(const char *site)
+int     flush_send_site(const char *site)
 {
-    const char *myname = "flush_send";
+    const char *myname = "flush_send_site";
     int     status;
 
     if (msg_verbose)
@@ -173,7 +179,7 @@ int     flush_send(const char *site)
        status = FLUSH_STAT_DENY;
     else
        status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
-                              ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND,
+                         ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND_SITE,
                                     ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
                                     ATTR_TYPE_END);
 
@@ -183,6 +189,30 @@ int     flush_send(const char *site)
     return (status);
 }
 
+/* flush_send_file - deliver specific message */
+
+int     flush_send_file(const char *queue_id)
+{
+    const char *myname = "flush_send_file";
+    int     status;
+
+    if (msg_verbose)
+       msg_info("%s: queue_id %s", myname, queue_id);
+
+    /*
+     * Require that the service is turned on.
+     */
+    status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
+                         ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND_FILE,
+                                ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
+                                ATTR_TYPE_END);
+
+    if (msg_verbose)
+       msg_info("%s: queue_id %s status %d", myname, queue_id, status);
+
+    return (status);
+}
+
 /* flush_add - inform "fast flush" cache manager */
 
 int     flush_add(const char *site, const char *queue_id)
index 2846fb377aaa80893f95fdbd0462d56a2420ff1c..6b891b21639dc50e698deffce93019e0a442eb91 100644 (file)
@@ -16,7 +16,8 @@
   */
 extern void flush_init(void);
 extern int flush_add(const char *, const char *);
-extern int flush_send(const char *);
+extern int flush_send_site(const char *);
+extern int flush_send_file(const char *);
 extern int flush_refresh(void);
 extern int flush_purge(void);
 
@@ -24,7 +25,8 @@ extern int flush_purge(void);
   * Mail flush server requests.
   */
 #define FLUSH_REQ_ADD          "add"   /* append queue ID to site log */
-#define FLUSH_REQ_SEND         "send"  /* flush mail queued for site */
+#define FLUSH_REQ_SEND_SITE    "send_site"     /* flush mail for site */
+#define FLUSH_REQ_SEND_FILE    "send_file"     /* flush one queue file */
 #define FLUSH_REQ_REFRESH      "rfrsh" /* refresh old logfiles */
 #define FLUSH_REQ_PURGE                "purge" /* refresh all logfiles */
 
index 8c4e3b89897b8332a1604d83797c866e37fb4d8f..f1c2389d90b10071e3c8708081892f5c7af56491 100644 (file)
 
  /*
   * Queue file modes.
+  * 
+  * 4.4BSD-like systems don't allow (sticky AND executable) together, so we use
+  * group read permission bits instead. These are more portable, but they
+  * also are more likely to be turned on by accident. It would not be the end
+  * of the world.
   */
 #define MAIL_QUEUE_STAT_READY  (S_IRUSR | S_IWUSR | S_IXUSR)
 #define MAIL_QUEUE_STAT_CORRUPT        (S_IRUSR)
+#ifndef MAIL_QUEUE_STAT_UNTHROTTLE
+#define MAIL_QUEUE_STAT_UNTHROTTLE (S_IRGRP)
+#endif
 
 extern struct VSTREAM *mail_queue_enter(const char *, mode_t, struct timeval *);
 extern struct VSTREAM *mail_queue_open(const char *, const char *, int, mode_t);
index ff1b9d834f581a4d17225994d7aab47ffd50c229..98879f1e0731b5d1e3f5f9d7ff97206fa7a6c19c 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      "20061210"
+#define MAIL_RELEASE_DATE      "20061217"
 #define MAIL_VERSION_NUMBER    "2.4"
 
 #ifdef SNAPSHOT
index d666d33817c1d07fff46970678d6df7f244890f5..927f1be2f6fa77f2f8c07380b5602a2cd2137ed0 100644 (file)
@@ -367,6 +367,8 @@ static void qmgr_trigger_event(char *buf, int len,
      * request in order. And as long as we don't have conflicting requests we
      * are free to sort them into the most suitable order.
      */
+#define QMGR_FLUSH_BEFORE      (QMGR_FLUSH_ONCE | QMGR_FLUSH_DFXP)
+
     for (i = 0; i < len; i++) {
        if (msg_verbose)
            msg_info("request: %d (%c)",
@@ -380,8 +382,8 @@ static void qmgr_trigger_event(char *buf, int len,
            deferred_flag |= QMGR_SCAN_START;
            break;
        case QMGR_REQ_FLUSH_DEAD:
-           deferred_flag |= QMGR_FLUSH_DEAD;
-           incoming_flag |= QMGR_FLUSH_DEAD;
+           deferred_flag |= QMGR_FLUSH_BEFORE;
+           incoming_flag |= QMGR_FLUSH_BEFORE;
            break;
        case QMGR_REQ_SCAN_ALL:
            deferred_flag |= QMGR_SCAN_ALL;
index 19f54b33ccb2b07737a5429fb11b0189069062a2..c28430c00efd59adc83abc9c157caaf40ad6d49f 100644 (file)
@@ -256,7 +256,7 @@ extern int qmgr_recipient_count;
 extern void qmgr_message_free(QMGR_MESSAGE *);
 extern void qmgr_message_update_warn(QMGR_MESSAGE *);
 extern void qmgr_message_kill_record(QMGR_MESSAGE *, long);
-extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int);
+extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int, mode_t);
 extern QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *);
 
 #define QMGR_MSG_STATS(stats, message) \
@@ -317,7 +317,9 @@ struct QMGR_SCAN {
   */
 #define QMGR_SCAN_START        (1<<0)          /* start now/restart when done */
 #define QMGR_SCAN_ALL  (1<<1)          /* all queue file time stamps */
-#define QMGR_FLUSH_DEAD        (1<<2)          /* all sites, all transports */
+#define QMGR_FLUSH_ONCE        (1<<2)          /* unthrottle once */
+#define QMGR_FLUSH_DFXP        (1<<3)          /* override defer_transports */
+#define QMGR_FLUSH_EACH        (1<<4)          /* unthrottle per message */
 
  /*
   * qmgr_scan.c
index 46a9cfdcd7f8ed2176e5a4088e2c038a61884fa5..59bae9af82e1af3882743ff3f3c866cec5714825 100644 (file)
@@ -226,8 +226,15 @@ int     qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id)
      * being delivered. In that case (the file is locked), defer delivery by
      * a minimal amount of time.
      */
+#define QMGR_FLUSH_AFTER       (QMGR_FLUSH_EACH | QMGR_FLUSH_DFXP)
+
     if ((message = qmgr_message_alloc(MAIL_QUEUE_ACTIVE, queue_id,
-                                     scan_info->flags)) == 0) {
+                                (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
+                                     scan_info->flags | QMGR_FLUSH_AFTER :
+                                     scan_info->flags,
+                                (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
+                                 st.st_mode & ~MAIL_QUEUE_STAT_UNTHROTTLE :
+                                     0)) == 0) {
        qmgr_active_corrupt(queue_id);
        return (0);
     } else if (message == QMGR_MESSAGE_LOCKED) {
index cf1bb6f7ecc10fd3c17efa741818a69741b7dd59..8e56e56e406fab7c77dd1eca6aee28d28a2e6a05 100644 (file)
@@ -9,10 +9,11 @@
 /*     int     qmgr_message_count;
 /*     int     qmgr_recipient_count;
 /*
-/*     QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags)
+/*     QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags, mode)
 /*     const char *class;
 /*     const char *name;
 /*     int     qflags;
+/*     mode_t  mode;
 /*
 /*     QMGR_MESSAGE *qmgr_message_realloc(message)
 /*     QMGR_MESSAGE *message;
@@ -49,6 +50,7 @@
 /*     run through the resolver, and are assigned to destination
 /*     queues. Recipients that cannot be assigned are deferred or
 /*     bounced. Mail that has bounced twice is silently absorbed.
+/*     A non-zero mode means change the queue file permissions.
 /*
 /*     qmgr_message_realloc() resumes reading recipients from the queue
 /*     file, and updates the recipient list and \fIrcpt_offset\fR message
@@ -929,9 +931,9 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
     for (recipient = list.info; recipient < list.info + list.len; recipient++) {
 
        /*
-        * Redirect overrides all else. But only once (per entire
-        * message). For consistency with the remainder of Postfix,
-        * rewrite the address to canonical form before resolving it.
+        * Redirect overrides all else. But only once (per entire message).
+        * For consistency with the remainder of Postfix, rewrite the address
+        * to canonical form before resolving it.
         */
        if (message->redirect_addr) {
            if (recipient > list.info) {
@@ -1040,7 +1042,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
         * Optionally defer deliveries over specific transports, unless the
         * restriction is lifted temporarily.
         */
-       if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DEAD) == 0) {
+       if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DFXP) == 0) {
            if (defer_xport_argv == 0)
                defer_xport_argv = argv_split(var_defer_xports, " \t\r\n,");
            for (cpp = defer_xport_argv->argv; *cpp; cpp++)
@@ -1061,6 +1063,14 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
            queue = 0;
        }
 
+       /*
+        * This message is being flushed. If need-be unthrottle the
+        * transport.
+        */
+       if ((message->qflags & QMGR_FLUSH_EACH) != 0
+           && QMGR_TRANSPORT_THROTTLED(transport))
+           qmgr_transport_unthrottle(transport);
+
        /*
         * This transport is dead. Defer delivery to this recipient.
         */
@@ -1137,6 +1147,13 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
                                          STR(reply.nexthop));
        }
 
+       /*
+        * This message is being flushed. If need-be unthrottle the queue.
+        */
+       if ((message->qflags & QMGR_FLUSH_EACH) != 0
+           && QMGR_QUEUE_THROTTLED(queue))
+           qmgr_queue_unthrottle(queue);
+
        /*
         * This queue is dead. Defer delivery to this recipient.
         */
@@ -1242,7 +1259,7 @@ void    qmgr_message_free(QMGR_MESSAGE *message)
 /* qmgr_message_alloc - create in-core message structure */
 
 QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
-                                        int qflags)
+                                        int qflags, mode_t mode)
 {
     const char *myname = "qmgr_message_alloc";
     QMGR_MESSAGE *message;
@@ -1277,6 +1294,13 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
        return (0);
     } else {
 
+       /*
+        * We have validated the queue file content, so it is safe to modify
+        * the file properties now.
+        */
+       if (mode != 0 && fchmod(vstream_fileno(message->fp), mode) < 0)
+           msg_fatal("fchmod %s: %m", VSTREAM_PATH(message->fp));
+
        /*
         * Reset the defer log. This code should not be here, but we must
         * reset the defer log *after* acquiring the exclusive lock on the
index 37a3ce8ded3edc7abfebe4d62bdecc56c0ddc879..0665a23ce8bfa5b1e8b29301b59f6bd39a4b948d 100644 (file)
 /*     qmgr_scan_request() records a request for the next queue scan. The
 /*     flags argument is the bit-wise OR of zero or more of the following,
 /*     unrecognized flags being ignored:
-/* .IP QMGR_FLUSH_DEAD
-/*     Forget state information about dead hosts or transports. This
-/*     request takes effect upon the next queue scan.
+/* .IP QMGR_FLUSH_ONCE
+/*     Forget state information about dead hosts or transports.
+/*     This request takes effect immediately.
+/* .IP QMGR_FLUSH_DFXP
+/*     Override the defer_transports setting. This takes effect
+/*     immediately when a queue scan is in progress, and affects
+/*     the next queue scan.
 /* .IP QMGR_SCAN_ALL
-/*     Ignore queue file time stamps.
-/*     This flag is passed on to the qmgr_active_feed() routine.
+/*     Ignore queue file time stamps. This takes effect immediately
+/*     when a queue scan is in progress, and affects the next queue
+/*     scan.
 /* .IP QMGR_SCAN_START
 /*     Start a queue scan when none is in progress, or restart the
 /*     current scan upon completion.
@@ -94,12 +99,6 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
                 scan_info->nflags & QMGR_SCAN_START ? "re" : "",
                 scan_info->queue);
 
-    /*
-     * Optionally forget all dead host information.
-     */
-    if (scan_info->nflags & QMGR_FLUSH_DEAD)
-       qmgr_enable_all();
-
     /*
      * Start or restart the scan.
      */
@@ -113,6 +112,33 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
 void    qmgr_scan_request(QMGR_SCAN *scan_info, int flags)
 {
 
+    /*
+     * Apply "forget all dead destinations" requests immediately. Throttle
+     * dead transports and queues at the earliest opportunity: preferably
+     * during an already ongoing queue scan, otherwise the throttling will
+     * have to wait until a "start scan" trigger arrives.
+     * 
+     * The QMGR_FLUSH_ONCE request always comes with QMGR_FLUSH_DFXP, and
+     * sometimes it also comes with QMGR_SCAN_ALL. It becomes a completely
+     * different story when a flush request is encoded in file permissions.
+     */
+    if (flags & QMGR_FLUSH_ONCE)
+       qmgr_enable_all();
+
+    /*
+     * Apply "ignore time stamp" requests also towards the scan that is
+     * already in progress.
+     */
+    if (scan_info->handle != 0 && (flags & QMGR_SCAN_ALL))
+       scan_info->flags |= QMGR_SCAN_ALL;
+
+    /*
+     * Apply "override defer_transports" requests also towards the scan that
+     * is already in progress.
+     */
+    if (scan_info->handle != 0 && (flags & QMGR_FLUSH_DFXP))
+       scan_info->flags |= QMGR_FLUSH_DFXP;
+
     /*
      * If a scan is in progress, just record the request.
      */
index 96086140697bc2f871debcdec0a9e991d678d260..376644fe9efc80d2fd1792f6b1cf6eb6af4da036 100644 (file)
@@ -381,17 +381,12 @@ static const char *check_myhostname(void)
     /*
      * If the local machine name is not in FQDN form, try to append the
      * contents of $mydomain.
-     * 
-     * XXX Do not complain when running as "postconf -d".
      */
     name = get_hostname();
-    if ((cmd_mode & SHOW_DEFS) == 0 && (dot = strchr(name, '.')) == 0) {
-       if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0) {
-           msg_warn("My hostname %s is not a fully qualified name - set %s or %s in %s/main.cf",
-                    name, VAR_MYHOSTNAME, VAR_MYDOMAIN, var_config_dir);
-       } else {
-           name = concatenate(name, ".", domain, (char *) 0);
-       }
+    if ((dot = strchr(name, '.')) == 0) {
+       if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0)
+           domain = DEF_MYDOMAIN;
+       name = concatenate(name, ".", domain, (char *) 0);
     }
     return (name);
 }
@@ -420,7 +415,7 @@ static const char *check_mydomainname(void)
     if (var_myhostname == 0)
        get_myhostname();
     if ((dot = strchr(var_myhostname, '.')) == 0 || strchr(dot + 1, '.') == 0)
-       return (var_myhostname);
+       return (DEF_MYDOMAIN);
     return (dot + 1);
 }
 
index 51894330c2d08f347d1431730235c76c6fc0ab51..7a0a39ca9f4c66508b2eabe7a41ced7a9b130690 100644 (file)
@@ -68,6 +68,7 @@ postqueue.o: ../../include/mail_dict.h
 postqueue.o: ../../include/mail_flush.h
 postqueue.o: ../../include/mail_params.h
 postqueue.o: ../../include/mail_proto.h
+postqueue.o: ../../include/mail_queue.h
 postqueue.o: ../../include/mail_run.h
 postqueue.o: ../../include/mail_task.h
 postqueue.o: ../../include/msg.h
index 9bfd2a2657715f17d340c159a0f749075ecba3d5..c8fa2d8709947cf0d411ad800c760bc3eeb721f9 100644 (file)
@@ -6,6 +6,8 @@
 /* SYNOPSIS
 /*     \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-f\fR
 /* .br
+/*     \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-i \fIqueue_id\fR
+/* .br
 /*     \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-p\fR
 /* .br
 /*     \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
 /*
 /*     Warning: flushing undeliverable mail frequently will result in
 /*     poor delivery performance of all other mail.
+/* .IP "\fB-i \fIqueue_id\fR"
+/*     Schedule immediate delivery of mail with the specified queue ID.
+/*     This feature uses the \fBflush\fR(8) server, and is available
+/*     with Postfix 2.4 and later.
 /* .IP \fB-p\fR
 /*     Produce a traditional sendmail-style queue listing.
 /*     This option implements the traditional \fBmailq\fR command,
 #include <mail_task.h>
 #include <mail_run.h>
 #include <mail_flush.h>
+#include <mail_queue.h>
 #include <flush_clnt.h>
 #include <smtp_stream.h>
 #include <user_acl.h>
 #define PQ_MODE_MAILQ_LIST     1       /* list mail queue */
 #define PQ_MODE_FLUSH_QUEUE    2       /* flush queue */
 #define PQ_MODE_FLUSH_SITE     3       /* flush site */
+#define PQ_MODE_FLUSH_FILE     4       /* flush message */
 
  /*
   * Silly little macros (SLMs).
@@ -345,7 +353,7 @@ static void flush_site(const char *site)
 
     flush_init();
 
-    switch (status = flush_send(site)) {
+    switch (status = flush_send_site(site)) {
     case FLUSH_STAT_OK:
        exit(0);
     case FLUSH_STAT_BAD:
@@ -363,11 +371,46 @@ static void flush_site(const char *site)
     }
 }
 
+/* flush_file - flush mail with specific queue ID */
+
+static void flush_file(const char *queue_id)
+{
+    int     status;
+    const char *errstr;
+    uid_t   uid = getuid();
+
+    if (uid != 0 && uid != var_owner_uid
+       && (errstr = check_user_acl_byuid(var_flush_acl, uid)) != 0)
+       msg_fatal_status(EX_NOPERM,
+                     "User %s(%ld) is not allowed to flush the mail queue",
+                        errstr, (long) uid);
+
+    switch (status = flush_send_file(queue_id)) {
+    case FLUSH_STAT_OK:
+       exit(0);
+    case FLUSH_STAT_BAD:
+       msg_fatal_status(EX_USAGE, "Invalid request: \"%s\"", queue_id);
+    case FLUSH_STAT_FAIL:
+       msg_fatal_status(EX_UNAVAILABLE,
+                        "Cannot flush mail queue - mail system is down");
+    default:
+       msg_fatal_status(EX_SOFTWARE,
+                        "Unexpected flush server reply status %d", status);
+    }
+}
+
+/* unavailable - sanitize exit status from library run-time errors */
+
+static void unavailable(void)
+{
+    exit(EX_UNAVAILABLE);
+}
+
 /* usage - scream and die */
 
 static NORETURN usage(void)
 {
-    msg_fatal_status(EX_USAGE, "usage: postqueue -f | postqueue -p | postqueue -s site");
+    msg_fatal_status(EX_USAGE, "usage: postqueue -f | postqueue -i queueid | postqueue -p | postqueue -s site");
 }
 
 /* main - the main program */
@@ -380,6 +423,7 @@ int     main(int argc, char **argv)
     int     fd;
     int     mode = PQ_MODE_DEFAULT;
     char   *site_to_flush = 0;
+    char   *id_to_flush = 0;
     ARGV   *import_env;
     int     bad_site;
 
@@ -406,6 +450,7 @@ int     main(int argc, char **argv)
     if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
        argv[0] = slash + 1;
     msg_vstream_init(argv[0], VSTREAM_ERR);
+    msg_cleanup(unavailable);
     msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY);
     set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
 
@@ -415,7 +460,7 @@ int     main(int argc, char **argv)
      * mail configuration read routine. Don't do complex things until we have
      * completed initializations.
      */
-    while ((c = GETOPT(argc, argv, "c:fps:v")) > 0) {
+    while ((c = GETOPT(argc, argv, "c:fi:ps:v")) > 0) {
        switch (c) {
        case 'c':                               /* non-default configuration */
            if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
@@ -426,6 +471,12 @@ int     main(int argc, char **argv)
                usage();
            mode = PQ_MODE_FLUSH_QUEUE;
            break;
+       case 'i':                               /* flush queue file */
+           if (mode != PQ_MODE_DEFAULT)
+               usage();
+           mode = PQ_MODE_FLUSH_FILE;
+           id_to_flush = optarg;
+           break;
        case 'p':                               /* traditional mailq */
            if (mode != PQ_MODE_DEFAULT)
                usage();
@@ -489,6 +540,12 @@ int     main(int argc, char **argv)
              "Cannot flush mail queue - invalid destination: \"%.100s%s\"",
                   site_to_flush, strlen(site_to_flush) > 100 ? "..." : "");
     }
+    if (id_to_flush != 0) {
+       if (!mail_queue_id_ok(id_to_flush))
+           msg_fatal_status(EX_USAGE,
+                      "Cannot flush queue ID - invalid name: \"%.100s%s\"",
+                      id_to_flush, strlen(id_to_flush) > 100 ? "..." : "");
+    }
 
     /*
      * Start processing.
@@ -505,6 +562,10 @@ int     main(int argc, char **argv)
        flush_site(site_to_flush);
        exit(0);
        break;
+    case PQ_MODE_FLUSH_FILE:
+       flush_file(id_to_flush);
+       exit(0);
+       break;
     case PQ_MODE_FLUSH_QUEUE:
        flush_queue();
        exit(0);
index 7a386f6a2d648accb26685ff5f35310297253050..4641f4cb8c6a11dbbd47e14f8e7d9061911de500 100644 (file)
@@ -427,6 +427,8 @@ static void qmgr_trigger_event(char *buf, int len,
      * request in order. And as long as we don't have conflicting requests we
      * are free to sort them into the most suitable order.
      */
+#define QMGR_FLUSH_BEFORE      (QMGR_FLUSH_ONCE | QMGR_FLUSH_DFXP)
+
     for (i = 0; i < len; i++) {
        if (msg_verbose)
            msg_info("request: %d (%c)",
@@ -440,8 +442,8 @@ static void qmgr_trigger_event(char *buf, int len,
            deferred_flag |= QMGR_SCAN_START;
            break;
        case QMGR_REQ_FLUSH_DEAD:
-           deferred_flag |= QMGR_FLUSH_DEAD;
-           incoming_flag |= QMGR_FLUSH_DEAD;
+           deferred_flag |= QMGR_FLUSH_BEFORE;
+           incoming_flag |= QMGR_FLUSH_BEFORE;
            break;
        case QMGR_REQ_SCAN_ALL:
            deferred_flag |= QMGR_SCAN_ALL;
index 03e1fa5ccf374542044728c25b367716aa320a54..d791a9ef059569644665e903d2fb980cc9e02ad9 100644 (file)
@@ -304,7 +304,7 @@ extern int qmgr_recipient_count;
 extern void qmgr_message_free(QMGR_MESSAGE *);
 extern void qmgr_message_update_warn(QMGR_MESSAGE *);
 extern void qmgr_message_kill_record(QMGR_MESSAGE *, long);
-extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int);
+extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int, mode_t);
 extern QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *);
 
 #define QMGR_MSG_STATS(stats, message) \
@@ -423,7 +423,9 @@ struct QMGR_SCAN {
   */
 #define QMGR_SCAN_START        (1<<0)          /* start now/restart when done */
 #define QMGR_SCAN_ALL  (1<<1)          /* all queue file time stamps */
-#define QMGR_FLUSH_DEAD        (1<<2)          /* all sites, all transports */
+#define QMGR_FLUSH_ONCE        (1<<2)          /* unthrottle once */
+#define QMGR_FLUSH_DFXP        (1<<3)          /* override defer_transports */
+#define QMGR_FLUSH_EACH        (1<<4)          /* unthrottle per message */
 
  /*
   * qmgr_scan.c
index 46a9cfdcd7f8ed2176e5a4088e2c038a61884fa5..59bae9af82e1af3882743ff3f3c866cec5714825 100644 (file)
@@ -226,8 +226,15 @@ int     qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id)
      * being delivered. In that case (the file is locked), defer delivery by
      * a minimal amount of time.
      */
+#define QMGR_FLUSH_AFTER       (QMGR_FLUSH_EACH | QMGR_FLUSH_DFXP)
+
     if ((message = qmgr_message_alloc(MAIL_QUEUE_ACTIVE, queue_id,
-                                     scan_info->flags)) == 0) {
+                                (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
+                                     scan_info->flags | QMGR_FLUSH_AFTER :
+                                     scan_info->flags,
+                                (st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
+                                 st.st_mode & ~MAIL_QUEUE_STAT_UNTHROTTLE :
+                                     0)) == 0) {
        qmgr_active_corrupt(queue_id);
        return (0);
     } else if (message == QMGR_MESSAGE_LOCKED) {
index b2567460dd29563d945d343b5ad3ce677571fcb9..ae0dd174d740d2347149934e9cb0e27bf7f9390c 100644 (file)
@@ -9,10 +9,11 @@
 /*     int     qmgr_message_count;
 /*     int     qmgr_recipient_count;
 /*
-/*     QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags)
+/*     QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags, mode)
 /*     const char *class;
 /*     const char *name;
 /*     int     qflags;
+/*     mode_t  mode;
 /*
 /*     QMGR_MESSAGE *qmgr_message_realloc(message)
 /*     QMGR_MESSAGE *message;
@@ -49,6 +50,7 @@
 /*     run through the resolver, and are assigned to destination
 /*     queues. Recipients that cannot be assigned are deferred or
 /*     bounced. Mail that has bounced twice is silently absorbed.
+/*     A non-zero mode means change the queue file permissions.
 /*
 /*     qmgr_message_realloc() resumes reading recipients from the queue
 /*     file, and updates the recipient list and \fIrcpt_offset\fR message
@@ -749,10 +751,11 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                     message->queue_id, orig_rcpt);
        myfree(orig_rcpt);
     }
-    
+
     /*
      * Remember when we have read the last recipient batch. Note that we do
-     * it here after reading as reading might have used considerable amount of time.
+     * it here after reading as reading might have used considerable amount
+     * of time.
      */
     message->refill_time = sane_time();
 
@@ -985,16 +988,15 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
     for (recipient = list.info; recipient < list.info + list.len; recipient++) {
 
        /*
-        * Redirect overrides all else. But only once (per entire
-        * message). For consistency with the remainder of Postfix,
-        * rewrite the address to canonical form before resolving it.
+        * Redirect overrides all else. But only once (per entire message).
+        * For consistency with the remainder of Postfix, rewrite the address
+        * to canonical form before resolving it.
         */
        if (message->redirect_addr) {
            if (recipient > list.info) {
                recipient->u.queue = 0;
                continue;
            }
-
            message->rcpt_offset = 0;
            message->rcpt_unread = 0;
 
@@ -1099,7 +1101,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
         * Optionally defer deliveries over specific transports, unless the
         * restriction is lifted temporarily.
         */
-       if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DEAD) == 0) {
+       if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DFXP) == 0) {
            if (defer_xport_argv == 0)
                defer_xport_argv = argv_split(var_defer_xports, " \t\r\n,");
            for (cpp = defer_xport_argv->argv; *cpp; cpp++)
@@ -1120,6 +1122,14 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
            queue = 0;
        }
 
+       /*
+        * This message is being flushed. If need-be unthrottle the
+        * transport.
+        */
+       if ((message->qflags & QMGR_FLUSH_EACH) != 0
+           && QMGR_TRANSPORT_THROTTLED(transport))
+           qmgr_transport_unthrottle(transport);
+
        /*
         * This transport is dead. Defer delivery to this recipient.
         */
@@ -1196,6 +1206,13 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
                                          STR(reply.nexthop));
        }
 
+       /*
+        * This message is being flushed. If need-be unthrottle the queue.
+        */
+       if ((message->qflags & QMGR_FLUSH_EACH) != 0
+           && QMGR_QUEUE_THROTTLED(queue))
+           qmgr_queue_unthrottle(queue);
+
        /*
         * This queue is dead. Defer delivery to this recipient.
         */
@@ -1244,7 +1261,7 @@ static void qmgr_message_assign(QMGR_MESSAGE *message)
         */
        if ((queue = recipient->u.queue) == 0)
            continue;
-           
+
        /*
         * Lookup or instantiate the message job if necessary.
         */
@@ -1258,10 +1275,10 @@ static void qmgr_message_assign(QMGR_MESSAGE *message)
         */
        if (peer == 0 || queue != peer->queue)
            peer = qmgr_peer_obtain(job, queue);
-       
+
        /*
-        * Lookup old or instantiate new recipient entry. We try to reuse
-        * the last existing entry whenever the recipient limit permits.
+        * Lookup old or instantiate new recipient entry. We try to reuse the
+        * last existing entry whenever the recipient limit permits.
         */
        entry = peer->entry_list.prev;
        if (message->single_rcpt || entry == 0
@@ -1363,7 +1380,7 @@ void    qmgr_message_free(QMGR_MESSAGE *message)
 /* qmgr_message_alloc - create in-core message structure */
 
 QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
-                                        int qflags)
+                                        int qflags, mode_t mode)
 {
     const char *myname = "qmgr_message_alloc";
     QMGR_MESSAGE *message;
@@ -1398,6 +1415,13 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
        return (0);
     } else {
 
+       /*
+        * We have validated the queue file content, so it is safe to modify
+        * the file properties now.
+        */
+       if (mode != 0 && fchmod(vstream_fileno(message->fp), mode) < 0)
+           msg_fatal("fchmod %s: %m", VSTREAM_PATH(message->fp));
+
        /*
         * Reset the defer log. This code should not be here, but we must
         * reset the defer log *after* acquiring the exclusive lock on the
index 37a3ce8ded3edc7abfebe4d62bdecc56c0ddc879..0665a23ce8bfa5b1e8b29301b59f6bd39a4b948d 100644 (file)
 /*     qmgr_scan_request() records a request for the next queue scan. The
 /*     flags argument is the bit-wise OR of zero or more of the following,
 /*     unrecognized flags being ignored:
-/* .IP QMGR_FLUSH_DEAD
-/*     Forget state information about dead hosts or transports. This
-/*     request takes effect upon the next queue scan.
+/* .IP QMGR_FLUSH_ONCE
+/*     Forget state information about dead hosts or transports.
+/*     This request takes effect immediately.
+/* .IP QMGR_FLUSH_DFXP
+/*     Override the defer_transports setting. This takes effect
+/*     immediately when a queue scan is in progress, and affects
+/*     the next queue scan.
 /* .IP QMGR_SCAN_ALL
-/*     Ignore queue file time stamps.
-/*     This flag is passed on to the qmgr_active_feed() routine.
+/*     Ignore queue file time stamps. This takes effect immediately
+/*     when a queue scan is in progress, and affects the next queue
+/*     scan.
 /* .IP QMGR_SCAN_START
 /*     Start a queue scan when none is in progress, or restart the
 /*     current scan upon completion.
@@ -94,12 +99,6 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
                 scan_info->nflags & QMGR_SCAN_START ? "re" : "",
                 scan_info->queue);
 
-    /*
-     * Optionally forget all dead host information.
-     */
-    if (scan_info->nflags & QMGR_FLUSH_DEAD)
-       qmgr_enable_all();
-
     /*
      * Start or restart the scan.
      */
@@ -113,6 +112,33 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
 void    qmgr_scan_request(QMGR_SCAN *scan_info, int flags)
 {
 
+    /*
+     * Apply "forget all dead destinations" requests immediately. Throttle
+     * dead transports and queues at the earliest opportunity: preferably
+     * during an already ongoing queue scan, otherwise the throttling will
+     * have to wait until a "start scan" trigger arrives.
+     * 
+     * The QMGR_FLUSH_ONCE request always comes with QMGR_FLUSH_DFXP, and
+     * sometimes it also comes with QMGR_SCAN_ALL. It becomes a completely
+     * different story when a flush request is encoded in file permissions.
+     */
+    if (flags & QMGR_FLUSH_ONCE)
+       qmgr_enable_all();
+
+    /*
+     * Apply "ignore time stamp" requests also towards the scan that is
+     * already in progress.
+     */
+    if (scan_info->handle != 0 && (flags & QMGR_SCAN_ALL))
+       scan_info->flags |= QMGR_SCAN_ALL;
+
+    /*
+     * Apply "override defer_transports" requests also towards the scan that
+     * is already in progress.
+     */
+    if (scan_info->handle != 0 && (flags & QMGR_FLUSH_DFXP))
+       scan_info->flags |= QMGR_FLUSH_DFXP;
+
     /*
      * If a scan is in progress, just record the request.
      */
index da88542b10a16162db8a1b720d2b91c67f3096ba..6e2d284e7eb16c20869f6ce0918665f61d07c8bf 100644 (file)
 /* .IP "\fB-q\fIinterval\fR (ignored)"
 /*     The interval between queue runs. Use the \fBqueue_run_delay\fR
 /*     configuration parameter instead.
+/* .IP \fB-qI\fIqueueid\fR
+/*     Schedule immediate delivery of mail with the specified queue
+/*     ID.  This option is implemented by executing the
+/*     \fBpostqueue\fR(1) command, and is available with Postfix
+/*     version 2.4 and later.
 /* .IP \fB-qR\fIsite\fR
 /*     Schedule immediate delivery of all mail that is queued for the named
 /*     \fIsite\fR. This option accepts only \fIsite\fR names that are
@@ -885,6 +890,13 @@ static void enqueue(const int flags, const char *encoding,
     myfree(saved_sender);
 }
 
+/* tempfail - sanitize exit status after library run-time error */
+
+static void tempfail(void)
+{
+    exit(EX_TEMPFAIL);
+}
+
 /* main - the main program */
 
 int     main(int argc, char **argv)
@@ -902,6 +914,7 @@ int     main(int argc, char **argv)
     int     n;
     int     flags = SM_FLAG_DEFAULT;
     char   *site_to_flush = 0;
+    char   *id_to_flush = 0;
     char   *encoding = 0;
     char   *qtime = 0;
     const char *errstr;
@@ -952,6 +965,7 @@ int     main(int argc, char **argv)
     if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
        argv[0] = slash + 1;
     msg_vstream_init(argv[0], VSTREAM_ERR);
+    msg_cleanup(tempfail);
     msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY);
     set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
 
@@ -1175,6 +1189,10 @@ int     main(int argc, char **argv)
                site_to_flush = optarg + 1;
                if (*site_to_flush == 0)
                    msg_fatal_status(EX_USAGE, "specify: -qRsitename");
+           } else if (optarg[0] == 'I') {
+               id_to_flush = optarg + 1;
+               if (*id_to_flush == 0)
+                   msg_fatal_status(EX_USAGE, "specify: -qIqueueid");
            } else {
                msg_fatal_status(EX_USAGE, "-q%c is not implemented",
                                 optarg[0]);
@@ -1200,6 +1218,9 @@ int     main(int argc, char **argv)
     if (site_to_flush && mode != SM_MODE_ENQUEUE)
        msg_fatal_status(EX_USAGE, "-qR can be used only in delivery mode");
 
+    if (id_to_flush && mode != SM_MODE_ENQUEUE)
+       msg_fatal_status(EX_USAGE, "-qI can be used only in delivery mode");
+
     if (flags & DEL_REQ_FLAG_USR_VRFY) {
        if (flags & SM_FLAG_XRCPT)
            msg_fatal_status(EX_USAGE, "-t option cannot be used with -bv");
@@ -1228,20 +1249,32 @@ int     main(int argc, char **argv)
        msg_panic("unknown operation mode: %d", mode);
        /* NOTREACHED */
     case SM_MODE_ENQUEUE:
-       if (site_to_flush == 0) {
+       if (site_to_flush) {
+           if (argv[OPTIND])
+               msg_fatal_status(EX_USAGE, "flush site requires no recipient");
+           ext_argv = argv_alloc(2);
+           argv_add(ext_argv, "postqueue", "-s", site_to_flush, (char *) 0);
+           for (n = 0; n < msg_verbose; n++)
+               argv_add(ext_argv, "-v", (char *) 0);
+           argv_terminate(ext_argv);
+           mail_run_replace(var_command_dir, ext_argv->argv);
+           /* NOTREACHED */
+       } else if (id_to_flush) {
+           if (argv[OPTIND])
+               msg_fatal_status(EX_USAGE, "flush queue_id requires no recipient");
+           ext_argv = argv_alloc(2);
+           argv_add(ext_argv, "postqueue", "-i", id_to_flush, (char *) 0);
+           for (n = 0; n < msg_verbose; n++)
+               argv_add(ext_argv, "-v", (char *) 0);
+           argv_terminate(ext_argv);
+           mail_run_replace(var_command_dir, ext_argv->argv);
+           /* NOTREACHED */
+       } else {
            enqueue(flags, encoding, dsn_envid, dsn_notify,
                    rewrite_context, sender, full_name, argv + OPTIND);
            exit(0);
+           /* NOTREACHED */
        }
-       if (argv[OPTIND])
-           msg_fatal_status(EX_USAGE, "flush site requires no recipient");
-       ext_argv = argv_alloc(2);
-       argv_add(ext_argv, "postqueue", "-s", site_to_flush, (char *) 0);
-       for (n = 0; n < msg_verbose; n++)
-           argv_add(ext_argv, "-v", (char *) 0);
-       argv_terminate(ext_argv);
-       mail_run_replace(var_command_dir, ext_argv->argv);
-       /* NOTREACHED */
        break;
     case SM_MODE_MAILQ:
        if (argv[OPTIND])
index 4a19510d2d0a21c1c909df89fd9326af0333c430..cce5136cc2bb79f74a69fa118aa49b8c65b68e6b 100644 (file)
@@ -1708,6 +1708,11 @@ static int mail_open_stream(SMTPD_STATE *state)
                            MAIL_ATTR_ACT_HELO_NAME, state->helo_name);
            rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%u",
                        MAIL_ATTR_ACT_CLIENT_AF, state->addr_family);
+
+           /*
+            * Don't send client certificate down the pipeline unless it is
+            * a) verified or b) just a fingerprint.
+            */
        }
        if (state->verp_delims)
            rec_fputs(state->cleanup, REC_TYPE_VERP, state->verp_delims);
@@ -2994,7 +2999,7 @@ static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        smtpd_chat_reply(state, "%s", err);
        return (-1);
     }
-    switch (flush_send(argv[1].strval)) {
+    switch (flush_send_site(argv[1].strval)) {
     case FLUSH_STAT_OK:
        smtpd_chat_reply(state, "250 Queuing started");
        return (0);
index 865930d249e964e9e23c041d0b3e14ffd7eb23e9..80d41ac25181f950b03f15979ada786e983f2057 100644 (file)
@@ -1221,8 +1221,12 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
            msg_info("Relaying allowed for all verified client certificates");
        return (SMTPD_CHECK_OK);
     }
-    if (state->tls_context->peer_verified
-       && state->tls_context->peer_fingerprint) {
+
+    /*
+     * When directly checking the fingerprint, it is OK if the issuing CA is
+     * not trusted.
+     */
+    if (state->tls_context->peer_fingerprint) {
        found = maps_find(relay_ccerts, state->tls_context->peer_fingerprint,
                          DICT_FLAG_NONE);
        if (found) {
@@ -2578,8 +2582,11 @@ static int check_ccert_access(SMTPD_STATE *state, const char *table,
     if (!state->tls_context)
        return SMTPD_CHECK_DUNNO;
 
-    if (state->tls_context->peer_verified
-       && state->tls_context->peer_fingerprint) {
+    /*
+     * When directly checking the fingerprint, it is OK if the issuing CA is
+     * not trusted.
+     */
+    if (state->tls_context->peer_fingerprint) {
        if (msg_verbose)
            msg_info("%s: %s", myname, state->tls_context->peer_fingerprint);
 
@@ -3335,11 +3342,18 @@ static int check_policy_service(SMTPD_STATE *state, const char *server,
 #define IF_VERIFIED(x) \
     ((state->tls_context && \
       state->tls_context->peer_verified && ((x) != 0)) ? (x) : "")
-                         ATTR_TYPE_STR, MAIL_ATTR_CCERT_SUBJECT, subject,
-                         ATTR_TYPE_STR, MAIL_ATTR_CCERT_ISSUER, issuer,
-                         ATTR_TYPE_STR, MAIL_ATTR_CCERT_FINGERPRINT,
-                         IF_VERIFIED(state->tls_context->peer_fingerprint),
 #define IF_ENCRYPTED(x, y) ((state->tls_context && ((x) != 0)) ? (x) : (y))
+                         ATTR_TYPE_STR, MAIL_ATTR_CCERT_SUBJECT,
+                         IF_VERIFIED(subject),
+                         ATTR_TYPE_STR, MAIL_ATTR_CCERT_ISSUER,
+                         IF_VERIFIED(issuer),
+
+    /*
+     * When directly checking the fingerprint, it is OK if the issuing CA is
+     * not trusted.
+     */
+                         ATTR_TYPE_STR, MAIL_ATTR_CCERT_FINGERPRINT,
+                    IF_ENCRYPTED(state->tls_context->peer_fingerprint, ""),
                          ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_PROTOCOL,
                          IF_ENCRYPTED(state->tls_context->protocol, ""),
                          ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_CIPHER,