-TCONFIG_INT_TABLE
-TCONFIG_STR_FN_TABLE
-TCONFIG_STR_TABLE
+-TCONFIG_TIME_FN_TABLE
+-TCONFIG_TIME_TABLE
-TDELIVER_ATTR
-TDELIVER_REQUEST
-TDICT
+Purpose of this document
+========================
+
+This document describes the purpose of the Postfix fast ETRN service,
+how the service works, and how it can be tested.
+
The Postfix fast ETRN service
=============================
The SMTP ETRN command was designed for sites that have intermittent
Internet connectivity. With ETRN, a site can tell the mail server
-of its network provider "Please deliver all my mail now".
+of its provider to "Please deliver all my mail now".
-Postfix versions before 20001001 implemented the ETRN command in
+Postfix versions before 20001003 implemented the ETRN command in
a lame manner: they would attempt to deliver all queued mail. This
is slow on mail servers that queue mail for many customers.
-The Postfix "fast ETRN" service speeds up deliveries by looking
+As of version 20001003, Postfix has a faster ETRN implementation.
+At the same time, the command "sendmail -qR" is now implemented by
+sending an ETRN command to the local SMTP server.
+
+Postfix "fast ETRN/sendmail -qR" speeds up deliveries by looking
only at mail that is queued for a given destination site. Postfix
"slow ETRN" is still used as a fall-back method.
-The "fast ETRN" service uses the new "fast flush" service which
-maintains per-destination logfiles of queued mail. The "fast flush"
-service is enabled by default:
-
- fast_flush_domains = $relay_domains
+How Postfix fast ETRN works
+===========================
-By default, Postfix "fast ETRN" service is available only for
-destinations that the local MTA is willing to relay mail to.
+The "fast ETRN" service uses the new "flush" daemon which maintains
+per-destination logfiles of queued mail. These logfiles are kept
+below /var/spool/postfix/flush. Each logfile is named after its
+destination domain name. Only destinations with syntactically valid
+domain names can have per-destination logfiles.
-To disable the "fast ETRN" service, specify an empty string:
+The behavior of the new "flush" daemon is controlled by parameters
+in the main.cf configuration file.
- fast_flush_domains =
+By default, Postfix "fast ETRN/sendmail -qR" service is available
+only for destinations that Postfix is willing to relay mail to:
-The syntax of the fast_flush_domains parameter is exactly the
-same as for the relay_domains parameter: a list of domain names,
-files with domain names, or maptype:mapname lookup tables where
-the right-hand side is ignored.
+ fast_flush_policy = relay
-For destinations that cannot have "fast ETRN" service, Postfix
-falls back to the old "slow ETRN" service that attempts to deliver
+The relay_domains parameter specifies what destinations Postfix
+will relay to. For destinations without "fast ETRN/sendmail -qR"
+service, Postfix falls back to the old "slow ETRN" which delivers
all queued mail.
-By default, every site can issue ETRN commands to your SMTP
-server:
+To enable "fast ETRN/sendmail -qR" for all destinations, specify:
- smtpd_etrn_restrictions =
+ fast_flush_policy = all
+
+To disable "fast ETRN/sendmail -qR", so that Postfix always uses
+the old "slow ETRN" which delivers all queued mail, specify:
+
+ fast_flush_policy = none
+
+Testing the fast ETRN service
+=============================
+
+If you run Postfix with "fast ETRN" service for the very first
+time, you need to run "sendmail -q" to populate the per-site deferred
+mail logfiles. If you omit this step, the logfiles will eventually
+become populated as Postfix routinely attempts to deliver delayed
+mail, but that will take a couple hours.
To test the "fast ETRN" service, telnet to the Postfix SMTP server
-from a client that is allowed to execute ETRN commands, and type:
+from a client that is allowed to execute ETRN commands (by default,
+that's every client), and type:
helo my.client.name
etrn some.customer.domain
where "some.customer.domain" is the name of a domain that your mail
-server is willing to relay mail to.
+server is willing to relay mail to, and that your server has some
+mail queued for.
+
+In the maillog file, you should immediately see a couple of logfile
+records, as evidence that the queue manager has opened queue files:
-In the maillog file, you should see something logged like:
+ Oct 2 10:51:19 localhost postfix/qmgr[51999]: 682E8440A4:
+ from=<whatever>, size=12345, nrcpt=1 (queue active)
+ Oct 2 10:51:19 localhost postfix/qmgr[51999]: 02249440B7:
+ from=<whatever>, size=4711, nrcpt=1 (queue active)
- created fast ETRN cache for some.customer.domain
+What happens next depends on whether the destination is reachable.
-It will then do a "slow ETRN" once. The next time the same ETRN
-command is given, Postfix will do "fast ETRN".
+Repeat the exercise with another domain that your server is willing
+to relay to, but that has no mail queued.
+
+ helo my.client.name
+ etrn some.other.customer.domain
-If Postfix logs that it cannot create a fast ETRN cache for
-"some.customer.domain", then execute the command "postfix check".
-You probably skipped some installation instructions so that the
-necessary directories were not created.
+This time, the "etrn" command should not trigger any mail deliveries
+at all.
+
+Finally, repeat the exercise with a destination that your mail
+server is not willing to relay to. It does not matter if your
+server has mail queued for that destination.
+
+ helo my.client.name
+ etrn not.a.customer.domain
-If Postfix logs that it uses slow ETRN service for "some.customer.domain",
-instead of creating a fast ETRN cache, then either "some.customer.domain"
-was not found in the DNS, or it was not listed as a valid fast ETRN
-destination. Check your fast_flush_domains or relay_domains settings.
+If your "fast ETRN" caching policy is left at its default setting,
+then the "etrn" command should trigger delivery of all queued mail.
rid of them. To disallow, specify "strict_rfc821_envelopes
= yes". File: smtpd/smtpd.c.
-20000926-8
+20000926-20001003
- First implementation of a logfile-based fast flush server,
- which is the basis for ETRN and "sendmail -qRsite".
+ Feature: a "flush" server that keeps per-destination records
+ of deferred mail. It is the basis of a faster ETRN and
+ "sendmail -qRsite" implementation. This code was rewritten
+ half a dozen times.
20000928
Robustness? Log errors from SASL library code as warnings
not as fatal errors. Files: smtp*/*glue.c.
+
+20001001
+
+ Feature: in master.cf, specify ? after wakeup time to avoid
+ waking up services that aren't being used.
+
+20001003
+
+ Feature: the fast flush refresh and purge time interval
+ parameters can now be specified in seconds or in user-specified
+ units by providing an appropriate suffix: s (seconds), m
+ (minutes), h (hours), d (days), w (weeks). unit. This
+ was needed so that I could test the flush server code in
+ a reasonable way. Other time parameters will be migrated
+ as time permits. Files: global/mail_conf_time.c,
+ postconf/postconf.c.
+
+ Unfeature: qmgr_hog_factor is now disabled by default. It
+ was just too confusing.
-Incompatible changes with snapshot-20000928
+Incompatible changes with snapshot-20001003
===========================================
If this release does not work for you, you can go back to a previous
After installing the new Postfix release:
-- Check the output from "postconf qmgr_message_active_limit". The
- recommended value has changed to 10000.
-
- If your setting is lower, either you need to remove the explicit
- setting from the main.cf file (so that Postfix uses the recommended
- default setting), or you need to update it.
-
- Check the output from "postconf hash_queue_names". The recommended
setting now includes the names of the "active", "bounce", "defer",
and "flush" directories.
file (so that Postfix uses the recommended default setting), or
you need to update it.
+- Check the output from "postconf qmgr_message_active_limit". The
+ recommended value has changed to 10000.
+
+ If your setting is lower, either you need to remove the explicit
+ setting from the main.cf file (so that Postfix uses the recommended
+ default setting), or you need to update it.
+
- Add a new entry to the master.cf file for the new flush service:
- flush unix - - n 18000? 0 flush
+ flush unix - - n 1000? 0 flush
- This entry is not needed if you won't use the fast flush service
- (this service is used by default; to disable, you need to specify
- in the main.cf file an empty fast_flush_domains parameter:
+ This entry is not needed if you won't use the fast flush service.
+ This service is used by default; to disable the fast flush service,
+ you need to specify in the main.cf file:
- fast_flush_domains =
+ fast_flush_policy = none
- The 18000? requests that the "fast flush" service does some
- cleaning up every 5 hours, but only if the fast flush service is
- being used by some other Postfix service, and the 0 means that
- Postfix should run as many flush servers as are needed, in order
- to avoid deadlock conditions.
+ In the new master.cf entry, the 1000? requests that the "fast
+ flush" service does some cleaning up every 15 minutes, but only
+ if the fast flush service is actually being used. The 0 means
+ that Postfix should run as many flush servers as are needed.
+ Changing this may cause deadlock.
Now you can start Postfix again.
-Major changes with snapshot-20000929
+Major changes with snapshot-20001001
====================================
In order to improve performance of one-to-one deliveries, Postfix
Until now, Postfix did a rather lame effort at implementing the
SMTP ETRN command - it attempted to deliver all mail in the queue,
regardless of its destination. This is slow if your mail server
-queues mail for lots of different sites.
-
-This release introduces "fast ETRN", which delivers only mail that
-is known to be queued for the specified site. Postfix now maintains
-so-called "fast flush" logfiles with information about what mail
-is queued for specific sites. A "fast flush" logfile is "flushed"
-after Postfix receives an appropriate ETRN command, or after someone
-executes the command "sendmail -qRsite" for an appropriate site.
-
-A missing "fast flush" logfile is created automatically when an
-SMTP client issues the ETRN command - but only for destinations
-that the local MTA is willing to relay mail to. This policy is
-controlled with the "fast_etrn_domains" configuration parameter
-(default: $relay_domains). Other destinations remain stuck with
-the old "slow ETRN" service that attempts to deliver all mail in
-the queue.
+queues mail for lots of different destinations.
+
+This release introduces fast "ETRN" and "sendmail -qR". Unlike
+their lame predecessor, these deliver only mail that is queued for
+the specified destinations.
+
+Postfix now maintains per-destination logfiles with information
+about what mail is queued for specific destinations. By default,
+these logfiles are maintained only for destinations that Postfix
+is willing to relay to (as controlled by the relay_domains parameter).
+
+The maintenance policy for deferred mail logfiles is selected with
+the "fast_flush_policy" configuration parameter. Possible values
+are: "all" (maintain logs for all destinations), "relay" (maintain
+logs for relay destinations) or "none" (maintain no logs).
+
+Postfix falls back to the old slow ETRN for destinations that are
+not eligible for the fast "ETRN" and "sendmail -qR" service.
See the file ETRN_README for details.
# FAST ETRN SERVICE
#
-# By default, Postfix does a rather lame effort at implementing the
-# SMTP ETRN command - it attempts to deliver all queued mail regardless
-# of its destination. This does not work well if your mail server
-# queues mail for lots of sites. In order to enable a faster ETRN
-# that only delivers mail that is known to be queued for a site,
-# enable the fast flush cache. Currently, "fast ETRN" is available
-# only for destinations that the local system is willing to relay
-# mail to (as specified in the relay_domains parameter).
+# Postfix maintains per-destination logfiles with information about
+# deferred mail, so that mail can be flushed quickly with the SMTP
+# "ETRN domain.name" command, or by executing "sendmail -qRdomain.name".
#
-#enable_fast_flush = yes
-#enable_fast_flush = no
+# By default, Postfix maintains deferred mail logfile information
+# only for destinations that Postfix is willing to relay to (as
+# specified in the relay_domains parameter). For other destinations,
+# Postfix attempts to deliver ALL queued mail after receiving the
+# SMTP "ETRN domain.name" command, or after execution of "sendmail
+# -qRdomain.name". This can be slow when a lot of mail is queued.
+#
+# The fast_flush_policy controls what destinations are eligible for
+# this "fast ETRN/sendmail -qR" service. Specify "all" to make all
+# destinations eligible, "relay" for relay destinations only, and
+# "none" to turn this feature off.
+#
+#fast_flush_policy = all
+#fast_flush_policy = relay
+#fast_flush_policy = none
# SHOW SOFTWARE VERSION OR NOT
#
rewrite unix - - n - - trivial-rewrite
bounce unix - - n - 0 bounce
defer unix - - n - 0 bounce
-flush unix - - n 18000? 0 flush
+flush unix - - n 1000? 0 flush
smtp unix - - n - - smtp
showq unix n - n - - showq
error unix - - n - - error
<b>NAME</b>
- flush - Postfix fast flush daemon
+ flush - Postfix fast flush cache manager
<b>SYNOPSIS</b>
<b>flush</b> [generic Postfix daemon options]
<b>DESCRIPTION</b>
- The flush server maintains so-called "fast flush" logfiles
- with information about what messages are queued for a spe-
- cific site. This program expects to be run from the <a href="master.8.html"><b>mas-</b>
- <b>ter</b>(8)</a> process manager.
+ The flush server maintains a record of deferred mail by
+ destination. This information is used to improve the per-
+ formance of the SMTP <b>ETRN</b> request, and of its command-line
+ equivalent, <b>sendmail</b> <b>-qR</b>. This program expects to be run
+ from the <a href="master.8.html"><b>master</b>(8)</a> process manager.
- This server implements the following requests:
+ The record is implemented as per-destination logfiles with
+ as contents the queue IDs of deferred mail. The files are
+ append-only, and are truncated when delivery is requested
+ for a specific site.
+
+ Deferred mail by destination information is recorded only
+ for destinations that are eligible according to a config-
+ urable policy. The policy is specified with the
+ <b>fast</b><i>_</i><b>flush</b><i>_</i><b>cache</b><i>_</i><b>policy</b> configuration parameter:
- <b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>ENABLE</b> <i>sitename</i>
- Enable fast flush logging for the specified site.
+ <b>all</b> Maintain per-destination deferred mail logfiles for
+ all destinations.
- <b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>APPEND</b> <i>sitename</i> <i>queue_id</i>
- Append <i>queue_id</i> to the fast flush log for the spec-
- ified site.
+ <b>relay</b> Maintain per-destination deferred mail logfiles
+ only for destinations that this system is willing
+ to relay mail to ($<b>relay</b><i>_</i><b>domains</b>).
+
+ <b>none</b> Do not maintain per-destination deferred mail log-
+ files.
+
+ This server implements the following requests:
+
+ <b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>ADD</b> <i>sitename</i> <i>queue_id</i>
+ Inform the cache manager that the specified message
+ is queued for the specified site. Depending on
+ caching policy, the cache manager stores or ignores
+ the information.
<b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>SEND</b> <i>sitename</i>
- Arrange for the delivery of all messages that are
- listed in the fast flush logfile for the specified
- site. After the logfile is processed, the file is
- truncated to length zero.
+ Request delivery of all messages that are queued
+ for the specified site. Depending on cache policy,
+ this triggers delivery of specific messages or of
+ all queued mail. The per-destination logfile is
+ discarded.
<b>TRIGGER</b><i>_</i><b>REQ</b><i>_</i><b>WAKEUP</b> (wakeup signal from master)
<b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>PURGE</b>
- Pretend that <b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>SEND</b> was received for all
- sites with a non-empty "fast flush" logfile, and
- delete empty "fast flush" logfiles that have not
- been updated in several days. This operation com-
- pletes in the background because it can take a
- noticeable amount of time.
-
- Fast flush logfiles are truncated only after a
- <b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>SEND</b> request, not when mail is actually
- delivered, and therefore can accumulate redundant
- or even outdated information. In order to maintain
- sanity, <b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>PURGE</b> must be requested occasion-
- ally.
+ Delete empty per-destination logfiles that haven't
+ been updated in $<b>fast</b><i>_</i><b>flush</b><i>_</i><b>purge</b><i>_</i><b>delay</b> seconds.
- The response to the client is one of:
- <b>FLUSH</b><i>_</i><b>STAT</b><i>_</i><b>OK</b>
- The request completed normally.
- <b>FLUSH</b><i>_</i><b>STAT</b><i>_</i><b>BAD</b>
- The flush server rejected the request (bad request
- name, bad request parameter value).
+
+ 1
- 1
+FLUSH(8) FLUSH(8)
+ Refresh non-empty per-destination logfiles that
+ were not read in $<b>fast</b><i>_</i><b>flush</b><i>_</i><b>refresh</b><i>_</i><b>delay</b> seconds.
+ This is done by pretending that send requests were
+ received for the corresponding sites.
+ Fast flush logfiles are truncated only after a
+ <b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>SEND</b> request, not when mail is actually
+ delivered, and therefore can accumulate outdated or
+ redundant data. In order to maintain sanity,
+ <b>FLUSH</b><i>_</i><b>REQ</b><i>_</i><b>PURGE</b> should be requested at regular
+ imtervals.
+ After an initial sanity check of request parame-
+ ters, this request proceeds in the background.
-FLUSH(8) FLUSH(8)
+ The response to the client is one of:
+ <b>FLUSH</b><i>_</i><b>STAT</b><i>_</i><b>OK</b>
+ The request completed normally.
- <b>FLUSH</b><i>_</i><b>STAT</b><i>_</i><b>UNKNOWN</b>
- The specified site has no fast flush log.
+ <b>FLUSH</b><i>_</i><b>STAT</b><i>_</i><b>BAD</b>
+ The flush server rejected the request (bad request
+ name, bad request parameter value).
+
+ <b>FLUSH</b><i>_</i><b>STAT</b><i>_</i><b>FAIL</b>
+ The request failed.
<b>SECURITY</b>
The fast flush server is not security-sensitive. It does
Problems and transactions are logged to <b>syslogd</b>(8).
<b>BUGS</b>
- In reality, this server schedules delivery of messages,
- regardless of their destination. This limitation is due to
- the fact that one queue runner has to handle mail for mul-
- tiple destinations.
+ In reality, this server schedules delivery of all recipi-
+ ents of deferred messages. This limitation is due to the
+ fact that one queue runner has to handle mail for multiple
+ destinations.
+
+<b>FILES</b>
+ /var/spool/postfix/flush, location of "fast flush" logfiles.
+
+<b>CONFIGURATION</b> <b>PARAMETERS</b>
+ 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>fast</b><i>_</i><b>flush</b><i>_</i><b>cache</b><i>_</i><b>policy</b>
+ What destinations can have a "fast flush" logfile:
+ <b>all</b>, <b>relay</b> (relay destinations) or <b>none</b>.
+
+
+
+
+ 2
+
+
+
+
+
+FLUSH(8) FLUSH(8)
+
+
+ <b>fast</b><i>_</i><b>flush</b><i>_</i><b>refresh</b><i>_</i><b>delay</b>
+ Refresh a non-empty "fast flush" logfile that was
+ not read in this amount of time, by simulating a
+ send request for the corresponding destination.
+
+ <b>fast</b><i>_</i><b>flush</b><i>_</i><b>purge</b><i>_</i><b>delay</b>
+ Remove an empty "fast flush" logfile that was not
+ updated in this amount of time.
<b>SEE</b> <b>ALSO</b>
<a href="smtpd.8.html">smtpd(8)</a> Postfix SMTP server
- 2
+
+
+
+
+
+
+
+
+
+ 3
</pre> </body> </html>
SMTP session before it is penalized with tarpit
delays.
-<b>ETRN</b> <b>controls</b>
- <b>smtpd</b><i>_</i><b>etrn</b><i>_</i><b>restrictions</b>
- Restrict what domain names can be used in <b>ETRN</b> com-
- mands, and what clients may issue <b>ETRN</b> commands.
-
- <b>fast</b><i>_</i><b>flush</b><i>_</i><b>domains</b>
- The destinations that this system is willing to
- provide "fast ETRN" service for. By default, "fast
- ETRN" service is available only for destinations
- that the local system is willing to relay mail to.
- For other destinations, Postfix simply attempts to
- deliver all mail in the queue.
-
<b>UCE</b> <b>control</b> <b>restrictions</b>
<b>smtpd</b><i>_</i><b>client</b><i>_</i><b>restrictions</b>
Restrict what clients may connect to this mail sys-
Restrict what sender addresses are allowed in <b>MAIL</b>
<b>FROM</b> commands.
+ <b>smtpd</b><i>_</i><b>recipient</b><i>_</i><b>restrictions</b>
+ Restrict what recipient addresses are allowed in
+ <b>RCPT</b> <b>TO</b> commands.
+
+ <b>smtpd</b><i>_</i><b>etrn</b><i>_</i><b>restrictions</b>
+ Restrict what domain names can be used in <b>ETRN</b> com-
+ mands, and what clients may issue <b>ETRN</b> commands.
+
+ <b>allow</b><i>_</i><b>untrusted</b><i>_</i><b>routing</b>
+ Allow untrusted clients to specify addresses with
+ sender-specified routing. Enabling this opens up
+ nasty relay loopholes involving trusted backup MX
+
4
SMTPD(8) SMTPD(8)
- <b>smtpd</b><i>_</i><b>recipient</b><i>_</i><b>restrictions</b>
- Restrict what recipient addresses are allowed in
- <b>RCPT</b> <b>TO</b> commands.
-
- <b>allow</b><i>_</i><b>untrusted</b><i>_</i><b>routing</b>
- Allow untrusted clients to specify addresses with
- sender-specified routing. Enabling this opens up
- nasty relay loopholes involving trusted backup MX
hosts.
<b>restriction</b><i>_</i><b>classes</b>
- Declares the name of zero or more parameters that
- contain a list of UCE restrictions. The names of
- these parameters can then be used instead of the
+ Declares the name of zero or more parameters that
+ contain a list of UCE restrictions. The names of
+ these parameters can then be used instead of the
restriction lists that they represent.
<b>maps</b><i>_</i><b>rbl</b><i>_</i><b>domains</b>
- List of DNS domains that publish the addresses of
+ List of DNS domains that publish the addresses of
blacklisted hosts.
<b>relay</b><i>_</i><b>domains</b>
- Restrict what domains or networks this mail system
+ Restrict what domains or networks this mail system
will relay mail from or to.
<b>UCE</b> <b>control</b> <b>responses</b>
<b>access</b><i>_</i><b>map</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client violates an access
+ Server response when a client violates an access
database restriction.
<b>invalid</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client violates the
+ Server response when a client violates the
<b>reject</b><i>_</i><b>invalid</b><i>_</i><b>hostname</b> restriction.
<b>maps</b><i>_</i><b>rbl</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client violates the
+ Server response when a client violates the
<b>maps</b><i>_</i><b>rbl</b><i>_</i><b>domains</b> restriction.
<b>reject</b><i>_</i><b>code</b>
- Response code when the client matches a <b>reject</b>
+ Response code when the client matches a <b>reject</b>
restriction.
<b>relay</b><i>_</i><b>domains</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client attempts to violate
+ Server response when a client attempts to violate
the mail relay policy.
<b>unknown</b><i>_</i><b>address</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client violates the
+ Server response when a client violates the
<b>reject</b><i>_</i><b>unknown</b><i>_</i><b>address</b> restriction.
<b>unknown</b><i>_</i><b>client</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client without address to
- name mapping violates the <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>clients</b>
+ Server response when a client without address to
+ name mapping violates the <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>clients</b>
restriction.
+ <b>unknown</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
+ Server response when a client violates the
+ <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>hostname</b> restriction.
+
+<b>SEE</b> <b>ALSO</b>
+ <a href="cleanup.8.html">cleanup(8)</a> message canonicalization
+ <a href="master.8.html">master(8)</a> process manager
+ syslogd(8) system logging
SMTPD(8) SMTPD(8)
- <b>unknown</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Server response when a client violates the
- <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>hostname</b> restriction.
-
-<b>SEE</b> <b>ALSO</b>
- <a href="cleanup.8.html">cleanup(8)</a> message canonicalization
- <a href="master.8.html">master(8)</a> process manager
- syslogd(8) system logging
-
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
+
+
+
+
+
+
+
+
+
.SH NAME
flush
\-
-Postfix fast flush daemon
+Postfix fast flush cache manager
.SH SYNOPSIS
.na
.nf
.SH DESCRIPTION
.ad
.fi
-The flush server maintains so-called "fast flush" logfiles with
-information about what messages are queued for a specific site.
+The flush server maintains a record of deferred mail by destination.
+This information is used to improve the performance of the SMTP
+\fBETRN\fR request, and of its command-line equivalent,
+\fBsendmail -qR\fR.
This program expects to be run from the \fBmaster\fR(8) process
manager.
+The record is implemented as per-destination logfiles with
+as contents the queue IDs of deferred mail. The files are
+append-only, and are truncated when delivery is requested
+for a specific site.
+
+Deferred mail by destination information is recorded only for
+destinations that are eligible according to a configurable policy.
+The policy is specified with the \fBfast_flush_cache_policy\fR
+configuration parameter:
+.IP \fBall\fR
+Maintain per-destination deferred mail logfiles for all destinations.
+.IP \fBrelay\fR
+Maintain per-destination deferred mail logfiles only for destinations
+that this system is willing to relay mail to ($\fBrelay_domains\fR).
+.IP \fBnone\fR
+Do not maintain per-destination deferred mail logfiles.
+.PP
This server implements the following requests:
-.IP "\fBFLUSH_REQ_ENABLE\fI sitename\fR"
-Enable fast flush logging for the specified site.
-.IP "\fBFLUSH_REQ_APPEND\fI sitename queue_id\fR"
-Append \fIqueue_id\fR to the fast flush log for the
-specified site.
+.IP "\fBFLUSH_REQ_ADD\fI sitename queue_id\fR"
+Inform the cache manager that the specified message is queued for
+the specified site. Depending on caching policy, the cache manager
+stores or ignores the information.
.IP "\fBFLUSH_REQ_SEND\fI sitename\fR"
-Arrange for the delivery of all messages that are listed in the fast
-flush logfile for the specified site. After the logfile is processed,
-the file is truncated to length zero.
+Request delivery of all messages that are queued for the specified
+site. Depending on cache policy, this triggers delivery of specific
+messages or of all queued mail. The per-destination logfile is
+discarded.
.IP "\fBTRIGGER_REQ_WAKEUP\fR (wakeup signal from master)"
.IP "\fBFLUSH_REQ_PURGE\fR"
-Pretend that \fBFLUSH_REQ_SEND\fR was received for all sites with
-a non-empty "fast flush" logfile, and delete empty "fast flush"
-logfiles that have not been updated in several days. This operation
-completes in the background because it can take a noticeable
-amount of time.
+Delete empty per-destination logfiles that haven't been updated in
+$\fBfast_flush_purge_delay\fR seconds.
+.sp
+Refresh non-empty per-destination logfiles that were not read in
+$\fBfast_flush_refresh_delay\fR seconds. This is done by pretending
+that send requests were received for the corresponding sites.
.sp
Fast flush logfiles are truncated only after a \fBFLUSH_REQ_SEND\fR
request, not when mail is actually delivered, and therefore can
-accumulate redundant or even outdated information. In order to
-maintain sanity, \fBFLUSH_REQ_PURGE\fR must be requested occasionally.
+accumulate outdated or redundant data. In order to maintain sanity,
+\fBFLUSH_REQ_PURGE\fR should be requested at regular imtervals.
+.sp
+After an initial sanity check of request parameters, this request
+proceeds in the background.
.PP
The response to the client is one of:
.IP \fBFLUSH_STAT_OK\fR
.IP \fBFLUSH_STAT_BAD\fR
The flush server rejected the request (bad request name, bad
request parameter value).
-.IP \fBFLUSH_STAT_UNKNOWN\fR
-The specified site has no fast flush log.
+.IP \fBFLUSH_STAT_FAIL\fR
+The request failed.
.SH SECURITY
.na
.nf
.SH BUGS
.ad
.fi
-In reality, this server schedules delivery of messages, regardless
-of their destination. This limitation is due to the fact that
+In reality, this server schedules delivery of all recipients
+of deferred messages. This limitation is due to the fact that
one queue runner has to handle mail for multiple destinations.
+.SH FILES
+.na
+.nf
+/var/spool/postfix/flush, location of "fast flush" logfiles.
+.SH CONFIGURATION PARAMETERS
+.na
+.nf
+.ad
+.fi
+See the Postfix \fBmain.cf\fR file for syntax details and for
+default values. Use the \fBpostfix reload\fR command after a
+configuration change.
+.IP \fBfast_flush_cache_policy\fR
+What destinations can have a "fast flush" logfile: \fBall\fR,
+\fBrelay\fR (relay destinations) or \fBnone\fR.
+.IP \fBfast_flush_refresh_delay\fR
+Refresh a non-empty "fast flush" logfile that was not read in
+this amount of time, by simulating a send request for the
+corresponding destination.
+.IP \fBfast_flush_purge_delay\fR
+Remove an empty "fast flush" logfile that was not updated in
+this amount of time.
.SH SEE ALSO
.na
.nf
Limit the number of times a client can issue a junk command
such as NOOP, VRFY, ETRN or RSET in one SMTP session before
it is penalized with tarpit delays.
-.SH "ETRN controls"
-.ad
-.fi
-.IP \fBsmtpd_etrn_restrictions\fR
-Restrict what domain names can be used in \fBETRN\fR commands,
-and what clients may issue \fBETRN\fR commands.
-.IP \fBfast_flush_domains\fR
-The destinations that this system is willing to provide "fast ETRN"
-service for. By default, "fast ETRN" service is available only
-for destinations that the local system is willing to relay mail to.
-For other destinations, Postfix simply attempts to deliver all mail
-in the queue.
.SH "UCE control restrictions"
.ad
.fi
Restrict what sender addresses are allowed in \fBMAIL FROM\fR commands.
.IP \fBsmtpd_recipient_restrictions\fR
Restrict what recipient addresses are allowed in \fBRCPT TO\fR commands.
+.IP \fBsmtpd_etrn_restrictions\fR
+Restrict what domain names can be used in \fBETRN\fR commands,
+and what clients may issue \fBETRN\fR commands.
.IP \fBallow_untrusted_routing\fR
Allow untrusted clients to specify addresses with sender-specified
routing. Enabling this opens up nasty relay loopholes involving
flush.o: ../../include/htable.h
flush.o: ../../include/dict.h
flush.o: ../../include/argv.h
+flush.o: ../../include/scan_dir.h
flush.o: ../../include/mail_params.h
flush.o: ../../include/mail_queue.h
flush.o: ../../include/mail_proto.h
flush.o: ../../include/iostuff.h
flush.o: ../../include/mail_flush.h
+flush.o: ../../include/flush_clnt.h
flush.o: ../../include/mail_conf.h
+flush.o: ../../include/mail_scan_dir.h
flush.o: ../../include/maps.h
+flush.o: ../../include/domain_list.h
flush.o: ../../include/mail_server.h
/* NAME
/* flush 8
/* SUMMARY
-/* Postfix fast flush daemon
+/* Postfix fast flush cache manager
/* SYNOPSIS
/* \fBflush\fR [generic Postfix daemon options]
/* DESCRIPTION
-/* The flush server maintains so-called "fast flush" logfiles with
-/* information about what messages are queued for a specific site.
+/* The flush server maintains a record of deferred mail by destination.
+/* This information is used to improve the performance of the SMTP
+/* \fBETRN\fR request, and of its command-line equivalent,
+/* \fBsendmail -qR\fR.
/* This program expects to be run from the \fBmaster\fR(8) process
/* manager.
/*
+/* The record is implemented as per-destination logfiles with
+/* as contents the queue IDs of deferred mail. The files are
+/* append-only, and are truncated when delivery is requested
+/* for a specific site.
+/*
+/* Deferred mail by destination information is recorded only for
+/* destinations that are eligible according to a configurable policy.
+/* The policy is specified with the \fBfast_flush_cache_policy\fR
+/* configuration parameter:
+/* .IP \fBall\fR
+/* Maintain per-destination deferred mail logfiles for all destinations.
+/* .IP \fBrelay\fR
+/* Maintain per-destination deferred mail logfiles only for destinations
+/* that this system is willing to relay mail to ($\fBrelay_domains\fR).
+/* .IP \fBnone\fR
+/* Do not maintain per-destination deferred mail logfiles.
+/* .PP
/* This server implements the following requests:
-/* .IP "\fBFLUSH_REQ_ENABLE\fI sitename\fR"
-/* Enable fast flush logging for the specified site.
-/* .IP "\fBFLUSH_REQ_APPEND\fI sitename queue_id\fR"
-/* Append \fIqueue_id\fR to the fast flush log for the
-/* specified site.
+/* .IP "\fBFLUSH_REQ_ADD\fI sitename queue_id\fR"
+/* Inform the cache manager that the specified message is queued for
+/* the specified site. Depending on caching policy, the cache manager
+/* stores or ignores the information.
/* .IP "\fBFLUSH_REQ_SEND\fI sitename\fR"
-/* Arrange for the delivery of all messages that are listed in the fast
-/* flush logfile for the specified site. After the logfile is processed,
-/* the file is truncated to length zero.
+/* Request delivery of all messages that are queued for the specified
+/* site. Depending on cache policy, this triggers delivery of specific
+/* messages or of all queued mail. The per-destination logfile is
+/* discarded.
/* .IP "\fBTRIGGER_REQ_WAKEUP\fR (wakeup signal from master)"
/* .IP "\fBFLUSH_REQ_PURGE\fR"
-/* Pretend that \fBFLUSH_REQ_SEND\fR was received for all sites with
-/* a non-empty "fast flush" logfile, and delete empty "fast flush"
-/* logfiles that have not been updated in several days. This operation
-/* completes in the background because it can take a noticeable
-/* amount of time.
+/* Delete empty per-destination logfiles that haven't been updated in
+/* $\fBfast_flush_purge_delay\fR seconds.
+/* .sp
+/* Refresh non-empty per-destination logfiles that were not read in
+/* $\fBfast_flush_refresh_delay\fR seconds. This is done by pretending
+/* that send requests were received for the corresponding sites.
/* .sp
/* Fast flush logfiles are truncated only after a \fBFLUSH_REQ_SEND\fR
-/* request, not when mail is actually delivered, and therefore can
-/* accumulate redundant or even outdated information. In order to
-/* maintain sanity, \fBFLUSH_REQ_PURGE\fR must be requested occasionally.
+/* request, not when mail is actually delivered, and therefore can
+/* accumulate outdated or redundant data. In order to maintain sanity,
+/* \fBFLUSH_REQ_PURGE\fR should be requested at regular imtervals.
+/* .sp
+/* After an initial sanity check of request parameters, this request
+/* proceeds in the background.
/* .PP
/* The response to the client is one of:
/* .IP \fBFLUSH_STAT_OK\fR
/* .IP \fBFLUSH_STAT_BAD\fR
/* The flush server rejected the request (bad request name, bad
/* request parameter value).
-/* .IP \fBFLUSH_STAT_UNKNOWN\fR
-/* The specified site has no fast flush log.
+/* .IP \fBFLUSH_STAT_FAIL\fR
+/* The request failed.
/* SECURITY
/* .ad
/* .fi
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* BUGS
-/* In reality, this server schedules delivery of messages, regardless
-/* of their destination. This limitation is due to the fact that
+/* In reality, this server schedules delivery of all recipients
+/* of deferred messages. This limitation is due to the fact that
/* one queue runner has to handle mail for multiple destinations.
+/* FILES
+/* /var/spool/postfix/flush, location of "fast flush" logfiles.
+/* CONFIGURATION PARAMETERS
+/* .ad
+/* .fi
+/* See the Postfix \fBmain.cf\fR file for syntax details and for
+/* default values. Use the \fBpostfix reload\fR command after a
+/* configuration change.
+/* .IP \fBfast_flush_cache_policy\fR
+/* What destinations can have a "fast flush" logfile: \fBall\fR,
+/* \fBrelay\fR (relay destinations) or \fBnone\fR.
+/* .IP \fBfast_flush_refresh_delay\fR
+/* Refresh a non-empty "fast flush" logfile that was not read in
+/* this amount of time, by simulating a send request for the
+/* corresponding destination.
+/* .IP \fBfast_flush_purge_delay\fR
+/* Remove an empty "fast flush" logfile that was not updated in
+/* this amount of time.
/* SEE ALSO
/* smtpd(8) Postfix SMTP server
/* qmgr(8) Postfix queue manager
#include <mail_queue.h>
#include <mail_proto.h>
#include <mail_flush.h>
+#include <flush_clnt.h>
#include <mail_conf.h>
#include <mail_scan_dir.h>
#include <maps.h>
+#include <domain_list.h>
/* Single server skeleton. */
/* Application-specific. */
-#define STR(x) vstring_str(x)
+ /*
+ * Tunable parameters.
+ */
+int var_fflush_refresh;
+int var_fflush_purge;
+char *var_relay_domains;
+
+ /*
+ * Flush policy stuff.
+ */
+#define FLUSH_POLICY_UNKNOWN 0
+#define FLUSH_POLICY_ALL 1
+#define FLUSH_POLICY_RELAY 2
+#define FLUSH_POLICY_NONE 3
+
+static DOMAIN_LIST *flush_domains;
+static int flush_policy = FLUSH_POLICY_UNKNOWN;
+
+ /*
+ * Some hard-wired policy: how many queue IDs we remember while we're
+ * flushing a logfile.
+ */
#define FLUSH_DUP_FILTER_SIZE 10000 /* graceful degradation */
-#define FLUSH_MAX_UNUSED (7 * 24 * 60 * 60)
-/* flush_append - append queue ID to per-site fast flush log */
+ /*
+ * Silly little macros.
+ */
+
+#define STR(x) vstring_str(x)
+#define STREQ(x,y) (strcmp(x,y) == 0)
+
+/* flush_policy_init - initialize fast flush policy stuff */
-static int flush_append(const char *site, const char *queue_id)
+static int flush_policy_init(void)
{
- char *myname = "flush_append";
+
+ if (STREQ(var_fflush_policy, FFLUSH_POLICY_ALL)) {
+ flush_policy = FLUSH_POLICY_ALL;
+ } else if (STREQ(var_fflush_policy, FFLUSH_POLICY_RELAY)) {
+ flush_domains = domain_list_init(var_relay_domains);
+ flush_policy = FLUSH_POLICY_RELAY;
+ } else if (STREQ(var_fflush_policy, FFLUSH_POLICY_NONE)) {
+ flush_policy = FLUSH_POLICY_NONE;
+ } else {
+ msg_fatal("invalid %s configuration parameter value: %s",
+ VAR_FFLUSH_POLICY, var_fflush_policy);
+ }
+}
+
+/* flush_policy_ok - check caching policy */
+
+static int flush_policy_ok(const char *site)
+{
+ if (flush_policy == FLUSH_POLICY_UNKNOWN)
+ flush_policy_init();
+
+ switch (flush_policy) {
+ case FLUSH_POLICY_ALL:
+ return (1);
+ case FLUSH_POLICY_RELAY:
+ return (domain_list_match(flush_domains, site));
+ case FLUSH_POLICY_NONE:
+ return (0);
+ default:
+ msg_panic("invalid fast flush policy %d", flush_policy);
+ }
+}
+
+/* flush_add_service - append queue ID to per-site fast flush log */
+
+static int flush_add_service(const char *site, const char *queue_id)
+{
+ char *myname = "flush_add_service";
VSTREAM *log;
if (msg_verbose)
msg_info("%s: site %s queue_id %s", myname, site, queue_id);
/*
- * Open the logfile.
+ * If this site is not eligible for caching, just ignore the request.
*/
- if ((log = mail_queue_open(MAIL_QUEUE_FLUSH, site, O_APPEND | O_WRONLY, 0600)) == 0) {
- if (errno != ENOENT)
- msg_fatal("%s: open fast flush log for site %s: %m", myname, site);
- return (FLUSH_STAT_UNKNOWN);
- }
+ if (flush_policy_ok(site) == 0)
+ return (FLUSH_STAT_OK);
+
+ /*
+ * Open the logfile or bust.
+ */
+ if ((log = mail_queue_open(MAIL_QUEUE_FLUSH, site,
+ O_CREAT | O_APPEND | O_WRONLY, 0600)) == 0)
+ msg_fatal("%s: open fast flush log for site %s: %m",
+ myname, site);
/*
* We must lock the logfile, so that we don't lose information due to
return (FLUSH_STAT_OK);
}
-/* flush_site - flush mail queued for site */
+/* flush_send_service - flush mail queued for site */
-static int flush_site(const char *site)
+static int flush_send_service(const char *site)
{
- char *myname = "flush_site";
+ char *myname = "flush_send_service";
VSTRING *queue_id;
VSTRING *queue_file;
VSTREAM *log;
msg_info("%s: site %s", myname, site);
/*
- * Open the logfile.
+ * If this site is not eligible for caching, deliver all queued mail.
+ */
+ if (flush_policy_ok(site) == 0)
+ return (mail_flush_deferred());
+
+ /*
+ * Open the logfile. If the file does not exist, then there is no queued
+ * mail for this destination.
*/
if ((log = mail_queue_open(MAIL_QUEUE_FLUSH, site, O_RDWR, 0600)) == 0) {
if (errno != ENOENT)
msg_fatal("%s: open fast flush log for site %s: %m", myname, site);
- return (FLUSH_STAT_UNKNOWN);
+ return (FLUSH_STAT_OK);
}
/*
/*
* This is the part that dominates running time: schedule the listed
* queue files for delivery by updating their file time stamps. This
- * should take no more than a couple seconds under normal conditions
- * (sites that receive millions of messages in a day should not use fast
- * flush service). Filter out duplicate names to avoid hammering the file
- * system, with some finite limit on the amount of memory that we are
- * willing to sacrifice. Graceful degradation.
+ * should take no more than a couple seconds under normal conditions.
+ * Filter out duplicate names to avoid hammering the file system, with
+ * some finite limit on the amount of memory that we are willing to
+ * sacrifice. Graceful degradation.
*/
queue_id = vstring_alloc(10);
queue_file = vstring_alloc(10);
msg_warn("%s: update %s time stamps: %m",
myname, STR(queue_file));
} else if (mail_queue_rename(STR(queue_id), MAIL_QUEUE_DEFERRED,
- MAIL_QUEUE_INCOMING) < 0
- && errno != ENOENT)
- msg_warn("%s: rename from %s to %s: %m",
- STR(queue_file), MAIL_QUEUE_DEFERRED,
- MAIL_QUEUE_INCOMING);
+ MAIL_QUEUE_INCOMING) < 0) {
+ if (errno != ENOENT)
+ msg_warn("%s: rename from %s to %s: %m",
+ STR(queue_file), MAIL_QUEUE_DEFERRED,
+ MAIL_QUEUE_INCOMING);
+ }
} else {
if (msg_verbose)
msg_info("%s: site %s: skip file %s as duplicate",
* Truncate the fast flush log.
*/
if (count > 0 && ftruncate(vstream_fileno(log), (off_t) 0) < 0)
- msg_fatal("%s: truncate fast flush log for site %s: %m",
- myname, site);
+ msg_fatal("%s: truncate fast flush log for site %s: %m", myname, site);
/*
* Request delivery and clean up.
return (FLUSH_STAT_OK);
}
-/* flush_enable - enable fast flush logging for site */
+/* flush_purge_service - housekeeping */
-static int flush_enable(const char *site)
+static int flush_purge_service(void)
{
- char *myname = "flush_enable";
- VSTREAM *log;
-
- if (msg_verbose)
- msg_info("%s: site %s", myname, site);
-
- /*
- * Open or create the logfile. Multiple requests may arrive in parallel,
- * so allow for the possibility that the file already exists.
- */
- if ((log = mail_queue_open(MAIL_QUEUE_FLUSH, site, O_CREAT | O_RDWR, 0600)) == 0)
- msg_fatal("%s: open fast flush log for site %s: %m", myname, site);
-
- if (vstream_fclose(log) != 0)
- msg_warn("write fast flush log for site %s: %m", site);
-
- return (FLUSH_STAT_OK);
-}
-
-/* flush_purge - housekeeping */
-
-static void flush_purge(void)
-{
- char *myname = "flush_purge";
+ char *myname = "flush_purge_service";
SCAN_DIR *scan;
char *site;
struct stat st;
scan = scan_dir_open(MAIL_QUEUE_FLUSH);
while ((site = mail_scan_dir_next(scan)) != 0) {
+ mail_queue_path(path, MAIL_QUEUE_FLUSH, site);
if (valid_hostname(site) == 0) {
- msg_warn("%s: bad fast flush logfile name: %s", myname, STR(path));
+ msg_warn("%s: bad fast flush logfile name: %s", myname, site);
if (unlink(STR(path)) < 0)
msg_warn("remove %s: %m", STR(path));
continue;
}
- if (stat(mail_queue_path(path, MAIL_QUEUE_FLUSH, site), &st) < 0) {
+ if (stat(STR(path), &st) < 0) {
if (errno != ENOENT)
msg_warn("%s: stat %s: %m", myname, STR(path));
else if (msg_verbose)
continue;
}
if (st.st_size == 0) {
- if (st.st_mtime + FLUSH_MAX_UNUSED < event_time()) {
+ if (st.st_mtime + var_fflush_purge < event_time()) {
if (unlink(STR(path)) < 0)
msg_warn("remove %s: %m", STR(path));
else if (msg_verbose)
- msg_info("%s: unlink %s, unused for %d days",
- myname, STR(path), FLUSH_MAX_UNUSED / 84600);
+ msg_info("%s: unlink %s, empty and unchanged for %d days",
+ myname, STR(path), var_fflush_purge / 86400);
} else if (msg_verbose)
msg_info("%s: skip site %s - empty log", myname, site);
- } else {
+ } else if (st.st_atime + var_fflush_refresh < event_time()) {
if (msg_verbose)
msg_info("%s: flush site %s", myname, site);
- flush_site(site);
+ flush_send_service(site);
+ } else {
+ if (msg_verbose)
+ msg_info("%s: skip site %s, unread for <%d hours(s) ",
+ myname, site, var_fflush_refresh / 3600);
}
}
scan_dir_close(scan);
vstring_free(path);
+
+ return (FLUSH_STAT_OK);
}
/* flush_service - perform service for client */
char **argv)
{
VSTRING *request = vstring_alloc(10);
- VSTRING *site = vstring_alloc(10);
- VSTRING *queue_id = vstring_alloc(10);
- int status = FLUSH_STAT_BAD;
+ VSTRING *site = 0;
+ VSTRING *queue_id = 0;
static char wakeup[] = { /* master wakeup request */
TRIGGER_REQ_WAKEUP,
0,
};
+ int status = FLUSH_STAT_OK;
/*
* Sanity check. This service takes no command-line arguments.
*
* All connection-management stuff is handled by the common code in
* single_server.c.
- *
- * Note that the purge operation only acknowledges receipt of the request
- * and proceeds in the background. All other operations send their result
- * status after the operation is completed.
*/
-#define STREQ(x,y) (strcmp((x), (y)) == 0)
-
if (mail_scan(client_stream, "%s", request) == 1) {
- if (STREQ(STR(request), FLUSH_REQ_APPEND)) {
+ if (STREQ(STR(request), FLUSH_REQ_ADD)) {
+ site = vstring_alloc(10);
+ queue_id = vstring_alloc(10);
if (mail_scan(client_stream, "%s %s", site, queue_id) == 2
&& valid_hostname(STR(site))
- && mail_queue_id_ok(STR(queue_id)))
- status = flush_append(STR(site), STR(queue_id));
- mail_print(client_stream, "%d", status);
+ && mail_queue_id_ok(STR(queue_id))) {
+ status = flush_add_service(STR(site), STR(queue_id));
+ }
} else if (STREQ(STR(request), FLUSH_REQ_SEND)) {
+ site = vstring_alloc(10);
if (mail_scan(client_stream, "%s", site) == 1
- && valid_hostname(STR(site)))
- status = flush_site(STR(site));
- mail_print(client_stream, "%d", status);
- } else if (STREQ(STR(request), FLUSH_REQ_ENABLE)) {
- if (mail_scan(client_stream, "%s", site) == 1
- && valid_hostname(STR(site)))
- status = flush_enable(STR(site));
- mail_print(client_stream, "%d", status);
+ && valid_hostname(STR(site))) {
+ status = flush_send_service(STR(site));
+ }
} else if (STREQ(STR(request), FLUSH_REQ_PURGE)
|| STREQ(STR(request), wakeup)) {
- mail_print(client_stream, "%d", FLUSH_STAT_OK);
- flush_purge();
+ status = flush_purge_service();
}
}
+ mail_print(client_stream, "%d", status);
vstring_free(request);
- vstring_free(site);
- vstring_free(queue_id);
+ if (site)
+ vstring_free(site);
+ if (queue_id)
+ vstring_free(queue_id);
}
/* main - pass control to the single-threaded skeleton */
int main(int argc, char **argv)
{
- single_server_main(argc, argv, flush_service, 0);
+ static CONFIG_TIME_TABLE time_table[] = {
+ VAR_FFLUSH_REFRESH, DEF_FFLUSH_REFRESH, &var_fflush_refresh, 1, 0,
+ VAR_FFLUSH_PURGE, DEF_FFLUSH_PURGE, &var_fflush_purge, 1, 0,
+ 0,
+ };
+ static CONFIG_STR_TABLE str_table[] = {
+ VAR_RELAY_DOMAINS, DEF_RELAY_DOMAINS, &var_relay_domains, 0, 0,
+ 0,
+ };
+
+ single_server_main(argc, argv, flush_service,
+ MAIL_SERVER_TIME_TABLE, time_table,
+ MAIL_SERVER_STR_TABLE, str_table,
+ 0);
}
record.c remove.c resolve_clnt.c resolve_local.c rewrite_clnt.c \
sent.c smtp_stream.c split_addr.c string_list.c sys_exits.c \
timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
- tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c
+ tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
+ flush_clnt.c mail_conf_time.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 \
record.o remove.o resolve_clnt.o resolve_local.o rewrite_clnt.o \
sent.o smtp_stream.o split_addr.o string_list.o sys_exits.o \
timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
- tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o
+ tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
+ flush_clnt.o mail_conf_time.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 \
quote_821_local.h quote_822_local.h rec_streamlf.h rec_type.h \
recipient_list.h record.h resolve_clnt.h resolve_local.h \
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
- sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h
+ sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
mail_addr_map mail_date maps mynetworks mypwd namadr_list \
off_cvt peer_name quote_822_local rec2stream recdump resolve_clnt \
resolve_local rewrite_clnt stream2rec string_list tok822_parse \
- quote_821_local
+ quote_821_local mail_conf_time
LIBS = ../../lib/libutil.a
LIB_DIR = ../../lib
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
+mail_conf_time: $(LIB) $(LIBS)
+ mv $@.o junk
+ $(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+ mv junk $@.o
+
tests: tok822_test
tok822_test: tok822_parse tok822_parse.in tok822_parse.ref
defer.o: ../../include/vstream.h
defer.o: mail_proto.h
defer.o: ../../include/iostuff.h
-defer.o: mail_params.h
-defer.o: mail_flush.h
+defer.o: flush_clnt.h
defer.o: bounce.h
defer.o: defer.h
deliver_completed.o: deliver_completed.c
file_id.o: ../../include/vstring.h
file_id.o: ../../include/vbuf.h
file_id.o: file_id.h
+flush_clnt.o: flush_clnt.c
+flush_clnt.o: ../../include/sys_defs.h
+flush_clnt.o: ../../include/msg.h
+flush_clnt.o: ../../include/vstream.h
+flush_clnt.o: ../../include/vbuf.h
+flush_clnt.o: mail_proto.h
+flush_clnt.o: ../../include/iostuff.h
+flush_clnt.o: mail_flush.h
+flush_clnt.o: flush_clnt.h
+flush_clnt.o: mail_params.h
header_opts.o: header_opts.c
header_opts.o: ../../include/sys_defs.h
header_opts.o: ../../include/msg.h
mail_conf_str.o: ../../include/msg.h
mail_conf_str.o: ../../include/mymalloc.h
mail_conf_str.o: mail_conf.h
+mail_conf_time.o: mail_conf_time.c
+mail_conf_time.o: ../../include/sys_defs.h
+mail_conf_time.o: ../../include/msg.h
+mail_conf_time.o: ../../include/mymalloc.h
+mail_conf_time.o: ../../include/dict.h
+mail_conf_time.o: ../../include/vstream.h
+mail_conf_time.o: ../../include/vbuf.h
+mail_conf_time.o: ../../include/argv.h
+mail_conf_time.o: ../../include/stringops.h
+mail_conf_time.o: ../../include/vstring.h
+mail_conf_time.o: mail_conf.h
mail_connect.o: mail_connect.c
mail_connect.o: ../../include/sys_defs.h
mail_connect.o: ../../include/msg.h
mail_error.o: ../../include/name_mask.h
mail_flush.o: mail_flush.c
mail_flush.o: ../../include/sys_defs.h
-mail_flush.o: ../../include/msg.h
+mail_flush.o: mail_proto.h
mail_flush.o: ../../include/vstream.h
mail_flush.o: ../../include/vbuf.h
-mail_flush.o: mail_proto.h
mail_flush.o: ../../include/iostuff.h
mail_flush.o: mail_flush.h
-mail_flush.o: mail_params.h
mail_open_ok.o: mail_open_ok.c
mail_open_ok.o: ../../include/sys_defs.h
mail_open_ok.o: ../../include/msg.h
mail_scan.o: ../../include/mymalloc.h
mail_scan.o: mail_proto.h
mail_scan.o: ../../include/iostuff.h
-mail_scan.o: mail_params.h
mail_scan_dir.o: mail_scan_dir.c
mail_scan_dir.o: ../../include/sys_defs.h
mail_scan_dir.o: ../../include/scan_dir.h
#include "mail_queue.h"
#include "mail_proto.h"
-#include "mail_params.h"
-#include "mail_flush.h"
+#include "flush_clnt.h"
#include "bounce.h"
#include "defer.h"
vstring_free(why);
/*
- * Notify the fast flush service.
+ * Notify the fast flush service. XXX Should not this belong in the
+ * bounce/defer daemon? Well, doing it here is more robust.
*/
- if (*var_fast_flush_domains
- && (rcpt_domain = strrchr(recipient, '@')) != 0
- && *++rcpt_domain != 0)
- mail_flush_append(rcpt_domain, id);
+ if ((rcpt_domain = strrchr(recipient, '@')) != 0 && *++rcpt_domain != 0)
+ flush_add(rcpt_domain, id);
return (-1);
}
/* opens the queue file, and acquires a shared lock.
/* A null result means that the client sent bad information or that
/* it went away unexpectedly.
-/* If the fast flush service is enabled, deliver_request_read()
-/* initializes the client-side fast flush duplicate filter.
/*
/* The \fBflags\fR structure member is the bit-wise OR of zero or more
/* of the following:
#include "mail_queue.h"
#include "mail_proto.h"
-#include "mail_params.h"
-#include "mail_flush.h"
#include "mail_open_ok.h"
#include "recipient_list.h"
#include "deliver_request.h"
request = deliver_request_alloc();
if (deliver_request_get(stream, request) < 0) {
deliver_request_free(request);
- return (0);
+ request = 0;
}
-
- /*
- * Make sure the mail flush dupfilter sees no false positive if we're
- * repeatedly delivering the same message.
- */
- if (*var_fast_flush_domains)
- mail_flush_append_init();
-
return (request);
}
--- /dev/null
+/*++
+/* NAME
+/* flush_clnt 3
+/* SUMMARY
+/* fast flush cache manager client interface
+/* SYNOPSIS
+/* #include <flush_clnt.h>
+/*
+/* int flush_add(site, queue_id)
+/* const char *site;
+/* const char *queue_id;
+/*
+/* int flush_send(site)
+/* const char *site;
+/*
+/* int flush_purge()
+/* DESCRIPTION
+/* The following routines operate through the "fast flush" service.
+/* This service maintains a cache of what mail is queued. The cache
+/* is maintained for eligible destinations. A destination is the
+/* right-hand side of a user@domain email address.
+/*
+/* flush_add() informs the "fast flush" cache manager that mail is
+/* queued for the specified site with the specified queue ID.
+/*
+/* flush_send() requests delivery of all mail that is queued for
+/* the specified destination.
+/*
+/* flush_purge() requests the "fast flush" cache manager to refresh
+/* cached information that was not used or not updated for some
+/* configurable amount of time.
+/* DIAGNOSTICS
+/* The result codes and their meanings are (see flush_clnt(5h)):
+/* .IP MAIL_FLUSH_OK
+/* The request completed successfully.
+/* .IP MAIL_FLUSH_FAIL
+/* The request failed (the request could not be sent to the server,
+/* or the server reported failure).
+/* .IP MAIL_FLUSH_BAD
+/* The "fast flush" server rejected the request (invalid request
+/* parameter).
+/* SEE ALSO
+/* flush(8) Postfix fast flush cache manager
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+#include <unistd.h>
+#include <stdarg.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstream.h>
+
+/* Global library. */
+
+#include <mail_proto.h>
+#include <mail_flush.h>
+#include <flush_clnt.h>
+#include <mail_params.h>
+
+/* Application-specific. */
+
+#define STR(x) vstring_str(x)
+
+/* flush_clnt - generic fast flush service client */
+
+static int flush_clnt(const char *format,...)
+{
+ VSTREAM *flush;
+ int status;
+ va_list ap;
+
+ /*
+ * Connect to the fast flush service over local IPC.
+ */
+ if ((flush = mail_connect(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
+ BLOCKING)) == 0)
+ return (FLUSH_STAT_FAIL);
+
+ /*
+ * Do not get stuck forever.
+ */
+ vstream_control(flush,
+ VSTREAM_CTL_TIMEOUT, var_ipc_timeout,
+ VSTREAM_CTL_END);
+
+ /*
+ * Send a request with the site name, and receive the request acceptance
+ * status.
+ */
+ va_start(ap, format);
+ mail_vprint(flush, format, ap);
+ va_end(ap);
+ if (mail_scan(flush, "%d", &status) != 1)
+ status = FLUSH_STAT_FAIL;
+
+ /*
+ * Clean up.
+ */
+ vstream_fclose(flush);
+
+ return (status);
+}
+
+/* flush_purge - house keeping */
+
+int flush_purge(void)
+{
+ char *myname = "flush_purge";
+ int status;
+
+ if (msg_verbose)
+ msg_info("%s", myname);
+
+ /*
+ * Don't bother the server if the service is turned off.
+ */
+ if (strcmp(var_fflush_policy, FFLUSH_POLICY_NONE) == 0)
+ status = FLUSH_STAT_OK;
+ else
+ status = flush_clnt("%s", FLUSH_REQ_PURGE);
+
+ if (msg_verbose)
+ msg_info("%s: status %d", myname, status);
+
+ return (status);
+}
+
+/* flush_send - deliver mail queued for site */
+
+int flush_send(const char *site)
+{
+ char *myname = "flush_send";
+ int status;
+
+ if (msg_verbose)
+ msg_info("%s: site %s", myname, site);
+
+ /*
+ * Don't bother the server if the service is turned off.
+ */
+ if (strcmp(var_fflush_policy, FFLUSH_POLICY_NONE) == 0)
+ status = mail_flush_deferred();
+ else
+ status = flush_clnt("%s %s", FLUSH_REQ_SEND, site);
+
+ if (msg_verbose)
+ msg_info("%s: site %s status %d", myname, site, status);
+
+ return (status);
+}
+
+/* flush_add - inform "fast flush" cache manager */
+
+int flush_add(const char *site, const char *queue_id)
+{
+ char *myname = "flush_add";
+ int status;
+
+ if (msg_verbose)
+ msg_info("%s: site %s id %s", myname, site, queue_id);
+
+ /*
+ * Don't bother the server if the service is turned off.
+ */
+ if (strcmp(var_fflush_policy, FFLUSH_POLICY_NONE) == 0)
+ status = FLUSH_STAT_OK;
+ else
+ status = flush_clnt("%s %s %s", FLUSH_REQ_ADD, site, queue_id);
+
+ if (msg_verbose)
+ msg_info("%s: site %s id %s status %d", myname, site, queue_id,
+ status);
+
+ return (status);
+}
--- /dev/null
+#ifndef _FLUSH_CLNT_H_INCLUDED_
+#define _FLUSH_CLNT_H_INCLUDED_
+
+/*++
+/* NAME
+/* flush_clnt 3h
+/* SUMMARY
+/* flush backed up mail
+/* SYNOPSIS
+/* #include <flush_clnt.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * External interface.
+ */
+extern int flush_add(const char *, const char *);
+extern int flush_send(const char *);
+extern int flush_purge(void);
+
+ /*
+ * Mail flush server requests.
+ */
+#define FLUSH_REQ_ADD "add" /* append queue ID to site log */
+#define FLUSH_REQ_SEND "send" /* flush mail queued for site */
+#define FLUSH_REQ_PURGE "purge" /* refresh or delete old info */
+
+ /*
+ * Mail flush server status codes.
+ */
+#define FLUSH_STAT_FAIL -1 /* request failed */
+#define FLUSH_STAT_OK 0 /* request executed */
+#define FLUSH_STAT_BAD 3 /* invalid parameter */
+
+
+/* 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
extern char *get_mail_conf_str(const char *, const char *, int, int);
extern int get_mail_conf_int(const char *, int, int, int);
extern int get_mail_conf_bool(const char *, int);
+extern int get_mail_conf_time(const char *, const char *, int, int);
extern char *get_mail_conf_raw(const char *, const char *, int, int);
extern int get_mail_conf_int2(const char *, const char *, int, int, int);
+extern int get_mail_conf_time2(const char *, const char *, const char *, int, int);
/*
* Lookup with function-call defaults.
extern char *get_mail_conf_str_fn(const char *, const char *(*) (void), int, int);
extern int get_mail_conf_int_fn(const char *, int (*) (void), int, int);
extern int get_mail_conf_bool_fn(const char *, int (*) (void));
+extern int get_mail_conf_time_fn(const char *, const char *(*) (void), int, int);
extern char *get_mail_conf_raw_fn(const char *, const char *(*) (void), int, int);
/*
extern void set_mail_conf_str(const char *, const char *);
extern void set_mail_conf_int(const char *, int);
extern void set_mail_conf_bool(const char *, int);
+extern void set_mail_conf_time(const char *, const char *);
/*
* Tables that allow us to selectively copy values from the global
int *target; /* pointer to global variable */
} CONFIG_BOOL_TABLE;
+typedef struct {
+ const char *name; /* config variable name */
+ const char *defval; /* default value */
+ int *target; /* pointer to global variable */
+ int min; /* lower bound or zero */
+ int max; /* upper bound or zero */
+} CONFIG_TIME_TABLE;
+
extern void get_mail_conf_str_table(CONFIG_STR_TABLE *);
extern void get_mail_conf_int_table(CONFIG_INT_TABLE *);
extern void get_mail_conf_bool_table(CONFIG_BOOL_TABLE *);
+extern void get_mail_conf_time_table(CONFIG_TIME_TABLE *);
extern void get_mail_conf_raw_table(CONFIG_STR_TABLE *);
/*
int *target; /* pointer to global variable */
} CONFIG_BOOL_FN_TABLE;
+typedef struct {
+ const char *name; /* config variable name */
+ const char *(*defval) (void); /* default value provider */
+ int *target; /* pointer to global variable */
+ int min; /* lower bound or zero */
+ int max; /* upper bound or zero */
+} CONFIG_TIME_FN_TABLE;
+
extern void get_mail_conf_str_fn_table(CONFIG_STR_FN_TABLE *);
extern void get_mail_conf_int_fn_table(CONFIG_INT_FN_TABLE *);
extern void get_mail_conf_bool_fn_table(CONFIG_BOOL_FN_TABLE *);
+extern void get_mail_conf_time_fn_table(CONFIG_TIME_FN_TABLE *);
extern void get_mail_conf_raw_fn_table(CONFIG_STR_FN_TABLE *);
/* LICENSE
--- /dev/null
+/*++
+/* NAME
+/* mail_conf_time 3
+/* SUMMARY
+/* time interval configuration parameter support
+/* SYNOPSIS
+/* #include <mail_conf.h>
+/*
+/* int get_mail_conf_time(name, defval, min, max);
+/* const char *name;
+/* const char *defval;
+/* int min;
+/* int max;
+/*
+/* int get_mail_conf_time_fn(name, defval, min, max);
+/* const char *name;
+/* const char *(*defval)();
+/* int min;
+/* int max;
+/*
+/* void set_mail_conf_time(name, value)
+/* const char *name;
+/* const char *value;
+/*
+/* void get_mail_conf_time_table(table)
+/* CONFIG_INT_TABLE *table;
+/*
+/* void get_mail_conf_time_fn_table(table)
+/* CONFIG_INT_TABLE *table;
+/* AUXILIARY FUNCTIONS
+/* int get_mail_conf_time2(name1, name2, defval, min, max);
+/* const char *name1;
+/* const char *name2;
+/* const char *defval;
+/* int min;
+/* int max;
+/* DESCRIPTION
+/* This module implements configuration parameter support
+/* for time interval values. By default, times are specified
+/* in units of seconds, but the conversion routines understand
+/* one-letter suffixes to specify an explicit time unit: s
+/* (seconds), m (minutes), h (hours), d (days) or w (weeks).
+/*
+/* get_mail_conf_time() looks up the named entry in the global
+/* configuration dictionary. The default value is returned
+/* when no value was found.
+/* \fImin\fR is zero or specifies a lower limit on the integer
+/* value or string length; \fImax\fR is zero or specifies an
+/* upper limit on the integer value or string length.
+/*
+/* get_mail_conf_time_fn() is similar but specifies a function that
+/* provides the default value. The function is called only
+/* when the default value is needed.
+/*
+/* set_mail_conf_time() updates the named entry in the global
+/* configuration dictionary. This has no effect on values that
+/* have been looked up earlier via the get_mail_conf_XXX() routines.
+/*
+/* get_mail_conf_time_table() and get_mail_conf_time_fn_table() initialize
+/* lists of variables, as directed by their table arguments. A table
+/* must be terminated by a null entry.
+/*
+/* get_mail_conf_time2() concatenates the two names and is otherwise
+/* identical to get_mail_conf_time().
+/* DIAGNOSTICS
+/* Fatal errors: malformed numerical value, unknown time unit.
+/* SEE ALSO
+/* config(3) general configuration
+/* mail_conf_str(3) string-valued configuration parameters
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <stdlib.h>
+#include <stdio.h> /* sscanf() */
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <dict.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include "mail_conf.h"
+
+#define MINUTE (60)
+#define HOUR (60 * MINUTE)
+#define DAY (24 * HOUR)
+#define WEEK (7 * DAY)
+
+/* convert_mail_conf_time - look up and convert integer parameter value */
+
+static int convert_mail_conf_time(const char *name, int *intval)
+{
+ const char *strval;
+ char unit;
+ char junk;
+
+ if ((strval = mail_conf_lookup_eval(name)) != 0) {
+ if (sscanf(strval, "%d%c%c", intval, &unit, &junk) == 2) {
+ switch (unit) {
+ case 'w':
+ *intval *= WEEK;
+ return (1);
+ case 'd':
+ *intval *= DAY;
+ return (1);
+ case 'h':
+ *intval *= HOUR;
+ return (1);
+ case 'm':
+ *intval *= MINUTE;
+ return (1);
+ case 's':
+ return (1);
+ break;
+ default:
+ msg_fatal("bad time unit: %s", strval);
+ }
+ }
+ if (sscanf(strval, "%d%c", intval, &junk) != 1)
+ msg_fatal("bad numerical configuration: %s = %s", name, strval);
+ return (1);
+ }
+ return (0);
+}
+
+/* check_mail_conf_time - validate integer value */
+
+static void check_mail_conf_time(const char *name, int intval, int min, int max)
+{
+ if (min && intval < min)
+ msg_fatal("invalid %s: %d (min %d)", name, intval, min);
+ if (max && intval > max)
+ msg_fatal("invalid %s: %d (max %d)", name, intval, max);
+}
+
+/* get_mail_conf_time - evaluate integer-valued configuration variable */
+
+int get_mail_conf_time(const char *name, const char *defval, int min, int max)
+{
+ int intval;
+
+ if (convert_mail_conf_time(name, &intval) == 0)
+ set_mail_conf_time(name, defval);
+ if (convert_mail_conf_time(name, &intval) == 0)
+ msg_panic("get_mail_conf_time: parameter not found: %s", name);
+ check_mail_conf_time(name, intval, min, max);
+ return (intval);
+}
+
+/* get_mail_conf_time2 - evaluate integer-valued configuration variable */
+
+int get_mail_conf_time2(const char *name1, const char *name2,
+ const char *defval, int min, int max)
+{
+ int intval;
+ char *name;
+
+ name = concatenate(name1, name2, (char *) 0);
+ if (convert_mail_conf_time(name, &intval) == 0)
+ set_mail_conf_time(name, defval);
+ if (convert_mail_conf_time(name, &intval) == 0)
+ msg_panic("get_mail_conf_time2: parameter not found: %s", name);
+ check_mail_conf_time(name, intval, min, max);
+ myfree(name);
+ return (intval);
+}
+
+/* get_mail_conf_time_fn - evaluate integer-valued configuration variable */
+
+typedef const char *(*stupid_indent_time) (void);
+
+int get_mail_conf_time_fn(const char *name, stupid_indent_time defval,
+ int min, int max)
+{
+ int intval;
+
+ if (convert_mail_conf_time(name, &intval) == 0)
+ set_mail_conf_time(name, defval());
+ if (convert_mail_conf_time(name, &intval) == 0)
+ msg_panic("get_mail_conf_time_fn: parameter not found: %s", name);
+ check_mail_conf_time(name, intval, min, max);
+ return (intval);
+}
+
+/* set_mail_conf_time - update integer-valued configuration dictionary entry */
+
+void set_mail_conf_time(const char *name, const char *value)
+{
+ mail_conf_update(name, value);
+}
+
+/* get_mail_conf_time_table - look up table of integers */
+
+void get_mail_conf_time_table(CONFIG_TIME_TABLE *table)
+{
+ while (table->name) {
+ table->target[0] = get_mail_conf_time(table->name, table->defval,
+ table->min, table->max);
+ table++;
+ }
+}
+
+/* get_mail_conf_time_fn_table - look up integers, defaults are functions */
+
+void get_mail_conf_time_fn_table(CONFIG_TIME_FN_TABLE *table)
+{
+ while (table->name) {
+ table->target[0] = get_mail_conf_time_fn(table->name, table->defval,
+ table->min, table->max);
+ table++;
+ }
+}
+
+#ifdef TEST
+
+ /*
+ * Stand-alone driver program for regression testing.
+ */
+#include <vstream.h>
+
+int main(int unused_argc, char **unused_argv)
+{
+ static int seconds;
+ static int minutes;
+ static int hours;
+ static int days;
+ static int weeks;
+ static CONFIG_TIME_TABLE time_table[] = {
+ "seconds", "10s", &seconds, 0, 0,
+ "minutes", "10m", &minutes, 0, 0,
+ "hours", "10h", &hours, 0, 0,
+ "days", "10d", &days, 0, 0,
+ "weeks", "10w", &weeks, 0, 0,
+ 0,
+ };
+
+ get_mail_conf_time_table(time_table);
+ vstream_printf("seconds = %d\n", seconds);
+ vstream_printf("minutes = %d\n", minutes);
+ vstream_printf("hours = %d\n", hours);
+ vstream_printf("days = %d\n", days);
+ vstream_printf("weeks = %d\n", weeks);
+ vstream_fflush(VSTREAM_OUT);
+}
+
+#endif
/* NAME
/* mail_flush 3
/* SUMMARY
-/* mail flush service client interface
+/* flush backed up mail
/* SYNOPSIS
/* #include <mail_flush.h>
/*
/* int mail_flush_deferred()
-/*
-/* int mail_flush_purge()
-/*
-/* int mail_flush_enable(site)
-/* const char *site;
-/*
-/* int mail_flush_site(site)
-/* const char *site;
-/*
-/* int mail_flush_append(site, queue_id)
-/* const char *site;
-/* const char *queue_id;
-/*
-/* void mail_flush_append_init()
/* DESCRIPTION
-/* This module deals with delivery of delayed mail.
+/* This module triggers delivery of backed up mail.
/*
/* mail_flush_deferred() triggers delivery of all deferred
/* or incoming mail.
-/*
-/* The following services are available only for sites that have a
-/* "fast flush" logfile. These files list all mail that is queued
-/* for a given site, and are created on demand when, for example,
-/* an eligible SMTP client issues the ETRN command.
-/*
-/* mail_flush_enable() enables the "fast flush" service for
-/* the named site.
-/*
-/* mail_flush_site() uses the "fast flush" service to trigger
-/* delivery of messages queued for the specified site.
-/*
-/* mail_flush_append() appends a record to the "fast flush"
-/* logfile for the specified site, with the queue ID of mail
-/* that still should be delivered. This routine uses a little
-/* duplicate filter to avoid appending multiple identical
-/* records when one has to defer multi-recipient mail.
-/*
-/* mail_flush_append_init() initializes a duplicate filter that is used
-/* by mail_flush_append(). mail_flush_append_init() must be called once
-/* before calling mail_flush_append() and must be called whenever
-/* the application opens a new queue file, to prevent false
-/* positives with the duplicate filter when repeated attempts
-/* are made to deliver the same message.
-/*
-/* mail_flush_purge() requests the "fast flush" service to
-/* flush all its "fast flush" logfiles. This is necessary
-/* once a day or so, in order to prevent accumulation of
-/* too much outdated information.
/* DIAGNOSTICS
-/* The result codes and their meaning are (see mail_flush(5h)):
-/* .IP MAIL_FLUSH_OK
-/* The request completed normally.
-/* .IP MAIL_FLUSH_FAIL
-/* The request failed.
-/* .IP MAIL_FLUSH_UNKNOWN
-/* The specified site has no "fast flush" logfile.
-/* .IP MAIL_FLUSH_BAD
-/* The "fast flush" server rejected the request (invalid request
-/* parameter).
+/* The result is 0 in case of success, -1 in case of failure.
/* LICENSE
/* .ad
/* .fi
/* System library. */
#include "sys_defs.h"
-#include <unistd.h>
-#include <stdarg.h>
/* Utility library. */
-#include <msg.h>
-#include <vstream.h>
-#include <vstring.h>
-
/* Global library. */
#include <mail_proto.h>
#include <mail_flush.h>
-#include <mail_params.h>
-
-/* Application-specific. */
-
-#define STR(x) vstring_str(x)
-
-static VSTRING *mail_flush_saved_site;
-static VSTRING *mail_flush_saved_id;
-static int mail_flush_saved_status;
/* mail_flush_deferred - flush deferred queue */
return (mail_trigger(MAIL_CLASS_PUBLIC, MAIL_SERVICE_QUEUE,
qmgr_trigger, sizeof(qmgr_trigger)));
}
-
-/* mail_flush_append_init - initialize repeat filter */
-
-void mail_flush_append_init(void)
-{
- if (mail_flush_saved_site == 0) {
- mail_flush_saved_site = vstring_alloc(10);
- mail_flush_saved_id = vstring_alloc(10);
- }
- vstring_strcpy(mail_flush_saved_site, "");
- vstring_strcpy(mail_flush_saved_id, "");
-}
-
-/* mail_flush_cached - see if request repeats */
-
-static int mail_flush_cached(const char *site, const char *queue_id)
-{
- if (strcmp(STR(mail_flush_saved_site), site) == 0
- && strcmp(STR(mail_flush_saved_id), queue_id) == 0) {
- return (1);
- } else {
- vstring_strcpy(mail_flush_saved_site, site);
- vstring_strcpy(mail_flush_saved_id, queue_id);
- return (0);
- }
-}
-
-/* mail_flush_clnt - generic fast flush service client */
-
-static int mail_flush_clnt(const char *format,...)
-{
- VSTREAM *flush;
- int status;
- va_list ap;
-
- /*
- * Connect to the fast flush service over local IPC.
- */
- if ((flush = mail_connect(MAIL_CLASS_PRIVATE, MAIL_SERVICE_FLUSH,
- BLOCKING)) == 0)
- return (FLUSH_STAT_FAIL);
-
- /*
- * Do not get stuck forever.
- */
- vstream_control(flush,
- VSTREAM_CTL_TIMEOUT, var_ipc_timeout,
- VSTREAM_CTL_END);
-
- /*
- * Send a request with the site name, and receive the request completion
- * status.
- */
- va_start(ap, format);
- mail_vprint(flush, format, ap);
- va_end(ap);
- if (mail_scan(flush, "%d", &status) != 1)
- status = FLUSH_STAT_FAIL;
-
- /*
- * Clean up.
- */
- vstream_fclose(flush);
-
- return (status);
-}
-
-/* mail_flush_enable - enable fast flush logging for site */
-
-int mail_flush_enable(const char *site)
-{
- char *myname = "mail_flush_enable";
- int status;
-
- if (msg_verbose)
- msg_info("%s: site %s", myname, site);
- status = mail_flush_clnt("%s %s", FLUSH_REQ_ENABLE, site);
- if (msg_verbose)
- msg_info("%s: site %s status %d", myname, site, status);
-
- return (status);
-}
-
-/* mail_flush_purge - house keeping */
-
-int mail_flush_purge(void)
-{
- char *myname = "mail_flush_purge";
- int status;
-
- if (msg_verbose)
- msg_info("%s", myname);
- status = mail_flush_clnt("%s", FLUSH_REQ_SEND);
- if (msg_verbose)
- msg_info("%s: status %d", myname, status);
-
- return (status);
-}
-
-/* mail_flush_site - flush deferred mail for site */
-
-int mail_flush_site(const char *site)
-{
- char *myname = "mail_flush_site";
- int status;
-
- if (msg_verbose)
- msg_info("%s: site %s", myname, site);
- status = mail_flush_clnt("%s %s", FLUSH_REQ_SEND, site);
- if (msg_verbose)
- msg_info("%s: site %s status %d", myname, site, status);
-
- return (status);
-}
-
-/* mail_flush_append - append record to fast flush log */
-
-int mail_flush_append(const char *site, const char *queue_id)
-{
- char *myname = "mail_flush_append";
-
- if (msg_verbose)
- msg_info("%s: site %s id %s", myname, site, queue_id);
- if (mail_flush_cached(site, queue_id) == 0)
- mail_flush_saved_status =
- mail_flush_clnt("%s %s %s", FLUSH_REQ_APPEND, site, queue_id);
- if (msg_verbose)
- msg_info("%s: site %s id %s status %d", myname, site, queue_id,
- mail_flush_saved_status);
-
- return (mail_flush_saved_status);
-}
/* DESCRIPTION
/* .nf
- /*
- * External interface.
- */
-extern int mail_flush_deferred(void);
-extern int mail_flush_purge(void);
-extern int mail_flush_enable(const char *);
-extern int mail_flush_site(const char *);
-extern int mail_flush_append(const char *, const char *);
-extern void mail_flush_append_init(void);
-
- /*
- * Mail flush server requests.
- */
-#define FLUSH_REQ_APPEND "append"/* append queue ID to site log */
-#define FLUSH_REQ_SEND "send" /* flush mail queued for site */
-#define FLUSH_REQ_ENABLE "enable"/* flush mail queued for site */
-#define FLUSH_REQ_PURGE "purge" /* flush mail queued for site */
-
- /*
- * Mail flush server status codes.
- */
-#define FLUSH_STAT_FAIL -1 /* everyone */
-#define FLUSH_STAT_OK 0 /* everyone */
-#define FLUSH_STAT_UNKNOWN 2 /* mail_flush_site() only */
-#define FLUSH_STAT_BAD 3 /* mail_flush_site() only */
+ /* External interface. */
+extern int mail_flush_deferred(void);
/* LICENSE
/* .ad
/* int var_ownreq_special;
/* int var_daemon_timeout;
/* char *var_syslog_facility;
-/* char *var_fast_flush_domains;
+/* char *var_fflush_policy;
/*
/* void mail_params_init()
/* DESCRIPTION
int var_ownreq_special;
int var_daemon_timeout;
char *var_syslog_facility;
-char *var_relay_domains;
-char *var_fast_flush_domains;
+char *var_fflush_policy;
/* check_myhostname - lookup hostname and validate */
VAR_DB_TYPE, DEF_DB_TYPE, &var_db_type, 1, 0,
VAR_HASH_QUEUE_NAMES, DEF_HASH_QUEUE_NAMES, &var_hash_queue_names, 1, 0,
VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 1,
- VAR_RELAY_DOMAINS, DEF_RELAY_DOMAINS, &var_relay_domains, 0, 0,
- VAR_FFLUSH_DOMAINS, DEF_FFLUSH_DOMAINS, &var_fast_flush_domains, 0, 0,
+ VAR_FFLUSH_POLICY, DEF_FFLUSH_POLICY, &var_fflush_policy, 1, 0,
0,
};
static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
extern int var_qmgr_fudge;
#define VAR_QMGR_HOG "qmgr_site_hog_factor"
-#define DEF_QMGR_HOG 90
+#define DEF_QMGR_HOG 100
extern int var_qmgr_hog;
/*
/*
* Fast flush service support.
*/
-#define VAR_FFLUSH_DOMAINS "fast_flush_domains"
-#define DEF_FFLUSH_DOMAINS "$relay_domains"
-extern char *var_fast_flush_domains;
+#define VAR_FFLUSH_POLICY "fast_flush_policy"
+#define DEF_FFLUSH_POLICY FFLUSH_POLICY_RELAY
+extern char *var_fflush_policy;
+
+#define FFLUSH_POLICY_ALL "all"
+#define FFLUSH_POLICY_RELAY "relay"
+#define FFLUSH_POLICY_NONE "none"
+
+#define VAR_FFLUSH_PURGE "fast_flush_purge_delay"
+#define DEF_FFLUSH_PURGE "7d"
+extern int var_fflush_purge;
+
+#define VAR_FFLUSH_REFRESH "fast_flush_refresh_delay"
+#define DEF_FFLUSH_REFRESH "12h"
+extern int var_fflush_refresh;
/* LICENSE
/* .ad
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-20001001"
+#define DEF_MAIL_VERSION "Snapshot-20001003"
extern char *var_mail_version;
/* LICENSE
#define MAIL_SERVER_INT_TABLE 1
#define MAIL_SERVER_STR_TABLE 2
#define MAIL_SERVER_BOOL_TABLE 3
-#define MAIL_SERVER_RAW_TABLE 4
+#define MAIL_SERVER_TIME_TABLE 4
+#define MAIL_SERVER_RAW_TABLE 5
#define MAIL_SERVER_PRE_INIT 10
#define MAIL_SERVER_POST_INIT 11
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
/* are allowed.
+/* .IP "MAIL_SERVER_TIME_TABLE (CONFIG_TIME_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_STR_TABLE *)"
/* A table with configurable parameters, to be loaded from the
/* global Postfix configuration file. Tables are loaded in the
case MAIL_SERVER_BOOL_TABLE:
get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
break;
+ case MAIL_SERVER_TIME_TABLE:
+ get_mail_conf_time_table(va_arg(ap, CONFIG_TIME_TABLE *));
+ break;
case MAIL_SERVER_RAW_TABLE:
get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
break;
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
/* are allowed.
+/* .IP "MAIL_SERVER_TIME_TABLE (CONFIG_TIME_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_STR_TABLE *)"
/* A table with configurable parameters, to be loaded from the
/* global Postfix configuration file. Tables are loaded in the
case MAIL_SERVER_BOOL_TABLE:
get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
break;
+ case MAIL_SERVER_TIME_TABLE:
+ get_mail_conf_time_table(va_arg(ap, CONFIG_TIME_TABLE *));
+ break;
case MAIL_SERVER_RAW_TABLE:
get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
break;
/* global Postfix configuration file. Tables are loaded in the
/* order as specified, and multiple instances of the same type
/* are allowed.
+/* .IP "MAIL_SERVER_TIME_TABLE (CONFIG_TIME_TABLE *)"
+/* A table with configurable parameters, to be loaded from the
+/* global Postfix configuration file. Tables are loaded in the
+/* order as specified, and multiple instances of the same type
+/* are allowed.
/* .IP "MAIL_SERVER_RAW_TABLE (CONFIG_STR_TABLE *)"
/* A table with configurable parameters, to be loaded from the
/* global Postfix configuration file. Tables are loaded in the
case MAIL_SERVER_BOOL_TABLE:
get_mail_conf_bool_table(va_arg(ap, CONFIG_BOOL_TABLE *));
break;
+ case MAIL_SERVER_TIME_TABLE:
+ get_mail_conf_time_table(va_arg(ap, CONFIG_TIME_TABLE *));
+ break;
case MAIL_SERVER_RAW_TABLE:
get_mail_conf_raw_table(va_arg(ap, CONFIG_STR_TABLE *));
break;
qmgr_active.o: ../../include/bounce.h
qmgr_active.o: ../../include/defer.h
qmgr_active.o: ../../include/rec_type.h
-qmgr_active.o: ../../include/mail_flush.h
qmgr_active.o: qmgr.h
qmgr_active.o: ../../include/scan_dir.h
qmgr_active.o: ../../include/maps.h
qmgr_scan.o: ../../include/mymalloc.h
qmgr_scan.o: ../../include/scan_dir.h
qmgr_scan.o: ../../include/mail_scan_dir.h
+qmgr_scan.o: ../../include/flush_clnt.h
qmgr_scan.o: qmgr.h
qmgr_scan.o: ../../include/vstream.h
qmgr_scan.o: ../../include/vbuf.h
#include <bounce.h>
#include <defer.h>
#include <rec_type.h>
-#include <mail_flush.h>
/* Application-specific. */
*/
if (message->refcount == 0)
qmgr_active_done(message);
-
- /*
- * Make sure the mail flush dupfilter sees no false positive if we're
- * repeatedly trying to deliver the same message.
- */
- else if (*var_fast_flush_domains)
- mail_flush_append_init();
}
}
* Optionally defer deliveries over specific transports, unless the
* restriction is lifted temporarily.
*/
- if (*var_defer_xports && (message->qflags & QMGR_SCAN_ALL) == 0) {
+ if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DEAD) == 0) {
if (defer_xport_argv == 0)
defer_xport_argv = argv_split(var_defer_xports, " \t\r\n,");
for (cpp = defer_xport_argv->argv; *cpp; cpp++)
/* Global library. */
#include <mail_scan_dir.h>
+#include <flush_clnt.h>
/* Application-specific. */
if (scan_info->nflags & QMGR_FLUSH_DEAD)
qmgr_enable_all();
+ /*
+ * Optionally inform the fast flush cache manager that we're attempting
+ * to deliver all queued mail.
+ */
+ if ((scan_info->nflags & QMGR_FLUSH_DEAD)
+ && (scan_info->nflags & QMGR_SCAN_ALL))
+ flush_purge();
+
/*
* Start or restart the scan.
*/
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=
MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \
- str_vars.h
+ str_vars.h time_table.h time_vars.h
PROG = postconf
SAMPLES = ../../conf/main.cf.default
INC_DIR = ../../include
postconf.o: ../../include/mail_version.h
postconf.o: ../../include/mail_params.h
postconf.o: ../../include/mail_addr.h
+postconf.o: time_vars.h
postconf.o: bool_vars.h
postconf.o: int_vars.h
postconf.o: str_vars.h
postconf.o: local_vars.h
postconf.o: smtp_vars.h
+postconf.o: time_table.h
postconf.o: bool_table.h
postconf.o: int_table.h
postconf.o: str_table.h
print | "sed 's/[ ][ ]*/ /g' | sort -u >bool_table.h"
}
}
+/^(static| )*CONFIG_TIME_TABLE .*\{/,/\};/ {
+ if ($1 ~ /VAR/) {
+ print "int " substr($3,2,length($3)-2) ";" > "time_vars.h"
+ print | "sed 's/[ ][ ]*/ /g' | sort -u >time_table.h"
+ }
+}
# Workaround for broken gawk versions.
/*
* Declarations generated by scanning actual C source files.
*/
+#include "time_vars.h"
#include "bool_vars.h"
#include "int_vars.h"
#include "str_vars.h"
/*
* Lookup tables generated by scanning actual C source files.
*/
+static CONFIG_TIME_TABLE time_table[] = {
+#include "time_table.h"
+ 0,
+};
+
static CONFIG_BOOL_TABLE bool_table[] = {
#include "bool_table.h"
0,
static void hash_parameters(void)
{
+ CONFIG_TIME_TABLE *ctt;
CONFIG_BOOL_TABLE *cbt;
CONFIG_INT_TABLE *cit;
CONFIG_STR_TABLE *cst;
param_table = htable_create(100);
+ for (ctt = time_table; ctt->name; ctt++)
+ htable_enter(param_table, ctt->name, (char *) ctt);
for (cbt = bool_table; cbt->name; cbt++)
htable_enter(param_table, cbt->name, (char *) cbt);
for (cit = int_table; cit->name; cit++)
}
}
+/* print_time - print relative time parameter */
+
+static void print_time(int mode, CONFIG_TIME_TABLE * ctt)
+{
+ const char *value;
+
+ if (mode & SHOW_DEFS) {
+ show_strval(mode, ctt->name, ctt->defval);
+ } else {
+ value = dict_lookup(CONFIG_DICT, ctt->name);
+ if ((mode & SHOW_NONDEF) == 0) {
+ if (value == 0) {
+ show_strval(mode, ctt->name, ctt->defval);
+ } else {
+ show_strval(mode, ctt->name, value);
+ }
+ } else {
+ if (value != 0)
+ show_strval(mode, ctt->name, value);
+ }
+ }
+}
+
/* print_int - print integer parameter */
static void print_int(int mode, CONFIG_INT_TABLE *cit)
/*
* This is gross, but the best we can do on short notice.
*/
+ if (INSIDE(ptr, time_table))
+ print_time(mode, (CONFIG_TIME_TABLE *) ptr);
if (INSIDE(ptr, bool_table))
print_bool(mode, (CONFIG_BOOL_TABLE *) ptr);
if (INSIDE(ptr, int_table))
qmgr_active.o: ../../include/bounce.h
qmgr_active.o: ../../include/defer.h
qmgr_active.o: ../../include/rec_type.h
-qmgr_active.o: ../../include/mail_flush.h
qmgr_active.o: qmgr.h
qmgr_active.o: ../../include/scan_dir.h
qmgr_active.o: ../../include/maps.h
qmgr_scan.o: ../../include/mymalloc.h
qmgr_scan.o: ../../include/scan_dir.h
qmgr_scan.o: ../../include/mail_scan_dir.h
+qmgr_scan.o: ../../include/flush_clnt.h
qmgr_scan.o: qmgr.h
qmgr_scan.o: ../../include/vstream.h
qmgr_scan.o: ../../include/vbuf.h
#include <bounce.h>
#include <defer.h>
#include <rec_type.h>
-#include <mail_flush.h>
/* Application-specific. */
*/
if (message->refcount == 0)
qmgr_active_done(message);
-
- /*
- * Make sure the mail flush dupfilter sees no false positive if we're
- * repeatedly trying to deliver the same message.
- */
- else if (*var_fast_flush_domains)
- mail_flush_append_init();
}
}
* Optionally defer deliveries over specific transports, unless the
* restriction is lifted temporarily.
*/
- if (*var_defer_xports && (message->qflags & QMGR_SCAN_ALL) == 0) {
+ if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DEAD) == 0) {
if (defer_xport_argv == 0)
defer_xport_argv = argv_split(var_defer_xports, " \t\r\n,");
for (cpp = defer_xport_argv->argv; *cpp; cpp++)
/* Global library. */
#include <mail_scan_dir.h>
+#include <flush_clnt.h>
/* Application-specific. */
if (scan_info->nflags & QMGR_FLUSH_DEAD)
qmgr_enable_all();
+ /*
+ * Optionally inform the fast flush cache manager that we're attempting
+ * to deliver all queued mail.
+ */
+ if ((scan_info->nflags & QMGR_FLUSH_DEAD)
+ && (scan_info->nflags & QMGR_SCAN_ALL))
+ flush_purge();
+
/*
* Start or restart the scan.
*/
sendmail.o: ../../include/mymalloc.h
sendmail.o: ../../include/vstream.h
sendmail.o: ../../include/vbuf.h
-sendmail.o: ../../include/vstring.h
sendmail.o: ../../include/msg_vstream.h
sendmail.o: ../../include/msg_syslog.h
sendmail.o: ../../include/vstring_vstream.h
+sendmail.o: ../../include/vstring.h
sendmail.o: ../../include/username.h
sendmail.o: ../../include/fullname.h
sendmail.o: ../../include/argv.h
sendmail.o: ../../include/iostuff.h
sendmail.o: ../../include/stringops.h
sendmail.o: ../../include/set_ugid.h
+sendmail.o: ../../include/connect.h
sendmail.o: ../../include/mail_queue.h
sendmail.o: ../../include/mail_proto.h
sendmail.o: ../../include/mail_params.h
sendmail.o: ../../include/resolve_clnt.h
sendmail.o: ../../include/mail_flush.h
sendmail.o: ../../include/mail_stream.h
+sendmail.o: ../../include/smtp_stream.h
smtpd.o: ../../include/debug_peer.h
smtpd.o: ../../include/mail_error.h
smtpd.o: ../../include/name_mask.h
-smtpd.o: ../../include/mail_flush.h
+smtpd.o: ../../include/flush_clnt.h
smtpd.o: ../../include/mail_stream.h
smtpd.o: ../../include/mail_queue.h
smtpd.o: ../../include/tok822.h
/* Limit the number of times a client can issue a junk command
/* such as NOOP, VRFY, ETRN or RSET in one SMTP session before
/* it is penalized with tarpit delays.
-/* .SH "ETRN controls"
-/* .ad
-/* .fi
-/* .IP \fBsmtpd_etrn_restrictions\fR
-/* Restrict what domain names can be used in \fBETRN\fR commands,
-/* and what clients may issue \fBETRN\fR commands.
-/* .IP \fBfast_flush_domains\fR
-/* The destinations that this system is willing to provide "fast ETRN"
-/* service for. By default, "fast ETRN" service is available only
-/* for destinations that the local system is willing to relay mail to.
-/* For other destinations, Postfix simply attempts to deliver all mail
-/* in the queue.
/* .SH "UCE control restrictions"
/* .ad
/* .fi
/* Restrict what sender addresses are allowed in \fBMAIL FROM\fR commands.
/* .IP \fBsmtpd_recipient_restrictions\fR
/* Restrict what recipient addresses are allowed in \fBRCPT TO\fR commands.
+/* .IP \fBsmtpd_etrn_restrictions\fR
+/* Restrict what domain names can be used in \fBETRN\fR commands,
+/* and what clients may issue \fBETRN\fR commands.
/* .IP \fBallow_untrusted_routing\fR
/* Allow untrusted clients to specify addresses with sender-specified
/* routing. Enabling this opens up nasty relay loopholes involving
#include <off_cvt.h>
#include <debug_peer.h>
#include <mail_error.h>
-#include <mail_flush.h>
+#include <flush_clnt.h>
#include <mail_stream.h>
#include <mail_queue.h>
#include <tok822.h>
*/
int var_smtpd_rcpt_limit;
int var_smtpd_tmout;
+char *var_relay_domains;
int var_smtpd_soft_erlim;
int var_smtpd_hard_erlim;
int var_queue_minfree; /* XXX use off_t */
char *var_smtpd_sasl_opts;
char *var_smtpd_sasl_realm;
char *var_filter_xport;
-char *var_fast_flush_domains;
/*
* Global state, for stand-alone mode queue file cleanup. When this is
smtpd_chat_reply(state, "501 Error: invalid parameter syntax");
return (-1);
}
- if (SMTPD_STAND_ALONE(state)) {
- smtpd_chat_reply(state, "458 Unable to queue messages");
- return (-1);
- }
/*
* XXX The implementation borrows heavily from the code that implements
* rejected. RFC 1985 requires that 459 be sent when the server refuses
* to perform the request.
*/
+ if (SMTPD_STAND_ALONE(state)) {
+ smtpd_chat_reply(state, "458 Unable to queue messages");
+ return (-1);
+ }
if ((err = smtpd_check_etrn(state, argv[1].strval)) != 0) {
smtpd_chat_reply(state, "%s", err);
return (-1);
}
- if (!*var_fast_flush_domains) {
- mail_flush_deferred();
- smtpd_chat_reply(state, "250 Queuing started");
- return (0);
- }
-
- /*
- * Create a fast ETRN cache file on the fly for an eligible site.
- */
- switch (mail_flush_site(argv[1].strval)) {
- case FLUSH_STAT_UNKNOWN:
- if (smtpd_check_etrn_cache_policy_ok(state, argv[1].strval)) {
- if (mail_flush_enable(argv[1].strval) != FLUSH_STAT_OK) {
- msg_warn("can't create fast ETRN cache for %s", argv[1].strval);
- } else {
- msg_info("created fast ETRN cache for %s (client=%s)",
- argv[1].strval, state->namaddr);
- }
- } else {
- msg_info("using slow ETRN service for %s (client=%s)",
- argv[1].strval, state->namaddr);
- }
- /* Fallthrough. */
- case FLUSH_STAT_FAIL:
- mail_flush_deferred();
- /* Fallthrough. */
+ switch (flush_send(argv[1].strval)) {
case FLUSH_STAT_OK:
smtpd_chat_reply(state, "250 Queuing started");
return (0);
+ case FLUSH_STAT_BAD:
+ msg_warn("bad ETRN %.100s... from %s", argv[1].strval, state->namaddr);
default:
smtpd_chat_reply(state, "458 Unable to queue messages");
- msg_warn("bad ETRN destination %.100s... from %s",
- argv[1].strval, state->namaddr);
return (-1);
}
}
0,
};
static CONFIG_STR_TABLE str_table[] = {
+ VAR_RELAY_DOMAINS, DEF_RELAY_DOMAINS, &var_relay_domains, 0, 0,
VAR_SMTPD_BANNER, DEF_SMTPD_BANNER, &var_smtpd_banner, 1, 0,
VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0,
VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
/* char *smtpd_check_etrn(state, destination)
/* SMTPD_STATE *state;
/* char *destination;
-/*
-/* int smtpd_check_etrn_cache_policy_ok(state, destination)
-/* SMTPD_STATE *state;
-/* char *destination;
/* DESCRIPTION
/* This module implements additional checks on SMTP client requests.
/* A client request is validated in the context of the session state.
/* Restrictions on the hostname that is sent with the HELO/EHLO
/* command.
/* .PP
-/* smtpd_check_etrn_cache_policy_ok() returns "true" if it is OK to
-/* create a fast ETRN cache file for the specified destination.
-/* The default policy ($smtpd_fast_flush_domains) is that the local MTA
-/* must be willing to relay mail to that destination.
-/*
/* smtpd_check_size() checks if a message with the given size can
/* be received (zero means that the message size is unknown). The
/* message is rejected when:
*/
static DOMAIN_LIST *relay_domains;
static NAMADR_LIST *mynetworks;
-static DOMAIN_LIST *fast_flush_domains;
/*
* Pre-parsed restriction lists.
*/
mynetworks = namadr_list_init(var_mynetworks);
relay_domains = domain_list_init(var_relay_domains);
- fast_flush_domains = domain_list_init(var_fast_flush_domains);
/*
* Pre-parse and pre-open the recipient maps.
msg_info("%s: host %s", myname, host);
/*
- * If we can't lookup the host, say we're not listed.
+ * If we can't lookup the host, play safe and assume it is OK.
*/
#define YUP 1
#define NOPE 0
if ((hp = gethostbyname(host)) == 0) {
if (msg_verbose)
msg_info("%s: host %s: not found", myname, host);
- return (NOPE);
+ return (YUP);
}
if (hp->h_addrtype != AF_INET || hp->h_length != sizeof(addr)) {
msg_warn("address type %d length %d for %s",
hp->h_addrtype, hp->h_length, host);
- return (NOPE);
+ return (YUP);
}
for (cpp = hp->h_addr_list; *cpp; cpp++) {
memcpy((char *) &addr, *cpp, sizeof(addr));
SMTPD_CHECK_ETRN_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
}
-/* smtpd_check_etrn_cache_policy_ok - is it OK to create a fast ETRN cache? */
-
-int smtpd_check_etrn_cache_policy_ok(SMTPD_STATE *unused_state, char *domain)
-{
-
- /*
- * Fast ETRN cache files are created on demand. Anything else would make
- * the feature unusable. However, it should not be possible that some
- * network vandal abuses this feature to create lots of bogus fast ETRN
- * cache files.
- *
- * By default, Postfix accepts ETRN commands from everywhere, but will
- * create fast ETRN cache files only for destinations that Postfix is
- * willing to relay mail to.
- */
-
- /*
- * The domain name must exist.
- */
- if (dns_lookup_types(domain, 0, (DNS_RR **) 0, (VSTRING *) 0,
- (VSTRING *) 0, T_A, T_MX, 0) != DNS_OK)
- return (0);
-
- /*
- * The domain name must be an authorized relay destination.
- */
- if (domain_list_match(fast_flush_domains, domain) == 0)
- return (0);
-
- /*
- * Must be OK then.
- */
- return (1);
-}
-
/* smtpd_check_rcptmap - permit if recipient address matches lookup table */
char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient)
extern char *smtpd_check_size(SMTPD_STATE *, off_t);
extern char *smtpd_check_rcpt(SMTPD_STATE *, char *);
extern char *smtpd_check_etrn(SMTPD_STATE *, char *);
-extern int smtpd_check_etrn_cache_policy_ok(SMTPD_STATE *, char *);
/* LICENSE
/* .ad