mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 13:48:06 +00:00
snapshot-20001003
This commit is contained in:
committed by
Viktor Dukhovni
parent
daf47b5f29
commit
04bda7598b
2
postfix/.indent.pro
vendored
2
postfix/.indent.pro
vendored
@@ -17,6 +17,8 @@
|
||||
-TCONFIG_INT_TABLE
|
||||
-TCONFIG_STR_FN_TABLE
|
||||
-TCONFIG_STR_TABLE
|
||||
-TCONFIG_TIME_FN_TABLE
|
||||
-TCONFIG_TIME_TABLE
|
||||
-TDELIVER_ATTR
|
||||
-TDELIVER_REQUEST
|
||||
-TDICT
|
||||
|
@@ -1,67 +1,104 @@
|
||||
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:
|
||||
How Postfix fast ETRN works
|
||||
===========================
|
||||
|
||||
fast_flush_domains = $relay_domains
|
||||
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.
|
||||
|
||||
By default, Postfix "fast ETRN" service is available only for
|
||||
destinations that the local MTA is willing to relay mail to.
|
||||
The behavior of the new "flush" daemon is controlled by parameters
|
||||
in the main.cf configuration file.
|
||||
|
||||
To disable the "fast ETRN" service, specify an empty string:
|
||||
By default, Postfix "fast ETRN/sendmail -qR" service is available
|
||||
only for destinations that Postfix is willing to relay mail to:
|
||||
|
||||
fast_flush_domains =
|
||||
fast_flush_policy = relay
|
||||
|
||||
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.
|
||||
|
||||
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 see something logged like:
|
||||
In the maillog file, you should immediately see a couple of logfile
|
||||
records, as evidence that the queue manager has opened queue files:
|
||||
|
||||
created fast ETRN cache for some.customer.domain
|
||||
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)
|
||||
|
||||
It will then do a "slow ETRN" once. The next time the same ETRN
|
||||
command is given, Postfix will do "fast ETRN".
|
||||
What happens next depends on whether the destination is reachable.
|
||||
|
||||
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.
|
||||
Repeat the exercise with another domain that your server is willing
|
||||
to relay to, but that has no mail queued.
|
||||
|
||||
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.
|
||||
helo my.client.name
|
||||
etrn some.other.customer.domain
|
||||
|
||||
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 your "fast ETRN" caching policy is left at its default setting,
|
||||
then the "etrn" command should trigger delivery of all queued mail.
|
||||
|
@@ -4300,10 +4300,12 @@ Apologies for any names omitted.
|
||||
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
|
||||
|
||||
@@ -4319,3 +4321,22 @@ Apologies for any names omitted.
|
||||
|
||||
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.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
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
|
||||
@@ -12,13 +12,6 @@ again.
|
||||
|
||||
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.
|
||||
@@ -28,25 +21,32 @@ After installing the new Postfix release:
|
||||
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
|
||||
@@ -55,22 +55,24 @@ by default now looks at up to 10000 messages at a time (was: 1000).
|
||||
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.
|
||||
queues mail for lots of different destinations.
|
||||
|
||||
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.
|
||||
This release introduces fast "ETRN" and "sendmail -qR". Unlike
|
||||
their lame predecessor, these deliver only mail that is queued for
|
||||
the specified destinations.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
@@ -343,17 +343,25 @@ mail_owner = postfix
|
||||
|
||||
# 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
|
||||
#
|
||||
|
@@ -75,7 +75,7 @@ qmgr fifo n - n 300 1 qmgr
|
||||
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
|
||||
|
@@ -6,58 +6,58 @@ FLUSH(8) FLUSH(8)
|
||||
|
||||
|
||||
<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.
|
||||
|
||||
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>all</b> Maintain per-destination deferred mail logfiles for
|
||||
all destinations.
|
||||
|
||||
<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>ENABLE</b> <i>sitename</i>
|
||||
Enable fast flush logging for the specified site.
|
||||
|
||||
<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>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.
|
||||
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
@@ -71,8 +71,32 @@ FLUSH(8) FLUSH(8)
|
||||
FLUSH(8) FLUSH(8)
|
||||
|
||||
|
||||
<b>FLUSH</b><i>_</i><b>STAT</b><i>_</i><b>UNKNOWN</b>
|
||||
The specified site has no fast flush log.
|
||||
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.
|
||||
|
||||
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).
|
||||
|
||||
<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
|
||||
@@ -84,10 +108,43 @@ FLUSH(8) FLUSH(8)
|
||||
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
|
||||
@@ -128,7 +185,16 @@ FLUSH(8) FLUSH(8)
|
||||
|
||||
|
||||
|
||||
2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3
|
||||
|
||||
|
||||
</pre> </body> </html>
|
||||
|
@@ -228,19 +228,6 @@ SMTPD(8) SMTPD(8)
|
||||
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-
|
||||
@@ -258,6 +245,19 @@ SMTPD(8) SMTPD(8)
|
||||
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
|
||||
@@ -269,60 +269,60 @@ SMTPD(8) SMTPD(8)
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -335,17 +335,8 @@ SMTPD(8) SMTPD(8)
|
||||
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>
|
||||
@@ -382,6 +373,15 @@ SMTPD(8) SMTPD(8)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
.SH NAME
|
||||
flush
|
||||
\-
|
||||
Postfix fast flush daemon
|
||||
Postfix fast flush cache manager
|
||||
.SH SYNOPSIS
|
||||
.na
|
||||
.nf
|
||||
@@ -12,33 +12,56 @@ Postfix fast flush daemon
|
||||
.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
|
||||
@@ -46,8 +69,8 @@ The request completed normally.
|
||||
.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
|
||||
@@ -63,9 +86,31 @@ Problems and transactions are logged to \fBsyslogd\fR(8).
|
||||
.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
|
||||
|
@@ -165,18 +165,6 @@ Disconnect after a client has made this number of errors.
|
||||
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
|
||||
@@ -192,6 +180,9 @@ Restrict what client hostnames are allowed in \fBHELO\fR and
|
||||
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
|
||||
|
@@ -66,11 +66,15 @@ flush.o: ../../include/valid_hostname.h
|
||||
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
|
||||
|
@@ -2,37 +2,60 @@
|
||||
/* 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
|
||||
@@ -40,8 +63,8 @@
|
||||
/* .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
|
||||
@@ -51,9 +74,27 @@
|
||||
/* 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
|
||||
@@ -97,9 +138,11 @@
|
||||
#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. */
|
||||
|
||||
@@ -107,28 +150,97 @@
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
static int flush_append(const char *site, const char *queue_id)
|
||||
#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_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
|
||||
@@ -158,11 +270,11 @@ static int flush_append(const char *site, const char *queue_id)
|
||||
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;
|
||||
@@ -178,12 +290,19 @@ static int flush_site(const char *site)
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -198,11 +317,10 @@ static int flush_site(const char *site)
|
||||
/*
|
||||
* 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);
|
||||
@@ -228,11 +346,12 @@ static int flush_site(const char *site)
|
||||
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",
|
||||
@@ -247,8 +366,7 @@ static int flush_site(const char *site)
|
||||
* 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.
|
||||
@@ -267,34 +385,11 @@ static int flush_site(const char *site)
|
||||
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;
|
||||
@@ -302,13 +397,14 @@ static void flush_purge(void)
|
||||
|
||||
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)
|
||||
@@ -316,22 +412,28 @@ static void flush_purge(void)
|
||||
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 */
|
||||
@@ -340,13 +442,13 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
|
||||
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.
|
||||
@@ -364,44 +466,51 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
@@ -17,7 +17,8 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \
|
||||
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 \
|
||||
@@ -36,7 +37,8 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.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 \
|
||||
@@ -51,7 +53,7 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.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 \
|
||||
@@ -64,7 +66,7 @@ TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
|
||||
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
|
||||
@@ -202,6 +204,11 @@ peer_name: $(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
|
||||
@@ -310,8 +317,7 @@ defer.o: mail_queue.h
|
||||
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
|
||||
@@ -386,6 +392,16 @@ file_id.o: ../../include/msg.h
|
||||
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
|
||||
@@ -503,6 +519,17 @@ mail_conf_str.o: ../../include/sys_defs.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
|
||||
@@ -541,13 +568,11 @@ mail_error.o: mail_error.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
|
||||
@@ -620,7 +645,6 @@ mail_scan.o: ../../include/vstring_vstream.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
|
||||
|
@@ -115,8 +115,7 @@
|
||||
|
||||
#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"
|
||||
|
||||
@@ -155,12 +154,11 @@ int vdefer_append(int flags, const char *id, const char *recipient,
|
||||
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);
|
||||
}
|
||||
|
@@ -40,8 +40,6 @@
|
||||
/* 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:
|
||||
@@ -101,8 +99,6 @@
|
||||
|
||||
#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"
|
||||
@@ -316,16 +312,8 @@ DELIVER_REQUEST *deliver_request_read(VSTREAM *stream)
|
||||
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);
|
||||
}
|
||||
|
||||
|
188
postfix/src/global/flush_clnt.c
Normal file
188
postfix/src/global/flush_clnt.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/*++
|
||||
/* 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);
|
||||
}
|
47
postfix/src/global/flush_clnt.h
Normal file
47
postfix/src/global/flush_clnt.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#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
|
@@ -46,9 +46,11 @@ extern const char *mail_conf_lookup_eval(const char *);
|
||||
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.
|
||||
@@ -56,6 +58,7 @@ extern int get_mail_conf_int2(const char *, const char *, int, int, int);
|
||||
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);
|
||||
|
||||
/*
|
||||
@@ -64,6 +67,7 @@ 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
|
||||
@@ -91,9 +95,18 @@ typedef struct {
|
||||
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 *);
|
||||
|
||||
/*
|
||||
@@ -122,9 +135,18 @@ typedef struct {
|
||||
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
|
||||
|
260
postfix/src/global/mail_conf_time.c
Normal file
260
postfix/src/global/mail_conf_time.c
Normal file
@@ -0,0 +1,260 @@
|
||||
/*++
|
||||
/* 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
|
@@ -2,70 +2,18 @@
|
||||
/* 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
|
||||
@@ -80,28 +28,13 @@
|
||||
/* 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 */
|
||||
|
||||
@@ -120,135 +53,3 @@ int mail_flush_deferred(void)
|
||||
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);
|
||||
}
|
||||
|
@@ -11,32 +11,9 @@
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
/* 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 */
|
||||
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@@ -58,7 +58,7 @@
|
||||
/* 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
|
||||
@@ -165,8 +165,7 @@ time_t var_starttime;
|
||||
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 */
|
||||
|
||||
@@ -277,8 +276,7 @@ void mail_params_init()
|
||||
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[] = {
|
||||
|
@@ -490,7 +490,7 @@ extern int var_min_delivery_slots;
|
||||
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;
|
||||
|
||||
/*
|
||||
@@ -1067,9 +1067,21 @@ extern char *var_filter_xport;
|
||||
/*
|
||||
* 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
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* 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
|
||||
|
@@ -19,7 +19,8 @@
|
||||
#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
|
||||
|
@@ -56,6 +56,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
|
||||
@@ -469,6 +474,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
|
||||
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;
|
||||
|
@@ -51,6 +51,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
|
||||
@@ -441,6 +446,9 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
|
||||
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;
|
||||
|
@@ -58,6 +58,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
|
||||
@@ -441,6 +446,9 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
|
||||
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;
|
||||
|
@@ -95,7 +95,6 @@ qmgr_active.o: ../../include/recipient_list.h
|
||||
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
|
||||
@@ -264,6 +263,7 @@ qmgr_scan.o: ../../include/msg.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
|
||||
|
@@ -103,7 +103,6 @@
|
||||
#include <bounce.h>
|
||||
#include <defer.h>
|
||||
#include <rec_type.h>
|
||||
#include <mail_flush.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@@ -227,13 +226,6 @@ void qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id)
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -697,7 +697,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
|
||||
* Optionally defer deliveries over specific transports, unless the
|
||||
* restriction is lifted temporarily.
|
||||
*/
|
||||
if (*var_defer_xports && (message->qflags & QMGR_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++)
|
||||
|
@@ -67,6 +67,7 @@
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_scan_dir.h>
|
||||
#include <flush_clnt.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@@ -100,6 +101,14 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
|
||||
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.
|
||||
*/
|
||||
|
@@ -10,7 +10,7 @@ DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
|
||||
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
|
||||
@@ -88,11 +88,13 @@ postconf.o: ../../include/iostuff.h
|
||||
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
|
||||
|
@@ -18,6 +18,12 @@
|
||||
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.
|
||||
|
||||
|
@@ -116,6 +116,7 @@ DICT *text_table;
|
||||
/*
|
||||
* Declarations generated by scanning actual C source files.
|
||||
*/
|
||||
#include "time_vars.h"
|
||||
#include "bool_vars.h"
|
||||
#include "int_vars.h"
|
||||
#include "str_vars.h"
|
||||
@@ -129,6 +130,11 @@ DICT *text_table;
|
||||
/*
|
||||
* 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,
|
||||
@@ -394,6 +400,7 @@ static void read_parameters(void)
|
||||
|
||||
static void hash_parameters(void)
|
||||
{
|
||||
CONFIG_TIME_TABLE *ctt;
|
||||
CONFIG_BOOL_TABLE *cbt;
|
||||
CONFIG_INT_TABLE *cit;
|
||||
CONFIG_STR_TABLE *cst;
|
||||
@@ -401,6 +408,8 @@ static void hash_parameters(void)
|
||||
|
||||
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++)
|
||||
@@ -458,6 +467,29 @@ static void print_bool(int mode, CONFIG_BOOL_TABLE *cbt)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
@@ -560,6 +592,8 @@ static void print_parameter(int mode, char *ptr)
|
||||
/*
|
||||
* 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))
|
||||
|
@@ -93,7 +93,6 @@ qmgr_active.o: ../../include/recipient_list.h
|
||||
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
|
||||
@@ -236,6 +235,7 @@ qmgr_scan.o: ../../include/msg.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
|
||||
|
@@ -103,7 +103,6 @@
|
||||
#include <bounce.h>
|
||||
#include <defer.h>
|
||||
#include <rec_type.h>
|
||||
#include <mail_flush.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@@ -227,13 +226,6 @@ void qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id)
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -580,7 +580,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
|
||||
* Optionally defer deliveries over specific transports, unless the
|
||||
* restriction is lifted temporarily.
|
||||
*/
|
||||
if (*var_defer_xports && (message->qflags & QMGR_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++)
|
||||
|
@@ -67,6 +67,7 @@
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_scan_dir.h>
|
||||
#include <flush_clnt.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@@ -100,6 +101,14 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
|
||||
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.
|
||||
*/
|
||||
|
@@ -59,10 +59,10 @@ sendmail.o: ../../include/msg.h
|
||||
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
|
||||
@@ -70,6 +70,7 @@ sendmail.o: ../../include/safe.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
|
||||
@@ -85,3 +86,4 @@ sendmail.o: ../../include/tok822.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
|
||||
|
@@ -120,7 +120,7 @@ smtpd.o: ../../include/off_cvt.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
|
||||
|
@@ -151,18 +151,6 @@
|
||||
/* 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
|
||||
@@ -178,6 +166,9 @@
|
||||
/* 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
|
||||
@@ -279,7 +270,7 @@
|
||||
#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>
|
||||
@@ -307,6 +298,7 @@
|
||||
*/
|
||||
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 */
|
||||
@@ -349,7 +341,6 @@ bool var_smtpd_sasl_enable;
|
||||
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
|
||||
@@ -1083,10 +1074,6 @@ static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
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
|
||||
@@ -1094,43 +1081,22 @@ static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -1460,6 +1426,7 @@ int main(int argc, char **argv)
|
||||
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,
|
||||
|
@@ -27,10 +27,6 @@
|
||||
/* 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.
|
||||
@@ -183,11 +179,6 @@
|
||||
/* 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:
|
||||
@@ -328,7 +319,6 @@ static MAPS *relocated_maps;
|
||||
*/
|
||||
static DOMAIN_LIST *relay_domains;
|
||||
static NAMADR_LIST *mynetworks;
|
||||
static DOMAIN_LIST *fast_flush_domains;
|
||||
|
||||
/*
|
||||
* Pre-parsed restriction lists.
|
||||
@@ -454,7 +444,6 @@ void smtpd_check_init(void)
|
||||
*/
|
||||
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.
|
||||
@@ -916,7 +905,7 @@ static int has_my_addr(char *host)
|
||||
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
|
||||
@@ -924,12 +913,12 @@ static int has_my_addr(char *host)
|
||||
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));
|
||||
@@ -1928,41 +1917,6 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain)
|
||||
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)
|
||||
|
@@ -20,7 +20,6 @@ extern char *smtpd_check_rcptmap(SMTPD_STATE *, char *);
|
||||
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
|
||||
|
Reference in New Issue
Block a user