From 041b9336661ee50ec1e8aedc8faa2580f7fe9feb Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Mon, 19 Aug 2002 00:00:00 -0500 Subject: [PATCH] postfix-1.1.11-20020819 --- postfix/HISTORY | 56 ++++++++- postfix/INSTALL | 9 +- postfix/README_FILES/DEBUG_README | 2 +- postfix/README_FILES/LDAP_README | 2 + postfix/README_FILES/SASL_README | 2 +- postfix/RELEASE_NOTES | 49 +++++--- postfix/html/nqmgr.8.html | 172 ++++++++++++++------------ postfix/html/postcat.1.html | 4 +- postfix/html/qmgr.8.html | 150 +++++++++++----------- postfix/html/queuing.html | 12 +- postfix/html/uce.html | 12 +- postfix/man/man8/nqmgr.8 | 6 + postfix/man/man8/qmgr.8 | 15 +-- postfix/src/bounce/Makefile.in | 3 +- postfix/src/cleanup/Makefile.in | 1 + postfix/src/cleanup/cleanup.h | 1 + postfix/src/cleanup/cleanup_api.c | 8 +- postfix/src/cleanup/cleanup_message.c | 5 + postfix/src/cleanup/cleanup_state.c | 3 + postfix/src/dns/dns_lookup.c | 9 ++ postfix/src/global/Makefile.in | 34 ++++- postfix/src/global/hold_message.c | 91 ++++++++++++++ postfix/src/global/hold_message.h | 30 +++++ postfix/src/global/mail_flush.c | 23 +++- postfix/src/global/mail_flush.h | 1 + postfix/src/global/mail_params.h | 12 +- postfix/src/global/mail_stream.c | 8 +- postfix/src/global/mail_version.h | 2 +- postfix/src/global/mime_8bit.ref | 4 +- postfix/src/global/mime_cvt.in | 83 +++++++++++++ postfix/src/global/mime_cvt.in2 | 83 +++++++++++++ postfix/src/global/mime_cvt.in3 | 83 +++++++++++++ postfix/src/global/mime_cvt.ref | 93 ++++++++++++++ postfix/src/global/mime_cvt.ref2 | 93 ++++++++++++++ postfix/src/global/mime_cvt.ref3 | 93 ++++++++++++++ postfix/src/global/mime_nest.ref | 92 +++++++------- postfix/src/global/mime_state.c | 23 ++-- postfix/src/global/mime_test.ref | 56 ++++----- postfix/src/nqmgr/qmgr.c | 17 +++ postfix/src/nqmgr/qmgr.h | 1 + postfix/src/nqmgr/qmgr_entry.c | 59 +++++++++ postfix/src/nqmgr/qmgr_queue.c | 1 + postfix/src/pickup/pickup.c | 3 + postfix/src/postcat/postcat.c | 10 +- postfix/src/postqueue/postqueue.c | 3 + postfix/src/qmgr/qmgr.c | 28 +++-- postfix/src/qmgr/qmgr.h | 1 + postfix/src/qmgr/qmgr_entry.c | 59 +++++++++ postfix/src/qmgr/qmgr_message.c | 17 --- postfix/src/qmgr/qmgr_queue.c | 1 + postfix/src/smtp/smtp_proto.c | 3 +- postfix/src/smtpd/Makefile.in | 1 + postfix/src/smtpd/smtpd_check.c | 15 ++- postfix/src/smtpstone/Makefile.in | 1 + postfix/src/smtpstone/smtp-sink.c | 134 ++++++++++++++++---- 55 files changed, 1414 insertions(+), 365 deletions(-) create mode 100644 postfix/src/global/hold_message.c create mode 100644 postfix/src/global/hold_message.h create mode 100644 postfix/src/global/mime_cvt.in create mode 100644 postfix/src/global/mime_cvt.in2 create mode 100644 postfix/src/global/mime_cvt.in3 create mode 100644 postfix/src/global/mime_cvt.ref create mode 100644 postfix/src/global/mime_cvt.ref2 create mode 100644 postfix/src/global/mime_cvt.ref3 diff --git a/postfix/HISTORY b/postfix/HISTORY index 105ef60ed..82c867d87 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -6776,14 +6776,64 @@ Apologies for any names omitted. global/bounce_log.c, global/bounce.c, bounce/bounce.c, bounce/bounce_notify_util.c, bounce/bounce_one_service.c. +20020809 + + Bugfix: the 20020531 bugfix could prepend '.' to lines when + it shouldn't (but only when converting 8-bit mail to 7-bit). + Problem experienced by Ralf Hildebrandt. File: + smtp/smtp_proto.c. + + Bugfix: smtpd_sender_login_maps did not do the @domain etc. + wild-card lookups that were promised. Problem experienced + by Sven Michels. File: smtpd/smtpd_check.c. + +20020810 + + Feature: new smtp-sink command-line options to specify the + SMTP hostname, to disable ESMTP protocol support, to + disable 8BITMIME support, and to syslog selected commands. + File: smtpstone/smtp-sink.c. + +20020814 + + Feature: the queue manager now warns when mail for some + destination is piling up in the active queue, and suggests + a variety of remedies. The qmgr_clog_warn_time parameter + controls the time between warnings, mainly so that I could + test the code. To disable these warnings, specify + "qmgr_clog_warn_time = 0". Files: *qmgr/qmgr_entry.c. + +20020815 + + Paranoia: truncate the DNS response length result value in + case it is larger than the result buffer length (the resolver + documentation is vague about this). File: dns/dns_lookup.c. + +20020816 + + Cleanup: "postqueue -f" now also trigger delivery of mail + in the maildrop directory. This is needed when the master + does not frequently wake up the pickup service. Files: + global/mail_flush.c, postqueue/postqueue.c. + +20020818 + + Cleanup: the qmgr_site_hog_factor feature is gone (defer + mail if a site uses up too much space in the active queue). + Instead, the qmgr_clog_warn_time feature provides better + solutions. File: qmgr/qmgr_message.c. + +20020819 + + Feature: new header/body_checks HOLD pattern that causes + mail to be placed on the "hold" queue for manual inspection. + Files: global/hold_message.[hc], cleanup/cleanup_message.c. + Open problems: Medium: should permit_mx_backup defer delivery if DNS has some error of some kind? - Medium: old maildrop files are no longer readable by the - pickup service. Log a message that suggests a fix. - Low: all table lookups should consistently use internalized (unquoted) or externalized (quoted) forms as lookup keys. smtpd, qmgr, local, etc. use unquoted address forms as diff --git a/postfix/INSTALL b/postfix/INSTALL index b495c125a..5ff2c83c1 100644 --- a/postfix/INSTALL +++ b/postfix/INSTALL @@ -49,6 +49,7 @@ If your system is supported, it is one of AIX 3.2.5 AIX 4.1.x AIX 4.2.0 + AIX 4.3.x BSD/OS 2.x BSD/OS 3.x BSD/OS 4.x @@ -64,27 +65,29 @@ If your system is supported, it is one of IRIX 6.x Linux Debian 1.3.1 Linux Debian 2.x + Linux RedHat 3.x (August 2002) Linux RedHat 4.x Linux RedHat 5.x Linux RedHat 6.x Linux RedHat 7.x - Linux Slackware 3.x + Linux Slackware 3.x (long ago) Linux Slackware 4.x Linux Slackware 7.x Linux SuSE 5.x Linux SuSE 6.x Linux SuSE 7.x Mac OS X - NEXTSTEP 3.x + NEXTSTEP 3.x (long ago) NetBSD 1.x OPENSTEP 4.x OSF1.V3 (Digital UNIX) OSF1.V4 aka Digital UNIX V4 OSF1.V5 aka Digital UNIX V5 OpenBSD 2.x + OpenBSD 3.x Reliant UNIX 5.x Rhapsody 5.x - SunOS 4.1.x (with Postfix 1.1.0) + SunOS 4.1.x (July 2002) SunOS 5.4..5.8 (Solaris 2.4..8) Ultrix 4.x (well, that was long ago) diff --git a/postfix/README_FILES/DEBUG_README b/postfix/README_FILES/DEBUG_README index 31466eb2e..0721c5137 100644 --- a/postfix/README_FILES/DEBUG_README +++ b/postfix/README_FILES/DEBUG_README @@ -83,7 +83,7 @@ Edit the debugger_command definition in /etc/postfix/main.cf so that it invokes the call tracer of your choice, for example: debugger_command = - PATH=/bin:/usr/bin:/usr/local/bin + PATH=/bin:/usr/bin:/usr/local/bin; (truss -p $process_id 2>&1 | logger -p mail.info) & sleep 5 Type "postfix reload" and watch the logfile. diff --git a/postfix/README_FILES/LDAP_README b/postfix/README_FILES/LDAP_README index 0b4dd869b..6f158d7b0 100644 --- a/postfix/README_FILES/LDAP_README +++ b/postfix/README_FILES/LDAP_README @@ -13,6 +13,8 @@ having to copy it to each. BUILDING WITH LDAP SUPPORT ========================== +Note: Postfix no longer supports the LDAP version 1 interface. + You need to have LDAP libraries and include files installed somewhere on your system, and you need to configure the Postfix Makefiles accordingly. diff --git a/postfix/README_FILES/SASL_README b/postfix/README_FILES/SASL_README index ee4f042ad..19e5ae95d 100644 --- a/postfix/README_FILES/SASL_README +++ b/postfix/README_FILES/SASL_README @@ -140,7 +140,7 @@ IMPORTANT: postfix processes need to have group read+execute permission for the /var/pwcheck directory, otherwise authentication attempts will fail. -Alternately, in SASL 1.5.27 and later (including 2.1.1), try: +Alternately, in SASL 1.5.5 and later (including 2.1.1), try: (SASL version 1.5.5) /usr/local/lib/sasl/smtpd.conf: diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index a8c522f77..58ec18c3a 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -12,40 +12,57 @@ snapshot release). Patches change the patchlevel and the release date. Snapshots change only the release date, unless they include the same bugfixes as a patch release. -Incompatible changes with Postfix snapshot 1.1.11-20020804 -========================================================== +Incompatible changes with Postfix snapshot 1.1.11-2002018 +========================================================= + +The qmgr_site_hog_factor feature is gone (this would defer mail +delivery for sites that occupy too much space in the active queue, +and be a real performance drain due to excessive disk I/O). The +new qmgr_clog_warn_time feature (see below) provides more useful +suggestions for dealing with Postfix congestion. LDAP API version 1 is no longer supported. The memory allocation and deallocation strategy has changed too much to maintain both version 1 and 2 at the same time. In mailq output, the queue ID is followed by the ! character when -the message is in the "hold" queue. This may break programs that -process mailq output. +the message is in the "hold" queue (see below). This may break +programs that process mailq output. The "permit_naked_ip_address" restriction on HELO command syntax -is unsafe when used with smtpd_recipient_restrictions, and will go -away. The user is requested to use "permit_mynetworks" instead. +is unsafe when used with most smtpd_XXX_restrictions, and will go +away. The user is now requested to use "permit_mynetworks" instead. The smtpd_sasl_local_domain setting now defaults to the null string, rather than $myhostname. This seems to work better with Cyrus SASL version 2. This change may cause incompatibility with the saslpasswd2 command. -Major changes with Postfix snapshot 1.1.11-20020804 +Major changes with Postfix snapshot 1.1.11-20020818 =================================================== -New "hold" queue for mail that should not be delivered. "postqueue --h" puts mail on hold, and "postqueue -H" releases mail, moving +When the Postfix local delivery agent detects a mail delivery loop +(usually the result of mis-configured mail pickup software), the +undeliverable mail is now sent to the mailing list owner instead +of the envelope sender address (usually the original poster who +has no guilt, and who cannot fix the problem). + +New "hold" queue for mail that should not be delivered. "postsuper +-h" puts mail on hold, and "postsuper -H" releases mail, moving mail that was "on hold" to the deferred queue. -Mail is now sent to the mailing list owner when Postfix detects a -Delivered-To: mail delivery loop. Delivery loops happen when idiots -forward mail that was already stored in a mailbox, setting the -envelope recipient address to the To: address (so that mail would -loop back to the mailing list), and setting the envelope sender -address to the From: address (so that the error report would be -sent to the poster). +New header/body HOLD action that causes mail to be placed on the +"hold" queue. Presently, all you can do with mail "on hold" is to +examine it with postcat, to take it "off hold" with "postsuper -H", +or to destroy it with "postsuper -d". See conf/sample-filter.cf. + +The Postfix queue manager now warns when mail for some destination +is piling up in the active queue, and suggests a variety of remedies +to speed up delivery (increase per-destination concurrency limit, +increase active queue size, use a separate delivery transport, +increase per-transport process limit). The qmgr_clog_warn_time +parameter controls the time between warnings. To disable these +warnings, specify "qmgr_clog_warn_time = 0". Incompatible changes with Postfix snapshot 1.1.11-20020717 ========================================================== diff --git a/postfix/html/nqmgr.8.html b/postfix/html/nqmgr.8.html index 6d2af0cf8..3c16b5889 100644 --- a/postfix/html/nqmgr.8.html +++ b/postfix/html/nqmgr.8.html @@ -44,36 +44,39 @@ NQMGR(8) NQMGR(8) Unreadable or damaged queue files are moved here for inspection. + hold Messages that are kept "on hold" are kept here + until someone sets them free. + DELIVERY STATUS REPORTS The nqmgr daemon keeps an eye on per-message delivery sta- - tus reports in the following directories. Each status + tus reports in the following directories. Each status report file has the same name as the corresponding message file: - bounce Per-recipient status information about why mail is - bounced. These files are maintained by the + bounce Per-recipient status information about why mail is + bounced. These files are maintained by the bounce(8) daemon. - defer Per-recipient status information about why mail is - delayed. These files are maintained by the + defer Per-recipient status information about why mail is + delayed. These files are maintained by the defer(8) daemon. - The nqmgr daemon is responsible for asking the bounce(8) + The nqmgr daemon is responsible for asking the bounce(8) or defer(8) daemons to send non-delivery reports. STRATEGIES - The queue manager implements a variety of strategies for + The queue manager implements a variety of strategies for either opening queue files (input) or for message delivery (output). leaky bucket - This strategy limits the number of messages in the - active queue and prevents the queue manager from + This strategy limits the number of messages in the + active queue and prevents the queue manager from running out of memory under heavy load. fairness - When the active queue has room, the queue manager - takes one message from the incoming queue and one + When the active queue has room, the queue manager + takes one message from the incoming queue and one from the deferred queue. This prevents a large mail backlog from blocking the delivery of new mail. @@ -84,42 +87,42 @@ NQMGR(8) NQMGR(8) round robin The queue manager sorts delivery requests by desti- - nation. Round-robin selection prevents one desti- + nation. Round-robin selection prevents one desti- nation from dominating deliveries to other destina- tions. exponential backoff Mail that cannot be delivered upon the first - attempt is deferred. The time interval between + attempt is deferred. The time interval between delivery attempts is doubled after each attempt. destination status cache - The queue manager avoids unnecessary delivery - attempts by maintaining a short-term, in-memory + The queue manager avoids unnecessary delivery + attempts by maintaining a short-term, in-memory list of unreachable destinations. preemptive message scheduling - The queue manager attempts to minimize the average + The queue manager attempts to minimize the average per-recipient delay while still preserving the cor- rect per-message delays, using a sophisticated pre- emptive message scheduling. TRIGGERS On an idle system, the queue manager waits for the arrival - of trigger events, or it waits for a timer to go off. A - trigger is a one-byte message. Depending on the message - received, the queue manager performs one of the following - actions (the message is followed by the symbolic constant + of trigger events, or it waits for a timer to go off. A + trigger is a one-byte message. Depending on the message + received, the queue manager performs one of the following + actions (the message is followed by the symbolic constant used internally by the software): D (QMGR_REQ_SCAN_DEFERRED) - Start a deferred queue scan. If a deferred queue - scan is already in progress, that scan will be + Start a deferred queue scan. If a deferred queue + scan is already in progress, that scan will be restarted as soon as it finishes. I (QMGR_REQ_SCAN_INCOMING) - Start an incoming queue scan. If an incoming queue - scan is already in progress, that scan will be + Start an incoming queue scan. If an incoming queue + scan is already in progress, that scan will be restarted as soon as it finishes. A (QMGR_REQ_SCAN_ALL) @@ -127,32 +130,32 @@ NQMGR(8) NQMGR(8) affects the next deferred queue scan. F (QMGR_REQ_FLUSH_DEAD) - Purge all information about dead transports and + Purge all information about dead transports and destinations. W (TRIGGER_REQ_WAKEUP) - Wakeup call, This is used by the master server to - instantiate servers that should not go away for- - ever. The action is to start an incoming queue + Wakeup call, This is used by the master server to + instantiate servers that should not go away for- + ever. The action is to start an incoming queue scan. The nqmgr daemon reads an entire buffer worth of triggers. - Multiple identical trigger requests are collapsed into - one, and trigger requests are sorted so that A and F pre- - cede D and I. Thus, in order to force a deferred queue + Multiple identical trigger requests are collapsed into + one, and trigger requests are sorted so that A and F pre- + cede D and I. Thus, in order to force a deferred queue run, one would request A F D; in order to notify the queue manager of the arrival of new mail one would request I. STANDARDS - None. The nqmgr daemon does not interact with the outside + None. The nqmgr daemon does not interact with the outside world. SECURITY - The nqmgr daemon is not security sensitive. It reads sin- - gle-character messages from untrusted local users, and - thus may be susceptible to denial of service attacks. The - nqmgr daemon does not talk to the outside world, and it - can be run at fixed low privilege in a chrooted environ- + The nqmgr daemon is not security sensitive. It reads sin- + gle-character messages from untrusted local users, and + thus may be susceptible to denial of service attacks. The + nqmgr daemon does not talk to the outside world, and it + can be run at fixed low privilege in a chrooted environ- ment. DIAGNOSTICS @@ -160,25 +163,25 @@ NQMGR(8) NQMGR(8) Corrupted message files are saved to the corrupt queue for further inspection. - Depending on the setting of the notify_classes parameter, - the postmaster is notified of bounces and of other trou- + Depending on the setting of the notify_classes parameter, + the postmaster is notified of bounces and of other trou- ble. BUGS - A single queue manager process has to compete for disk - access with multiple front-end processes such as smtpd. A - sudden burst of inbound mail can negatively impact out- + A single queue manager process has to compete for disk + access with multiple front-end processes such as smtpd. A + sudden burst of inbound mail can negatively impact out- bound delivery rates. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this program. See the Postfix main.cf file for syntax - details and for default values. Use the postfix reload + The following main.cf parameters are especially relevant + to this program. See the Postfix main.cf file for syntax + details and for default values. Use the postfix reload command after a configuration change. Miscellaneous allow_min_user - Do not bounce recipient addresses that begin with + Do not bounce recipient addresses that begin with '-'. relocated_maps @@ -189,16 +192,21 @@ NQMGR(8) NQMGR(8) Top-level directory of the Postfix queue. Active queue controls - In the text below, transport is the first field in a mas- + In the text below, transport is the first field in a mas- ter.cf entry. + qmgr_clog_warn_time + Minimal delay between warnings that a specific des- + tination is clogging up the active queue. Specify 0 + to disable. + qmgr_message_active_limit Limit the number of messages in the active queue. qmgr_message_recipient_limit Limit the number of in-memory recipients. - This parameter also limits the size of the short- + This parameter also limits the size of the short- term, in-memory destination cache. qmgr_message_recipient_minimum @@ -209,34 +217,34 @@ NQMGR(8) NQMGR(8) per transport. transport_recipient_limit - Limit on the number of in-memory recipients, for + Limit on the number of in-memory recipients, for the named message transport. default_extra_recipient_limit - Default limit on the total number of per transport - in-memory recipients that the preempting messages + Default limit on the total number of per transport + in-memory recipients that the preempting messages can have. transport_extra_recipient_limit - Limit on the number of in-memory recipients which - all preempting messages delivered by the transport + Limit on the number of in-memory recipients which + all preempting messages delivered by the transport transport can have. Timing controls minimal_backoff_time - Minimal time in seconds between delivery attempts + Minimal time in seconds between delivery attempts of a deferred message. - This parameter also limits the time an unreachable - destination is kept in the short-term, in-memory + This parameter also limits the time an unreachable + destination is kept in the short-term, in-memory destination status cache. maximal_backoff_time - Maximal time in seconds between delivery attempts + Maximal time in seconds between delivery attempts of a deferred message. maximal_queue_lifetime - Maximal time in days a message is queued before it + Maximal time in days a message is queued before it is sent back as undeliverable. queue_run_delay @@ -244,52 +252,52 @@ NQMGR(8) NQMGR(8) scans do not overlap. transport_retry_time - Time in seconds between attempts to contact a bro- + Time in seconds between attempts to contact a bro- ken delivery transport. Concurrency controls initial_destination_concurrency - Initial per-destination concurrency level for par- + Initial per-destination concurrency level for par- allel delivery to the same destination. default_destination_concurrency_limit - Default limit on the number of parallel deliveries + Default limit on the number of parallel deliveries to the same destination. transport_destination_concurrency_limit - Limit on the number of parallel deliveries to the - same destination, for delivery via the named mes- + Limit on the number of parallel deliveries to the + same destination, for delivery via the named mes- sage transport. Recipient controls default_destination_recipient_limit - Default limit on the number of recipients per mes- + Default limit on the number of recipients per mes- sage transfer. transport_destination_recipient_limit - Limit on the number of recipients per message + Limit on the number of recipients per message transfer, for the named message transport. Message scheduling transport_delivery_slot_cost (valid range: 0,2,3...) - This parameter basically controls how often a mes- - sage delivered by transport can be preempted by + This parameter basically controls how often a mes- + sage delivered by transport can be preempted by another message. An internal per-message/transport - counter is incremented by one for each trans- + counter is incremented by one for each trans- port_delivery_slot_cost deliveries handled by - transport. This counter represents the number of - "available delivery slots" for use by other mes- + transport. This counter represents the number of + "available delivery slots" for use by other mes- sages. Current message can be preempted by another - message when that other message can be delivered - using less transport agents than the value of the + message when that other message can be delivered + using less transport agents than the value of the "available delivery slots" counter. - Value equal to 0 disables the message preemption + Value equal to 0 disables the message preemption for transport. transport_minimum_delivery_slots Message preemption is not attempted at all whenever - a message that can't ever accumulate at least + a message that can't ever accumulate at least transport_minimum_delivery_slots available delivery slots is being delivered by transport. @@ -297,13 +305,13 @@ NQMGR(8) NQMGR(8) transport_delivery_slot_loan These parameters speed up the moment when a message - preemption can happen. Instead of waiting until - the full amount of delivery slots required is - available, the preemption can happen when trans- + preemption can happen. Instead of waiting until + the full amount of delivery slots required is + available, the preemption can happen when trans- port_delivery_slot_discount percent of the required - amount plus transport_delivery_slot_loan still - remains to be accumulated. Note that the full - amount will still have to be accumulated before + amount plus transport_delivery_slot_loan still + remains to be accumulated. Note that the full + amount will still have to be accumulated before another preemption can take place later. default_delivery_slot_cost @@ -313,7 +321,7 @@ NQMGR(8) NQMGR(8) default_delivery_slot_discount default_delivery_slot_loan - Default values for the transport specific parame- + Default values for the transport specific parame- ters described above. SEE ALSO @@ -323,7 +331,7 @@ NQMGR(8) NQMGR(8) trivial-rewrite(8), address routing LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/postcat.1.html b/postfix/html/postcat.1.html index a2b89ddf4..94e6d8ee0 100644 --- a/postfix/html/postcat.1.html +++ b/postfix/html/postcat.1.html @@ -1,5 +1,4 @@
-
 POSTCAT(1)                                             POSTCAT(1)
 
 NAME
