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
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
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)
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.
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.
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:
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
==========================================================
Unreadable or damaged queue files are moved here
for inspection.
+ <b>hold</b> Messages that are kept "on hold" are kept here
+ until someone sets them free.
+
<b>DELIVERY</b> <b>STATUS</b> <b>REPORTS</b>
The <b>nqmgr</b> 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:
- <b>bounce</b> Per-recipient status information about why mail is
- bounced. These files are maintained by the
+ <b>bounce</b> Per-recipient status information about why mail is
+ bounced. These files are maintained by the
<a href="bounce.8.html"><b>bounce</b>(8)</a> daemon.
- <b>defer</b> Per-recipient status information about why mail is
- delayed. These files are maintained by the
+ <b>defer</b> Per-recipient status information about why mail is
+ delayed. These files are maintained by the
<a href="defer.8.html"><b>defer</b>(8)</a> daemon.
- The <b>nqmgr</b> daemon is responsible for asking the <a href="bounce.8.html"><b>bounce</b>(8)</a>
+ The <b>nqmgr</b> daemon is responsible for asking the <a href="bounce.8.html"><b>bounce</b>(8)</a>
or <a href="defer.8.html"><b>defer</b>(8)</a> daemons to send non-delivery reports.
<b>STRATEGIES</b>
- 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).
<b>leaky</b> <b>bucket</b>
- This strategy limits the number of messages in the
- <b>active</b> queue and prevents the queue manager from
+ This strategy limits the number of messages in the
+ <b>active</b> queue and prevents the queue manager from
running out of memory under heavy load.
<b>fairness</b>
- When the <b>active</b> queue has room, the queue manager
- takes one message from the <b>incoming</b> queue and one
+ When the <b>active</b> queue has room, the queue manager
+ takes one message from the <b>incoming</b> queue and one
from the <b>deferred</b> queue. This prevents a large mail
backlog from blocking the delivery of new mail.
<b>round</b> <b>robin</b>
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.
<b>exponential</b> <b>backoff</b>
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.
<b>destination</b> <b>status</b> <b>cache</b>
- 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.
<b>preemptive</b> <b>message</b> <b>scheduling</b>
- 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.
<b>TRIGGERS</b>
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):
<b>D</b> <b>(QMGR</b><i>_</i><b>REQ</b><i>_</i><b>SCAN</b><i>_</i><b>DEFERRED)</b>
- 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.
<b>I</b> <b>(QMGR</b><i>_</i><b>REQ</b><i>_</i><b>SCAN</b><i>_</i><b>INCOMING)</b>
- 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.
<b>A</b> <b>(QMGR</b><i>_</i><b>REQ</b><i>_</i><b>SCAN</b><i>_</i><b>ALL)</b>
affects the next deferred queue scan.
<b>F</b> <b>(QMGR</b><i>_</i><b>REQ</b><i>_</i><b>FLUSH</b><i>_</i><b>DEAD)</b>
- Purge all information about dead transports and
+ Purge all information about dead transports and
destinations.
<b>W</b> <b>(TRIGGER</b><i>_</i><b>REQ</b><i>_</i><b>WAKEUP)</b>
- 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 <b>nqmgr</b> daemon reads an entire buffer worth of triggers.
- Multiple identical trigger requests are collapsed into
- one, and trigger requests are sorted so that <b>A</b> and <b>F</b> pre-
- cede <b>D</b> and <b>I</b>. Thus, in order to force a deferred queue
+ Multiple identical trigger requests are collapsed into
+ one, and trigger requests are sorted so that <b>A</b> and <b>F</b> pre-
+ cede <b>D</b> and <b>I</b>. Thus, in order to force a deferred queue
run, one would request <b>A</b> <b>F</b> <b>D</b>; in order to notify the queue
manager of the arrival of new mail one would request <b>I</b>.
<b>STANDARDS</b>
- None. The <b>nqmgr</b> daemon does not interact with the outside
+ None. The <b>nqmgr</b> daemon does not interact with the outside
world.
<b>SECURITY</b>
- The <b>nqmgr</b> 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
- <b>nqmgr</b> daemon does not talk to the outside world, and it
- can be run at fixed low privilege in a chrooted environ-
+ The <b>nqmgr</b> 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
+ <b>nqmgr</b> daemon does not talk to the outside world, and it
+ can be run at fixed low privilege in a chrooted environ-
ment.
<b>DIAGNOSTICS</b>
Corrupted message files are saved to the <b>corrupt</b> queue for
further inspection.
- Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
- the postmaster is notified of bounces and of other trou-
+ Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
+ the postmaster is notified of bounces and of other trou-
ble.
<b>BUGS</b>
- A single queue manager process has to compete for disk
- access with multiple front-end processes such as <b>smtpd</b>. 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 <b>smtpd</b>. A
+ sudden burst of inbound mail can negatively impact out-
bound delivery rates.
<b>CONFIGURATION</b> <b>PARAMETERS</b>
- The following <b>main.cf</b> parameters are especially relevant
- to this program. See the Postfix <b>main.cf</b> file for syntax
- details and for default values. Use the <b>postfix</b> <b>reload</b>
+ The following <b>main.cf</b> parameters are especially relevant
+ to this program. See the Postfix <b>main.cf</b> file for syntax
+ details and for default values. Use the <b>postfix</b> <b>reload</b>
command after a configuration change.
<b>Miscellaneous</b>
<b>allow</b><i>_</i><b>min</b><i>_</i><b>user</b>
- Do not bounce recipient addresses that begin with
+ Do not bounce recipient addresses that begin with
'-'.
<b>relocated</b><i>_</i><b>maps</b>
Top-level directory of the Postfix queue.
<b>Active</b> <b>queue</b> <b>controls</b>
- In the text below, <i>transport</i> is the first field in a <b>mas-</b>
+ In the text below, <i>transport</i> is the first field in a <b>mas-</b>
<b>ter.cf</b> entry.
+ <b>qmgr</b><i>_</i><b>clog</b><i>_</i><b>warn</b><i>_</i><b>time</b>
+ Minimal delay between warnings that a specific des-
+ tination is clogging up the active queue. Specify 0
+ to disable.
+
<b>qmgr</b><i>_</i><b>message</b><i>_</i><b>active</b><i>_</i><b>limit</b>
Limit the number of messages in the active queue.
<b>qmgr</b><i>_</i><b>message</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
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.
<b>qmgr</b><i>_</i><b>message</b><i>_</i><b>recipient</b><i>_</i><b>minimum</b>
per transport.
<i>transport_</i><b>recipient</b><i>_</i><b>limit</b>
- Limit on the number of in-memory recipients, for
+ Limit on the number of in-memory recipients, for
the named message <i>transport</i>.
<b>default</b><i>_</i><b>extra</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- 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.
<i>transport_</i><b>extra</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- 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
<i>transport</i> can have.
<b>Timing</b> <b>controls</b>
<b>minimal</b><i>_</i><b>backoff</b><i>_</i><b>time</b>
- 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.
<b>maximal</b><i>_</i><b>backoff</b><i>_</i><b>time</b>
- Maximal time in seconds between delivery attempts
+ Maximal time in seconds between delivery attempts
of a deferred message.
<b>maximal</b><i>_</i><b>queue</b><i>_</i><b>lifetime</b>
- 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.
<b>queue</b><i>_</i><b>run</b><i>_</i><b>delay</b>
scans do not overlap.
<b>transport</b><i>_</i><b>retry</b><i>_</i><b>time</b>
- Time in seconds between attempts to contact a bro-
+ Time in seconds between attempts to contact a bro-
ken delivery transport.
<b>Concurrency</b> <b>controls</b>
<b>initial</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b>
- Initial per-destination concurrency level for par-
+ Initial per-destination concurrency level for par-
allel delivery to the same destination.
<b>default</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
- Default limit on the number of parallel deliveries
+ Default limit on the number of parallel deliveries
to the same destination.
<i>transport_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
- 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 <i>transport</i>.
<b>Recipient</b> <b>controls</b>
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Default limit on the number of recipients per mes-
+ Default limit on the number of recipients per mes-
sage transfer.
<i>transport_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Limit on the number of recipients per message
+ Limit on the number of recipients per message
transfer, for the named message <i>transport</i>.
<b>Message</b> <b>scheduling</b>
<i>transport_</i><b>delivery</b><i>_</i><b>slot</b><i>_</i><b>cost</b> (valid range: 0,2,3...)
- This parameter basically controls how often a mes-
- sage delivered by <i>transport</i> can be preempted by
+ This parameter basically controls how often a mes-
+ sage delivered by <i>transport</i> can be preempted by
another message. An internal per-message/transport
- counter is incremented by one for each <i>trans-</i>
+ counter is incremented by one for each <i>trans-</i>
<i>port_</i><b>delivery</b><i>_</i><b>slot</b><i>_</i><b>cost</b> deliveries handled by
- <i>transport</i>. This counter represents the number of
- "available delivery slots" for use by other mes-
+ <i>transport</i>. 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 <i>transport</i> agents than the value of the
+ message when that other message can be delivered
+ using less <i>transport</i> 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 <i>transport</i>.
<i>transport_</i><b>minimum</b><i>_</i><b>delivery</b><i>_</i><b>slots</b>
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
<i>transport_</i><b>minimum</b><i>_</i><b>delivery</b><i>_</i><b>slots</b> available delivery
slots is being delivered by <i>transport</i>.
<i>transport_</i><b>delivery</b><i>_</i><b>slot</b><i>_</i><b>loan</b>
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 <i>trans-</i>
+ preemption can happen. Instead of waiting until
+ the full amount of delivery slots required is
+ available, the preemption can happen when <i>trans-</i>
<i>port_</i><b>delivery</b><i>_</i><b>slot</b><i>_</i><b>discount</b> percent of the required
- amount plus <i>transport_</i><b>delivery</b><i>_</i><b>slot</b><i>_</i><b>loan</b> still
- remains to be accumulated. Note that the full
- amount will still have to be accumulated before
+ amount plus <i>transport_</i><b>delivery</b><i>_</i><b>slot</b><i>_</i><b>loan</b> still
+ remains to be accumulated. Note that the full
+ amount will still have to be accumulated before
another preemption can take place later.
<b>default</b><i>_</i><b>delivery</b><i>_</i><b>slot</b><i>_</i><b>cost</b>
<b>default</b><i>_</i><b>delivery</b><i>_</i><b>slot</b><i>_</i><b>discount</b>
<b>default</b><i>_</i><b>delivery</b><i>_</i><b>slot</b><i>_</i><b>loan</b>
- Default values for the transport specific parame-
+ Default values for the transport specific parame-
ters described above.
<b>SEE</b> <b>ALSO</b>
<a href="trivial-rewrite.8.html">trivial-rewrite(8)</a>, address routing
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
<html> <head> </head> <body> <pre>
-
POSTCAT(1) POSTCAT(1)
<b>NAME</b>
P.O. Box 704
Yorktown Heights, NY 10598, USA
- 1
-
+ POSTCAT(1)
</pre> </body> </html>
Unreadable or damaged queue files are moved here
for inspection.
+ <b>hold</b> Messages that are kept "on hold" are kept here
+ until someone sets them free.
+
<b>DELIVERY</b> <b>STATUS</b> <b>REPORTS</b>
- The <b>qmgr</b> daemon keeps an eye on per-message delivery sta-
- tus reports in the following directories. Each status
+ The <b>qmgr</b> 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:
- <b>bounce</b> Per-recipient status information about why mail is
- bounced. These files are maintained by the
+ <b>bounce</b> Per-recipient status information about why mail is
+ bounced. These files are maintained by the
<a href="bounce.8.html"><b>bounce</b>(8)</a> daemon.
- <b>defer</b> Per-recipient status information about why mail is
- delayed. These files are maintained by the
+ <b>defer</b> Per-recipient status information about why mail is
+ delayed. These files are maintained by the
<a href="defer.8.html"><b>defer</b>(8)</a> daemon.
The <b>qmgr</b> daemon is responsible for asking the <a href="bounce.8.html"><b>bounce</b>(8)</a> or
<a href="defer.8.html"><b>defer</b>(8)</a> daemons to send non-delivery reports.
<b>STRATEGIES</b>
- 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).
<b>leaky</b> <b>bucket</b>
- This strategy limits the number of messages in the
- <b>active</b> queue and prevents the queue manager from
+ This strategy limits the number of messages in the
+ <b>active</b> queue and prevents the queue manager from
running out of memory under heavy load.
<b>fairness</b>
- When the <b>active</b> queue has room, the queue manager
- takes one message from the <b>incoming</b> queue and one
+ When the <b>active</b> queue has room, the queue manager
+ takes one message from the <b>incoming</b> queue and one
from the <b>deferred</b> queue. This prevents a large mail
backlog from blocking the delivery of new mail.
<b>round</b> <b>robin</b>
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.
<b>exponential</b> <b>backoff</b>
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.
<b>destination</b> <b>status</b> <b>cache</b>
- 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.
<b>TRIGGERS</b>
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):
<b>D</b> <b>(QMGR</b><i>_</i><b>REQ</b><i>_</i><b>SCAN</b><i>_</i><b>DEFERRED)</b>
- 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.
<b>I</b> <b>(QMGR</b><i>_</i><b>REQ</b><i>_</i><b>SCAN</b><i>_</i><b>INCOMING)</b>
- 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.
<b>A</b> <b>(QMGR</b><i>_</i><b>REQ</b><i>_</i><b>SCAN</b><i>_</i><b>ALL)</b>
affects the next deferred queue scan.
<b>F</b> <b>(QMGR</b><i>_</i><b>REQ</b><i>_</i><b>FLUSH</b><i>_</i><b>DEAD)</b>
- Purge all information about dead transports and
+ Purge all information about dead transports and
destinations.
<b>W</b> <b>(TRIGGER</b><i>_</i><b>REQ</b><i>_</i><b>WAKEUP)</b>
- 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 <b>qmgr</b> daemon reads an entire buffer worth of triggers.
- Multiple identical trigger requests are collapsed into
- one, and trigger requests are sorted so that <b>A</b> and <b>F</b> pre-
- cede <b>D</b> and <b>I</b>. Thus, in order to force a deferred queue
+ The <b>qmgr</b> daemon reads an entire buffer worth of triggers.
+ Multiple identical trigger requests are collapsed into
+ one, and trigger requests are sorted so that <b>A</b> and <b>F</b> pre-
+ cede <b>D</b> and <b>I</b>. Thus, in order to force a deferred queue
run, one would request <b>A</b> <b>F</b> <b>D</b>; in order to notify the queue
manager of the arrival of new mail one would request <b>I</b>.
<b>STANDARDS</b>
- None. The <b>qmgr</b> daemon does not interact with the outside
+ None. The <b>qmgr</b> daemon does not interact with the outside
world.
<b>SECURITY</b>
- The <b>qmgr</b> 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 <b>qmgr</b> 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
<b>qmgr</b> daemon does not talk to the outside world, and it can
be run at fixed low privilege in a chrooted environment.
Corrupted message files are saved to the <b>corrupt</b> queue for
further inspection.
- Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
- the postmaster is notified of bounces and of other trou-
+ Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
+ the postmaster is notified of bounces and of other trou-
ble.
<b>BUGS</b>
- A single queue manager process has to compete for disk
- access with multiple front-end processes such as <b>smtpd</b>. 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 <b>smtpd</b>. A
+ sudden burst of inbound mail can negatively impact out-
bound delivery rates.
<b>CONFIGURATION</b> <b>PARAMETERS</b>
- The following <b>main.cf</b> parameters are especially relevant
- to this program. See the Postfix <b>main.cf</b> file for syntax
- details and for default values. Use the <b>postfix</b> <b>reload</b>
+ The following <b>main.cf</b> parameters are especially relevant
+ to this program. See the Postfix <b>main.cf</b> file for syntax
+ details and for default values. Use the <b>postfix</b> <b>reload</b>
command after a configuration change.
<b>Miscellaneous</b>
<b>allow</b><i>_</i><b>min</b><i>_</i><b>user</b>
- Do not bounce recipient addresses that begin with
+ Do not bounce recipient addresses that begin with
'-'.
<b>relocated</b><i>_</i><b>maps</b>
Top-level directory of the Postfix queue.
<b>Active</b> <b>queue</b> <b>controls</b>
+ <b>qmgr</b><i>_</i><b>clog</b><i>_</i><b>warn</b><i>_</i><b>time</b>
+ Minimal delay between warnings that a specific des-
+ tination is clogging up the active queue. Specify 0
+ to disable.
+
<b>qmgr</b><i>_</i><b>message</b><i>_</i><b>active</b><i>_</i><b>limit</b>
Limit the number of messages in the active queue.
<b>qmgr</b><i>_</i><b>message</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
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.
<b>Timing</b> <b>controls</b>
<b>minimal</b><i>_</i><b>backoff</b><i>_</i><b>time</b>
- 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.
<b>maximal</b><i>_</i><b>backoff</b><i>_</i><b>time</b>
- Maximal time in seconds between delivery attempts
+ Maximal time in seconds between delivery attempts
of a deferred message.
<b>maximal</b><i>_</i><b>queue</b><i>_</i><b>lifetime</b>
- 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.
<b>queue</b><i>_</i><b>run</b><i>_</i><b>delay</b>
scans do not overlap.
<b>transport</b><i>_</i><b>retry</b><i>_</i><b>time</b>
- Time in seconds between attempts to contact a bro-
+ Time in seconds between attempts to contact a bro-
ken delivery transport.
<b>Concurrency</b> <b>controls</b>
- In the text below, <i>transport</i> is the first field in a <b>mas-</b>
+ In the text below, <i>transport</i> is the first field in a <b>mas-</b>
<b>ter.cf</b> entry.
<b>qmgr</b><i>_</i><b>fudge</b><i>_</i><b>factor</b> (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-
+ 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
+ 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.
- <b>qmgr</b><i>_</i><b>site</b><i>_</i><b>hog</b><i>_</i><b>factor</b> (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.
-
<b>initial</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b>
Initial per-destination concurrency level for par-
allel delivery to the same destination.
<h2>Postfix mail queues</h2>
-Postfix has four different queues: <b>maildrop</b>, <b>incoming</b>,
+Postfix has four main queues: <b>maildrop</b>, <b>incoming</b>,
<b>active</b> and <b>deferred</b> (click the upper left-hand icon
for the big picture). Locally-posted mail is deposited into the
<b>maildrop</b>, and is copied to the <b>incoming</b> queue after
guarantees that new mail will get through even when there is a
large backlog.
+<p>
+
+In addition to the queues mentioned above Postfix also maintains
+two parking spaces. The <b>hold</b> queue is for mail that is frozen
+in the queue; no delivery attempts are made until someone releases
+these messages with the <a href="postsuper.1.html">postsuper</a>
+command. The <b>corrupt</b> directory is for damaged queue files.
+Rather than discarding these, Postfix leaves them here for human
+inspection.
+
<h2>No thundering herd</h2>
Implementing a high-performance mail system is one thing. However,
<dt>IGNORE <dd> Delete the header from the message.
+<dt>HOLD <dd> Place the message on the <b>hold</b> queue. Mail on
+hold can be inspected with the <a href="postcat.1.html">postcat</a>
+command, and can be destroyed or taken off hold with the <a
+href="postsuper.1.html">postsuper</a> command.
+
<dt>WARN <dd> Log (but do not reject) the header with a warning.
<dt>WARN text... <dd> As above, and also log the text.
<dt>IGNORE <dd> Delete the matched line from the message.
+<dt>HOLD <dd> Place the message on the <b>hold</b> queue. Mail on
+hold can be inspected with the <a href="postcat.1.html">postcat</a>
+command, and can be destroyed or taken off hold with the <a
+href="postsuper.1.html">postsuper</a> command.
+
<dt>WARN <dd> Log (but do not reject) the matched line with a warning.
<dt>WARN text... <dd> As above, and also log the text.
<dt>Default:
-<dd><b>maps_rbl_domains = blackholes.mail-abuse.org</b>
+<dd><b>maps_rbl_domains = </b>
<p>
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
.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
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
.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
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.
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
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
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 */
/*
* 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));
"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,
#include <mail_proto.h>
#include <mime_state.h>
#include <lex_822.h>
+#include <hold_message.h>
/* Application-specific. */
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);
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;
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);
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.
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 \
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 \
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 \
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.in >tok822_parse.tmp
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.in >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.in2 >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.in3 >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.in >tok822_limit.tmp
diff tok822_limit.ref tok822_limit.tmp
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
--- /dev/null
+/*++
+/* NAME
+/* hold_message 3
+/* SUMMARY
+/* move message to hold queue
+/* SYNOPSIS
+/* #include <hold_message.h>
+/*
+/* 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 <sys_defs.h>
+#include <stdio.h> /* rename() */
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <set_eugid.h>
+
+/* Global library. */
+
+#include <mail_queue.h>
+#include <mail_params.h>
+#include <hold_message.h>
+
+#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);
+}
--- /dev/null
+#ifndef _HOLD_MESSAGE_H_INCLUDED_
+#define _HOLD_MESSAGE_H_INCLUDED_
+
+/*++
+/* NAME
+/* hold_message 3h
+/* SUMMARY
+/* mark queue file as corrupt
+/* SYNOPSIS
+/* #include <hold_message.h>
+/* 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
/* #include <mail_flush.h>
/*
/* 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
#include <mail_proto.h>
#include <mail_flush.h>
-/* mail_flush_deferred - flush deferred queue */
+/* mail_flush_deferred - flush deferred/incoming queue */
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)));
+}
/* External interface. */
extern int mail_flush_deferred(void);
+extern int mail_flush_maildrop(void);
/* LICENSE
/* .ad
#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.
*/
#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.
*/
* 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)
* 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
mime_state: warning: improper use of 8-bit data in message header: Header: f??bar
MAIN Header: f\80\80bar
HEADER END
-BODY
+BODY N
mime_state: warning: improper use of 8-bit data in message body: b?dy
-BODY b\80dy
+BODY N b\80dy
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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+mime-version: 1.0
+content-type: text/plain
+content-transfer-encoding: 8bit
+
+\ 1
+x\ 1
+xx\ 1
+xxx\ 1
+xxxx\ 1
+xxxxx\ 1
+xxxxxx\ 1
+xxxxxxx\ 1
+xxxxxxxx\ 1
+xxxxxxxxx\ 1
+xxxxxxxxxx\ 1
+xxxxxxxxxxx\ 1
+xxxxxxxxxxxx\ 1
+xxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ 1
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
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
{
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]); \
}
/*
/* 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));
/* 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);
}
* 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));
{
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);
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
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
/* 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
/* .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
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;
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
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[] = {
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 */
};
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;
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);
}
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);
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);
}
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));
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 */
/* 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
/* .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
/* 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.
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;
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
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[] = {
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,
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 */
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;
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);
}
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.
*/
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);
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);
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
/* 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;
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))
* 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;
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);
}
} 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,
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
/* .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
/* .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
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
+#include <syslog.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#include <mymalloc.h>
#include <iostuff.h>
#include <msg_vstream.h>
+#include <stringops.h>
/* Global library. */
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;
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 */
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)
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
/*
* 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)
/*
* 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);
}
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 {
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);
}
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);
}
}
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)
/*
* 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;
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++;
if ((fixed_delay = atoi(optarg)) <= 0)
usage(argv[0]);
break;
+ case '8':
+ disable_8bitmime = 1;
+ break;
default:
usage(argv[0]);
}
/*
* 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 {