]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.9-20110320
authorWietse Venema <wietse@porcupine.org>
Sun, 20 Mar 2011 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:37:15 +0000 (06:37 +0000)
32 files changed:
postfix/HISTORY
postfix/README_FILES/POSTSCREEN_README
postfix/RELEASE_NOTES
postfix/WISHLIST
postfix/conf/main.cf
postfix/html/POSTSCREEN_README.html
postfix/html/cleanup.8.html
postfix/html/postconf.5.html
postfix/html/postsuper.1.html
postfix/html/showq.8.html
postfix/man/man1/postsuper.1
postfix/man/man5/postconf.5
postfix/man/man8/cleanup.8
postfix/man/man8/showq.8
postfix/mantools/postlink
postfix/proto/POSTSCREEN_README.html
postfix/proto/postconf.proto
postfix/src/cleanup/cleanup.c
postfix/src/cleanup/cleanup_message.c
postfix/src/global/Makefile.in
postfix/src/global/file_id.c
postfix/src/global/file_id.h
postfix/src/global/mail_params.c
postfix/src/global/mail_params.h
postfix/src/global/mail_queue.c
postfix/src/global/mail_queue.h
postfix/src/global/mail_version.h
postfix/src/global/safe_ultostr.c [new file with mode: 0644]
postfix/src/global/safe_ultostr.h [new file with mode: 0644]
postfix/src/postsuper/Makefile.in
postfix/src/postsuper/postsuper.c
postfix/src/showq/showq.c

index 0e388c9425fb098afb76eefb89d5d1b52f48c6b3..ac1b98e6acfaa811fdd3c7e859d7cfa3c2bf3ed8 100644 (file)
@@ -16685,6 +16685,22 @@ Apologies for any names omitted.
        src/global/dict_ldap.c src/global/cfg_parser.h
        src/global/cfg_parser.c.
 
+20110320
+
+       Feature: specify "enable_long_queue_ids = yes" to enable
+       support for non-repeating queue IDs (also used as queue
+       file names). These queue IDs encode the time and inode
+       number with a safe alphabet of the 52 characters 0-9B-Zb-z.
+       The alphabet excludes vowels (AEIOUaeiou) to avoid creating
+       real words.  The queue ID format is: time in seconds, time
+       in microseconds, 'z', inode number (the inode number is
+       encoded without using the 'z' character of the safe alphabet).
+       Turning on long queue IDs changes the width of the first
+       output column of the mailq (postqueue -p) command, and
+       changes the appearance of Postfix Message-ID headers to
+       queueID@myhostname.  Files: global/file_id.[hc],
+       global/safe_ultostr.[hc], global/mail_queue.[hc],
+       postsuper/postsuper.c, showq/showq.c
 20110311
 
        Feature: Base 32 encoder/decoder per RFC 4648. This code
@@ -16693,11 +16709,19 @@ Apologies for any names omitted.
 
 20110313
 
-       Bugfix (introduced Postfix 2.8): number the postscreen DNSBL
-       requests, so that delayed results for an old session are
-       not added to the score when the same remote SMTP client has
-       reconnected in the mean time. Files: postscreen/postscreen_dnsbl.c,
-       dnsblog/dnsblog.c.
+       Bugfix (introduced Postfix 2.8): postscreen DNSBL scoring
+       error. When a client disconnected and then reconnected
+       before all DNSBL results for the earlier session arrived,
+       DNSBL results for the earlier session would be added to the
+       score for the later session. Problem report by Larry Vaden.
+       Files: dnsblog/dnsblog.c, postscreen/postscreen_dnsbl.c.
 
        Cleanup: protocol description in dnsblog(8) manpage. File:
        dnsblog/dnsblog.c.
+
+20110314
+
+       Portability: the SUN compiler had trouble with a pointer
+       expression of the form ``("text1" "text2") + constant'' so
+       we don't try to be so clever. Fix by Victor Duchovni.  File:
+       global/mail_params.h.
index 4b68315a1684b19161e736424ec3e259450940b3..19df31b0a8a70765c2dafc147983e80553b649c1 100644 (file)
@@ -604,8 +604,9 @@ Notes:
 
   * Some postscreen(8) configuration parameters implement stress-dependent
     behavior. This is supported only when the default value is stress-dependent