@@ -33,6 +32,5 @@ POSTCAT(1)                                             POSTCAT(1)
        P.O. Box 704
        Yorktown Heights, NY 10598, USA
 
-                                                                1
-
+                                                       POSTCAT(1)
 
diff --git a/postfix/html/qmgr.8.html b/postfix/html/qmgr.8.html index 2ca5e6b72..6dc1e6f53 100644 --- a/postfix/html/qmgr.8.html +++ b/postfix/html/qmgr.8.html @@ -44,36 +44,39 @@ QMGR(8) QMGR(8) Unreadable or damaged queue files are moved here for inspection. + hold Messages that are kept "on hold" are kept here + until someone sets them free. + DELIVERY STATUS REPORTS - The qmgr daemon keeps an eye on per-message delivery sta- - tus reports in the following directories. Each status + The qmgr daemon keeps an eye on per-message delivery sta- + tus reports in the following directories. Each status report file has the same name as the corresponding message file: - bounce Per-recipient status information about why mail is - bounced. These files are maintained by the + bounce Per-recipient status information about why mail is + bounced. These files are maintained by the bounce(8) daemon. - defer Per-recipient status information about why mail is - delayed. These files are maintained by the + defer Per-recipient status information about why mail is + delayed. These files are maintained by the defer(8) daemon. The qmgr daemon is responsible for asking the bounce(8) or defer(8) daemons to send non-delivery reports. STRATEGIES - The queue manager implements a variety of strategies for + The queue manager implements a variety of strategies for either opening queue files (input) or for message delivery (output). leaky bucket - This strategy limits the number of messages in the - active queue and prevents the queue manager from + This strategy limits the number of messages in the + active queue and prevents the queue manager from running out of memory under heavy load. fairness - When the active queue has room, the queue manager - takes one message from the incoming queue and one + When the active queue has room, the queue manager + takes one message from the incoming queue and one from the deferred queue. This prevents a large mail backlog from blocking the delivery of new mail. @@ -84,36 +87,36 @@ QMGR(8) QMGR(8) round robin The queue manager sorts delivery requests by desti- - nation. Round-robin selection prevents one desti- + nation. Round-robin selection prevents one desti- nation from dominating deliveries to other destina- tions. exponential backoff Mail that cannot be delivered upon the first - attempt is deferred. The time interval between + attempt is deferred. The time interval between delivery attempts is doubled after each attempt. destination status cache - The queue manager avoids unnecessary delivery - attempts by maintaining a short-term, in-memory + The queue manager avoids unnecessary delivery + attempts by maintaining a short-term, in-memory list of unreachable destinations. TRIGGERS On an idle system, the queue manager waits for the arrival - of trigger events, or it waits for a timer to go off. A - trigger is a one-byte message. Depending on the message - received, the queue manager performs one of the following - actions (the message is followed by the symbolic constant + of trigger events, or it waits for a timer to go off. A + trigger is a one-byte message. Depending on the message + received, the queue manager performs one of the following + actions (the message is followed by the symbolic constant used internally by the software): D (QMGR_REQ_SCAN_DEFERRED) - Start a deferred queue scan. If a deferred queue - scan is already in progress, that scan will be + Start a deferred queue scan. If a deferred queue + scan is already in progress, that scan will be restarted as soon as it finishes. I (QMGR_REQ_SCAN_INCOMING) - Start an incoming queue scan. If an incoming queue - scan is already in progress, that scan will be + Start an incoming queue scan. If an incoming queue + scan is already in progress, that scan will be restarted as soon as it finishes. A (QMGR_REQ_SCAN_ALL) @@ -121,30 +124,30 @@ QMGR(8) QMGR(8) affects the next deferred queue scan. F (QMGR_REQ_FLUSH_DEAD) - Purge all information about dead transports and + Purge all information about dead transports and destinations. W (TRIGGER_REQ_WAKEUP) - Wakeup call, This is used by the master server to - instantiate servers that should not go away for- - ever. The action is to start an incoming queue + Wakeup call, This is used by the master server to + instantiate servers that should not go away for- + ever. The action is to start an incoming queue scan. - The qmgr daemon reads an entire buffer worth of triggers. - Multiple identical trigger requests are collapsed into - one, and trigger requests are sorted so that A and F pre- - cede D and I. Thus, in order to force a deferred queue + The qmgr daemon reads an entire buffer worth of triggers. + Multiple identical trigger requests are collapsed into + one, and trigger requests are sorted so that A and F pre- + cede D and I. Thus, in order to force a deferred queue run, one would request A F D; in order to notify the queue manager of the arrival of new mail one would request I. STANDARDS - None. The qmgr daemon does not interact with the outside + None. The qmgr daemon does not interact with the outside world. SECURITY - The qmgr daemon is not security sensitive. It reads sin- - gle-character messages from untrusted local users, and - thus may be susceptible to denial of service attacks. The + The qmgr daemon is not security sensitive. It reads sin- + gle-character messages from untrusted local users, and + thus may be susceptible to denial of service attacks. The qmgr daemon does not talk to the outside world, and it can be run at fixed low privilege in a chrooted environment. @@ -153,25 +156,25 @@ QMGR(8) QMGR(8) Corrupted message files are saved to the corrupt queue for further inspection. - Depending on the setting of the notify_classes parameter, - the postmaster is notified of bounces and of other trou- + Depending on the setting of the notify_classes parameter, + the postmaster is notified of bounces and of other trou- ble. BUGS - A single queue manager process has to compete for disk - access with multiple front-end processes such as smtpd. A - sudden burst of inbound mail can negatively impact out- + A single queue manager process has to compete for disk + access with multiple front-end processes such as smtpd. A + sudden burst of inbound mail can negatively impact out- bound delivery rates. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this program. See the Postfix main.cf file for syntax - details and for default values. Use the postfix reload + The following main.cf parameters are especially relevant + to this program. See the Postfix main.cf file for syntax + details and for default values. Use the postfix reload command after a configuration change. Miscellaneous allow_min_user - Do not bounce recipient addresses that begin with + Do not bounce recipient addresses that begin with '-'. relocated_maps @@ -182,30 +185,35 @@ QMGR(8) QMGR(8) Top-level directory of the Postfix queue. Active queue controls + qmgr_clog_warn_time + Minimal delay between warnings that a specific des- + tination is clogging up the active queue. Specify 0 + to disable. + qmgr_message_active_limit Limit the number of messages in the active queue. qmgr_message_recipient_limit Limit the number of in-memory recipients. - This parameter also limits the size of the short- + This parameter also limits the size of the short- term, in-memory destination cache. Timing controls minimal_backoff_time - Minimal time in seconds between delivery attempts + Minimal time in seconds between delivery attempts of a deferred message. - This parameter also limits the time an unreachable - destination is kept in the short-term, in-memory + This parameter also limits the time an unreachable + destination is kept in the short-term, in-memory destination status cache. maximal_backoff_time - Maximal time in seconds between delivery attempts + Maximal time in seconds between delivery attempts of a deferred message. maximal_queue_lifetime - Maximal time in days a message is queued before it + Maximal time in days a message is queued before it is sent back as undeliverable. queue_run_delay @@ -213,40 +221,28 @@ QMGR(8) QMGR(8) scans do not overlap. transport_retry_time - Time in seconds between attempts to contact a bro- + Time in seconds between attempts to contact a bro- ken delivery transport. Concurrency controls - In the text below, transport is the first field in a mas- + In the text below, transport is the first field in a mas- ter.cf entry. qmgr_fudge_factor (valid range: 10..100) - The percentage of delivery resources that a busy - mail system will use up for delivery of a large - mailing list message. With 100%, delivery of one - message does not begin before the previous message - has been delivered. This results in good perfor- - mance for large mailing lists, but results in poor - response time for one-to-one mail. With less than - 100%, response time for one-to-one mail improves, - but large mailing list delivery performance suf- - fers. In the worst case, recipients near the begin- - ning of a large list receive a burst of messages - immediately, while recipients near the end of that - list receive that same burst of messages a whole - day later. - - qmgr_site_hog_factor (valid range: 10..100) The percentage of delivery resources that a busy - mail system will use up for delivery to a single - site. With 100%, mail is delivered in first-in, - first-out order, so that a burst of mail for one - site can block mail for other destinations. With - less than 100%, the excess mail is deferred. The - deferred mail is delivered in little bursts, the - remainder of the backlog being deferred again, with - a lot of I/O activity happening as Postfix searches - the deferred queue for deliverable mail. + mail system will use up for delivery of a large + mailing list message. With 100%, delivery of one + message does not begin before the previous message + has been delivered. This results in good perfor- + mance for large mailing lists, but results in poor + response time for one-to-one mail. With less than + 100%, response time for one-to-one mail improves, + but large mailing list delivery performance suf- + fers. In the worst case, recipients near the begin- + ning of a large list receive a burst of messages + immediately, while recipients near the end of that + list receive that same burst of messages a whole + day later. initial_destination_concurrency Initial per-destination concurrency level for par- diff --git a/postfix/html/queuing.html b/postfix/html/queuing.html index 13652fb2c..ee3387df0 100644 --- a/postfix/html/queuing.html +++ b/postfix/html/queuing.html @@ -20,7 +20,7 @@ and features | Global architecture

Postfix mail queues

-Postfix has four different queues: maildrop, incoming, +Postfix has four main queues: maildrop, incoming, active and deferred (click the upper left-hand icon for the big picture). Locally-posted mail is deposited into the maildrop, and is copied to the incoming queue after @@ -42,6 +42,16 @@ peak message workload. Whenever there is space in the guarantees that new mail will get through even when there is a large backlog. +

+ +In addition to the queues mentioned above Postfix also maintains +two parking spaces. The hold queue is for mail that is frozen +in the queue; no delivery attempts are made until someone releases +these messages with the postsuper +command. The corrupt directory is for damaged queue files. +Rather than discarding these, Postfix leaves them here for human +inspection. +

No thundering herd

Implementing a high-performance mail system is one thing. However, diff --git a/postfix/html/uce.html b/postfix/html/uce.html index e04e44781..5532378ec 100644 --- a/postfix/html/uce.html +++ b/postfix/html/uce.html @@ -134,6 +134,11 @@ the originator.
IGNORE
Delete the header from the message. +
HOLD
Place the message on the hold queue. Mail on +hold can be inspected with the postcat +command, and can be destroyed or taken off hold with the postsuper command. +
WARN
Log (but do not reject) the header with a warning.
WARN text...
As above, and also log the text. @@ -211,6 +216,11 @@ the originator.
IGNORE
Delete the matched line from the message. +
HOLD
Place the message on the hold queue. Mail on +hold can be inspected with the postcat +command, and can be destroyed or taken off hold with the postsuper command. +
WARN
Log (but do not reject) the matched line with a warning.
WARN text...
As above, and also log the text. @@ -1219,7 +1229,7 @@ appear as part of a client hostname/address restriction list.
Default: -
maps_rbl_domains = blackholes.mail-abuse.org +
maps_rbl_domains =

diff --git a/postfix/man/man8/nqmgr.8 b/postfix/man/man8/nqmgr.8 index 84a783f40..a343f92a2 100644 --- a/postfix/man/man8/nqmgr.8 +++ b/postfix/man/man8/nqmgr.8 @@ -45,6 +45,9 @@ manager implements exponential backoff by doubling the time between delivery attempts. .IP \fBcorrupt\fR Unreadable or damaged queue files are moved here for inspection. +.IP \fBhold\fR +Messages that are kept "on hold" are kept here until someone +sets them free. .SH DELIVERY STATUS REPORTS .na .nf @@ -185,6 +188,9 @@ Top-level directory of the Postfix queue. .fi In the text below, \fItransport\fR is the first field in a \fBmaster.cf\fR entry. +.IP \fBqmgr_clog_warn_time\fR +Minimal delay between warnings that a specific destination +is clogging up the active queue. Specify 0 to disable. .IP \fBqmgr_message_active_limit\fR Limit the number of messages in the active queue. .IP \fBqmgr_message_recipient_limit\fR diff --git a/postfix/man/man8/qmgr.8 b/postfix/man/man8/qmgr.8 index 44b1492c6..f54801953 100644 --- a/postfix/man/man8/qmgr.8 +++ b/postfix/man/man8/qmgr.8 @@ -45,6 +45,9 @@ manager implements exponential backoff by doubling the time between delivery attempts. .IP \fBcorrupt\fR Unreadable or damaged queue files are moved here for inspection. +.IP \fBhold\fR +Messages that are kept "on hold" are kept here until someone +sets them free. .SH DELIVERY STATUS REPORTS .na .nf @@ -179,6 +182,9 @@ Top-level directory of the Postfix queue. .SH "Active queue controls" .ad .fi +.IP \fBqmgr_clog_warn_time\fR +Minimal delay between warnings that a specific destination +is clogging up the active queue. Specify 0 to disable. .IP \fBqmgr_message_active_limit\fR Limit the number of messages in the active queue. .IP \fBqmgr_message_recipient_limit\fR @@ -223,15 +229,6 @@ but large mailing list delivery performance suffers. In the worst case, recipients near the beginning of a large list receive a burst of messages immediately, while recipients near the end of that list receive that same burst of messages a whole day later. -.IP "\fBqmgr_site_hog_factor\fR (valid range: 10..100)" -The percentage of delivery resources that a busy mail system will -use up for delivery to a single site. -With 100%, mail is delivered in first-in, first-out order, so that -a burst of mail for one site can block mail for other destinations. -With less than 100%, the excess mail is deferred. The deferred mail -is delivered in little bursts, the remainder of the backlog being -deferred again, with a lot of I/O activity happening as Postfix -searches the deferred queue for deliverable mail. .IP \fBinitial_destination_concurrency\fR Initial per-destination concurrency level for parallel delivery to the same destination. diff --git a/postfix/src/bounce/Makefile.in b/postfix/src/bounce/Makefile.in index 8eed9c27c..bd8451ea5 100644 --- a/postfix/src/bounce/Makefile.in +++ b/postfix/src/bounce/Makefile.in @@ -168,11 +168,10 @@ bounce_one_service.o: ../../include/vstream.h bounce_one_service.o: ../../include/vbuf.h bounce_one_service.o: ../../include/name_mask.h bounce_one_service.o: ../../include/mail_params.h -bounce_one_service.o: ../../include/mail_queue.h -bounce_one_service.o: ../../include/vstring.h bounce_one_service.o: ../../include/post_mail.h bounce_one_service.o: ../../include/cleanup_user.h bounce_one_service.o: ../../include/mail_addr.h bounce_one_service.o: ../../include/mail_error.h bounce_one_service.o: bounce_service.h +bounce_one_service.o: ../../include/vstring.h bounce_one_service.o: ../../include/bounce_log.h diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index 8872993dc..7a7ab688d 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -321,6 +321,7 @@ cleanup_message.o: ../../include/iostuff.h cleanup_message.o: ../../include/attr.h cleanup_message.o: ../../include/mime_state.h cleanup_message.o: ../../include/lex_822.h +cleanup_message.o: ../../include/hold_message.h cleanup_message.o: cleanup.h cleanup_message.o: ../../include/maps.h cleanup_message.o: ../../include/dict.h diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index 389361d42..c795b350f 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -35,6 +35,7 @@ typedef struct CLEANUP_STATE { VSTRING *temp2; /* scratch buffer, local use only */ VSTREAM *dst; /* current output stream */ MAIL_STREAM *handle; /* mail stream handle */ + char *queue_name; /* queue name */ char *queue_id; /* queue file basename */ time_t time; /* posting time */ char *fullname; /* envelope sender full name */ diff --git a/postfix/src/cleanup/cleanup_api.c b/postfix/src/cleanup/cleanup_api.c index 80cac48e3..9b6e39b60 100644 --- a/postfix/src/cleanup/cleanup_api.c +++ b/postfix/src/cleanup/cleanup_api.c @@ -123,8 +123,12 @@ CLEANUP_STATE *cleanup_open(void) /* * Open the queue file. Save the queue file name in a global variable, so * that the runtime error handler can clean up in case of problems. + * + * XXX For now, a lot of detail is frozen that could be more useful if it + * were made configurable. */ - state->handle = mail_stream_file(MAIL_QUEUE_INCOMING, + state->queue_name = mystrdup(MAIL_QUEUE_INCOMING); + state->handle = mail_stream_file(state->queue_name, MAIL_CLASS_PUBLIC, var_queue_service, 0); state->dst = state->handle->stream; cleanup_path = mystrdup(VSTREAM_PATH(state->dst)); @@ -235,7 +239,7 @@ int cleanup_flush(CLEANUP_STATE *state) "cleanup", state->time, "%s", state->reason ? state->reason : cleanup_strerror(state->errs)) == 0 - && bounce_flush(BOUNCE_FLAG_CLEAN, MAIL_QUEUE_INCOMING, + && bounce_flush(BOUNCE_FLAG_CLEAN, state->queue_name, state->queue_id, (encoding = nvtable_find(state->attr, MAIL_ATTR_ENCODING)) ? encoding : MAIL_ATTR_ENC_NONE, diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index e93eb91c9..faa2ab66a 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -80,6 +80,7 @@ #include #include #include +#include /* Application-specific. */ @@ -313,6 +314,10 @@ static int cleanup_act(CLEANUP_STATE *state, char *context, const char *buf, if (STREQUAL(value, "IGNORE", command_len)) return (CLEANUP_ACT_DROP); + if (STREQUAL(value, "HOLD", command_len)) { + hold_message(state->queue_name, state->queue_id); + return (CLEANUP_ACT_KEEP); + } if (STREQUAL(value, "OK", command_len)) return (CLEANUP_ACT_KEEP); diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index f2944f471..1e7bb8890 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -60,6 +60,7 @@ CLEANUP_STATE *cleanup_state_alloc(void) state->temp2 = vstring_alloc(10); state->dst = 0; state->handle = 0; + state->queue_name = 0; state->queue_id = 0; state->time = 0; state->fullname = 0; @@ -115,6 +116,8 @@ void cleanup_state_free(CLEANUP_STATE *state) myfree(state->errors_to); argv_free(state->recipients); argv_free(state->resent_recip); + if (state->queue_name) + myfree(state->queue_name); if (state->queue_id) myfree(state->queue_id); been_here_free(state->dups); diff --git a/postfix/src/dns/dns_lookup.c b/postfix/src/dns/dns_lookup.c index 68a161417..b1a17fba5 100644 --- a/postfix/src/dns/dns_lookup.c +++ b/postfix/src/dns/dns_lookup.c @@ -187,6 +187,15 @@ static int dns_query(const char *name, int type, int flags, if (msg_verbose) msg_info("dns_query: %s (%s): OK", name, dns_strtype(type)); + /* + * Paranoia. + */ + if (len > sizeof(reply->buf)) { + msg_warn("reply length %d > buffer length %d for name=%s type=%s", + len, sizeof(reply->buf), name, dns_strtype(type)); + len = sizeof(reply->buf); + } + /* * Initialize the reply structure. Some structure members are filled on * the fly while the reply is being parsed. diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 9b3cba78d..ecfabc29e 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -20,7 +20,7 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \ tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \ flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \ verp_sender.c match_parent_style.c mime_state.c header_token.c \ - strip_addr.c virtual8_maps_find.c + strip_addr.c virtual8_maps_find.c hold_message.c OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \ debug_peer.o debug_process.o defer.o deliver_completed.o \ deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \ @@ -42,7 +42,7 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \ tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \ flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \ verp_sender.o match_parent_style.o mime_state.o header_token.o \ - strip_addr.o virtual8_maps_find.o + strip_addr.o virtual8_maps_find.o hold_message.o HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \ config.h debug_peer.h debug_process.h defer.h deliver_completed.h \ deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \ @@ -60,7 +60,7 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \ sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \ mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \ match_parent_style.h quote_flags.h mime_state.h header_token.h \ - lex_822.h strip_addr.h virtual8.h + lex_822.h strip_addr.h virtual8.h hold_message.h TESTSRC = rec2stream.c stream2rec.c recdump.c WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \ @@ -233,7 +233,8 @@ virtual8_maps_find: $(LIB) $(LIBS) mv junk $@.o tests: tok822_test mime_test mime_nest mime_8bit mime_dom mime_trunc \ - strip_addr_test tok822_limit_test virtual8_test + mime_cvt mime_cvt2 mime_cvt3 strip_addr_test tok822_limit_test \ + virtual8_test tok822_test: tok822_parse tok822_parse.in tok822_parse.ref ./tok822_parse tok822_parse.tmp @@ -265,6 +266,21 @@ mime_trunc: mime_state mime_trunc.in mime_trunc.ref diff mime_trunc.ref mime_trunc.tmp rm -f mime_trunc.tmp +mime_cvt: mime_state mime_cvt.in mime_cvt.ref + ./mime_state mime_cvt.tmp + diff mime_cvt.ref mime_cvt.tmp + rm -f mime_cvt.tmp + +mime_cvt2: mime_state mime_cvt.in2 mime_cvt.ref2 + ./mime_state mime_cvt.tmp + diff mime_cvt.ref2 mime_cvt.tmp + rm -f mime_cvt.tmp + +mime_cvt3: mime_state mime_cvt.in3 mime_cvt.ref3 + ./mime_state mime_cvt.tmp + diff mime_cvt.ref3 mime_cvt.tmp + rm -f mime_cvt.tmp + tok822_limit_test: tok822_parse tok822_limit.in tok822_limit.ref ./tok822_parse tok822_limit.tmp diff tok822_limit.ref tok822_limit.tmp @@ -512,6 +528,16 @@ header_token.o: ../../include/vstring.h header_token.o: ../../include/vbuf.h header_token.o: lex_822.h header_token.o: header_token.h +hold_message.o: hold_message.c +hold_message.o: ../../include/sys_defs.h +hold_message.o: ../../include/msg.h +hold_message.o: ../../include/set_eugid.h +hold_message.o: mail_queue.h +hold_message.o: ../../include/vstring.h +hold_message.o: ../../include/vbuf.h +hold_message.o: ../../include/vstream.h +hold_message.o: mail_params.h +hold_message.o: hold_message.h is_header.o: is_header.c is_header.o: ../../include/sys_defs.h is_header.o: is_header.h diff --git a/postfix/src/global/hold_message.c b/postfix/src/global/hold_message.c new file mode 100644 index 000000000..241a021b2 --- /dev/null +++ b/postfix/src/global/hold_message.c @@ -0,0 +1,91 @@ +/*++ +/* NAME +/* hold_message 3 +/* SUMMARY +/* move message to hold queue +/* SYNOPSIS +/* #include +/* +/* void hold_message(queue_name, queue_id) +/* const char *queue_name; +/* const char *queue_id; +/* DESCRIPTION +/* The \fBhold_message\fR() routine moves the specified +/* queue file to the \fBhold\fR queue, where it will sit +/* until someone either destroys it or releases it. +/* 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 +#include /* rename() */ +#include +#include +#include + +/* Utility library. */ + +#include +#include + +/* Global library. */ + +#include +#include +#include + +#define STR(x) vstring_str(x) + +/* hold_message - move message to hold queue */ + +void hold_message(const char *queue_name, const char *queue_id) +{ + VSTRING *old_path = vstring_alloc(100); + VSTRING *new_path = vstring_alloc(100); + uid_t saved_uid; + gid_t saved_gid; + + /* + * If not running as the mail system, change privileges first. + */ + if ((saved_uid = geteuid()) != var_owner_uid) { + saved_gid = getegid(); + set_eugid(var_owner_uid, var_owner_gid); + } + + /* + * Grr. Don't do stupid things when this function is called multiple + * times. sane_rename() would emit a bogus warning about spurious NFS + * problems. + */ + (void) mail_queue_path(old_path, queue_name, queue_id); + (void) mail_queue_path(new_path, MAIL_QUEUE_HOLD, queue_id); + if (access(STR(old_path), F_OK) == 0) { + if (rename(STR(old_path), STR(new_path)) == 0 + || access(STR(new_path), F_OK) == 0) + msg_info("%s: placed on hold", queue_id); + else + msg_warn("%s: could not place message on hold: %m", queue_id); + } + + /* + * Restore privileges. + */ + if (saved_uid != var_owner_uid) + set_eugid(saved_uid, saved_gid); + + /* + * Cleanup. + */ + vstring_free(old_path); + vstring_free(new_path); +} diff --git a/postfix/src/global/hold_message.h b/postfix/src/global/hold_message.h new file mode 100644 index 000000000..0092c8ca0 --- /dev/null +++ b/postfix/src/global/hold_message.h @@ -0,0 +1,30 @@ +#ifndef _HOLD_MESSAGE_H_INCLUDED_ +#define _HOLD_MESSAGE_H_INCLUDED_ + +/*++ +/* NAME +/* hold_message 3h +/* SUMMARY +/* mark queue file as corrupt +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * External interface. + */ +extern void hold_message(const char *, const char *); + +/* 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 diff --git a/postfix/src/global/mail_flush.c b/postfix/src/global/mail_flush.c index 33f765e87..cfa9c3254 100644 --- a/postfix/src/global/mail_flush.c +++ b/postfix/src/global/mail_flush.c @@ -7,11 +7,17 @@ /* #include /* /* int mail_flush_deferred() +/* +/* int mail_flush_maildrop() /* DESCRIPTION /* This module triggers delivery of backed up mail. /* /* mail_flush_deferred() triggers delivery of all deferred -/* or incoming mail. +/* or incoming mail. This function tickles the queue manager. +/* +/* mail_flush_maildrop() triggers delivery of all mail in +/* the maildrop directory. This function tickles the pickup +/* service. /* DIAGNOSTICS /* The result is 0 in case of success, -1 in case of failure. /* LICENSE @@ -37,7 +43,7 @@ #include #include -/* mail_flush_deferred - flush deferred queue */ +/* mail_flush_deferred - flush deferred/incoming queue */ int mail_flush_deferred(void) { @@ -54,3 +60,16 @@ int mail_flush_deferred(void) return (mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service, qmgr_trigger, sizeof(qmgr_trigger))); } + +/* mail_flush_maildrop - flush maildrop queue */ + +int mail_flush_maildrop(void) +{ + static char wakeup[] = {TRIGGER_REQ_WAKEUP}; + + /* + * Trigger the pickup service. + */ + return (mail_trigger(MAIL_CLASS_PUBLIC, var_pickup_service, + wakeup, sizeof(wakeup))); +} diff --git a/postfix/src/global/mail_flush.h b/postfix/src/global/mail_flush.h index 9d951682f..03f3945f6 100644 --- a/postfix/src/global/mail_flush.h +++ b/postfix/src/global/mail_flush.h @@ -14,6 +14,7 @@ /* External interface. */ extern int mail_flush_deferred(void); +extern int mail_flush_maildrop(void); /* LICENSE /* .ad diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 7c6cce559..eeb44f325 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -542,10 +542,6 @@ extern int var_min_delivery_slots; #define DEF_QMGR_FUDGE 100 extern int var_qmgr_fudge; -#define VAR_QMGR_HOG "qmgr_site_hog_factor" -#define DEF_QMGR_HOG 100 -extern int var_qmgr_hog; - /* * Queue manager: default destination concurrency levels. */ @@ -588,6 +584,14 @@ extern int var_transport_retry_time; #define DEF_DEFER_XPORTS "" extern char *var_defer_xports; + /* + * Queue manager: how often to warn that a destination is clogging the + * active queue. + */ +#define VAR_QMGR_CLOG_WARN_TIME "qmgr_clog_warn_time" +#define DEF_QMGR_CLOG_WARN_TIME "300s" +extern int var_qmgr_clog_warn_time; + /* * Master: default process count limit per mail subsystem. */ diff --git a/postfix/src/global/mail_stream.c b/postfix/src/global/mail_stream.c index 74a8ada8c..6e4812e03 100644 --- a/postfix/src/global/mail_stream.c +++ b/postfix/src/global/mail_stream.c @@ -133,10 +133,10 @@ static int mail_stream_finish_file(MAIL_STREAM * info, VSTRING *unused_why) * take effect before all the data blocks are written. Wietse claims that * this is not a problem. Postfix rejects incomplete queue files, even * when the +x attribute is set. Every Postfix queue file record has a - * type code and a length field. Files with truncated records are - * rejected, as are files with unknown type codes. Every Postfix queue - * file must end with an explicit END record. Postfix queue files without - * END record are discarded. + * type code and a length field. Files with missing records are rejected, + * as are files with unknown record type codes. Every Postfix queue file + * must end with an explicit END record. Postfix queue files without END + * record are discarded. */ if (vstream_fflush(info->stream) || fchmod(vstream_fileno(info->stream), 0700 | info->mode) diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 74542bfe1..a3f5d3564 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ -#define MAIL_RELEASE_DATE "20020804" +#define MAIL_RELEASE_DATE "20020819" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "1.1.11-" MAIL_RELEASE_DATE diff --git a/postfix/src/global/mime_8bit.ref b/postfix/src/global/mime_8bit.ref index 0e70ac9b3..e9d6eae09 100644 --- a/postfix/src/global/mime_8bit.ref +++ b/postfix/src/global/mime_8bit.ref @@ -1,9 +1,9 @@ mime_state: warning: improper use of 8-bit data in message header: Header: f??bar MAIN Header: f€€bar HEADER END -BODY +BODY N mime_state: warning: improper use of 8-bit data in message body: b?dy -BODY b€dy +BODY N b€dy BODY END mime_state: warning: improper use of 8-bit data in message header mime_state: warning: improper use of 8-bit data in message body diff --git a/postfix/src/global/mime_cvt.in b/postfix/src/global/mime_cvt.in new file mode 100644 index 000000000..f3b73217b --- /dev/null +++ b/postfix/src/global/mime_cvt.in @@ -0,0 +1,83 @@ +mime-version: 1.0 +content-type: text/plain +content-transfer-encoding: 8bit + + +x +xx +xxx +xxxx +xxxxx +xxxxxx +xxxxxxx +xxxxxxxx +xxxxxxxxx +xxxxxxxxxx +xxxxxxxxxxx +xxxxxxxxxxxx +xxxxxxxxxxxxx +xxxxxxxxxxxxxx +xxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/postfix/src/global/mime_cvt.in2 b/postfix/src/global/mime_cvt.in2 new file mode 100644 index 000000000..c7b35ae97 --- /dev/null +++ b/postfix/src/global/mime_cvt.in2 @@ -0,0 +1,83 @@ +mime-version: 1.0 +content-type: text/plain +content-transfer-encoding: 8bit + + +x +xx +xxx +xxxx +xxxxx +xxxxxx +xxxxxxx +xxxxxxxx +xxxxxxxxx +xxxxxxxxxx +xxxxxxxxxxx +xxxxxxxxxxxx +xxxxxxxxxxxxx +xxxxxxxxxxxxxx +xxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/postfix/src/global/mime_cvt.in3 b/postfix/src/global/mime_cvt.in3 new file mode 100644 index 000000000..31621b6c2 --- /dev/null +++ b/postfix/src/global/mime_cvt.in3 @@ -0,0 +1,83 @@ +mime-version: 1.0 +content-type: text/plain +content-transfer-encoding: 8bit + + +x +xx +xxx +xxxx +xxxxx +xxxxxx +xxxxxxx +xxxxxxxx +xxxxxxxxx +xxxxxxxxxx +xxxxxxxxxxx +xxxxxxxxxxxx +xxxxxxxxxxxxx +xxxxxxxxxxxxxx +xxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/postfix/src/global/mime_cvt.ref b/postfix/src/global/mime_cvt.ref new file mode 100644 index 000000000..a6e0227c2 --- /dev/null +++ b/postfix/src/global/mime_cvt.ref @@ -0,0 +1,93 @@ +MAIN mime-version: 1.0 +mime_state: header_token: text / plain +MAIN content-type: text/plain +mime_state: header_token: 8bit +MAIN Content-Transfer-Encoding: quoted-printable +HEADER END +BODY N +BODY N =20 +BODY N x=20 +BODY N xx=20 +BODY N xxx=20 +BODY N xxxx=20 +BODY N xxxxx=20 +BODY N xxxxxx=20 +BODY N xxxxxxx=20 +BODY N xxxxxxxx=20 +BODY N xxxxxxxxx=20 +BODY N xxxxxxxxxx=20 +BODY N xxxxxxxxxxx=20 +BODY N xxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N =20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N x=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xxxx=20 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xxxxx=20 +BODY END diff --git a/postfix/src/global/mime_cvt.ref2 b/postfix/src/global/mime_cvt.ref2 new file mode 100644 index 000000000..fa0d00a43 --- /dev/null +++ b/postfix/src/global/mime_cvt.ref2 @@ -0,0 +1,93 @@ +MAIN mime-version: 1.0 +mime_state: header_token: text / plain +MAIN content-type: text/plain +mime_state: header_token: 8bit +MAIN Content-Transfer-Encoding: quoted-printable +HEADER END +BODY N +BODY N =09 +BODY N x=09 +BODY N xx=09 +BODY N xxx=09 +BODY N xxxx=09 +BODY N xxxxx=09 +BODY N xxxxxx=09 +BODY N xxxxxxx=09 +BODY N xxxxxxxx=09 +BODY N xxxxxxxxx=09 +BODY N xxxxxxxxxx=09 +BODY N xxxxxxxxxxx=09 +BODY N xxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N =09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N x=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xxxx=09 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xxxxx=09 +BODY END diff --git a/postfix/src/global/mime_cvt.ref3 b/postfix/src/global/mime_cvt.ref3 new file mode 100644 index 000000000..a5b4f64d8 --- /dev/null +++ b/postfix/src/global/mime_cvt.ref3 @@ -0,0 +1,93 @@ +MAIN mime-version: 1.0 +mime_state: header_token: text / plain +MAIN content-type: text/plain +mime_state: header_token: 8bit +MAIN Content-Transfer-Encoding: quoted-printable +HEADER END +BODY N +BODY N =01 +BODY N x=01 +BODY N xx=01 +BODY N xxx=01 +BODY N xxxx=01 +BODY N xxxxx=01 +BODY N xxxxxx=01 +BODY N xxxxxxx=01 +BODY N xxxxxxxx=01 +BODY N xxxxxxxxx=01 +BODY N xxxxxxxxxx=01 +BODY N xxxxxxxxxxx=01 +BODY N xxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N =01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N x=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xxxx=01 +BODY N xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= +BODY N xxxxx=01 +BODY END diff --git a/postfix/src/global/mime_nest.ref b/postfix/src/global/mime_nest.ref index dd1a92fdd..d1e32cb37 100644 --- a/postfix/src/global/mime_nest.ref +++ b/postfix/src/global/mime_nest.ref @@ -3,140 +3,140 @@ mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MAIN content-type: multipart/mixed; boundary=foobar HEADER END -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: PUSH boundary foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar mime_state: header_token: multipart / mixed mime_state: header_token: boundary = foobar mime_state: warning: MIME nesting exceeds safety limit: content-type: multipart/mixed; boundary=foobar MULT content-type: multipart/mixed; boundary=foobar -BODY -BODY --foobar +BODY N +BODY N --foobar BODY END mime_state: warning: MIME nesting exceeds safety limit mime_state: POP boundary foobar diff --git a/postfix/src/global/mime_state.c b/postfix/src/global/mime_state.c index badec42f6..b5cf003fa 100644 --- a/postfix/src/global/mime_state.c +++ b/postfix/src/global/mime_state.c @@ -618,12 +618,12 @@ static void mime_state_downgrade(MIME_STATE *state, int rec_type, { static char hexchars[] = "0123456789ABCDEF"; const unsigned char *cp; - int ch = 0; + int ch; -#define QP_ENCODE(state, ch) { \ - VSTRING_ADDCH(state->output_buffer, '='); \ - VSTRING_ADDCH(state->output_buffer, hexchars[(ch >> 4) & 0xff]); \ - VSTRING_ADDCH(state->output_buffer, hexchars[ch & 0xf]); \ +#define QP_ENCODE(buffer, ch) { \ + VSTRING_ADDCH(buffer, '='); \ + VSTRING_ADDCH(buffer, hexchars[(ch >> 4) & 0xff]); \ + VSTRING_ADDCH(buffer, hexchars[ch & 0xf]); \ } /* @@ -634,6 +634,7 @@ static void mime_state_downgrade(MIME_STATE *state, int rec_type, /* Critical length before hard line break. */ if (LEN(state->output_buffer) > 72) { VSTRING_ADDCH(state->output_buffer, '='); + VSTRING_TERMINATE(state->output_buffer); state->body_out(state->app_context, REC_TYPE_NORM, STR(state->output_buffer), LEN(state->output_buffer)); @@ -642,7 +643,7 @@ static void mime_state_downgrade(MIME_STATE *state, int rec_type, /* Append the next character. */ ch = *cp; if ((ch < 32 && ch != '\t') || ch == '=' || ch > 126) { - QP_ENCODE(state, ch); + QP_ENCODE(state->output_buffer, ch); } else { VSTRING_ADDCH(state->output_buffer, ch); } @@ -654,13 +655,13 @@ static void mime_state_downgrade(MIME_STATE *state, int rec_type, * the output length will grow from 73 characters to 75 characters. */ if (rec_type == REC_TYPE_NORM) { - if (ch == 0 && LEN(state->output_buffer) > 0) - ch = END(state->output_buffer)[-1]; - if (ch == ' ' || ch == '\t') { + if (LEN(state->output_buffer) > 0 + && ((ch = END(state->output_buffer)[-1]) == ' ' || ch == '\t')) { vstring_truncate(state->output_buffer, LEN(state->output_buffer) - 1); - QP_ENCODE(state, ch); + QP_ENCODE(state->output_buffer, ch); } + VSTRING_TERMINATE(state->output_buffer); state->body_out(state->app_context, REC_TYPE_NORM, STR(state->output_buffer), LEN(state->output_buffer)); @@ -1034,7 +1035,7 @@ static void body_out(void *context, int rec_type, const char *buf, int len) { VSTREAM *stream = (VSTREAM *) context; - vstream_fprintf(stream, "BODY\t"); + vstream_fprintf(stream, "BODY %c\t", rec_type); vstream_fwrite(stream, buf, len); if (rec_type == REC_TYPE_NORM) VSTREAM_PUTC('\n', stream); diff --git a/postfix/src/global/mime_test.ref b/postfix/src/global/mime_test.ref index 614574ff0..ef36f7810 100644 --- a/postfix/src/global/mime_test.ref +++ b/postfix/src/global/mime_test.ref @@ -5,13 +5,13 @@ mime_state: PUSH boundary abcd ef MAIN content-type: multipart/(co\m\)ment)mumble mumble; boundary = "ab\cd ef" mumble HEADER END -BODY -BODY abcdef prolog -BODY -BODY --abcd ef +BODY N +BODY N abcdef prolog +BODY N +BODY N --abcd ef mime_state: header_token: message / rfc822 MULT content-type: message/rfc822; mumble -BODY +BODY N NEST subject: nested subject mime_state: header_token: multipart / mumble mime_state: header_token: boundary = pqrs @@ -20,33 +20,33 @@ NEST content-type: multipart/mumble; boundary(comment)="pqrs" mime_state: header_token: base64 NEST content-transfer-encoding: base64 mime_state: warning: invalid message/* or multipart/* encoding domain: base64 -BODY -BODY pqrs prolog -BODY -BODY --pqrs +BODY N +BODY N pqrs prolog +BODY N +BODY N --pqrs MULT header: pqrs part 01 -BODY -BODY body pqrs part 01 -BODY -BODY --pqrs +BODY N +BODY N body pqrs part 01 +BODY N +BODY N --pqrs MULT header: pqrs part 02 -BODY -BODY body pqrs part 02 -BODY -BODY --bogus-boundary -BODY header: wietse -BODY -BODY body asdasads -BODY +BODY N +BODY N body pqrs part 02 +BODY N +BODY N --bogus-boundary +BODY N header: wietse +BODY N +BODY N body asdasads +BODY N mime_state: POP boundary pqrs -BODY --abcd ef +BODY N --abcd ef MULT header: abcdef part 02 -BODY -BODY body abcdef part 02 -BODY +BODY N +BODY N body abcdef part 02 +BODY N mime_state: POP boundary abcd ef -BODY --abcd ef-- -BODY -BODY epilog +BODY N --abcd ef-- +BODY N +BODY N epilog BODY END mime_state: warning: improper message/* or multipart/* encoding domain diff --git a/postfix/src/nqmgr/qmgr.c b/postfix/src/nqmgr/qmgr.c index 7da725d3d..57f65cac4 100644 --- a/postfix/src/nqmgr/qmgr.c +++ b/postfix/src/nqmgr/qmgr.c @@ -37,6 +37,9 @@ /* delivery attempts. /* .IP \fBcorrupt\fR /* Unreadable or damaged queue files are moved here for inspection. +/* .IP \fBhold\fR +/* Messages that are kept "on hold" are kept here until someone +/* sets them free. /* DELIVERY STATUS REPORTS /* .ad /* .fi @@ -161,6 +164,9 @@ /* .fi /* In the text below, \fItransport\fR is the first field in a /* \fBmaster.cf\fR entry. +/* .IP \fBqmgr_clog_warn_time\fR +/* Minimal delay between warnings that a specific destination +/* is clogging up the active queue. Specify 0 to disable. /* .IP \fBqmgr_message_active_limit\fR /* Limit the number of messages in the active queue. /* .IP \fBqmgr_message_recipient_limit\fR @@ -338,6 +344,7 @@ int var_local_rcpt_lim; int var_proc_limit; bool var_verp_bounce_off; bool var_sender_routing; +int var_qmgr_clog_warn_time; static QMGR_SCAN *qmgr_incoming; static QMGR_SCAN *qmgr_deferred; @@ -502,6 +509,15 @@ static void qmgr_pre_init(char *unused_name, char **unused_argv) static void qmgr_post_init(char *unused_name, char **unused_argv) { + /* + * Sanity check. + */ + if (var_qmgr_rcpt_limit < var_qmgr_active_limit) { + msg_warn("%s is smaller than %s", + VAR_QMGR_RCPT_LIMIT, VAR_QMGR_ACT_LIMIT); + var_qmgr_rcpt_limit = var_qmgr_active_limit; + } + /* * This routine runs after the skeleton code has entered the chroot jail. * Prevent automatic process suicide after a limited number of client @@ -539,6 +555,7 @@ int main(int argc, char **argv) VAR_MAX_BACKOFF_TIME, DEF_MAX_BACKOFF_TIME, &var_max_backoff_time, 1, 0, VAR_MAX_QUEUE_TIME, DEF_MAX_QUEUE_TIME, &var_max_queue_time, 1, 8640000, VAR_XPORT_RETRY_TIME, DEF_XPORT_RETRY_TIME, &var_transport_retry_time, 1, 0, + VAR_QMGR_CLOG_WARN_TIME, DEF_QMGR_CLOG_WARN_TIME, &var_qmgr_clog_warn_time, 0, 0, 0, }; static CONFIG_INT_TABLE int_table[] = { diff --git a/postfix/src/nqmgr/qmgr.h b/postfix/src/nqmgr/qmgr.h index 9607268f6..16505f6e4 100644 --- a/postfix/src/nqmgr/qmgr.h +++ b/postfix/src/nqmgr/qmgr.h @@ -190,6 +190,7 @@ struct QMGR_QUEUE { QMGR_ENTRY_LIST busy; /* messages on the wire */ QMGR_QUEUE_LIST peers; /* neighbor queues */ char *reason; /* why unavailable */ + time_t clog_time_to_warn; /* time of last warning */ int blocker_tag; /* tagged if blocks job list */ }; diff --git a/postfix/src/nqmgr/qmgr_entry.c b/postfix/src/nqmgr/qmgr_entry.c index 64cec0b28..e1e733f2a 100644 --- a/postfix/src/nqmgr/qmgr_entry.c +++ b/postfix/src/nqmgr/qmgr_entry.c @@ -253,6 +253,9 @@ QMGR_ENTRY *qmgr_entry_create(QMGR_PEER *peer, QMGR_MESSAGE *message) if (queue->window == 0) msg_panic("qmgr_entry_create: dead queue: %s", queue->name); + /* + * Create the delivery request. + */ entry = (QMGR_ENTRY *) mymalloc(sizeof(QMGR_ENTRY)); entry->stream = 0; entry->message = message; @@ -264,5 +267,61 @@ QMGR_ENTRY *qmgr_entry_create(QMGR_PEER *peer, QMGR_MESSAGE *message) entry->queue = queue; QMGR_LIST_APPEND(queue->todo, entry, queue_peers); queue->todo_refcount++; + + /* + * Warn if a destination is falling behind while the active queue + * contains a non-trivial amount of single-recipient email. When a + * destination takes up more and more space in the active queue, then + * other mail will not get through and delivery performance will suffer. + * + * XXX At this point in the code, the busy reference count is still less + * than the concurrency limit (otherwise this code would not be invoked + * in the first place) so we have to make make some awkward adjustments + * below. + * + * XXX The queue length test below looks at the active queue share of an + * individual destination. This catches the case where mail for one + * destination is falling behind because it has to round-robin compete + * with many other destinations. However, Postfix will also perform + * poorly when most of the active queue is tied up by a small number of + * concurrency limited destinations. The queue length test below detects + * such conditions only indirectly. + * + * XXX This code does not detect the case that the active queue is being + * starved because incoming mail is pounding the disk. + */ + if (var_qmgr_clog_warn_time > 0) { + int queue_length = queue->todo_refcount + queue->busy_refcount; + time_t now; + QMGR_TRANSPORT *transport; + double active_share; + + if (queue_length > var_qmgr_active_limit / 5 + && (now = event_time()) >= queue->clog_time_to_warn) { + active_share = queue_length / (double) qmgr_message_count; + msg_warn("mail for %s is using up %d of %d active queue entries", + queue->name, queue_length, qmgr_message_count); + if (active_share < 0.9) + msg_warn("this may slow down other mail deliveries"); + transport = queue->transport; + if (transport->dest_concurrency_limit > 0 + && transport->dest_concurrency_limit <= queue->busy_refcount + 1) + msg_warn("you may need to increase the main.cf %s%s from %d", + transport->name, _DEST_CON_LIMIT, + transport->dest_concurrency_limit); + else if (queue->window > var_qmgr_active_limit * active_share) + msg_warn("you may need to increase the main.cf %s from %d", + VAR_QMGR_ACT_LIMIT, var_qmgr_active_limit); + else if (queue->peers.next != queue->peers.prev) + msg_warn("you may need a separate master.cf transport for %s", + queue->name); + else if (transport->dest_concurrency_limit / 2 > queue->busy_refcount) + msg_warn("you may need to increase the master.cf %s process limit", + transport->name); + msg_warn("to turn off these warnings specify: %s = 0", + VAR_QMGR_CLOG_WARN_TIME); + queue->clog_time_to_warn = now + var_qmgr_clog_warn_time; + } + } return (entry); } diff --git a/postfix/src/nqmgr/qmgr_queue.c b/postfix/src/nqmgr/qmgr_queue.c index d4aced58e..9854011b6 100644 --- a/postfix/src/nqmgr/qmgr_queue.c +++ b/postfix/src/nqmgr/qmgr_queue.c @@ -237,6 +237,7 @@ QMGR_QUEUE *qmgr_queue_create(QMGR_TRANSPORT *transport, const char *site) QMGR_LIST_INIT(queue->todo); QMGR_LIST_INIT(queue->busy); queue->reason = 0; + queue->clog_time_to_warn = 0; queue->blocker_tag = 0; QMGR_LIST_APPEND(transport->queue_list, queue, peers); htable_enter(transport->queue_byname, site, (char *) queue); diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index e50c72117..9b3dba8d3 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -381,6 +381,9 @@ static int pickup_file(PICKUP_INFO *info) if (errno != ENOENT) msg_warn("open input file %s: %s", info->path, vstring_str(buf)); vstring_free(buf); + if (errno == EACCES) + msg_warn("if this file was created by Postfix < 1.1, then you may have to chmod a+r %s/%s", + var_queue_dir, info->path); return (errno == EACCES ? KEEP_MESSAGE_FILE : REMOVE_MESSAGE_FILE); } diff --git a/postfix/src/postcat/postcat.c b/postfix/src/postcat/postcat.c index dc76c8a09..824c95422 100644 --- a/postfix/src/postcat/postcat.c +++ b/postfix/src/postcat/postcat.c @@ -106,10 +106,16 @@ static void postcat(VSTREAM *fp, VSTRING *buffer) vstream_printf("defer_warn_time: %s", asctime(localtime(&time))); break; case REC_TYPE_CONT: - vstream_printf("%s", STR(buffer)); + if (msg_verbose) + vstream_printf("non-final line fragment: %s\n", STR(buffer)); + else + vstream_printf("%s", STR(buffer)); break; case REC_TYPE_NORM: - vstream_printf("%s\n", STR(buffer)); + if (msg_verbose) + vstream_printf("final line fragment: %s\n", STR(buffer)); + else + vstream_printf("%s\n", STR(buffer)); break; case REC_TYPE_MESG: vstream_printf("*** MESSAGE CONTENTS %s ***\n", VSTREAM_PATH(fp)); diff --git a/postfix/src/postqueue/postqueue.c b/postfix/src/postqueue/postqueue.c index ad8a159b7..41b15b44c 100644 --- a/postfix/src/postqueue/postqueue.c +++ b/postfix/src/postqueue/postqueue.c @@ -249,6 +249,9 @@ static void flush_queue(void) if (mail_flush_deferred() < 0) msg_fatal_status(EX_UNAVAILABLE, "Cannot flush mail queue - mail system is down"); + if (mail_flush_maildrop() < 0) + msg_fatal_status(EX_UNAVAILABLE, + "Cannot flush mail queue - mail system is down"); } /* flush_site - flush mail for site */ diff --git a/postfix/src/qmgr/qmgr.c b/postfix/src/qmgr/qmgr.c index 963532059..87d75dd82 100644 --- a/postfix/src/qmgr/qmgr.c +++ b/postfix/src/qmgr/qmgr.c @@ -37,6 +37,9 @@ /* delivery attempts. /* .IP \fBcorrupt\fR /* Unreadable or damaged queue files are moved here for inspection. +/* .IP \fBhold\fR +/* Messages that are kept "on hold" are kept here until someone +/* sets them free. /* DELIVERY STATUS REPORTS /* .ad /* .fi @@ -155,6 +158,9 @@ /* .SH "Active queue controls" /* .ad /* .fi +/* .IP \fBqmgr_clog_warn_time\fR +/* Minimal delay between warnings that a specific destination +/* is clogging up the active queue. Specify 0 to disable. /* .IP \fBqmgr_message_active_limit\fR /* Limit the number of messages in the active queue. /* .IP \fBqmgr_message_recipient_limit\fR @@ -199,15 +205,6 @@ /* case, recipients near the beginning of a large list receive a burst /* of messages immediately, while recipients near the end of that list /* receive that same burst of messages a whole day later. -/* .IP "\fBqmgr_site_hog_factor\fR (valid range: 10..100)" -/* The percentage of delivery resources that a busy mail system will -/* use up for delivery to a single site. -/* With 100%, mail is delivered in first-in, first-out order, so that -/* a burst of mail for one site can block mail for other destinations. -/* With less than 100%, the excess mail is deferred. The deferred mail -/* is delivered in little bursts, the remainder of the backlog being -/* deferred again, with a lot of I/O activity happening as Postfix -/* searches the deferred queue for deliverable mail. /* .IP \fBinitial_destination_concurrency\fR /* Initial per-destination concurrency level for parallel delivery /* to the same destination. @@ -291,12 +288,12 @@ char *var_virtual_maps; char *var_defer_xports; bool var_allow_min_user; int var_qmgr_fudge; -int var_qmgr_hog; int var_local_rcpt_lim; /* XXX */ int var_local_con_lim; /* XXX */ int var_proc_limit; bool var_verp_bounce_off; bool var_sender_routing; +int var_qmgr_clog_warn_time; static QMGR_SCAN *qmgr_incoming; static QMGR_SCAN *qmgr_deferred; @@ -464,6 +461,15 @@ static void qmgr_pre_init(char *unused_name, char **unused_argv) static void qmgr_post_init(char *unused_name, char **unused_argv) { + /* + * Sanity check. + */ + if (var_qmgr_rcpt_limit < var_qmgr_active_limit) { + msg_warn("%s is smaller than %s", + VAR_QMGR_RCPT_LIMIT, VAR_QMGR_ACT_LIMIT); + var_qmgr_rcpt_limit = var_qmgr_active_limit; + } + /* * This routine runs after the skeleton code has entered the chroot jail. * Prevent automatic process suicide after a limited number of client @@ -501,6 +507,7 @@ int main(int argc, char **argv) VAR_MAX_BACKOFF_TIME, DEF_MAX_BACKOFF_TIME, &var_max_backoff_time, 1, 0, VAR_MAX_QUEUE_TIME, DEF_MAX_QUEUE_TIME, &var_max_queue_time, 1, 8640000, VAR_XPORT_RETRY_TIME, DEF_XPORT_RETRY_TIME, &var_transport_retry_time, 1, 0, + VAR_QMGR_CLOG_WARN_TIME, DEF_QMGR_CLOG_WARN_TIME, &var_qmgr_clog_warn_time, 0, 0, 0, }; static CONFIG_INT_TABLE int_table[] = { @@ -510,7 +517,6 @@ int main(int argc, char **argv) VAR_DEST_CON_LIMIT, DEF_DEST_CON_LIMIT, &var_dest_con_limit, 0, 0, VAR_DEST_RCPT_LIMIT, DEF_DEST_RCPT_LIMIT, &var_dest_rcpt_limit, 0, 0, VAR_QMGR_FUDGE, DEF_QMGR_FUDGE, &var_qmgr_fudge, 10, 100, - VAR_QMGR_HOG, DEF_QMGR_HOG, &var_qmgr_hog, 10, 100, VAR_LOCAL_RCPT_LIMIT, DEF_LOCAL_RCPT_LIMIT, &var_local_rcpt_lim, 0, 0, VAR_LOCAL_CON_LIMIT, DEF_LOCAL_CON_LIMIT, &var_local_con_lim, 0, 0, VAR_PROC_LIMIT, DEF_PROC_LIMIT, &var_proc_limit, 1, 0, diff --git a/postfix/src/qmgr/qmgr.h b/postfix/src/qmgr/qmgr.h index 4f15f8c90..6f01c4f32 100644 --- a/postfix/src/qmgr/qmgr.h +++ b/postfix/src/qmgr/qmgr.h @@ -154,6 +154,7 @@ struct QMGR_QUEUE { QMGR_ENTRY_LIST busy; /* messages on the wire */ QMGR_QUEUE_LIST peers; /* neighbor queues */ char *reason; /* why unavailable */ + time_t clog_time_to_warn; /* time of next warning */ }; #define QMGR_QUEUE_TODO 1 /* waiting for service */ diff --git a/postfix/src/qmgr/qmgr_entry.c b/postfix/src/qmgr/qmgr_entry.c index 1d5c3afac..7a5f9dfdb 100644 --- a/postfix/src/qmgr/qmgr_entry.c +++ b/postfix/src/qmgr/qmgr_entry.c @@ -195,6 +195,9 @@ QMGR_ENTRY *qmgr_entry_create(QMGR_QUEUE *queue, QMGR_MESSAGE *message) if (queue->window == 0) msg_panic("qmgr_entry_create: dead queue: %s", queue->name); + /* + * Create the delivery request. + */ entry = (QMGR_ENTRY *) mymalloc(sizeof(QMGR_ENTRY)); entry->stream = 0; entry->message = message; @@ -203,5 +206,61 @@ QMGR_ENTRY *qmgr_entry_create(QMGR_QUEUE *queue, QMGR_MESSAGE *message) entry->queue = queue; QMGR_LIST_APPEND(queue->todo, entry); queue->todo_refcount++; + + /* + * Warn if a destination is falling behind while the active queue + * contains a non-trivial amount of single-recipient email. When a + * destination takes up more and more space in the active queue, then + * other mail will not get through and delivery performance will suffer. + * + * XXX At this point in the code, the busy reference count is still less + * than the concurrency limit (otherwise this code would not be invoked + * in the first place) so we have to make make some awkward adjustments + * below. + * + * XXX The queue length test below looks at the active queue share of an + * individual destination. This catches the case where mail for one + * destination is falling behind because it has to round-robin compete + * with many other destinations. However, Postfix will also perform + * poorly when most of the active queue is tied up by a small number of + * concurrency limited destinations. The queue length test below detects + * such conditions only indirectly. + * + * XXX This code does not detect the case that the active queue is being + * starved because incoming mail is pounding the disk. + */ + if (var_qmgr_clog_warn_time > 0) { + int queue_length = queue->todo_refcount + queue->busy_refcount; + time_t now; + QMGR_TRANSPORT *transport; + double active_share; + + if (queue_length > var_qmgr_active_limit / 5 + && (now = event_time()) >= queue->clog_time_to_warn) { + active_share = queue_length / (double) qmgr_message_count; + msg_warn("mail for %s is using up %d of %d active queue entries", + queue->name, queue_length, qmgr_message_count); + if (active_share < 0.9) + msg_warn("this may slow down other mail deliveries"); + transport = queue->transport; + if (transport->dest_concurrency_limit > 0 + && transport->dest_concurrency_limit <= queue->busy_refcount + 1) + msg_warn("you may need to increase the main.cf %s%s from %d", + transport->name, _DEST_CON_LIMIT, + transport->dest_concurrency_limit); + else if (queue->window > var_qmgr_active_limit * active_share) + msg_warn("you may need to increase the main.cf %s from %d", + VAR_QMGR_ACT_LIMIT, var_qmgr_active_limit); + else if (queue->peers.next != queue->peers.prev) + msg_warn("you may need a separate master.cf transport for %s", + queue->name); + else if (transport->dest_concurrency_limit / 2 > queue->busy_refcount) + msg_warn("you may need to increase the master.cf %s process limit", + transport->name); + msg_warn("to turn off these warnings specify: %s = 0", + VAR_QMGR_CLOG_WARN_TIME); + queue->clog_time_to_warn = now + var_qmgr_clog_warn_time; + } + } return (entry); } diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c index 9bbac6975..9eb702376 100644 --- a/postfix/src/qmgr/qmgr_message.c +++ b/postfix/src/qmgr/qmgr_message.c @@ -722,23 +722,6 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) continue; } - /* - * This queue is a hog. Defer this recipient until the queue drains. - * When a site accumulates a large backlog, Postfix will deliver a - * little chunk and hammer the disk as it defers the remainder of the - * backlog and searches the deferred queue for deliverable mail. - */ - if (var_qmgr_hog < 100) { - if (queue->todo_refcount + queue->busy_refcount - > (var_qmgr_hog / 100.0) - * (qmgr_recipient_count > 0.8 * var_qmgr_rcpt_limit ? - qmgr_message_count : var_qmgr_active_limit)) { - qmgr_defer_recipient(message, recipient->address, - "site destination queue overflow"); - continue; - } - } - /* * This queue is alive. Bind this recipient to this queue instance. */ diff --git a/postfix/src/qmgr/qmgr_queue.c b/postfix/src/qmgr/qmgr_queue.c index 8b38d4462..7d4214f70 100644 --- a/postfix/src/qmgr/qmgr_queue.c +++ b/postfix/src/qmgr/qmgr_queue.c @@ -260,6 +260,7 @@ QMGR_QUEUE *qmgr_queue_create(QMGR_TRANSPORT *transport, const char *site) QMGR_LIST_INIT(queue->todo); QMGR_LIST_INIT(queue->busy); queue->reason = 0; + queue->clog_time_to_warn = 0; QMGR_LIST_PREPEND(transport->queue_list, queue); htable_enter(transport->queue_byname, site, (char *) queue); return (queue); diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index c402bc4ad..1b3215110 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -305,7 +305,8 @@ static void smtp_text_out(void *context, int rec_type, data_left = len; data_start = text; do { - if (state->space_left == var_smtp_line_limit && *data_start == '.') + if (state->space_left == var_smtp_line_limit + && data_left > 0 && *data_start == '.') smtp_fputc('.', session->stream); if (var_smtp_line_limit > 0 && data_left >= state->space_left) { smtp_fputs(data_start, state->space_left, session->stream); diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index bb8cc7189..32fbaeb2b 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -197,6 +197,7 @@ smtpd_check.o: ../../include/maps.h smtpd_check.o: ../../include/mail_addr_find.h smtpd_check.o: ../../include/match_parent_style.h smtpd_check.o: ../../include/strip_addr.h +smtpd_check.o: ../../include/virtual8.h smtpd_check.o: smtpd.h smtpd_check.o: ../../include/mail_stream.h smtpd_check.o: smtpd_sasl_glue.h diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 88308b543..0c94c4cca 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -727,7 +727,7 @@ static const char *check_maps_find(SMTPD_STATE *state, const char *reply_name, /* checkv8_maps_find - reject with temporary failure if dict lookup fails */ static const char *checkv8_maps_find(SMTPD_STATE *state, const char *reply_name, - MAPS *maps, const char *key) + MAPS *maps, const char *key) { const char *result; @@ -767,12 +767,11 @@ static int resolve_final(SMTPD_STATE *state, const char *reply_name, msg_warn("list domain %s in only one of $%s and $%s", domain, VAR_MYDEST, VAR_VIRTUAL_MAPS); if (*var_virt_mailbox_maps - && checkv8_maps_find(state, reply_name, virt_mailbox_maps, domain)) + && checkv8_maps_find(state, reply_name, virt_mailbox_maps, domain)) msg_warn("list domain %s in only one of $%s and $%s", domain, VAR_MYDEST, VAR_VIRT_MAILBOX_MAPS); return (1); } - /* If Postfix-style virtual domain. */ if (*var_virtual_maps && check_maps_find(state, reply_name, virtual_maps, domain, 0)) @@ -1966,8 +1965,8 @@ static int reject_sender_login_mismatch(SMTPD_STATE *state, const char *sender) * the sender address. */ reply = (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, sender); - owner = check_maps_find(state, sender, smtpd_sender_login_maps, - STR(reply->recipient), 0); + owner = check_mail_addr_find(state, sender, smtpd_sender_login_maps, + STR(reply->recipient), (char **) 0); #ifdef USE_SASL_AUTH if (var_smtpd_sasl_enable && state->sasl_username != 0) login = state->sasl_username; @@ -2061,8 +2060,8 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, cpp[1], PERMIT_ALL); } else if (strcasecmp(name, DEFER_ALL) == 0) { status = smtpd_check_reject(state, MAIL_ERROR_POLICY, - "%d <%s>: %s rejected: Try again later", - var_defer_code, reply_name, reply_class); + "%d <%s>: %s rejected: Try again later", + var_defer_code, reply_name, reply_class); if (cpp[1] != 0 && state->warn_if_reject == 0) msg_warn("restriction `%s' after `%s' is ignored", cpp[1], DEFER_ALL); @@ -2120,7 +2119,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, } } else if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) { msg_warn("restriction %s is deprecated. Use %s instead", - PERMIT_NAKED_IP_ADDR, PERMIT_MYNETWORKS); + PERMIT_NAKED_IP_ADDR, PERMIT_MYNETWORKS); if (state->helo_name) { if (state->helo_name[strspn(state->helo_name, "0123456789.")] == 0 && (status = reject_invalid_hostaddr(state, state->helo_name, diff --git a/postfix/src/smtpstone/Makefile.in b/postfix/src/smtpstone/Makefile.in index fb9cacbdc..186538bb6 100644 --- a/postfix/src/smtpstone/Makefile.in +++ b/postfix/src/smtpstone/Makefile.in @@ -118,6 +118,7 @@ smtp-sink.o: ../../include/iostuff.h smtp-sink.o: ../../include/events.h smtp-sink.o: ../../include/mymalloc.h smtp-sink.o: ../../include/msg_vstream.h +smtp-sink.o: ../../include/stringops.h smtp-sink.o: ../../include/smtp_stream.h smtp-source.o: smtp-source.c smtp-source.o: ../../include/sys_defs.h diff --git a/postfix/src/smtpstone/smtp-sink.c b/postfix/src/smtpstone/smtp-sink.c index 0b62b26df..ac3fac7f5 100644 --- a/postfix/src/smtpstone/smtp-sink.c +++ b/postfix/src/smtpstone/smtp-sink.c @@ -22,8 +22,13 @@ /* .IP \fB-c\fR /* Display a running counter that is updated whenever an SMTP /* QUIT command is executed. +/* .IP \fB-e\fR +/* Disable ESMTP support. +/* .IP \fB-h\fI hostname\fR +/* Use \fIhostname\fR in the SMTP greeting, in the HELO response, +/* and in the EHLO response. The default hostname is "smtp-sink". /* .IP \fB-L\fR -/* Speak LMTP rather than SMTP. +/* Enable LMTP rather than SMTP. /* .IP "\fB-n \fIcount\fR" /* Terminate after \fIcount\fR sessions. This is for testing purposes. /* .IP \fB-p\fR @@ -31,10 +36,18 @@ /* .IP \fB-P\fR /* Change the server greeting so that it appears to come through /* a CISCO PIX system. +/* .IP "\fB-s \fIcommand,command,...\fR" +/* Log the named commands to syslogd. +/* Examples of commands that can be logged are HELO, EHLO, LHLO, MAIL, +/* RCPT, VRFY, RSET, NOOP, and QUIT. Separate command names by white +/* space or commas, and use quotes to protect white space from the +/* shell. Command names are case-insensitive. /* .IP \fB-v\fR /* Show the SMTP conversations. /* .IP "\fB-w \fIdelay\fR" /* Wait \fIdelay\fR seconds before responding to a DATA command. +/* .IP \fB-8\fR +/* Disable 8BITMIME support. /* .IP [\fBinet:\fR][\fIhost\fR]:\fIport\fR /* Listen on network interface \fIhost\fR (default: any interface) /* TCP port \fIport\fR. Both \fIhost\fR and \fIport\fR may be @@ -66,6 +79,7 @@ #include #include #include +#include #ifdef STRCASECMP_IN_STRINGS_H #include @@ -83,6 +97,7 @@ #include #include #include +#include /* Global library. */ @@ -115,7 +130,9 @@ static int count; static int counter; static int max_count; static int disable_pipelining; +static int disable_8bitmime; static int fixed_delay; +static int disable_esmtp; static int enable_lmtp; static int pretend_pix; @@ -126,7 +143,16 @@ static void ehlo_response(SINK_STATE *state) smtp_printf(state->stream, "250-%s", var_myhostname); if (!disable_pipelining) smtp_printf(state->stream, "250-PIPELINING"); - smtp_printf(state->stream, "250 8BITMIME"); + if (!disable_8bitmime) + smtp_printf(state->stream, "250-8BITMIME"); + smtp_printf(state->stream, "250 "); +} + +/* helo_response - respond to HELO command */ + +static void helo_response(SINK_STATE *state) +{ + smtp_printf(state->stream, "250 %s", var_myhostname); } /* ok_response - send 250 OK */ @@ -261,22 +287,54 @@ static int data_read(SINK_STATE *state) typedef struct SINK_COMMAND { char *name; void (*response) (SINK_STATE *); + int flags; } SINK_COMMAND; +#define FLAG_ENABLE (1<<0) /* command is enabled */ +#define FLAG_SYSLOG (1<<1) /* log the command */ + static SINK_COMMAND command_table[] = { - "helo", ok_response, - "ehlo", ehlo_response, - "lhlo", ehlo_response, - "mail", mail_response, - "rcpt", rcpt_response, - "data", data_response, - "rset", ok_response, - "noop", ok_response, - "vrfy", ok_response, - "quit", quit_response, + "helo", helo_response, 0, + "ehlo", ehlo_response, 0, + "lhlo", ehlo_response, 0, + "mail", mail_response, FLAG_ENABLE, + "rcpt", rcpt_response, FLAG_ENABLE, + "data", data_response, FLAG_ENABLE, + "rset", ok_response, FLAG_ENABLE, + "noop", ok_response, FLAG_ENABLE, + "vrfy", ok_response, FLAG_ENABLE, + "quit", quit_response, FLAG_ENABLE, 0, }; +/* set_cmd_flags - set per-command command flags */ + +static void set_cmd_flags(const char *cmd, int flags) +{ + SINK_COMMAND *cmdp; + + for (cmdp = command_table; cmdp->name != 0; cmdp++) + if (strcasecmp(cmd, cmdp->name) == 0) + break; + if (cmdp->name == 0) + msg_fatal("unknown command: %s", cmd); + cmdp->flags |= flags; +} + +/* set_cmds_flags - set per-command flags for multiple commands */ + +static void set_cmds_flags(const char *cmds, int flags) +{ + char *saved_cmds; + char *cp; + char *cmd; + + saved_cmds = cp = mystrdup(cmds); + while ((cmd = mystrtok(&cp, " \t\r\n,")) != 0) + set_cmd_flags(cmd, flags); + myfree(saved_cmds); +} + /* command_read - talk the SMTP protocol, server side */ static int command_read(SINK_STATE *state) @@ -294,6 +352,7 @@ static int command_read(SINK_STATE *state) ST_CR, '\n', ST_CR_LF, }; struct cmd_trans *cp; + char *ptr; /* * A read may result in EOF, but is never supposed to time out - a time @@ -331,6 +390,12 @@ static int command_read(SINK_STATE *state) /* * We must avoid blocking I/O, so get out of here as soon as both the * VSTREAM and kernel read buffers dry up. + * + * XXX Solaris non-blocking read() may fail on a socket when ioctl + * FIONREAD reports there is unread data. Diagnosis by Max Pashkov. + * As a workaround we use readable() (which uses poll or select()) + * instead of peek_fd() (which uses ioctl FIONREAD). Workaround added + * 20020604. */ if (vstream_peek(state->stream) <= 0 && readable(vstream_fileno(state->stream)) <= 0) @@ -350,7 +415,8 @@ static int command_read(SINK_STATE *state) /* * Got a complete command line. Parse it. */ - if ((command = strtok(vstring_str(state->buffer), " \t")) == 0) { + ptr = vstring_str(state->buffer); + if ((command = mystrtok(&ptr, " \t")) == 0) { smtp_printf(state->stream, "500 Error: unknown command"); return (0); } @@ -359,10 +425,13 @@ static int command_read(SINK_STATE *state) for (cmdp = command_table; cmdp->name != 0; cmdp++) if (strcasecmp(command, cmdp->name) == 0) break; - if (cmdp->name == 0) { + if (cmdp->name == 0 || (cmdp->flags & FLAG_ENABLE) == 0) { smtp_printf(state->stream, "500 Error: unknown command"); return (0); } + /* We use raw syslog. Sanitize data content and length. */ + if (cmdp->flags & FLAG_SYSLOG) + syslog(LOG_INFO, "%s %.100s", command, printable(ptr, '?')); if (cmdp->response == data_response && fixed_delay > 0) { event_request_timer(data_event, (char *) state, fixed_delay); } else { @@ -413,7 +482,7 @@ static void disconnect(SINK_STATE *state) vstream_fclose(state->stream); vstring_free(state->buffer); myfree((char *) state); - if (max_count > 0 && counter >= max_count) + if (max_count > 0 && ++counter >= max_count) exit(0); } @@ -447,10 +516,12 @@ static void connect_event(int unused_event, char *context) state->read = command_read; state->data_state = ST_ANY; smtp_timeout_setup(state->stream, var_tmout); -if (pretend_pix) - smtp_printf(state->stream, "220 ********"); -else - smtp_printf(state->stream, "220 %s ESMTP", var_myhostname); + if (pretend_pix) + smtp_printf(state->stream, "220 ********"); + else if (disable_esmtp) + smtp_printf(state->stream, "220 %s", var_myhostname); + else + smtp_printf(state->stream, "220 %s ESMTP", var_myhostname); event_enable_read(fd, read_event, (char *) state); } } @@ -459,7 +530,7 @@ else static void usage(char *myname) { - msg_fatal("usage: %s [-cLpPv] [-n count] [-w delay] [host]:port backlog", myname); + msg_fatal("usage: %s [-ceLpPv8] [-h hostname] [-n count] [-s commands] [-w delay] [host]:port backlog", myname); } int main(int argc, char **argv) @@ -476,11 +547,17 @@ int main(int argc, char **argv) /* * Parse JCL. */ - while ((ch = GETOPT(argc, argv, "cLn:pPvw:")) > 0) { + while ((ch = GETOPT(argc, argv, "ceh:Ln:pPs:vw:8")) > 0) { switch (ch) { case 'c': count++; break; + case 'e': + disable_esmtp = 1; + break; + case 'h': + var_myhostname = optarg; + break; case 'L': enable_lmtp = 1; break; @@ -491,7 +568,11 @@ int main(int argc, char **argv) disable_pipelining = 1; break; case 'P': - pretend_pix=1; + pretend_pix = 1; + break; + case 's': + openlog(basename(argv[0]), LOG_PID, LOG_MAIL); + set_cmds_flags(optarg, FLAG_SYSLOG); break; case 'v': msg_verbose++; @@ -500,6 +581,9 @@ int main(int argc, char **argv) if ((fixed_delay = atoi(optarg)) <= 0) usage(argv[0]); break; + case '8': + disable_8bitmime = 1; + break; default: usage(argv[0]); } @@ -512,7 +596,11 @@ int main(int argc, char **argv) /* * Initialize. */ - var_myhostname = "smtp-sink"; + if (var_myhostname == 0) + var_myhostname = "smtp-sink"; + set_cmds_flags(enable_lmtp ? "lhlo" : + disable_esmtp ? "helo" : + "helo, ehlo", FLAG_ENABLE); if (strncmp(argv[optind], "unix:", 5) == 0) { sock = unix_listen(argv[optind] + 5, backlog, BLOCKING); } else {