-    (that is, it looks like ${stress?X}${stress:Y}). Other parameters always
-    evaluate as if the stress value is the empty string.
+    (that is, "postconf -d parametername" output shows "parametername = $
+    {stress?something}${stress:something}"). Other parameters always evaluate
+    as if the stress value is the empty string.
 
   * See "Tests before the 220 SMTP server greeting" for details about the
     logging from these postscreen(8) tests.
index 01d988efb9c77371044dede327818d719ffdab7b..b51bc45932c87987727c2233635f10a610cbcc2e 100644 (file)
@@ -14,6 +14,47 @@ specifies the release date of a stable release or snapshot release.
 If you upgrade from Postfix 2.7 or earlier, read RELEASE_NOTES-2.8
 before proceeding.
 
+Incompatible changes with snapshot 20110320
+===========================================
+
+If you enable support for long queue file names, you need to be
+aware that these file names are not compatible with Postfix <= 2.8.
+If you must migrate to Postfix <= 2.8, you must first convert all
+long queue file names into short names, otherwise the old Postfix
+version will complain.
+
+The conversion procedure before migration to Postfix <= 2.8 is:
+
+    # postfix stop
+    # postconf enable_long_queue_ids=no
+    # postsuper
+
+Run the postsuper command repeatedly until it no longer reports
+queue file name changes.
+
+Major changes with snapshot 20110320
+====================================
+
+Support for long, non-repeating, queue IDs (queue file names).  The
+benefit of non-repeating names is simpler logfile analysis, and
+easier queue migration (there is no need to run "postsuper" to
+change queue file names that don't match their message file inode
+number).
+
+Specify "enable_long_queue_ids = yes" to enable the feature. This
+does not change the names of existing queue files. See postconf(5)
+or postconf.5.html#enable_long_queue_ids for a detailed description
+of the differences with the old short queue IDs.
+
+This changes new Postfix queue IDs from the short form 0FCEE9247A9
+into the longer form 3Ps0FS1Zhtz1PFjb, and changes new Message-ID
+header values from YYMMDDHHMMSS.queueid@myhostname into the shorter
+form queueid@myhostname.
+
+See the note on "Incompatible changes" for a backwards migration
+procedure to convert long queue file names into a form that is
+compatible with Postfix <= 2.8.
+
 Incompatible changes with snapshot 20110313
 ===========================================
 
index fa63f559de30927ae0a72666c72dcee19e880f23..bf1570fd3e0f1932e729772d2de85513fc02fa0f 100644 (file)
@@ -11,9 +11,6 @@ Wish list:
        Don't forget Apple's code donation for fetching mail from
        IMAP server.
 
-       Use queue ID (file name) based on inode number and enough
-       (time or random) bits to avoid repetition in 10+ years.
-
        Simplify postscreen logic: set the noforward flag if the
        client made an unforgivable error. Individual "fail" flags
        are needed only to avoid logging the same offense multiple
index 2264a2c75d7c5ff345af471c814748e2a4c619fc..ca28c9319fa22f27ee3708837336cbe6f680edff 100644 (file)
@@ -458,7 +458,12 @@ unknown_local_recipient_reject_code = 550
 # the main.cf file, otherwise the SMTP server will reject mail for    
 # non-UNIX accounts with "User unknown in local recipient table".
 #
-#mailbox_transport = lmtp:unix:/file/name
+# Cyrus IMAP over LMTP. Specify ``lmtpunix      cmd="lmtpd"
+# listen="/var/imap/socket/lmtp" prefork=0'' in cyrus.conf.
+#mailbox_transport = lmtp:unix:/var/imap/socket/lmtp
+#
+# Cyrus IMAP via command line. Uncomment the "cyrus...pipe" and
+# subsequent line in master.cf.
 #mailbox_transport = cyrus
 
 # The fallback_transport specifies the optional transport in master.cf
index 369fbf2a823cd3095ef3affad77c595b0c1efcc7..d20d13672db6e1614ea379cb11baada69698e3d1 100644 (file)
@@ -837,7 +837,9 @@ Postfix version 2.8. </p>
 
 <li> <p> Some <a href="postscreen.8.html">postscreen(8)</a> configuration parameters implement
 stress-dependent behavior. This is supported only when the default
-value is stress-dependent (that is, it looks like ${stress?X}${stress:Y}).
+value is stress-dependent (that is, "postconf -d <i>parametername</i>"
+output shows "<i>parametername</i> =
+${stress?<i>something</i>}${stress:<i>something</i>}").
 Other parameters always evaluate as if the stress value is the empty
 string. </p>
 
index 70e5e4098fdce78a8816a3a23de4e0f4939fd69f..1071b1efa290d288aea569fd7cd62be535a03485 100644 (file)
@@ -80,8 +80,7 @@ CLEANUP(8)                                                          CLEANUP(8)
        <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
 
 <b>COMPATIBILITY CONTROLS</b>
-       <b><a href="postconf.5.html#undisclosed_recipients_header">undisclosed_recipients_header</a>   (To:   undisclosed-recipi-</b>
-       <b>ents:;)</b>
+       <b><a href="postconf.5.html#undisclosed_recipients_header">undisclosed_recipients_header</a> (see 'postconf -d' output)</b>
               Message  header  that the Postfix <a href="cleanup.8.html"><b>cleanup</b>(8)</a> server
               inserts when a message contains no To: or Cc:  mes-
               sage header.
@@ -103,41 +102,47 @@ CLEANUP(8)                                                          CLEANUP(8)
               Always  add (Resent-) From:, To:, Date: or Message-
               ID: headers when not present.
 
+       Available in Postfix version 2.9 and later:
+
+       <b><a href="postconf.5.html#enable_long_queue_ids">enable_long_queue_ids</a> (no)</b>
+              Enable long, non-repeating, queue IDs  (queue  file
+              names).
+
 <b>BUILT-IN CONTENT FILTERING CONTROLS</b>
-       Postfix built-in content filtering  is  meant  to  stop  a
-       flood  of  worms  or  viruses. It is not a general content
+       Postfix  built-in  content  filtering  is  meant to stop a
+       flood of worms or viruses. It is  not  a  general  content
        filter.
 
        <b><a href="postconf.5.html#body_checks">body_checks</a> (empty)</b>
-              Optional lookup tables for  content  inspection  as
+              Optional  lookup  tables  for content inspection as
               specified in the <a href="header_checks.5.html"><b>body_checks</b>(5)</a> manual page.
 
        <b><a href="postconf.5.html#header_checks">header_checks</a> (empty)</b>
-              Optional  lookup  tables  for content inspection of
-              primary non-MIME message headers, as  specified  in
+              Optional lookup tables for  content  inspection  of
+              primary  non-MIME  message headers, as specified in
               the <a href="header_checks.5.html"><b>header_checks</b>(5)</a> manual page.
 
        Available in Postfix version 2.0 and later:
 
        <b><a href="postconf.5.html#body_checks_size_limit">body_checks_size_limit</a> (51200)</b>
               How much text in a message body segment (or attach-
-              ment, if you prefer to use that term) is  subjected
+              ment,  if you prefer to use that term) is subjected
               to <a href="postconf.5.html#body_checks">body_checks</a> inspection.
 
        <b><a href="postconf.5.html#mime_header_checks">mime_header_checks</a> ($<a href="postconf.5.html#header_checks">header_checks</a>)</b>
-              Optional  lookup  tables  for content inspection of
-              MIME related message headers, as described  in  the
+              Optional lookup tables for  content  inspection  of
+              MIME  related  message headers, as described in the
               <a href="header_checks.5.html"><b>header_checks</b>(5)</a> manual page.
 
        <b><a href="postconf.5.html#nested_header_checks">nested_header_checks</a> ($<a href="postconf.5.html#header_checks">header_checks</a>)</b>
-              Optional  lookup  tables  for content inspection of
-              non-MIME message headers in attached  messages,  as
+              Optional lookup tables for  content  inspection  of
+              non-MIME  message  headers in attached messages, as
               described in the <a href="header_checks.5.html"><b>header_checks</b>(5)</a> manual page.
 
        Available in Postfix version 2.3 and later:
 
        <b><a href="postconf.5.html#message_reject_characters">message_reject_characters</a> (empty)</b>
-              The  set  of characters that Postfix will reject in
+              The set of characters that Postfix will  reject  in
               message content.
 
        <b><a href="postconf.5.html#message_strip_characters">message_strip_characters</a> (empty)</b>
@@ -146,24 +151,24 @@ CLEANUP(8)                                                          CLEANUP(8)
 
 <b>BEFORE QUEUE MILTER CONTROLS</b>
        As of version 2.3, Postfix supports the Sendmail version 8
-       Milter (mail filter) protocol. When mail is  not  received
-       via  the <a href="smtpd.8.html">smtpd(8)</a> server, the <a href="cleanup.8.html">cleanup(8)</a> server will simu-
-       late SMTP events to the extent that this is possible.  For
+       Milter  (mail  filter) protocol. When mail is not received
+       via the <a href="smtpd.8.html">smtpd(8)</a> server, the <a href="cleanup.8.html">cleanup(8)</a> server will  simu-
+       late  SMTP events to the extent that this is possible. For
        details see the <a href="MILTER_README.html">MILTER_README</a> document.
 
        <b><a href="postconf.5.html#non_smtpd_milters">non_smtpd_milters</a> (empty)</b>
               A list of Milter (mail filter) applications for new
-              mail that does not arrive via the Postfix  <a href="smtpd.8.html"><b>smtpd</b>(8)</a>
+              mail  that does not arrive via the Postfix <a href="smtpd.8.html"><b>smtpd</b>(8)</a>
               server.
 
        <b><a href="postconf.5.html#milter_protocol">milter_protocol</a> (6)</b>
-              The  mail filter protocol version and optional pro-
-              tocol extensions for communication  with  a  Milter
-              application;  prior to Postfix 2.6 the default pro-
+              The mail filter protocol version and optional  pro-
+              tocol  extensions  for  communication with a Milter
+              application; prior to Postfix 2.6 the default  pro-
               tocol is 2.
 
        <b><a href="postconf.5.html#milter_default_action">milter_default_action</a> (tempfail)</b>
-              The default action  when  a  Milter  (mail  filter)
+              The  default  action  when  a  Milter (mail filter)
               application is unavailable or mis-configured.
 
        <b><a href="postconf.5.html#milter_macro_daemon_name">milter_macro_daemon_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
@@ -175,62 +180,62 @@ CLEANUP(8)                                                          CLEANUP(8)
               cations.
 
        <b><a href="postconf.5.html#milter_connect_timeout">milter_connect_timeout</a> (30s)</b>
-              The  time  limit  for  connecting to a Milter (mail
-              filter) application, and for  negotiating  protocol
+              The time limit for connecting  to  a  Milter  (mail
+              filter)  application,  and for negotiating protocol
               options.
 
        <b><a href="postconf.5.html#milter_command_timeout">milter_command_timeout</a> (30s)</b>
-              The  time  limit  for  sending an SMTP command to a
+              The time limit for sending an  SMTP  command  to  a
               Milter (mail filter) application, and for receiving
               the response.
 
        <b><a href="postconf.5.html#milter_content_timeout">milter_content_timeout</a> (300s)</b>
-              The  time  limit  for  sending message content to a
+              The time limit for sending  message  content  to  a
               Milter (mail filter) application, and for receiving
               the response.
 
        <b><a href="postconf.5.html#milter_connect_macros">milter_connect_macros</a> (see 'postconf -d' output)</b>
-              The  macros  that  are sent to Milter (mail filter)
-              applications after completion of  an  SMTP  connec-
+              The macros that are sent to  Milter  (mail  filter)
+              applications  after  completion  of an SMTP connec-
               tion.
 
        <b><a href="postconf.5.html#milter_helo_macros">milter_helo_macros</a> (see 'postconf -d' output)</b>
-              The  macros  that  are sent to Milter (mail filter)
+              The macros that are sent to  Milter  (mail  filter)
               applications after the SMTP HELO or EHLO command.
 
        <b><a href="postconf.5.html#milter_mail_macros">milter_mail_macros</a> (see 'postconf -d' output)</b>
-              The macros that are sent to  Milter  (mail  filter)
+              The  macros  that  are sent to Milter (mail filter)
               applications after the SMTP MAIL FROM command.
 
        <b><a href="postconf.5.html#milter_rcpt_macros">milter_rcpt_macros</a> (see 'postconf -d' output)</b>
-              The  macros  that  are sent to Milter (mail filter)
+              The macros that are sent to  Milter  (mail  filter)
               applications after the SMTP RCPT TO command.
 
        <b><a href="postconf.5.html#milter_data_macros">milter_data_macros</a> (see 'postconf -d' output)</b>
-              The macros that are sent to  version  4  or  higher
-              Milter  (mail  filter)  applications after the SMTP
+              The  macros  that  are  sent to version 4 or higher
+              Milter (mail filter) applications  after  the  SMTP
               DATA command.
 
        <b><a href="postconf.5.html#milter_unknown_command_macros">milter_unknown_command_macros</a> (see 'postconf -d' output)</b>
-              The macros that are sent to  version  3  or  higher
-              Milter  (mail filter) applications after an unknown
+              The  macros  that  are  sent to version 3 or higher
+              Milter (mail filter) applications after an  unknown
               SMTP command.
 
        <b><a href="postconf.5.html#milter_end_of_data_macros">milter_end_of_data_macros</a> (see 'postconf -d' output)</b>
-              The macros that are sent to  Milter  (mail  filter)
+              The  macros  that  are sent to Milter (mail filter)
               applications after the message end-of-data.
 
        Available in Postfix version 2.5 and later:
 
        <b><a href="postconf.5.html#milter_end_of_header_macros">milter_end_of_header_macros</a> (see 'postconf -d' output)</b>
-              The  macros  that  are sent to Milter (mail filter)
+              The macros that are sent to  Milter  (mail  filter)
               applications after the end of the message header.
 
        Available in Postfix version 2.7 and later:
 
        <b><a href="postconf.5.html#milter_header_checks">milter_header_checks</a> (empty)</b>
-              Optional lookup tables for  content  inspection  of
-              message  headers that are produced by Milter appli-
+              Optional  lookup  tables  for content inspection of
+              message headers that are produced by Milter  appli-
               cations.
 
 <b>MIME PROCESSING CONTROLS</b>
@@ -248,27 +253,27 @@ CLEANUP(8)                                                          CLEANUP(8)
               will handle.
 
        <b><a href="postconf.5.html#strict_8bitmime">strict_8bitmime</a> (no)</b>
-              Enable both  <a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a>  and  strict_8bit-
+              Enable  both  <a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a>  and strict_8bit-
               mime_body.
 
        <b><a href="postconf.5.html#strict_7bit_headers">strict_7bit_headers</a> (no)</b>
               Reject mail with 8-bit text in message headers.
 
        <b><a href="postconf.5.html#strict_8bitmime_body">strict_8bitmime_body</a> (no)</b>
-              Reject  8-bit  message body text without 8-bit MIME
+              Reject 8-bit message body text without  8-bit  MIME
               content encoding information.
 
        <b><a href="postconf.5.html#strict_mime_encoding_domain">strict_mime_encoding_domain</a> (no)</b>
               Reject mail with invalid Content-Transfer-Encoding:
-              information  for  the message/* or multipart/* MIME
+              information for the message/* or  multipart/*  MIME
               content types.
 
        Available in Postfix version 2.5 and later:
 
        <b><a href="postconf.5.html#detect_8bit_encoding_header">detect_8bit_encoding_header</a> (yes)</b>
               Automatically detect 8BITMIME body content by look-
-              ing  at Content-Transfer-Encoding: message headers;
-              historically, this behavior was  hard-coded  to  be
+              ing at Content-Transfer-Encoding: message  headers;
+              historically,  this  behavior  was hard-coded to be
               "always on".
 
 <b>AUTOMATIC BCC RECIPIENT CONTROLS</b>
@@ -276,31 +281,31 @@ CLEANUP(8)                                                          CLEANUP(8)
        mail enters the mail system:
 
        <b><a href="postconf.5.html#always_bcc">always_bcc</a> (empty)</b>
-              Optional address  that  receives  a  "blind  carbon
+              Optional  address  that  receives  a  "blind carbon
               copy" of each message that is received by the Post-
               fix mail system.
 
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#sender_bcc_maps">sender_bcc_maps</a> (empty)</b>
-              Optional BCC  (blind  carbon-copy)  address  lookup
+              Optional  BCC  (blind  carbon-copy)  address lookup
               tables, indexed by sender address.
 
        <b><a href="postconf.5.html#recipient_bcc_maps">recipient_bcc_maps</a> (empty)</b>
-              Optional  BCC  (blind  carbon-copy)  address lookup
+              Optional BCC  (blind  carbon-copy)  address  lookup
               tables, indexed by recipient address.
 
 <b>ADDRESS TRANSFORMATION CONTROLS</b>
-       Address rewriting is delegated to  the  <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a>
-       daemon.   The  <a href="cleanup.8.html"><b>cleanup</b>(8)</a>  server  implements table driven
+       Address  rewriting  is delegated to the <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a>
+       daemon.  The <a href="cleanup.8.html"><b>cleanup</b>(8)</a>  server  implements  table  driven
        address mapping.
 
        <b><a href="postconf.5.html#empty_address_recipient">empty_address_recipient</a> (MAILER-DAEMON)</b>
-              The  recipient  of  mail  addressed  to  the   null
+              The   recipient  of  mail  addressed  to  the  null
               address.
 
        <b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b>
-              Optional  address mapping lookup tables for message
+              Optional address mapping lookup tables for  message
               headers and envelopes.
 
        <b><a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> (empty)</b>
@@ -311,49 +316,49 @@ CLEANUP(8)                                                          CLEANUP(8)
               Optional address mapping lookup tables for envelope
               and header sender addresses.
 
-       <b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a>    (envelope_sender,     header_sender,</b>
+       <b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a>     (envelope_sender,    header_sender,</b>
        <b>header_recipient)</b>
               What addresses are subject to address masquerading.
 
        <b><a href="postconf.5.html#masquerade_domains">masquerade_domains</a> (empty)</b>
-              Optional  list of domains whose subdomain structure
+              Optional list of domains whose subdomain  structure
               will be stripped off in email addresses.
 
        <b><a href="postconf.5.html#masquerade_exceptions">masquerade_exceptions</a> (empty)</b>
-              Optional list of user names that are not  subjected
-              to  address  masquerading,  even when their address
+              Optional  list of user names that are not subjected
+              to address masquerading, even  when  their  address
               matches $<a href="postconf.5.html#masquerade_domains">masquerade_domains</a>.
 
        <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
-              What address lookup tables copy an  address  exten-
+              What  address  lookup tables copy an address exten-
               sion from the lookup key to the lookup result.
 
        Available before Postfix version 2.0:
 
        <b><a href="postconf.5.html#virtual_maps">virtual_maps</a> (empty)</b>
               Optional lookup tables with a) names of domains for
-              which all addresses are  aliased  to  addresses  in
-              other  local  or  remote  domains, and b) addresses
-              that are aliased to addresses  in  other  local  or
+              which  all  addresses  are  aliased to addresses in
+              other local or remote  domains,  and  b)  addresses
+              that  are  aliased  to  addresses in other local or
               remote domains.
 
        Available in Postfix version 2.0 and later:
 
        <b><a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> ($<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b>
-              Optional  lookup  tables  that  alias specific mail
-              addresses or  domains  to  other  local  or  remote
+              Optional lookup tables  that  alias  specific  mail
+              addresses  or  domains  to  other  local  or remote
               address.
 
        Available in Postfix version 2.2 and later:
 
-       <b><a href="postconf.5.html#canonical_classes">canonical_classes</a>   (envelope_sender,  envelope_recipient,</b>
+       <b><a href="postconf.5.html#canonical_classes">canonical_classes</a>  (envelope_sender,   envelope_recipient,</b>
        <b>header_sender, header_recipient)</b>
-              What   addresses   are  subject  to  <a href="postconf.5.html#canonical_maps">canonical_maps</a>
+              What  addresses  are  subject   to   <a href="postconf.5.html#canonical_maps">canonical_maps</a>
               address mapping.
 
        <b><a href="postconf.5.html#recipient_canonical_classes">recipient_canonical_classes</a>           (envelope_recipient,</b>
        <b>header_recipient)</b>
-              What addresses  are  subject  to  <a href="postconf.5.html#recipient_canonical_maps">recipient_canoni</a>-
+              What  addresses  are  subject  to <a href="postconf.5.html#recipient_canonical_maps">recipient_canoni</a>-
               <a href="postconf.5.html#recipient_canonical_maps">cal_maps</a> address mapping.
 
        <b><a href="postconf.5.html#sender_canonical_classes">sender_canonical_classes</a> (envelope_sender, header_sender)</b>
@@ -361,15 +366,15 @@ CLEANUP(8)                                                          CLEANUP(8)
               address mapping.
 
        <b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
-              Don't rewrite message headers from  remote  clients
+              Don't  rewrite  message headers from remote clients
               at all when this parameter is empty; otherwise, re-
-              write message  headers  and  append  the  specified
+              write  message  headers  and  append  the specified
               domain name to incomplete addresses.
 
 <b>RESOURCE AND RATE CONTROLS</b>
        <b><a href="postconf.5.html#duplicate_filter_limit">duplicate_filter_limit</a> (1000)</b>
-              The  maximal  number of addresses remembered by the
-              address duplicate filter  for  <a href="aliases.5.html"><b>aliases</b>(5)</a>  or  <a href="virtual.5.html"><b>vir-</b></a>
+              The maximal number of addresses remembered  by  the
+              address  duplicate  filter  for  <a href="aliases.5.html"><b>aliases</b>(5)</a> or <a href="virtual.5.html"><b>vir-</b></a>
               <a href="virtual.5.html"><b>tual</b>(5)</a> alias expansion, or for <a href="showq.8.html"><b>showq</b>(8)</a> queue dis-
               plays.
 
@@ -378,16 +383,16 @@ CLEANUP(8)                                                          CLEANUP(8)
               message header.
 
        <b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b>
-              The  maximal  number  of Received:  message headers
+              The maximal number of  Received:   message  headers
               that is allowed in the primary message headers.
 
        <b><a href="postconf.5.html#in_flow_delay">in_flow_delay</a> (1s)</b>
-              Time to pause before accepting a new message,  when
+              Time  to pause before accepting a new message, when
               the message arrival rate exceeds the message deliv-
               ery rate.
 
        <b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
-              The maximal size in bytes of a  message,  including
+              The  maximal  size in bytes of a message, including
               envelope information.
 
        Available in Postfix version 2.0 and later:
@@ -405,35 +410,35 @@ CLEANUP(8)                                                          CLEANUP(8)
               will handle.
 
        <b><a href="postconf.5.html#queue_file_attribute_count_limit">queue_file_attribute_count_limit</a> (100)</b>
-              The maximal number of (name=value) attributes  that
+              The  maximal number of (name=value) attributes that
               may be stored in a Postfix queue file.
 
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#virtual_alias_expansion_limit">virtual_alias_expansion_limit</a> (1000)</b>
-              The  maximal number of addresses that virtual alias
+              The maximal number of addresses that virtual  alias
               expansion produces from each original recipient.
 
        <b><a href="postconf.5.html#virtual_alias_recursion_limit">virtual_alias_recursion_limit</a> (1000)</b>
-              The maximal nesting depth of virtual  alias  expan-
+              The  maximal  nesting depth of virtual alias expan-
               sion.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The  default  location  of  the Postfix <a href="postconf.5.html">main.cf</a> and
+              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
               <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
-              How much time a Postfix daemon process may take  to
-              handle  a  request  before  it  is  terminated by a
+              How  much time a Postfix daemon process may take to
+              handle a request  before  it  is  terminated  by  a
               built-in watchdog timer.
 
        <b><a href="postconf.5.html#delay_logging_resolution_limit">delay_logging_resolution_limit</a> (2)</b>
-              The maximal number  of  digits  after  the  decimal
+              The  maximal  number  of  digits  after the decimal
               point when logging sub-second delay values.
 
        <b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b>
-              The  time  after which the sender receives the mes-
+              The time after which the sender receives  the  mes-
               sage headers of mail that is still queued.
 
        <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
@@ -441,13 +446,13 @@ CLEANUP(8)                                                          CLEANUP(8)
               over an internal communication channel.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The  maximum  amount  of  time that an idle Postfix
-              daemon process waits  for  an  incoming  connection
+              The maximum amount of time  that  an  idle  Postfix
+              daemon  process  waits  for  an incoming connection
               before terminating voluntarily.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The  maximal  number of incoming connections that a
-              Postfix daemon process will service  before  termi-
+              The maximal number of incoming connections  that  a
+              Postfix  daemon  process will service before termi-
               nating voluntarily.
 
        <b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
@@ -455,19 +460,19 @@ CLEANUP(8)                                                          CLEANUP(8)
 
        <b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
               The domain name that locally-posted mail appears to
-              come from, and that locally posted mail  is  deliv-
+              come  from,  and that locally posted mail is deliv-
               ered to.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The  process  ID  of  a  Postfix  command or daemon
+              The process ID  of  a  Postfix  command  or  daemon
               process.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The process name of a  Postfix  command  or  daemon
+              The  process  name  of  a Postfix command or daemon
               process.
 
        <b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
-              The  location of the Postfix top-level queue direc-
+              The location of the Postfix top-level queue  direc-
               tory.
 
        <b><a href="postconf.5.html#soft_bounce">soft_bounce</a> (no)</b>
@@ -478,14 +483,14 @@ CLEANUP(8)                                                          CLEANUP(8)
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
-              The  mail  system  name  that  is  prepended to the
-              process name in syslog  records,  so  that  "smtpd"
+              The mail system  name  that  is  prepended  to  the
+              process  name  in  syslog  records, so that "smtpd"
               becomes, for example, "postfix/smtpd".
 
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#enable_original_recipient">enable_original_recipient</a> (yes)</b>
-              Enable   support   for  the  X-Original-To  message
+              Enable  support  for  the   X-Original-To   message
               header.
 
 <b>FILES</b>
@@ -509,7 +514,7 @@ CLEANUP(8)                                                          CLEANUP(8)
        <a href="CONTENT_INSPECTION_README.html">CONTENT_INSPECTION_README</a> content inspection
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index 891ea211dc64b457a865a04edacf13c2a87842ea..e0123aa129bedb7bb0b086b10a8e505b7eeb0414 100644 (file)
@@ -2688,6 +2688,80 @@ turned off by default with Postfix version 2.1, and is always turned on
 with older Postfix versions).  </p>
 
 
+</DD>
+
+<DT><b><a name="enable_long_queue_ids">enable_long_queue_ids</a>
+(default: no)</b></DT><DD>
+
+<p> Enable long, non-repeating, queue IDs (queue file names).  The
+benefit of non-repeating names is simpler logfile analysis and
+easier queue migration (there is no need to run "postsuper" to
+change queue file names that don't match their message file inode
+number).  </p>
+
+<p> Note: see below for how to prepare long queue file names
+for migration to Postfix &le; 2.8. </p>
+
+<p> Changing the parameter value to "yes" has the following effects:
+</p>
+
+<ul>
+
+<li> <p> Existing queue file names are not affected. </p>
+
+<li> <p> New queue files are created with names such as 3Pt2mN2VXxznjll.
+These are encoded in a 52-character alphabet that contains digits
+(0-9), upper-case letters (B-Z) and lower-case letters (b-z). For
+safety reasons the vowels (AEIOUaeiou) are excluded from the alphabet.
+The name format is: 6 or more characters for the time in seconds,
+4 characters for the time in microseconds, the 'z'; the remainder
+is the file inode number encoded in the first 51 characters of the
+52-character alphabet.  </p>
+
+<li> <p> New messages have a Message-ID header with
+<i>queueID</i>@<i><a href="postconf.5.html#myhostname">myhostname</a></i>.  </p>
+
+<li> <p> The mailq (postqueue -p) output has a wider Queue ID column.
+The number of whitespace-separated fields is not changed. <p>
+
+</ul>
+
+<p> Changing the parameter value to "no" has the following effects:
+</p>
+
+<ul>
+
+<li> <p> Existing long queue file names are renamed to the short
+form (while running "postfix reload" or "postsuper").  </p>
+
+<li> New queue files are created with names such as C3CD21F3E90
+from a hexadecimal alphabet that contains digits (0-9) and upper-case
+letters (A-F). The name format is: 5 characters for the time in
+microseconds; the remainder is the file inode number. </p>
+
+<li> <p> New messages have a Message-ID header with
+<i>YYYYMMDDHHMMSS.queueid</i>@<i><a href="postconf.5.html#myhostname">myhostname</a></i>, where
+<i>YYYYMMDDHHMMSS</i> are the year, month, day, hour, minute and
+second.
+
+<li> <p> The mailq (postqueue -p) output has the same format as
+with Postfix &le; 2.8. <p>
+
+</ul>
+
+<p> Before migration to Postfix &le; 2.8, the following commands
+are required to convert long queue file names into short names: </p>
+
+<pre>
+# postfix stop
+# postconf <a href="postconf.5.html#enable_long_queue_ids">enable_long_queue_ids</a>=no
+# postsuper
+</pre>
+
+<p> Repeat the postsuper command until it reports no more queue file
+name changes. </p>
+
+
 </DD>
 
 <DT><b><a name="enable_original_recipient">enable_original_recipient</a>
index bb819abd0d19492ca7347fcf33a593bab43cdbe4..1421c48ebf440ff26e2f640f3d1311c01fc069f4 100644 (file)
@@ -10,7 +10,7 @@ POSTSUPER(1)                                                      POSTSUPER(1)
        postsuper - Postfix superintendent
 
 <b>SYNOPSIS</b>
-       <b>postsuper</b> [<b>-psv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<b>-d</b> <i>queue</i><b>_</b><i>id</i>]
+       <b>postsuper</b> [<b>-psSv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<b>-d</b> <i>queue</i><b>_</b><i>id</i>]
                [<b>-h</b> <i>queue</i><b>_</b><i>id</i>] [<b>-H</b> <i>queue</i><b>_</b><i>id</i>]
                [<b>-r</b> <i>queue</i><b>_</b><i>id</i>] [<i>directory ...</i>]
 
@@ -180,7 +180,9 @@ POSTSUPER(1)                                                      POSTSUPER(1)
               <b>o</b>      Rename  files  whose name does not match the
                      message file inode number. This operation is
                      necessary  after restoring a mail queue from
-                     a different machine, or from backup media.
+                     a different machine  or  from  backup,  when
+                     queue files were created with Postfix &lt;= 2.8
+                     or with "<a href="postconf.5.html#enable_long_queue_ids">enable_long_queue_ids</a> = no".
 
               <b>o</b>      Move queue files that are in the wrong place
                      in the file system hierarchy and remove sub-
@@ -189,6 +191,22 @@ POSTSUPER(1)                                                      POSTSUPER(1)
                      a  change  in  the  <b><a href="postconf.5.html#hash_queue_names">hash_queue_names</a></b>  and/or
                      <b><a href="postconf.5.html#hash_queue_depth">hash_queue_depth</a></b> configuration parameters.
 
+              <b>o</b>      Rename     queue    files    created    with
+                     "<a href="postconf.5.html#enable_long_queue_ids">enable_long_queue_ids</a>  =  yes"   to   short
+                     names, for migration to Postfix &lt;= 2.8.  The
+                     procedure is as follows:
+
+                     # postfix stop
+                     # postconf <a href="postconf.5.html#enable_long_queue_ids">enable_long_queue_ids</a>=no
+                     # postsuper
+
+                     Run <a href="postsuper.1.html"><b>postsuper</b>(1)</a> repeatedly until  it  stops
+                     reporting file name changes.
+
+       <b>-S</b>     A  redundant  version of <b>-s</b> that requires that long
+              file names also match the message file  inode  num-
+              ber. This option exists for testing purposes.
+
        <b>-v</b>     Enable verbose logging for debugging purposes. Mul-
               tiple <b>-v</b> options  make  the  software  increasingly
               verbose.
@@ -241,12 +259,18 @@ POSTSUPER(1)                                                      POSTSUPER(1)
               process name in syslog  records,  so  that  "smtpd"
               becomes, for example, "postfix/smtpd".
 
+       Available in Postfix version 2.9 and later:
+
+       <b><a href="postconf.5.html#enable_long_queue_ids">enable_long_queue_ids</a> (no)</b>
+              Enable  long,  non-repeating, queue IDs (queue file
+              names).
+
 <b>SEE ALSO</b>
        <a href="sendmail.1.html">sendmail(1)</a>, Sendmail-compatible user interface
        <a href="postqueue.1.html">postqueue(1)</a>, unprivileged queue operations
 
 <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 c399c68ec5701193e77e9016c446beecdc45cdb4..b03b6d722fa0feac77e3f79d7eb7a604c173ec91 100644 (file)
@@ -95,6 +95,12 @@ SHOWQ(8)                                                              SHOWQ(8)
               process  name  in  syslog  records, so that "smtpd"
               becomes, for example, "postfix/smtpd".
 
+       Available in Postfix version 2.9 and later:
+
+       <b><a href="postconf.5.html#enable_long_queue_ids">enable_long_queue_ids</a> (no)</b>
+              Enable long, non-repeating, queue IDs  (queue  file
+              names).
+
 <b>FILES</b>
        /var/spool/postfix, queue directories
 
@@ -107,7 +113,7 @@ SHOWQ(8)                                                              SHOWQ(8)
        syslogd(8), system logging
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
index 9b292a987f126c31f16e5397dbda7f1b038f5637..093315de348c0f6537e3237c2f0ed08e28d70850 100644 (file)
@@ -9,7 +9,7 @@ Postfix superintendent
 .na
 .nf
 .fi
-\fBpostsuper\fR [\fB-psv\fR]
+\fBpostsuper\fR [\fB-psSv\fR]
 [\fB-c \fIconfig_dir\fR] [\fB-d \fIqueue_id\fR]
         [\fB-h \fIqueue_id\fR] [\fB-H \fIqueue_id\fR]
         [\fB-r \fIqueue_id\fR] [\fIdirectory ...\fR]
@@ -166,15 +166,36 @@ before Postfix startup.
 .RS
 .IP \(bu
 Rename files whose name does not match the message file inode
-number. This operation is necessary after restoring a mail queue
-from a different machine, or from backup media.
+number. This operation is necessary after restoring a mail
+queue from a different machine or from backup, when queue
+files were created with Postfix <= 2.8 or with
+"enable_long_queue_ids = no".
 .IP \(bu
 Move queue files that are in the wrong place in the file system
 hierarchy and remove subdirectories that are no longer needed.
 File position rearrangements are necessary after a change in the
 \fBhash_queue_names\fR and/or \fBhash_queue_depth\fR
 configuration parameters.
+.IP \(bu
+Rename queue files created with "enable_long_queue_ids =
+yes" to short names, for migration to Postfix <= 2.8.  The
+procedure is as follows:
+.sp
+.nf
+.na
+# postfix stop
+# postconf enable_long_queue_ids=no
+# postsuper
+.ad
+.fi
+.sp
+Run \fBpostsuper\fR(1) repeatedly until it stops reporting
+file name changes.
 .RE
+.IP \fB-S\fR
+A redundant version of \fB-s\fR that requires that long
+file names also match the message file inode number. This
+option exists for testing purposes.
 .IP \fB-v\fR
 Enable verbose logging for debugging purposes. Multiple \fB-v\fR
 options make the software increasingly verbose.
@@ -225,6 +246,10 @@ The syslog facility of Postfix logging.
 .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 The mail system name that is prepended to the process name in syslog
 records, so that "smtpd" becomes, for example, "postfix/smtpd".
+.PP
+Available in Postfix version 2.9 and later:
+.IP "\fBenable_long_queue_ids (no)\fR"
+Enable long, non-repeating, queue IDs (queue file names).
 .SH "SEE ALSO"
 .na
 .nf
index b07bbd1dff92b1b1937d0e86a4a62088787ba830..f245f0ab4a532541ae4d7bda802c541bc12b9cc2 100644 (file)
@@ -1509,6 +1509,68 @@ non-standard Errors-To: message header, instead of the envelope
 sender address (this feature is removed with Postfix version 2.2, is
 turned off by default with Postfix version 2.1, and is always turned on
 with older Postfix versions).
+.SH enable_long_queue_ids (default: no)
+Enable long, non-repeating, queue IDs (queue file names).  The
+benefit of non-repeating names is simpler logfile analysis and
+easier queue migration (there is no need to run "postsuper" to
+change queue file names that don't match their message file inode
+number).
+.PP
+Note: see below for how to prepare long queue file names
+for migration to Postfix <= 2.8.
+.PP
+Changing the parameter value to "yes" has the following effects:
+.IP \(bu
+Existing queue file names are not affected.
+.IP \(bu
+New queue files are created with names such as 3Pt2mN2VXxznjll.
+These are encoded in a 52-character alphabet that contains digits
+(0-9), upper-case letters (B-Z) and lower-case letters (b-z). For
+safety reasons the vowels (AEIOUaeiou) are excluded from the alphabet.
+The name format is: 6 or more characters for the time in seconds,
+4 characters for the time in microseconds, the 'z'; the remainder
+is the file inode number encoded in the first 51 characters of the
+52-character alphabet.
+.IP \(bu
+New messages have a Message-ID header with
+\fIqueueID\fR@\fImyhostname\fR.
+.IP \(bu
+The mailq (postqueue -p) output has a wider Queue ID column.
+The number of whitespace-separated fields is not changed.
+.PP
+Changing the parameter value to "no" has the following effects:
+.IP \(bu
+Existing long queue file names are renamed to the short
+form (while running "postfix reload" or "postsuper").
+.IP \(bu
+New queue files are created with names such as C3CD21F3E90
+from a hexadecimal alphabet that contains digits (0-9) and upper-case
+letters (A-F). The name format is: 5 characters for the time in
+microseconds; the remainder is the file inode number.
+.IP \(bu
+New messages have a Message-ID header with
+\fIYYYYMMDDHHMMSS.queueid\fR@\fImyhostname\fR, where
+\fIYYYYMMDDHHMMSS\fR are the year, month, day, hour, minute and
+second.
+.IP \(bu
+The mailq (postqueue -p) output has the same format as
+with Postfix <= 2.8.
+.PP
+Before migration to Postfix <= 2.8, the following commands
+are required to convert long queue file names into short names:
+.PP
+.nf
+.na
+.ft C
+# postfix stop
+# postconf enable_long_queue_ids=no
+# postsuper
+.fi
+.ad
+.ft R
+.PP
+Repeat the postsuper command until it reports no more queue file
+name changes.
 .SH enable_original_recipient (default: yes)
 Enable support for the X-Original-To message header. This header
 is needed for multi-recipient mailboxes.
index 5407ab0757ec0b0c134fde4a951c2ce39ece9b6c..d789450c54fa358bcf73212da1c49bb79168aca7 100644 (file)
@@ -84,7 +84,7 @@ The text below provides only a parameter summary. See
 .nf
 .ad
 .fi
-.IP "\fBundisclosed_recipients_header (To: undisclosed-recipients:;)\fR"
+.IP "\fBundisclosed_recipients_header (see 'postconf -d' output)\fR"
 Message header that the Postfix \fBcleanup\fR(8) server inserts when a
 message contains no To: or Cc: message header.
 .PP
@@ -100,6 +100,10 @@ Available in Postfix version 2.6 and later:
 .IP "\fBalways_add_missing_headers (no)\fR"
 Always add (Resent-) From:, To:, Date: or Message-ID: headers
 when not present.
+.PP
+Available in Postfix version 2.9 and later:
+.IP "\fBenable_long_queue_ids (no)\fR"
+Enable long, non-repeating, queue IDs (queue file names).
 .SH "BUILT-IN CONTENT FILTERING CONTROLS"
 .na
 .nf
index 389b29e7867cbd39fd104e506ad2c9abd97fa517..a200429e8649d3a901e3c5326fec4d178ec706d6 100644 (file)
@@ -81,6 +81,10 @@ The syslog facility of Postfix logging.
 .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 The mail system name that is prepended to the process name in syslog
 records, so that "smtpd" becomes, for example, "postfix/smtpd".
+.PP
+Available in Postfix version 2.9 and later:
+.IP "\fBenable_long_queue_ids (no)\fR"
+Enable long, non-repeating, queue IDs (queue file names).
 .SH "FILES"
 .na
 .nf
index 387d952554f61b6f28359c2b2105c7c7f980e9ff..eb1baec77cd615db7461f8c02d73d2b952792f09 100755 (executable)
@@ -689,6 +689,7 @@ while (<>) {
  
     s;\bfrozen_delivered_to\b;<a href="postconf.5.html#frozen_delivered_to">$&</a>;g;
     s;\breset_owner_alias\b;<a href="postconf.5.html#reset_owner_alias">$&</a>;g;
+    s;\benable_long_queue_ids\b;<a href="postconf.5.html#enable_long_queue_ids">$&</a>;g;
 
     # Transport-dependent magical parameters.
 
index 0d31c7d467d374e7b16febe6eb68039c6494eb4d..a86a7fd485dd3583daaca8c5f2535fe23ecf820b 100644 (file)
@@ -837,7 +837,9 @@ Postfix version 2.8. </p>
 
 <li> <p> Some postscreen(8) configuration parameters implement
 stress-dependent behavior. This is supported only when the default
-value is stress-dependent (that is, it looks like ${stress?X}${stress:Y}).
+value is stress-dependent (that is, "postconf -d <i>parametername</i>"
+output shows "<i>parametername</i> =
+${stress?<i>something</i>}${stress:<i>something</i>}").
 Other parameters always evaluate as if the stress value is the empty
 string. </p>
 
index 023051d99ca69d33d23cb307a2828edbcfe46c22..fddc672f3a0d4c01467ef6f3f279c7585babf833 100644 (file)
@@ -14080,3 +14080,73 @@ talking to a Postfix SMTP server process.  </p>
 </pre>
 
 <p> This feature is available in Postfix 2.9 and later.  </p>
+
+%PARAM enable_long_queue_ids no
+
+<p> Enable long, non-repeating, queue IDs (queue file names).  The
+benefit of non-repeating names is simpler logfile analysis and
+easier queue migration (there is no need to run "postsuper" to
+change queue file names that don't match their message file inode
+number).  </p>
+
+<p> Note: see below for how to prepare long queue file names
+for migration to Postfix &le; 2.8. </p>
+
+<p> Changing the parameter value to "yes" has the following effects:
+</p>
+
+<ul>
+
+<li> <p> Existing queue file names are not affected. </p>
+
+<li> <p> New queue files are created with names such as 3Pt2mN2VXxznjll.
+These are encoded in a 52-character alphabet that contains digits
+(0-9), upper-case letters (B-Z) and lower-case letters (b-z). For
+safety reasons the vowels (AEIOUaeiou) are excluded from the alphabet.
+The name format is: 6 or more characters for the time in seconds,
+4 characters for the time in microseconds, the 'z'; the remainder
+is the file inode number encoded in the first 51 characters of the
+52-character alphabet.  </p>
+
+<li> <p> New messages have a Message-ID header with
+<i>queueID</i>@<i>myhostname</i>.  </p>
+
+<li> <p> The mailq (postqueue -p) output has a wider Queue ID column.
+The number of whitespace-separated fields is not changed. <p>
+
+</ul>
+
+<p> Changing the parameter value to "no" has the following effects:
+</p>
+
+<ul>
+
+<li> <p> Existing long queue file names are renamed to the short
+form (while running "postfix reload" or "postsuper").  </p>
+
+<li> New queue files are created with names such as C3CD21F3E90
+from a hexadecimal alphabet that contains digits (0-9) and upper-case
+letters (A-F). The name format is: 5 characters for the time in
+microseconds; the remainder is the file inode number. </p>
+
+<li> <p> New messages have a Message-ID header with
+<i>YYYYMMDDHHMMSS.queueid</i>@<i>myhostname</i>, where
+<i>YYYYMMDDHHMMSS</i> are the year, month, day, hour, minute and
+second.
+
+<li> <p> The mailq (postqueue -p) output has the same format as
+with Postfix &le; 2.8. <p>
+
+</ul>
+
+<p> Before migration to Postfix &le; 2.8, the following commands
+are required to convert long queue file names into short names: </p>
+
+<pre>
+# postfix stop
+# postconf enable_long_queue_ids=no
+# postsuper
+</pre>
+
+<p> Repeat the postsuper command until it reports no more queue file
+name changes. </p>
index c5b71e9d82f08cfa9b1eadafd23f20de6d0efc2d..0f8df6616f9bf7ac07ba2550deb912649bdc26de 100644 (file)
@@ -68,7 +68,7 @@
 /* COMPATIBILITY CONTROLS
 /* .ad
 /* .fi
-/* .IP "\fBundisclosed_recipients_header (To: undisclosed-recipients:;)\fR"
+/* .IP "\fBundisclosed_recipients_header (see 'postconf -d' output)\fR"
 /*     Message header that the Postfix \fBcleanup\fR(8) server inserts when a
 /*     message contains no To: or Cc: message header.
 /* .PP
 /* .IP "\fBalways_add_missing_headers (no)\fR"
 /*     Always add (Resent-) From:, To:, Date: or Message-ID: headers
 /*     when not present.
+/* .PP
+/*     Available in Postfix version 2.9 and later:
+/* .IP "\fBenable_long_queue_ids (no)\fR"
+/*     Enable long, non-repeating, queue IDs (queue file names).
 /* BUILT-IN CONTENT FILTERING CONTROLS
 /* .ad
 /* .fi
index 4de1aa5309b88b4be4fd8387b9428e7e105b0689..08f694ad2cd4fe551e4c2b357d0c41d9559b67d4 100644 (file)
@@ -636,14 +636,21 @@ static void cleanup_header_done_callback(void *context)
     if ((state->hdr_rewrite_context || var_always_add_hdrs)
        && (state->headers_seen & (1 << (state->resent[0] ?
                           HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID))) == 0) {
-       tv = state->handle->ctime.tv_sec;
-       tp = gmtime(&tv);
-       strftime(time_stamp, sizeof(time_stamp), "%Y%m%d%H%M%S", tp);
-       cleanup_out_format(state, REC_TYPE_NORM, "%sMessage-Id: <%s.%s@%s>",
-               state->resent, time_stamp, state->queue_id, var_myhostname);
-       msg_info("%s: %smessage-id=<%s.%s@%s>",
+       if (var_long_queue_ids) {
+           vstring_sprintf(state->temp1, "%s@%s",
+                           state->queue_id, var_myhostname);
+       } else {
+           tv = state->handle->ctime.tv_sec;
+           tp = gmtime(&tv);
+           strftime(time_stamp, sizeof(time_stamp), "%Y%m%d%H%M%S", tp);
+           vstring_sprintf(state->temp1, "%s.%s@%s",
+                           time_stamp, state->queue_id, var_myhostname);
+       }
+       cleanup_out_format(state, REC_TYPE_NORM, "%sMessage-Id: <%s>",
+                          state->resent, vstring_str(state->temp1));
+       msg_info("%s: %smessage-id=<%s>",
                 state->queue_id, *state->resent ? "resent-" : "",
-                time_stamp, state->queue_id, var_myhostname);
+                vstring_str(state->temp1));
        state->headers_seen |= (1 << (state->resent[0] ?
                                   HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID));
     }
index 1a35114125896dd8646e7d0ac9c3dbb0c5e13e42..123944275cf773c349034897c3fde37713fb650e 100644 (file)
@@ -30,7 +30,7 @@ SRCS  = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
        verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c \
        fold_addr.c header_body_checks.c mkmap_proxy.c data_redirect.c \
        match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \
-       smtp_reply_footer.c
+       smtp_reply_footer.c safe_ultostr.c
 OBJS   = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
        canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
        clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
@@ -62,7 +62,7 @@ OBJS  = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
        verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o \
        fold_addr.o header_body_checks.o mkmap_proxy.o data_redirect.o \
        match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \
-       smtp_reply_footer.o
+       smtp_reply_footer.o safe_ultostr.o
 HDRS   = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
        canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
        conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
@@ -87,7 +87,7 @@ HDRS  = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
        trace.h user_acl.h valid_mailhost_addr.h verify.h verify_clnt.h \
        verp_sender.h wildcard_inet_addr.h xtext.h delivered_hdr.h \
        fold_addr.h header_body_checks.h data_redirect.h match_service.h \
-       addr_match_list.h smtp_reply_footer.h
+       addr_match_list.h smtp_reply_footer.h safe_ultostr.h
 TESTSRC        = rec2stream.c stream2rec.c recdump.c
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
@@ -100,7 +100,7 @@ TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
        quote_821_local mail_conf_time mime_state strip_addr \
        verify_clnt xtext anvil_clnt scache ehlo_mask \
        valid_mailhost_addr own_inet_addr header_body_checks \
-       data_redirect
+       data_redirect addr_match_list safe_ultostr
 
 LIBS   = ../../lib/libutil.a
 LIB_DIR        = ../../lib
@@ -286,6 +286,9 @@ data_redirect: data_redirect.c $(LIB) $(LIBS)
 addr_match_list: addr_match_list.c $(LIB) $(LIBS)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
 
+safe_ultostr: safe_ultostr.c $(LIB) $(LIBS)
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+
 tests: tok822_test mime_tests strip_addr_test tok822_limit_test \
        xtext_test scache_multi_test ehlo_mask_test \
        namadr_list_test mail_conf_time_test header_body_checks_tests
@@ -978,9 +981,12 @@ ext_prop.o: mail_params.h
 file_id.o: ../../include/msg.h
 file_id.o: ../../include/sys_defs.h
 file_id.o: ../../include/vbuf.h
+file_id.o: ../../include/vstream.h
 file_id.o: ../../include/vstring.h
 file_id.o: file_id.c
 file_id.o: file_id.h
+file_id.o: mail_queue.h
+file_id.o: safe_ultostr.h
 flush_clnt.o: ../../include/attr.h
 flush_clnt.o: ../../include/iostuff.h
 flush_clnt.o: ../../include/match_list.h
@@ -1352,6 +1358,7 @@ mail_queue.o: file_id.h
 mail_queue.o: mail_params.h
 mail_queue.o: mail_queue.c
 mail_queue.o: mail_queue.h
+mail_queue.o: safe_ultostr.h
 mail_run.o: ../../include/msg.h
 mail_run.o: ../../include/mymalloc.h
 mail_run.o: ../../include/stringops.h
@@ -1799,6 +1806,13 @@ rewrite_clnt.o: quote_822_local.h
 rewrite_clnt.o: quote_flags.h
 rewrite_clnt.o: rewrite_clnt.c
 rewrite_clnt.o: rewrite_clnt.h
+safe_ultostr.o: ../../include/msg.h
+safe_ultostr.o: ../../include/mymalloc.h
+safe_ultostr.o: ../../include/sys_defs.h
+safe_ultostr.o: ../../include/vbuf.h
+safe_ultostr.o: ../../include/vstring.h
+safe_ultostr.o: safe_ultostr.c
+safe_ultostr.o: safe_ultostr.h
 scache.o: ../../include/argv.h
 scache.o: ../../include/events.h
 scache.o: ../../include/msg.h
index e130087db2467e8b0634a5f95ebaff60d80aa688..c482017ae7266d9da98ee2bb6184ef1ec9a98e91 100644 (file)
@@ -6,26 +6,37 @@
 /* SYNOPSIS
 /*     #include <file_id.h>
 /*
-/*     const char *get_file_id(fd)
+/*     const char *get_file_id_fd(fd, long_flag)
 /*     int     fd;
+/*     int     long_flag;
+/*
+/*     const char *get_file_id_st(st, long_flag)
+/*     struct stat *st;
+/*     int     long_flag;
 /*
-/*     int     check_file_id(fd, id)
+/*     const char *get_file_id(fd)
 /*     int     fd;
-/*     const char *id;
 /* DESCRIPTION
-/*     get_file_id() queries the operating system for the unique identifier
-/*     for the specified file and returns a printable representation.
-/*     The result is volatile.  Make a copy if it is to be used for any
-/*     appreciable amount of time.
+/*     get_file_id_fd() queries the operating system for the unique
+/*     file identifier for the specified file descriptor and returns
+/*     a printable representation.  The result is volatile.  Make
+/*     a copy if it is to be used for any appreciable amount of
+/*     time.
+/*
+/*     get_file_id_st() returns the unique identifier for the
+/*     specified file status information.
 /*
-/*     check_file_id() tests if an open file matches the given
-/*     printable FILE ID representation.
+/*     get_file_id() provides binary compatibility for old programs.
+/*     This function should not be used by new programs.
 /*
 /*     Arguments:
 /* .IP fd
 /*     A valid file descriptor that is associated with an open file.
-/* .IP id
-/*     Printable file ID.
+/* .IP st
+/*     The result from e.g., stat(2) or fstat(2).
+/* .IP long_flag
+/*     Encode the result as appropriate for long or short queue
+/*     identifiers.
 /* DIAGNOSTICS
 /*     All errors are fatal.
 /* LICENSE
 
 /* Global library. */
 
+#define MAIL_QUEUE_INTERNAL
+#include <mail_queue.h>
 #include "file_id.h"
 
-/* get_file_id - lookup file ID, convert to printable form */
+/* get_file_id - binary compatibility */
 
 const char *get_file_id(int fd)
 {
-    static VSTRING *result;
+    return (get_file_id_fd(fd, 0));
+}
+
+/* get_file_id_fd - return printable file identifier for file descriptor */
+
+const char *get_file_id_fd(int fd, int long_flag)
+{
     struct stat st;
 
-    if (result == 0)
-       result = vstring_alloc(1);
     if (fstat(fd, &st) < 0)
        msg_fatal("fstat: %m");
-    vstring_sprintf(result, "%lX", (long) st.st_ino);
-    return (vstring_str(result));
+    return (get_file_id_st(&st, long_flag));
 }
 
-/* check_file_id - make sure file name matches ID */
+/* get_file_id_st - return printable file identifier for file status */
 
-int     check_file_id(int fd, const char *name)
+const char *get_file_id_st(struct stat * st, int long_flag)
 {
-    return (strcmp(get_file_id(fd), name));
+    static VSTRING *result;
+
+    if (result == 0)
+       result = vstring_alloc(1);
+    if (long_flag)
+       return (MQID_LG_ENCODE_INUM(result, st->st_ino));
+    else
+       return (MQID_SH_ENCODE_INUM(result, st->st_ino));
 }
index c954e36bcf9712d51a2020dda27a6169dfa22851..a20b0abface0ebcd217ee8251e890d992621469b 100644 (file)
 /* DESCRIPTION
 /* .nf
 
+ /*
+System library.
+*/
+#include <sys/stat.h>
+
  /* External interface. */
 
+extern const char *get_file_id_fd(int, int);
+extern const char *get_file_id_st(struct stat *, int);
+
+ /* Legacy interface. */
 extern const char *get_file_id(int);
-extern int check_file_id(int, const char *);
 
 /* LICENSE
 /* .ad
index dc744cf7a6cfa51aadb0bbea9336b5fc9ac6684b..009beb49b1a223c26495529c5fb969753c4781fe 100644 (file)
 /*     char    *var_multi_group;
 /*     char    *var_multi_name;
 /*     bool    var_multi_enable;
+/*     bool    var_long_queue_ids;
 /*
 /*     void    mail_params_init()
 /*
@@ -302,6 +303,7 @@ char   *var_multi_wrapper;
 char   *var_multi_group;
 char   *var_multi_name;
 bool    var_multi_enable;
+bool    var_long_queue_ids;
 
 const char null_format_string[1] = "";
 
@@ -627,6 +629,7 @@ void    mail_params_init()
        VAR_HELPFUL_WARNINGS, DEF_HELPFUL_WARNINGS, &var_helpful_warnings,
        VAR_CYRUS_SASL_AUTHZID, DEF_CYRUS_SASL_AUTHZID, &var_cyrus_sasl_authzid,
        VAR_MULTI_ENABLE, DEF_MULTI_ENABLE, &var_multi_enable,
+       VAR_LONG_QUEUE_IDS, DEF_LONG_QUEUE_IDS, &var_long_queue_ids,
        0,
     };
     const char *cp;
index 169a9100ad35f47966680d31ae1bc2bda39fa618..ebd3c2c7b86301d436e7d4f4e86848f71c9fa564 100644 (file)
@@ -910,6 +910,14 @@ extern char *var_hash_queue_names;
 #define DEF_HASH_QUEUE_DEPTH   1
 extern int var_hash_queue_depth;
 
+ /*
+  * Short queue IDs contain the time in microseconds and file inode number.
+  * Long queue IDs also contain the time in seconds.
+  */
+#define VAR_LONG_QUEUE_IDS     "enable_long_queue_ids"
+#define DEF_LONG_QUEUE_IDS     0
+extern bool var_long_queue_ids;
+
  /*
   * Multi-protocol support.
   */
@@ -2988,33 +2996,20 @@ extern char *var_tls_eecdh_ultra;
 #define DEF_TLS_PREEMPT_CLIST  0
 extern bool var_tls_preempt_clist;
 
-#ifdef USE_TLS
-
- /*
-  * The tweak for CVE-2005-2969 is needed in some versions prior to 1.0.0
-  */
+ /* The tweak for CVE-2010-4180 is needed in some versions prior to 1.0.1 */
+ /* The tweak for CVE-2005-2969 is needed in some versions prior to 1.0.0 */
+#if defined(USE_TLS) && (OPENSSL_VERSION_NUMBER < 0x1000100fL)
 #if (OPENSSL_VERSION_NUMBER < 0x1000000fL)
-#define TLS_BUG_TWEAK_A        " CVE-2005-2969"
+#define TLS_BUG_TWEAKS         "CVE-2005-2969 CVE-2010-4180"
 #else
-#define TLS_BUG_TWEAK_A ""
+#define TLS_BUG_TWEAKS         "CVE-2010-4180"
 #endif
-
- /*
-  * The tweak for CVE-2010-4180 is needed in some versions prior to 1.0.1
-  */
-#if (OPENSSL_VERSION_NUMBER < 0x1000100fL)
-#define TLS_BUG_TWEAK_B        " CVE-2010-4180"
 #else
-#define TLS_BUG_TWEAK_B        " "
+#define TLS_BUG_TWEAKS         ""
 #endif
 
-#else                                  /* USE_TLS */
-#define TLS_BUG_TWEAK_A        ""
-#define TLS_BUG_TWEAK_B        " "
-#endif                                 /* USE_TLS */
-
 #define VAR_TLS_BUG_TWEAKS     "tls_disable_workarounds"
-#define DEF_TLS_BUG_TWEAKS     ((TLS_BUG_TWEAK_A TLS_BUG_TWEAK_B)+1)
+#define DEF_TLS_BUG_TWEAKS     TLS_BUG_TWEAKS
 extern char *var_tls_bug_tweaks;
 
  /*
index 0d997080c6aac8aee6d36eb83f544933141b3da3..820b682a915bed6bcc4cffefac1edc356cdc0451 100644 (file)
 
 #include "file_id.h"
 #include "mail_params.h"
+#define MAIL_QUEUE_INTERNAL
 #include "mail_queue.h"
 
 #define STR    vstring_str
@@ -311,6 +312,8 @@ VSTREAM *mail_queue_enter(const char *queue_name, mode_t mode,
                                  struct timeval * tp)
 {
     const char *myname = "mail_queue_enter";
+    static VSTRING *sec_buf;
+    static VSTRING *usec_buf;
     static VSTRING *id_buf;
     static int pid;
     static VSTRING *path_buf;
@@ -326,6 +329,8 @@ VSTREAM *mail_queue_enter(const char *queue_name, mode_t mode,
      */
     if (id_buf == 0) {
        pid = getpid();
+       sec_buf = vstring_alloc(10);
+       usec_buf = vstring_alloc(10);
        id_buf = vstring_alloc(10);
        path_buf = vstring_alloc(10);
        temp_path = vstring_alloc(100);
@@ -366,7 +371,7 @@ VSTREAM *mail_queue_enter(const char *queue_name, mode_t mode,
      * 
      * If someone is racing against us, try to win.
      */
-    file_id = get_file_id(fd);
+    file_id = get_file_id_fd(fd, var_long_queue_ids);
 
     /*
      * XXX Some systems seem to have clocks that correlate with process
@@ -377,7 +382,16 @@ VSTREAM *mail_queue_enter(const char *queue_name, mode_t mode,
      */
     for (count = 0;; count++) {
        GETTIMEOFDAY(tp);
-       vstring_sprintf(id_buf, "%05X%s", (int) tp->tv_usec, file_id);
+       if (var_long_queue_ids) {
+           vstring_sprintf(id_buf, "%s%s%c%s",
+                           MQID_LG_ENCODE_SEC(sec_buf, tp->tv_sec),
+                           MQID_LG_ENCODE_USEC(usec_buf, tp->tv_usec),
+                           MQID_LG_INUM_SEP, file_id);
+       } else {
+           vstring_sprintf(id_buf, "%s%s",
+                           MQID_SH_ENCODE_USEC(usec_buf, tp->tv_usec),
+                           file_id);
+       }
        mail_queue_path(path_buf, queue_name, STR(id_buf));
        if (sane_rename(STR(temp_path), STR(path_buf)) == 0)    /* success */
            break;
index 47cb61bdf329b16ec228574b78adebf096b5a449..a1a0e8b9edde5fbb57d59a55c20fe585a31364ca 100644 (file)
@@ -61,6 +61,105 @@ extern int mail_queue_mkdirs(const char *);
 extern int mail_queue_name_ok(const char *);
 extern int mail_queue_id_ok(const char *);
 
+ /*
+  * MQID - Mail Queue ID format definitions. Needed only by code that creates
+  * or parses queue ID strings.
+  */
+#ifdef MAIL_QUEUE_INTERNAL
+
+ /*
+  * System library.
+  */
+#include <errno.h>
+
+ /*
+  * Global library.
+  */
+#include <safe_ultostr.h>
+
+ /*
+  * The long non-repeating queue ID is encoded in an alphabet of 10 digits,
+  * 21 upper-case characters, and 21 or fewer lower-case characters. The
+  * alphabet is made "safe" by removing all the vowels (AEIOUaeiou). The ID
+  * is the concatenation of:
+  * 
+  * - the time in seconds (base 52 encoded, six or more chars),
+  * 
+  * - the time in microseconds (base 52 encoded, exactly four chars),
+  * 
+  * - the 'z' character to separate the time and inode information,
+  * 
+  * - the inode number (base 51 encoded so that it contains no 'z').
+  */
+#define MQID_LG_SEC_BASE       52      /* seconds safe alphabet base */
+#define MQID_LG_SEC_PAD        6       /* seconds minumum field width */
+#define MQID_LG_USEC_BASE      52      /* microseconds safe alphabet base */
+#define MQID_LG_USEC_PAD       4       /* microseconds exact field width */
+#define MQID_LG_TIME_PAD       (MQID_LG_SEC_PAD + MQID_LG_USEC_PAD)
+#define MQID_LG_INUM_SEP       'z'     /* time-inode separator */
+#define MQID_LG_INUM_BASE      51      /* inode safe alphabet base */
+#define MQID_LG_INUM_PAD       0       /* no padding needed */
+
+#define MQID_FIND_LG_INUM_SEPARATOR(cp, path) \
+       ((cp) = strrchr((path), MQID_LG_INUM_SEP)) != 0 \
+           && ((cp) - (path) >= MQID_LG_TIME_PAD)
+
+#define MQID_GET_INUM(path, inum, long_form, error) do { \
+       char *_cp; \
+       if (((long_form) = MQID_FIND_LG_INUM_SEPARATOR(_cp, (path))) != 0) { \
+           MQID_LG_DECODE_INUM(_cp + 1, (inum), (error)); \
+       } else { \
+           MQID_SH_DECODE_INUM((path) + MQID_SH_USEC_PAD, (inum), (error)); \
+       } \
+    } while (0)
+
+#define MQID_LG_ENCODE_SEC(buf, val) \
+       MQID_LG_ENCODE((buf), (val), MQID_LG_SEC_BASE, MQID_LG_SEC_PAD)
+
+#define MQID_LG_ENCODE_USEC(buf, val) \
+       MQID_LG_ENCODE((buf), (val), MQID_LG_USEC_BASE, MQID_LG_USEC_PAD)
+
+#define MQID_LG_ENCODE_INUM(buf, val) \
+       MQID_LG_ENCODE((buf), (val), MQID_LG_INUM_BASE, MQID_LG_INUM_PAD)
+
+#define MQID_LG_DECODE_INUM(str, ulval, error) \
+       MQID_LG_DECODE((str), (ulval), MQID_LG_INUM_BASE, (error))
+
+#define MQID_LG_ENCODE(buf, val, base, padlen) \
+       safe_ultostr((buf), (unsigned long) (val), (base), (padlen), '0')
+
+#define MQID_LG_DECODE(str, ulval, base, error) do { \
+       char *_end; \
+       errno = 0; \
+       (ulval) = safe_strtoul((str), &_end, (base)); \
+       (error) = (*_end != 0 || ((ulval) == ULONG_MAX && errno == ERANGE)); \
+    } while (0)
+
+ /*
+  * The short repeating queue ID is encoded in upper-case hexadecimal, and is
+  * the concatenation of:
+  * 
+  * - the time in microseconds (exactly five chars),
+  * 
+  * - the inode number.
+  */
+#define MQID_SH_USEC_PAD       5       /* microseconds exact field width */
+
+#define MQID_SH_ENCODE_USEC(buf, usec) \
+       vstring_str(vstring_sprintf((buf), "%05X", (int) (usec)))
+
+#define MQID_SH_ENCODE_INUM(buf, inum) \
+       vstring_str(vstring_sprintf((buf), "%lX", (unsigned long) (inum)))
+
+#define MQID_SH_DECODE_INUM(str, ulval, error) do { \
+        char *_end; \
+       errno = 0; \
+       (ulval) = strtoul((str), &_end, 16); \
+       (error) = (*_end != 0 || ((ulval) == ULONG_MAX && errno == ERANGE)); \
+    } while (0)
+
+#endif                                 /* MAIL_QUEUE_INTERNAL */
+
 /* LICENSE
 /* .ad
 /* .fi
@@ -72,4 +171,4 @@ extern int mail_queue_id_ok(const char *);
 /*     Yorktown Heights, NY 10598, USA
 /*--*/
 
-#endif
+#endif                                 /* _MAIL_QUEUE_H_INCLUDED_ */
index b6924097dbee101538dea72479b3f5b7cd17e86d..692f46cca5332dce2eaa046efeed9e18208d6af8 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      "20110313"
+#define MAIL_RELEASE_DATE      "20110320"
 #define MAIL_VERSION_NUMBER    "2.9"
 
 #ifdef SNAPSHOT
diff --git a/postfix/src/global/safe_ultostr.c b/postfix/src/global/safe_ultostr.c
new file mode 100644 (file)
index 0000000..a16e87b
--- /dev/null
@@ -0,0 +1,239 @@
+/*++
+/* NAME
+/*     safe_ultostr 3
+/* SUMMARY
+/*     convert unsigned long to safe string
+/* SYNOPSIS
+/*     #include <safe_ultostr.h>
+/*
+/*     char    *safe_ultostr(result, ulval, base, padlen, padchar)
+/*     VSTRING *result;
+/*     unsigned long ulval;
+/*     int     base;
+/*     int     padlen;
+/*     int     padchar;
+/*
+/*     unsigned long safe_strtoul(start, end, base)
+/*     const char *start;
+/*     char **end;
+/*     int     base;
+/* DESCRIPTION
+/*     The functions in this module perform conversions between
+/*     unsigned long values and "safe" alphanumerical strings
+/*     (strings with digits, uppercase letters and lowercase
+/*     letters, but without the vowels AEIOUaeiou). Specifically,
+/*     the characters B-Z represent the numbers 10-30, and b-z
+/*     represent 31-51.
+/*
+/*     safe_ultostr() converts an unsigned long value to a safe
+/*     alphanumerical string. This is the reverse of safe_strtoul().
+/*
+/*     safe_strtoul() implements similar functionality as strtoul()
+/*     except that it uses a safe alphanumerical string as input,
+/*     and that it supports no signs or 0/0x prefixes.
+/*
+/*     Arguments:
+/* .IP result
+/*     Buffer for storage of the result of conversion to string.
+/* .IP ulval
+/*     Unsigned long value.
+/* .IP base
+/*     Value between 2 and 52 inclusive.
+/* .IP padlen
+/* .IP padchar
+/*     Left-pad a short result with padchar characters to the
+/*     specified length.  Specify padlen=0 to disable padding.
+/* DIAGNOSTICS
+/*     Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <mymalloc.h>
+
+/* Global library. */
+
+#include <safe_ultostr.h>
+
+/* Application-specific. */
+
+#define STR    vstring_str
+#define END    vstring_end
+#define SWAP(type, a, b) { type temp; temp = a; a = b; b = temp; }
+
+static unsigned char safe_chars[] =
+"0123456789BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz";
+
+#define SAFE_MAX_BASE  (sizeof(safe_chars) - 1)
+#define SAFE_MIN_BASE  (2)
+
+/* safe_ultostr - convert unsigned long to safe alphanumerical string */
+
+char   *safe_ultostr(VSTRING *buf, unsigned long ulval, int base,
+                              int padlen, int padchar)
+{
+    const char *myname = "safe_ultostr";
+    char   *start;
+    char   *last;
+    int     i;
+
+    /*
+     * Sanity check.
+     */
+    if (base < SAFE_MIN_BASE || base > SAFE_MAX_BASE)
+       msg_panic("%s: bad base: %d", myname, base);
+
+    /*
+     * First accumulate the result, backwards.
+     */
+    VSTRING_RESET(buf);
+    while (ulval != 0) {
+       VSTRING_ADDCH(buf, safe_chars[ulval % base]);
+       ulval /= base;
+    }
+    while (VSTRING_LEN(buf) < padlen)
+       VSTRING_ADDCH(buf, padchar);
+    VSTRING_TERMINATE(buf);
+
+    /*
+     * Then, reverse the result.
+     */
+    start = STR(buf);
+    last = END(buf) - 1;
+    for (i = 0; i < VSTRING_LEN(buf) / 2; i++)
+       SWAP(int, start[i], last[-i]);
+    return (STR(buf));
+}
+
+/* safe_strtoul - convert safe alphanumerical string to unsigned long */
+
+unsigned long safe_strtoul(char *start, char **end, int base)
+{
+    const char *myname = "safe_strtoul";
+    static unsigned char *char_map = 0;
+    unsigned char *cp;
+    unsigned long sum;
+    unsigned long div_limit;
+    unsigned long mod_limit;
+    int     char_val;
+
+    /*
+     * Sanity check.
+     */
+    if (base < SAFE_MIN_BASE || base > SAFE_MAX_BASE)
+       msg_panic("%s: bad base: %d", myname, base);
+
+    /*
+     * One-time initialization. Assume 8-bit bytes.
+     */
+    if (char_map == 0) {
+       char_map = (unsigned char *) mymalloc(256);
+       for (char_val = 0; char_val < 256; char_val++)
+           char_map[char_val] = SAFE_MAX_BASE;
+       for (char_val = 0; char_val < SAFE_MAX_BASE; char_val++)
+           char_map[safe_chars[char_val]] = char_val;
+    }
+
+    /*
+     * Per-call initialization.
+     */
+    sum = 0;
+    div_limit = ULONG_MAX / base;
+    mod_limit = ULONG_MAX % base;
+
+    /*
+     * Skip leading whitespace. We don't implement sign/base prefixes.
+     */
+    while (ISSPACE(*start))
+       ++start;
+
+    /*
+     * Start the conversion.
+     */
+    for (cp = (unsigned char *) start; *cp; cp++) {
+       /* Return (0, EINVAL) if no conversion was made. */
+       if ((char_val = char_map[*cp]) >= base) {
+           if (cp == (unsigned char *) start)
+               errno = EINVAL;
+           break;
+       }
+       /* Return (ULONG_MAX, ERANGE) if the result is too large. */
+       if (sum > div_limit
+           || (sum == div_limit && char_val > mod_limit)) {
+           sum = ULONG_MAX;
+           errno = ERANGE;
+           /* Skip "valid" characters, per the strtoul() spec. */
+           while (char_map[*++cp] < base)
+                /* void */ ;
+           break;
+       }
+       sum = sum * base + char_val;
+    }
+    if (end)
+       *end = (char *) cp;
+    return (sum);
+}
+
+#ifdef TEST
+
+ /*
+  * Proof-of-concept test program. Read a number from stdin, convert to
+  * string, and print the result.
+  */
+#include <stdio.h>                     /* sscanf */
+#include <vstream.h>
+#include <vstring_vstream.h>
+
+int     main(int unused_argc, char **unused_argv)
+{
+    VSTRING *buf = vstring_alloc(100);
+    char   *junk;
+    unsigned long ulval;
+    int     base;
+    char    ch;
+    unsigned long ulval2;
+
+#ifdef MISSING_STRTOUL
+#define strtoul strtol
+#endif
+
+    while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) {
+       ch = 0;
+       if (sscanf(STR(buf), "%lu %d%c", &ulval, &base, &ch) != 2 || ch) {
+           msg_warn("bad input %s", STR(buf));
+       } else {
+           (void) safe_ultostr(buf, ulval, base, 5, '0');
+           vstream_printf("%lu = %s\n", ulval, STR(buf));
+           errno = 0;
+           ulval2 = safe_strtoul(STR(buf), &junk, base);
+           if (*junk || (ulval2 == ULONG_MAX && errno == ERANGE))
+               msg_warn("%s: %m", STR(buf));
+           if (ulval2 != ulval)
+               msg_warn("%lu != %lu", ulval2, ulval);
+       }
+       vstream_fflush(VSTREAM_OUT);
+    }
+    vstring_free(buf);
+    return (0);
+}
+
+#endif
diff --git a/postfix/src/global/safe_ultostr.h b/postfix/src/global/safe_ultostr.h
new file mode 100644 (file)
index 0000000..2d88f54
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _SAFE_ULTOSTR_H_INCLUDED_
+#define _SAFE_ULTOSTR_H_INCLUDED_
+
+/*++
+/* NAME
+/*     safe_ultostr 3h
+/* SUMMARY
+/*     convert unsigned long to safe string
+/* SYNOPSIS
+/*     #include <safe_ultostr.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <vstring.h>
+
+ /*
+  * External interface.
+  */
+extern char *safe_ultostr(VSTRING *, unsigned long, int, int, int);
+extern unsigned long safe_strtoul(char *, char **, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
index 0df70b1ad20b5026c1823515c5a532d1da5665ab..7367d601f1b4a716030a92a20aa784d9f773c43e 100644 (file)
@@ -58,6 +58,7 @@ depend: $(MAKES)
 
 # do not edit below this line - it is generated by 'make depend'
 postsuper.o: ../../include/argv.h
+postsuper.o: ../../include/file_id.h
 postsuper.o: ../../include/mail_conf.h
 postsuper.o: ../../include/mail_open_ok.h
 postsuper.o: ../../include/mail_params.h
@@ -68,7 +69,9 @@ postsuper.o: ../../include/msg.h
 postsuper.o: ../../include/msg_syslog.h
 postsuper.o: ../../include/msg_vstream.h
 postsuper.o: ../../include/mymalloc.h
+postsuper.o: ../../include/myrand.h
 postsuper.o: ../../include/safe.h
+postsuper.o: ../../include/safe_ultostr.h
 postsuper.o: ../../include/sane_fsops.h
 postsuper.o: ../../include/scan_dir.h
 postsuper.o: ../../include/set_ugid.h
index 7b6ea74f5f5abf48a22e2472e63dd4a05c532ac4..ea513ddf9c94379833bcaf31442bd03eb702f4f3 100644 (file)
@@ -5,7 +5,7 @@
 /*     Postfix superintendent
 /* SYNOPSIS
 /* .fi
-/*     \fBpostsuper\fR [\fB-psv\fR]
+/*     \fBpostsuper\fR [\fB-psSv\fR]
 /*     [\fB-c \fIconfig_dir\fR] [\fB-d \fIqueue_id\fR]
 /*             [\fB-h \fIqueue_id\fR] [\fB-H \fIqueue_id\fR]
 /*             [\fB-r \fIqueue_id\fR] [\fIdirectory ...\fR]
 /* .RS
 /* .IP \(bu
 /*     Rename files whose name does not match the message file inode
-/*     number. This operation is necessary after restoring a mail queue
-/*     from a different machine, or from backup media.
+/*     number. This operation is necessary after restoring a mail
+/*     queue from a different machine or from backup, when queue
+/*     files were created with Postfix <= 2.8 or with
+/*     "enable_long_queue_ids = no".
 /* .IP \(bu
 /*     Move queue files that are in the wrong place in the file system
 /*     hierarchy and remove subdirectories that are no longer needed.
 /*     File position rearrangements are necessary after a change in the
 /*     \fBhash_queue_names\fR and/or \fBhash_queue_depth\fR
 /*     configuration parameters.
+/* .IP \(bu
+/*     Rename queue files created with "enable_long_queue_ids =
+/*     yes" to short names, for migration to Postfix <= 2.8.  The
+/*     procedure is as follows:
+/* .sp
+/* .nf
+/* .na
+/*     # postfix stop
+/*     # postconf enable_long_queue_ids=no
+/*     # postsuper
+/* .ad
+/* .fi
+/* .sp
+/*     Run \fBpostsuper\fR(1) repeatedly until it stops reporting
+/*     file name changes.
 /* .RE
+/* .IP \fB-S\fR
+/*     A redundant version of \fB-s\fR that requires that long
+/*     file names also match the message file inode number. This
+/*     option exists for testing purposes.
 /* .IP \fB-v\fR
 /*     Enable verbose logging for debugging purposes. Multiple \fB-v\fR
 /*     options make the software increasingly verbose.
 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 /*     The mail system name that is prepended to the process name in syslog
 /*     records, so that "smtpd" becomes, for example, "postfix/smtpd".
+/* .PP
+/*     Available in Postfix version 2.9 and later:
+/* .IP "\fBenable_long_queue_ids (no)\fR"
+/*     Enable long, non-repeating, queue IDs (queue file names).
 /* SEE ALSO
 /*     sendmail(1), Sendmail-compatible user interface
 /*     postqueue(1), unprivileged queue operations
 #include <argv.h>
 #include <vstring_vstream.h>
 #include <sane_fsops.h>
+#include <myrand.h>
 
 /* Global library. */
 
 #include <mail_conf.h>
 #include <mail_params.h>
 #include <mail_version.h>
+#define MAIL_QUEUE_INTERNAL
 #include <mail_queue.h>
 #include <mail_open_ok.h>
+#include <file_id.h>
 
 /* Application-specific. */
 
 #define ACTION_HOLD_ALL        (1<<7)          /* put all messages on hold */
 #define ACTION_RELEASE_ONE (1<<8)      /* release named queue file(s) */
 #define ACTION_RELEASE_ALL (1<<9)      /* release all "on hold" mail */
+#define ACTION_STRUCT_RED (1<<10)      /* fix long queue ID inode fields */
 
 #define ACTION_DEFAULT (ACTION_STRUCT | ACTION_PURGE)
 
@@ -629,12 +658,13 @@ static int operate_stream(VSTREAM *fp,
 /* fix_queue_id - make message queue ID match inode number */
 
 static int fix_queue_id(const char *actual_path, const char *actual_queue,
-                               const char *actual_id, ino_t inum)
+                               const char *actual_id, struct stat * st)
 {
     VSTRING *old_path = vstring_alloc(10);
     VSTRING *new_path = vstring_alloc(10);
     VSTRING *new_id = vstring_alloc(10);
     const char **log_qpp;
+    char   *cp;
     int     ret;
 
     /*
@@ -643,7 +673,15 @@ static int fix_queue_id(const char *actual_path, const char *actual_queue,
      * be deterministic so that we can recover even when the renaming
      * operation is interrupted in the middle.
      */
-    vstring_sprintf(new_id, "%.5s%lX", actual_id, (unsigned long) inum);
+    if (MQID_FIND_LG_INUM_SEPARATOR(cp, actual_id) && var_long_queue_ids) {
+       vstring_sprintf(new_id, "%.*s%c%s",
+                       (int) (cp - actual_id), actual_id, MQID_LG_INUM_SEP,
+                       get_file_id_st(st, 1));
+    } else {
+       vstring_sprintf(new_id, "%0*X%s",
+                       MQID_SH_USEC_PAD, myrand() % 1000000, 
+                       get_file_id_st(st, 0));
+    }
 
     /*
      * Rename logfiles before renaming the message file, so that we can
@@ -690,6 +728,8 @@ static void super(const char **queues, int action)
     char  **cpp;
     struct queue_info *qp;
     unsigned long inum;
+    int     long_name;
+    int     error;
 
     /*
      * Make sure every file is in the right place, clean out stale files, and
@@ -827,7 +867,8 @@ static void super(const char **queues, int action)
                    continue;
                }
                if (MESSAGE_QUEUE(qp)) {
-                   if (sscanf(path + 5, "%lx", &inum) != 1) {
+                   MQID_GET_INUM(path, inum, long_name, error);
+                   if (error) {
                        msg_warn("bogus file name: %s", STR(actual_path));
                        continue;
                    }
@@ -869,16 +910,24 @@ static void super(const char **queues, int action)
             * have to be handled properly. XXX This option cannot use
             * mail_queue_rename(), because the queue file name violates
             * normal queue file syntax.
+            * 
+            * By design there is no need to "fix" non-repeating names. What
+            * follows is applicable only when reverting from long names to
+            * short names, or when migrating short names from one queue to
+            * another.
             */
            if ((action & ACTION_STRUCT) != 0 && MESSAGE_QUEUE(qp)) {
-               if (sscanf(path + 5, "%lx", &inum) != 1) {
+               MQID_GET_INUM(path, inum, long_name, error);
+               if (error) {
                    msg_warn("bogus file name: %s", STR(actual_path));
                    continue;
                }
-               if (inum != (unsigned long) st.st_ino) {
+               if ((long_name != 0 && var_long_queue_ids == 0)
+                   || (inum != (unsigned long) st.st_ino
+                    && (long_name == 0 || (action & ACTION_STRUCT_RED)))) {
                    inode_mismatch++;           /* before we fix */
                    action &= ~ACTIONS_AFTER_INUM_FIX;
-                   fix_queue_id(STR(actual_path), queue_name, path, st.st_ino);
+                   fix_queue_id(STR(actual_path), queue_name, path, &st);
                    /* At this point, path and actual_path are invalidated. */
                    continue;
                }
@@ -1094,7 +1143,7 @@ int     main(int argc, char **argv)
     /*
      * Parse JCL.
      */
-    while ((c = GETOPT(argc, argv, "c:d:h:H:pr:sv")) > 0) {
+    while ((c = GETOPT(argc, argv, "c:d:h:H:pr:sSv")) > 0) {
        switch (c) {
        default:
            msg_fatal("usage: %s "
@@ -1102,8 +1151,8 @@ int     main(int argc, char **argv)
                      "[-d queue_id (delete)] "
                      "[-h queue_id (hold)] [-H queue_id (un-hold)] "
                      "[-p (purge temporary files)] [-r queue_id (requeue)] "
-                     "[-s (structure fix)] [-v (verbose)] "
-                     "[queue...]", argv[0]);
+                     "[-s (structure fix)] [-S (redundant structure fix)]"
+                     "[-v (verbose)] [queue...]", argv[0]);
        case 'c':
            if (*optarg != '/')
                msg_fatal("-c requires absolute pathname");
@@ -1141,6 +1190,9 @@ int     main(int argc, char **argv)
            action |= (strcmp(optarg, "ALL") == 0 ?
                       ACTION_REQUEUE_ALL : ACTION_REQUEUE_ONE);
            break;
+       case 'S':
+           action |= ACTION_STRUCT_RED;
+           /* FALLTHROUGH */
        case 's':
            action |= ACTION_STRUCT;
            break;
index ff23d337b376e16c8ec6da62456f761624b2d39d..9f19808164856088fcf0e00c3f6584bd1c8255ae 100644 (file)
 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
 /*     The mail system name that is prepended to the process name in syslog
 /*     records, so that "smtpd" becomes, for example, "postfix/smtpd".
+/* .PP
+/*     Available in Postfix version 2.9 and later:
+/* .IP "\fBenable_long_queue_ids (no)\fR"
+/*     Enable long, non-repeating, queue IDs (queue file names).
 /* FILES
 /*     /var/spool/postfix, queue directories
 /* SEE ALSO
 int     var_dup_filter_limit;
 char   *var_empty_addr;
 
-#define STRING_FORMAT  "%-10s %8s %-20s %s\n"
-#define SENDER_FORMAT  "%-11s %7ld %20.20s %s\n"
-#define DROP_FORMAT    "%-10s%c %7ld %20.20s (maildrop queue, sender UID %u)\n"
+#define S_STRING_FORMAT        "%-10s %8s %-20s %s\n"
+#define S_SENDER_FORMAT        "%-11s %7ld %20.20s %s\n"
+#define S_DROP_FORMAT  "%-10s%c %7ld %20.20s (maildrop queue, sender UID %u)\n"
+#define S_HEADINGS     "-Queue ID-", "--Size--", \
+                           "----Arrival Time----", "-Sender/Recipient-------"
+
+#define L_STRING_FORMAT        "%-17s %8s %-19s %s\n"
+#define L_SENDER_FORMAT        "%-17s %8ld %19.19s %s\n"
+#define L_DROP_FORMAT  "%-16s%c %8ld %19.19s (maildrop queue, sender UID %u)\n"
+#define L_HEADINGS     "----Queue ID-----", "--Size--", \
+                           "---Arrival Time----", "--Sender/Recipient------"
 
 static void showq_reasons(VSTREAM *, BOUNCE_LOG *, RCPT_BUF *, DSN_BUF *,
                                  HTABLE *);
@@ -198,7 +210,8 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
            printable(STR(printable_quoted_addr), '?');
            /* quote_822_local() saves buf, so we can reuse its space. */
            vstring_sprintf(buf, "%s%c", id, status);
-           vstream_fprintf(client, SENDER_FORMAT, STR(buf),
+           vstream_fprintf(client, var_long_queue_ids ?
+                           L_SENDER_FORMAT : S_SENDER_FORMAT, STR(buf),
                          msg_size > 0 ? msg_size : size, arrival_time > 0 ?
                            asctime(localtime(&arrival_time)) :
                            asctime(localtime(&mtime)),
@@ -211,7 +224,8 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
            printable(STR(printable_quoted_addr), '?');
            if (dup_filter == 0
              || htable_locate(dup_filter, STR(printable_quoted_addr)) == 0)
-               vstream_fprintf(client, STRING_FORMAT,
+               vstream_fprintf(client, var_long_queue_ids ?
+                               L_STRING_FORMAT : S_STRING_FORMAT,
                                "", "", "", STR(printable_quoted_addr));
            break;
        case REC_TYPE_MESG:
@@ -287,7 +301,8 @@ static void showq_reasons(VSTREAM *client, BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf,
                padding = 0;
            vstream_fprintf(client, "%*s(%s)\n", padding, "", saved_reason);
        }
-       vstream_fprintf(client, STRING_FORMAT, "", "", "", rcpt->address);
+       vstream_fprintf(client, var_long_queue_ids ? L_STRING_FORMAT :
+                       S_STRING_FORMAT, "", "", "", rcpt->address);
     }
     if (saved_reason)
        myfree(saved_reason);
@@ -353,12 +368,12 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
            saved_id = mystrdup(id);
            status = mail_open_ok(qp->name, id, &st, &path);
            if (status == MAIL_OPEN_YES) {
-               if (file_count == 0)
-                   vstream_fprintf(client, STRING_FORMAT,
-                                   "-Queue ID-", "--Size--",
-                                   "----Arrival Time----",
-                                   "-Sender/Recipient-------");
-               else
+               if (file_count == 0) {
+                   if (var_long_queue_ids)
+                       vstream_fprintf(client, L_STRING_FORMAT, L_HEADINGS);
+                   else
+                       vstream_fprintf(client, S_STRING_FORMAT, S_HEADINGS);
+               else
                    vstream_fprintf(client, "\n");
                if ((qfile = mail_queue_open(qp->name, id, O_RDONLY, 0)) != 0) {
                    queue_size += st.st_size;
@@ -368,7 +383,8 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
                        msg_warn("close file %s %s: %m", qp->name, id);
                } else if (strcmp(qp->name, MAIL_QUEUE_MAILDROP) == 0) {
                    queue_size += st.st_size;
-                   vstream_fprintf(client, DROP_FORMAT, id, ' ',
+                   vstream_fprintf(client, var_long_queue_ids ?
+                                   L_DROP_FORMAT : S_DROP_FORMAT, id, ' ',
                                    (long) st.st_size,
                                    asctime(localtime(&st.st_mtime)),
                                    (unsigned) st.st_uid);