2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-29 13:18:12 +00:00

postfix-2.4-20061217

This commit is contained in:
Wietse Venema 2006-12-17 00:00:00 -05:00 committed by Viktor Dukhovni
parent 39feae3a7e
commit 4be2bc6036
36 changed files with 878 additions and 303 deletions

View File

@ -12935,7 +12935,8 @@ Apologies for any names omitted.
after-the-fact consistency of the thread that was interrupted.
File: util/msg_output.c.
Robustness: replace exit() calls by _exit(). File: util/msg.c.
Robustness: replace exit() calls by _exit(). File: util/msg.c,
bounce/bounce_cleanup.c.
20061207
@ -12982,7 +12983,47 @@ Apologies for any names omitted.
Cleanup: streamline the signal handler reentrancy protections,
and document under what conditions these protections work,
with REENTRANCY sections in the relevant man pages. Files:
util/vbuf.c. util/msg.c, util/msg_output.c.
util/vbuf_print.c. util/msg.c, util/msg_output.c.
20061211
When doing server access control by the TLS client fingerprint,
do not require client certificate verification. Victor
Duchovni. File: smtpd/smtpd_check.c.
When the remote SMTP client certificate isn't verified,
don't send ccert_subject and ccert_issuer attributes in
check_policy_service requests. Victor Duchovni. File:
smtpd/smtpd_check.c.
Bugfix: the postconf command still complained about an
unqualified machine name, because it was not updated with
the 20050513 change that introduced a default "mydomain =
localdomain". File: postconf/postconf.c.
20061213
Bugfix: race condition in "ETRN site", "sendmail -qRsite"
and "postqueue -s site". When the command arrived while an
incoming queue scan was already in progress, mail could
stay deferred instead of being flushed. The fix was to
unthrottle the queue manager before moving files from the
deferred queue to the incoming queue. Files: flush/flush.c,
qmgr/qmgr_scan.c.
Feature: "sendmail -qIqueueid" and "postqueue -i queueid"
to flush a specific queue file. Files: sendmail/sendmail.c,
postqueue/postqueue.c, global/flush_clnt.c, flush/flush.c.
20061214
Performance: "sendmail -qIqueueid" and "postqueue -i queueid"
unthrottle only the necessary message delivery transports
and queues. The unthrottle request now is propagated to the
queue manager via queue file group read permission bits.
Based on initial implementation by Victor Duchovni. Files:
flush/flush.c, *qmgr/qmgr.c, *qmgr/qmgr_scan.c,
*qmgr/qmgr_active.c, *qmgr/qmgr_message.c.
Wish list:
@ -13037,9 +13078,6 @@ Wish list:
Are transport:nexthop null fields the same as in the case
of default_transport etc. parameters?
Introduce structured API for tls_server_mumble() just like
with smtp(8): this eliminates ever-growing lists of arguments.
Don't lose bits when converting st_dev into maildir file
name. It's 64 bits on Linux. Found with the BEAM source
code analyzer. Is this really a problem, or are they just
@ -13054,9 +13092,6 @@ Wish list:
while it is configured in an SMTP server that runs before
the smtpd_proxy filter.
The sendmail command should not return non-std exit status
after fatal error in some internal library routine.
Log DSN original recipient when rejecting mail.
Keep whitespace between label and ":"?
@ -13190,20 +13225,13 @@ Wish list:
would allow correlation of rejected RCPT TO requests with
accepted requests for the same mail transaction.
Med: silly queue file bit so that the queue manager doesn't
skip files when fast flush is requested while a queue scan
is in progress. The bit is set by the flush server and is
reset when the mail is deferred, so that it survives queue
manager restart. It's not clear, however, how one would
unthrottle disabled transports or queues.
Med: postsuper -r should do something with recipients in
bounce logfiles, to make sure the sender will be notified.
To be perfectly safe, no process other than the queue manager
should move a queue file away from the active queue.
This could involve tagging a queue file, and use up another
permission bit.
permission bit (postsuper tags a "hot" file, qmgr requeues it).
Low: postsuper re-run after renaming files, but only a
limited number of times.
@ -13222,7 +13250,7 @@ Wish list:
Low: have a configurable list of errno values for mailbox
or maildir delivery that result in deferral rather than
bouncing mail.
bouncing mail. What about "killed by signal" exits?
Low: after reorganizing configuration parameters, add flags
to all parameters whose value can be read from file.

View File

@ -110,6 +110,7 @@ this:
/^Received:.* +by +(porcupine\.org)[[:>:]]/
reject forged mail server name in Received: header: $1
endif
/^Message-ID:.* <!&!/ DUNNO
/^Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
@ -123,6 +124,7 @@ this:
/^[> ]*Received:.* +by +(porcupine\.org)[[:>:]]/
reject forged mail server name in Received: header: $1
endif
/^[> ]*Message-ID:.* <!&!/ DUNNO
/^[> ]*Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
@ -143,30 +145,54 @@ Notes:
* The "if /pattern/" and "endif" eliminate unnecessary matching attempts. DO
NOT indent lines starting with /pattern/ between the "if" and "endif"!
* The two "Message-ID:.* <!&!" rules are workarounds for some versions of
Outlook express, as described in the caveats section below.
CCaavveeaattss
Netscape Messenger (and reportedly, Mozilla) sends a HELO name that is
identical to the sender address domain part. If you have such clients then the
above patterns would block legitimate email.
* Netscape Messenger (and reportedly, Mozilla) sends a HELO name that is
identical to the sender address domain part. If you have such clients then
the above patterns would block legitimate email.
My network has only one such machine, and to prevent its mail from being
blocked I have configured it to send mail as user@hostname.porcupine.org. On
the Postfix server, a canonical mapping translates this temporary address into
user@porcupine.org.
My network has only one such machine, and to prevent its mail from being
blocked I have configured it to send mail as user@hostname.porcupine.org.
On the Postfix server, a canonical mapping translates this temporary
address into user@porcupine.org.
/etc/postfix/main.cf:
canonical_maps = hash:/etc/postfix/canonical
/etc/postfix/main.cf:
canonical_maps = hash:/etc/postfix/canonical
/etc/postfix/canonical:
@hostname.porcupine.org @porcupine.org
/etc/postfix/canonical:
@hostname.porcupine.org @porcupine.org
This is of course practical only when you have very few systems that send HELO
commands like this, and when you never have to send mail to a user on such a
host.
This is of course practical only when you have very few systems that send
HELO commands like this, and when you never have to send mail to a user on
such a host.
An alternative would be to remove the hostname from "hostname.porcupine.org"
with address masquerading, as described in the ADDRESS_REWRITING_README
document.
An alternative would be to remove the hostname from
"hostname.porcupine.org" with address masquerading, as described in the
ADDRESS_REWRITING_README document.
* Reportedly, Outlook 2003 (perhaps Outlook Express, and other versions as
well) present substantially different Message-ID headers depending upon
whether or not a DSN is requested (via Options "Request a delivery receipt
for this message").
When a DSN is requested, Outlook 2003 uses a Message-ID string that ends in
the sender's domain name:
Message-ID: <!&! ...very long string... ==@example.com>
where example.com is the domain name part of the email address specified in
Outlook's account settings for the user. Since many users configure their
email addresses as username@example.com, messages with DSN turned on will
trigger the REJECT action in the previous section.
If you have such clients then you can to exclude their Message-ID strings
with the two "Message-ID:.* <!&!" patterns that are shown in the previous
section. Otherwise you will not be able to use the two backscatter rules to
stop forged Message ID strings. Of course this workaround may break the
next time Outlook is changed.
BBlloocckkiinngg bbaacckkssccaatttteerr mmaaiill wwiitthh ffoorrggeedd sseennddeerr iinnffoorrmmaattiioonn

View File

@ -17,6 +17,14 @@ Incompatibility with Postfix 2.2 and earlier
If you upgrade from Postfix 2.2 or earlier, read RELEASE_NOTES-2.3
before proceeding.
Incompatible changes with Postfix snapshot 20061217
===================================================
Postfix no longer requires a domain name. It uses "localdomain" as
the default Internet domain name when no domain is specified in
main.cf, and when the machine hostname does not include domain name
information.
Incompatible changes with Postfix snapshot 20061209
===================================================

View File

@ -186,6 +186,7 @@ patterns like this: </p>
/^Received:.* +by +(porcupine\.org)[[:&gt;:]]/
reject forged mail server name in Received: header: $1
endif
/^Message-ID:.* &lt;!&amp;!/ DUNNO
/^Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
@ -198,6 +199,7 @@ patterns like this: </p>
/^[&gt; ]*Received:.* +by +(porcupine\.org)[[:&gt;:]]/
reject forged mail server name in Received: header: $1
endif
/^[&gt; ]*Message-ID:.* &lt;!&amp;!/ DUNNO
/^[&gt; ]*Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
</pre>
@ -226,10 +228,18 @@ see your system documentation. </p>
matching attempts. DO NOT indent lines starting with /pattern/
between the "if" and "endif"! </p>
<li> <p> The two "<tt>Message-ID:.* &lt;!&amp;!</tt>" rules are
workarounds for some versions of Outlook express, as described in
the <a href="#caveats"> caveats </a> section below.
</ul>
<p><a name="caveats"><strong>Caveats</strong></a></p>
<ul>
<li>
<p> Netscape Messenger (and reportedly, Mozilla) sends a HELO name
that is identical to the sender address domain part. If you have
such clients then the above patterns would block legitimate email.
@ -260,6 +270,35 @@ mail to a user on such a host. </p>
masquerading, as described in the <a href="ADDRESS_REWRITING_README.html">ADDRESS_REWRITING_README</a> document.
</p>
<li> <p> Reportedly, Outlook 2003 (perhaps Outlook Express, and
other versions as well) present substantially different Message-ID
headers depending upon whether or not a DSN is requested (via Options
"Request a delivery receipt for this message"). </p>
<p> When a DSN is requested, Outlook 2003 uses a Message-ID string
that ends in the sender's domain name: </p>
<blockquote>
<pre>
Message-ID: &lt;!&amp;! ...very long string... ==@example.com&gt;
</pre>
</blockquote>
<p> where <i>example.com</i> is the domain name part of the email
address specified in Outlook's account settings for the user. Since
many users configure their email addresses as <i>username@example.com</i>,
messages with DSN turned on will trigger the REJECT action in the
previous section. </p>
<p> If you have such clients then you can to exclude their Message-ID
strings with the two "<tt>Message-ID:.* &lt;!&amp;!</tt>" patterns
that are shown in the previous section. Otherwise you will not be
able to use the two backscatter rules to stop forged Message ID
strings. Of course this workaround may break the next time Outlook
is changed. </p>
</ul>
<h3><a name="forged_sender">Blocking backscatter mail with forged
sender information</a></h3>

View File

@ -38,10 +38,13 @@ FLUSH(8) FLUSH(8)
the specified queue ID is queued for the specified
destination.
<b>send</b> <i>sitename</i>
<b>send_site</b> <i>sitename</i>
Request delivery of mail that is queued for the
specified destination.
<b>send_file</b> <i>queueid</i>
Request delivery of the specified deferred message.
<b>refresh</b>
Refresh non-empty per-destination logfiles that
were not read in <b>$<a href="postconf.5.html#fast_flush_refresh_time">fast_flush_refresh_time</a></b> hours, by
@ -57,7 +60,7 @@ FLUSH(8) FLUSH(8)
<b>SECURITY</b>
The <a href="flush.8.html"><b>flush</b>(8)</a> server is not security-sensitive. It does not
talk to the network, and it does not talk to local users.
talk to the network, and it does not talk to local users.
The fast flush server can run chrooted at fixed low privi-
lege.
@ -65,46 +68,46 @@ FLUSH(8) FLUSH(8)
Problems and transactions are logged to <b>syslogd</b>(8).
<b>BUGS</b>
Fast flush logfiles are truncated only after a "send"
request, not when mail is actually delivered, and there-
fore can accumulate outdated or redundant data. In order
to maintain sanity, "refresh" must be executed periodi-
cally. This can be automated with a suitable wakeup timer
Fast flush logfiles are truncated only after a "send"
request, not when mail is actually delivered, and there-
fore can accumulate outdated or redundant data. In order
to maintain sanity, "refresh" must be executed periodi-
cally. This can be automated with a suitable wakeup timer
setting in the <a href="master.5.html"><b>master.cf</b></a> configuration file.
Upon receipt of a request to deliver mail for an eligible
destination, the <a href="flush.8.html"><b>flush</b>(8)</a> server requests delivery of all
messages that are listed in that destination's logfile,
regardless of the recipients of those messages. This is
Upon receipt of a request to deliver mail for an eligible
destination, the <a href="flush.8.html"><b>flush</b>(8)</a> server requests delivery of all
messages that are listed in that destination's logfile,
regardless of the recipients of those messages. This is
not an issue for mail that is sent to a <b><a href="postconf.5.html#relay_domains">relay_domains</a></b> des-
tination because such mail typically only has recipients
tination because such mail typically only has recipients
in one domain.
<b>CONFIGURATION PARAMETERS</b>
Changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up automatically as <a href="flush.8.html"><b>flush</b>(8)</a>
processes run for only a limited amount of time. Use the
processes run for only a limited amount of time. Use the
command "<b>postfix reload</b>" to speed up a change.
The text below provides only a parameter summary. See
The text below provides only a parameter summary. See
<a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
How much time a Postfix daemon process may take to
handle a request before it is terminated by a
How much time a Postfix daemon process may take to
handle a request before it is terminated by a
built-in watchdog timer.
<b><a href="postconf.5.html#fast_flush_domains">fast_flush_domains</a> ($<a href="postconf.5.html#relay_domains">relay_domains</a>)</b>
Optional list of destinations that are eligible for
per-destination logfiles with mail that is queued
per-destination logfiles with mail that is queued
to those destinations.
<b><a href="postconf.5.html#fast_flush_refresh_time">fast_flush_refresh_time</a> (12h)</b>
The time after which a non-empty but unread per-
destination "fast flush" logfile needs to be
The time after which a non-empty but unread per-
destination "fast flush" logfile needs to be
refreshed.
<b><a href="postconf.5.html#fast_flush_purge_time">fast_flush_purge_time</a> (7d)</b>
@ -116,38 +119,38 @@ FLUSH(8) FLUSH(8)
over an internal communication channel.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
The maximum amount of time that an idle Postfix
daemon process waits for the next service request
The maximum amount of time that an idle Postfix
daemon process waits for the next service request
before exiting.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
The maximal number of connection requests before a
The maximal number of connection requests before a
Postfix daemon process terminates.
<b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' out-</b>
<b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' out-</b>
<b>put)</b>
What Postfix features match subdomains of
"domain.tld" automatically, instead of requiring an
explicit ".domain.tld" pattern.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
The process ID of a Postfix command or daemon
The process ID of a Postfix command or daemon
process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
The process name of a Postfix command or daemon
The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
The location of the Postfix top-level queue direc-
The location of the Postfix top-level queue direc-
tory.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
The mail system name that is prepended to the
process name in syslog records, so that "smtpd"
The mail system name that is prepended to the
process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
<b>FILES</b>
@ -165,7 +168,7 @@ FLUSH(8) FLUSH(8)
<a href="ETRN_README.html">ETRN_README</a>, Postfix ETRN howto
<b>LICENSE</b>
The Secure Mailer license must be distributed with this
The Secure Mailer license must be distributed with this
software.
<b>HISTORY</b>

View File

@ -9190,9 +9190,10 @@ client network address information.
<dt><b><a name="check_ccert_access">check_ccert_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
<dd>When the remote SMTP client certificate is verified successfully,
use the client certificate fingerprint as lookup key for the specified
<a href="access.5.html">access(5)</a> database. This feature is available with Postfix version 2.2.</dd>
<dd> Use the client certificate fingerprint as lookup key for the
specified <a href="access.5.html">access(5)</a> database; with Postfix version 2.2, also require
that the SMTP client certificate is verified successfully. This
feature is available with Postfix version 2.2 and later.</dd>
<dt><b><a name="check_client_access">check_client_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>

View File

@ -11,6 +11,7 @@ POSTQUEUE(1) POSTQUEUE(1)
<b>SYNOPSIS</b>
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-f</b>
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-i</b> <i>queue</i><b>_</b><i>id</i>
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-p</b>
<b>postqueue</b> [<b>-v</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] <b>-s</b> <i>site</i>
@ -41,115 +42,121 @@ POSTQUEUE(1) POSTQUEUE(1)
will result in poor delivery performance of all
other mail.
<b>-i</b> <i>queue</i><b>_</b><i>id</i>
Schedule immediate delivery of mail with the speci-
fied queue ID. This feature uses the <a href="flush.8.html"><b>flush</b>(8)</a>
server, and is available with Postfix 2.4 and
later.
<b>-p</b> Produce a traditional sendmail-style queue listing.
This option implements the traditional <b>mailq</b> com-
This option implements the traditional <b>mailq</b> com-
mand, by contacting the Postfix <a href="showq.8.html"><b>showq</b>(8)</a> daemon.
Each queue entry shows the queue file ID, message
Each queue entry shows the queue file ID, message
size, arrival time, sender, and the recipients that
still need to be delivered. If mail could not be
delivered upon the last attempt, the reason for
failure is shown. This mode of operation is imple-
mented by executing the <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command. The
queue ID string is followed by an optional status
still need to be delivered. If mail could not be
delivered upon the last attempt, the reason for
failure is shown. This mode of operation is imple-
mented by executing the <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command. The
queue ID string is followed by an optional status
character:
<b>*</b> The message is in the <b>active</b> queue, i.e. the
message is selected for delivery.
<b>!</b> The message is in the <b>hold</b> queue, i.e. no
further delivery attempt will be made until
<b>!</b> The message is in the <b>hold</b> queue, i.e. no
further delivery attempt will be made until
the mail is taken off hold.
<b>-s</b> <i>site</i>
Schedule immediate delivery of all mail that is
Schedule immediate delivery of all mail that is
queued for the named <i>site</i>. A numerical site must be
specified as a valid <a href="http://www.faqs.org/rfcs/rfc2821.html">RFC 2821</a> address literal
enclosed in [], just like in email addresses. The
specified as a valid <a href="http://www.faqs.org/rfcs/rfc2821.html">RFC 2821</a> address literal
enclosed in [], just like in email addresses. The
site must be eligible for the "fast flush" service.
See <a href="flush.8.html"><b>flush</b>(8)</a> for more information about the "fast
See <a href="flush.8.html"><b>flush</b>(8)</a> for more information about the "fast
flush" service.
This option implements the traditional "<b>sendmail</b>
<b>-qR</b><i>site</i>" command, by contacting the Postfix
This option implements the traditional "<b>sendmail</b>
<b>-qR</b><i>site</i>" command, by contacting the Postfix
<a href="flush.8.html"><b>flush</b>(8)</a> daemon.
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
tiple <b>-v</b> options make the software increasingly
verbose. As of Postfix 2.3, this option is avail-
tiple <b>-v</b> options make the software increasingly
verbose. As of Postfix 2.3, this option is avail-
able for the super-user only.
<b>SECURITY</b>
This program is designed to run with set-group ID privi-
This program is designed to run with set-group ID privi-
leges, so that it can connect to Postfix daemon processes.
<b>DIAGNOSTICS</b>
Problems are logged to <b>syslogd</b>(8) and to the standard
Problems are logged to <b>syslogd</b>(8) and to the standard
error stream.
<b>ENVIRONMENT</b>
MAIL_CONFIG
Directory with the <a href="postconf.5.html"><b>main.cf</b></a> file. In order to avoid
exploitation of set-group ID privileges, a non-
Directory with the <a href="postconf.5.html"><b>main.cf</b></a> file. In order to avoid
exploitation of set-group ID privileges, a non-
standard directory is allowed only if:
<b>o</b> The name is listed in the standard <a href="postconf.5.html"><b>main.cf</b></a>
file with the <b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a></b>
<b>o</b> The name is listed in the standard <a href="postconf.5.html"><b>main.cf</b></a>
file with the <b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a></b>
configuration parameter.
<b>o</b> The command is invoked by the super-user.
<b>CONFIGURATION PARAMETERS</b>
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
to this program. The text below provides only a parameter
summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including exam-
summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including exam-
ples.
<b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a> (empty)</b>
A list of non-default Postfix configuration direc-
A list of non-default Postfix configuration direc-
tories that may be specified with "-c <a href="postconf.5.html#config_directory">config_direc</a>-
<a href="postconf.5.html#config_directory">tory</a>" on the command line, or via the MAIL_CONFIG
<a href="postconf.5.html#config_directory">tory</a>" on the command line, or via the MAIL_CONFIG
environment parameter.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
The location of all postfix administrative com-
The location of all postfix administrative com-
mands.
<b><a href="postconf.5.html#fast_flush_domains">fast_flush_domains</a> ($<a href="postconf.5.html#relay_domains">relay_domains</a>)</b>
Optional list of destinations that are eligible for
per-destination logfiles with mail that is queued
per-destination logfiles with mail that is queued
to those destinations.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
The list of environment parameters that a Postfix
The list of environment parameters that a Postfix
process will import from a non-Postfix parent
process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
The location of the Postfix top-level queue direc-
The location of the Postfix top-level queue direc-
tory.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
The mail system name that is prepended to the
process name in syslog records, so that "smtpd"
The mail system name that is prepended to the
process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
<b><a href="postconf.5.html#trigger_timeout">trigger_timeout</a> (10s)</b>
The time limit for sending a trigger to a Postfix
daemon (for example, the <a href="pickup.8.html"><b>pickup</b>(8)</a> or <a href="qmgr.8.html"><b>qmgr</b>(8)</a> dae-
The time limit for sending a trigger to a Postfix
daemon (for example, the <a href="pickup.8.html"><b>pickup</b>(8)</a> or <a href="qmgr.8.html"><b>qmgr</b>(8)</a> dae-
mon).
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#authorized_flush_users">authorized_flush_users</a> (static:anyone)</b>
List of users who are authorized to flush the
List of users who are authorized to flush the
queue.
<b><a href="postconf.5.html#authorized_mailq_users">authorized_mailq_users</a> (static:anyone)</b>
@ -169,11 +176,11 @@ POSTQUEUE(1) POSTQUEUE(1)
<a href="ETRN_README.html">ETRN_README</a>, Postfix ETRN howto
<b>LICENSE</b>
The Secure Mailer license must be distributed with this
The Secure Mailer license must be distributed with this
software.
<b>HISTORY</b>
The postqueue command was introduced with Postfix version
The postqueue command was introduced with Postfix version
1.1.
<b>AUTHOR(S)</b>

View File

@ -217,24 +217,30 @@ SENDMAIL(1) SENDMAIL(1)
The interval between queue runs. Use the
<b><a href="postconf.5.html#queue_run_delay">queue_run_delay</a></b> configuration parameter instead.
<b>-qI</b><i>queueid</i>
Schedule immediate delivery of mail with the speci-
fied queue ID. This option is implemented by exe-
cuting the <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command, and is available
with Postfix version 2.4 and later.
<b>-qR</b><i>site</i>
Schedule immediate delivery of all mail that is
Schedule immediate delivery of all mail that is
queued for the named <i>site</i>. This option accepts only
<i>site</i> names that are eligible for the "fast flush"
service, and is implemented by executing the
<i>site</i> names that are eligible for the "fast flush"
service, and is implemented by executing the
<a href="postqueue.1.html"><b>postqueue</b>(1)</a> command. See <a href="flush.8.html"><b>flush</b>(8)</a> for more infor-
mation about the "fast flush" service.
<b>-qS</b><i>site</i>
This command is not implemented. Use the slower
This command is not implemented. Use the slower
"<b>sendmail -q</b>" command instead.
<b>-t</b> Extract recipients from message headers. These are
added to any recipients specified on the command
<b>-t</b> Extract recipients from message headers. These are
added to any recipients specified on the command
line.
With Postfix versions prior to 2.1, this option
requires that no recipient addresses are specified
With Postfix versions prior to 2.1, this option
requires that no recipient addresses are specified
on the command line.
<b>-U</b> (ignored)
@ -247,41 +253,41 @@ SENDMAIL(1) SENDMAIL(1)
This feature is available in Postfix 2.3 and later.
<b>-XV</b> (Postfix 2.2 and earlier: <b>-V</b>)
Variable Envelope Return Path. Given an envelope
sender address of the form <i>owner-listname</i>@<i>origin</i>,
each recipient <i>user</i>@<i>domain</i> receives mail with a
Variable Envelope Return Path. Given an envelope
sender address of the form <i>owner-listname</i>@<i>origin</i>,
each recipient <i>user</i>@<i>domain</i> receives mail with a
personalized envelope sender address.
By default, the personalized envelope sender
address is <i>owner-listname</i><b>+</b><i>user</i><b>=</b><i>domain</i>@<i>origin</i>. The
default <b>+</b> and <b>=</b> characters are configurable with
the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b> configuration parame-
By default, the personalized envelope sender
address is <i>owner-listname</i><b>+</b><i>user</i><b>=</b><i>domain</i>@<i>origin</i>. The
default <b>+</b> and <b>=</b> characters are configurable with
the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b> configuration parame-
ter.
<b>-XV</b><i>xy</i> (Postfix 2.2 and earlier: <b>-V</b><i>xy</i>)
As <b>-XV</b>, but uses <i>x</i> and <i>y</i> as the VERP delimiter
characters, instead of the characters specified
with the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b> configuration
As <b>-XV</b>, but uses <i>x</i> and <i>y</i> as the VERP delimiter
characters, instead of the characters specified
with the <b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a></b> configuration
parameter.
<b>-v</b> Send an email report of the first delivery attempt
(Postfix versions 2.1 and later). Mail delivery
always happens in the background. When multiple <b>-v</b>
<b>-v</b> Send an email report of the first delivery attempt
(Postfix versions 2.1 and later). Mail delivery
always happens in the background. When multiple <b>-v</b>
options are given, enable verbose logging for
debugging purposes.
<b>-X</b> <i>log</i><b>_</b><i>file</i> (ignored)
Log mailer traffic. Use the <b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a></b> and
<b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a></b> configuration parameters instead.
Log mailer traffic. Use the <b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a></b> and
<b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a></b> configuration parameters instead.
<b>SECURITY</b>
By design, this program is not set-user (or group) id.
However, it must handle data from untrusted users or
untrusted machines. Thus, the usual precautions need to
By design, this program is not set-user (or group) id.
However, it must handle data from untrusted users or
untrusted machines. Thus, the usual precautions need to
be taken against malicious inputs.
<b>DIAGNOSTICS</b>
Problems are logged to <b>syslogd</b>(8) and to the standard
Problems are logged to <b>syslogd</b>(8) and to the standard
error stream.
<b>ENVIRONMENT</b>
@ -293,21 +299,21 @@ SENDMAIL(1) SENDMAIL(1)
<b>MAIL_DEBUG</b> (value does not matter)
Enable debugging with an external command, as spec-
ified with the <b><a href="postconf.5.html#debugger_command">debugger_command</a></b> configuration
ified with the <b><a href="postconf.5.html#debugger_command">debugger_command</a></b> configuration
parameter.
<b>NAME</b> The sender full name. This is used only with mes-
sages that have no <b>From:</b> message header. See also
<b>NAME</b> The sender full name. This is used only with mes-
sages that have no <b>From:</b> message header. See also
the <b>-F</b> option above.
<b>CONFIGURATION PARAMETERS</b>
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
to this program. The text below provides only a parameter
summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including exam-
summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including exam-
ples.
<b>TROUBLE SHOOTING CONTROLS</b>
The <a href="DEBUG_README.html">DEBUG_README</a> file gives examples of how to trouble
The <a href="DEBUG_README.html">DEBUG_README</a> file gives examples of how to trouble
shoot a Postfix system.
<b><a href="postconf.5.html#debugger_command">debugger_command</a> (empty)</b>
@ -315,29 +321,29 @@ SENDMAIL(1) SENDMAIL(1)
mon program is invoked with the -D option.
<b><a href="postconf.5.html#debug_peer_level">debug_peer_level</a> (2)</b>
The increment in verbose logging level when a
remote client or server matches a pattern in the
The increment in verbose logging level when a
remote client or server matches a pattern in the
<a href="postconf.5.html#debug_peer_list">debug_peer_list</a> parameter.
<b><a href="postconf.5.html#debug_peer_list">debug_peer_list</a> (empty)</b>
Optional list of remote client or server hostname
or network address patterns that cause the verbose
logging level to increase by the amount specified
Optional list of remote client or server hostname
or network address patterns that cause the verbose
logging level to increase by the amount specified
in $<a href="postconf.5.html#debug_peer_level">debug_peer_level</a>.
<b>ACCESS CONTROLS</b>
Available in Postfix version 2.2 and later:
<b><a href="postconf.5.html#authorized_flush_users">authorized_flush_users</a> (static:anyone)</b>
List of users who are authorized to flush the
List of users who are authorized to flush the
queue.
<b><a href="postconf.5.html#authorized_mailq_users">authorized_mailq_users</a> (static:anyone)</b>
List of users who are authorized to view the queue.
<b><a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> (static:anyone)</b>
List of users who are authorized to submit mail
with the <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command (and with the privi-
List of users who are authorized to submit mail
with the <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command (and with the privi-
leged <a href="postdrop.1.html"><b>postdrop</b>(1)</a> helper command).
<b>RESOURCE AND RATE CONTROLS</b>
@ -346,7 +352,7 @@ SENDMAIL(1) SENDMAIL(1)
sent in a non-delivery notification.
<b><a href="postconf.5.html#fork_attempts">fork_attempts</a> (5)</b>
The maximal number of attempts to fork() a child
The maximal number of attempts to fork() a child
process.
<b><a href="postconf.5.html#fork_delay">fork_delay</a> (1s)</b>
@ -354,11 +360,11 @@ SENDMAIL(1) SENDMAIL(1)
process.
<b><a href="postconf.5.html#hopcount_limit">hopcount_limit</a> (50)</b>
The maximal number of Received: message headers
The maximal number of Received: message headers
that is allowed in the primary message headers.
<b><a href="postconf.5.html#queue_run_delay">queue_run_delay</a> (1000s)</b>
The time between <a href="QSHAPE_README.html#deferred_queue">deferred queue</a> scans by the queue
The time between <a href="QSHAPE_README.html#deferred_queue">deferred queue</a> scans by the queue
manager.
<b>FAST FLUSH CONTROLS</b>
@ -367,37 +373,37 @@ SENDMAIL(1) SENDMAIL(1)
<b><a href="postconf.5.html#fast_flush_domains">fast_flush_domains</a> ($<a href="postconf.5.html#relay_domains">relay_domains</a>)</b>
Optional list of destinations that are eligible for
per-destination logfiles with mail that is queued
per-destination logfiles with mail that is queued
to those destinations.
<b>VERP CONTROLS</b>
The <a href="VERP_README.html">VERP_README</a> file describes configuration and operation
details of Postfix support for variable envelope return
details of Postfix support for variable envelope return
path addresses.
<b><a href="postconf.5.html#default_verp_delimiters">default_verp_delimiters</a> (+=)</b>
The two default VERP delimiter characters.
<b><a href="postconf.5.html#verp_delimiter_filter">verp_delimiter_filter</a> (-=+)</b>
The characters Postfix accepts as VERP delimiter
characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
The characters Postfix accepts as VERP delimiter
characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
and in SMTP commands.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#alias_database">alias_database</a> (see 'postconf -d' output)</b>
The alias databases for <a href="local.8.html"><b>local</b>(8)</a> delivery that are
The alias databases for <a href="local.8.html"><b>local</b>(8)</a> delivery that are
updated with "<b>newaliases</b>" or with "<b>sendmail -bi</b>".
<b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
The location of all postfix administrative com-
The location of all postfix administrative com-
mands.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
The default location of the Postfix <a href="postconf.5.html">main.cf</a> and
<a href="master.5.html">master.cf</a> configuration files.
<b><a href="postconf.5.html#daemon_directory">daemon_directory</a> (see 'postconf -d' output)</b>
The directory with Postfix support programs and
The directory with Postfix support programs and
daemon programs.
<b><a href="postconf.5.html#default_database_type">default_database_type</a> (see 'postconf -d' output)</b>
@ -405,16 +411,16 @@ SENDMAIL(1) SENDMAIL(1)
<a href="postalias.1.html"><b>postalias</b>(1)</a> and <a href="postmap.1.html"><b>postmap</b>(1)</a> commands.
<b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a> (0h)</b>
The time after which the sender receives the mes-
The time after which the sender receives the mes-
sage headers of mail that is still queued.
<b><a href="postconf.5.html#enable_errors_to">enable_errors_to</a> (no)</b>
Report mail delivery errors to the address speci-
fied with the non-standard Errors-To: message
header, instead of the envelope sender address
(this feature is removed with Postfix version 2.2,
is turned off by default with Postfix version 2.1,
and is always turned on with older Postfix ver-
Report mail delivery errors to the address speci-
fied with the non-standard Errors-To: message
header, instead of the envelope sender address
(this feature is removed with Postfix version 2.2,
is turned off by default with Postfix version 2.1,
and is always turned on with older Postfix ver-
sions).
<b><a href="postconf.5.html#mail_owner">mail_owner</a> (postfix)</b>
@ -422,21 +428,21 @@ SENDMAIL(1) SENDMAIL(1)
and most Postfix daemon processes.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
The location of the Postfix top-level queue direc-
The location of the Postfix top-level queue direc-
tory.
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
Don't rewrite message headers from remote clients
Don't rewrite message headers from remote clients
at all when this parameter is empty; otherwise, re-
write message headers and append the specified
write message headers and append the specified
domain name to incomplete addresses.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
The mail system name that is prepended to the
process name in syslog records, so that "smtpd"
The mail system name that is prepended to the
process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
<b>FILES</b>
@ -461,7 +467,7 @@ SENDMAIL(1) SENDMAIL(1)
<a href="VERP_README.html">VERP_README</a>, Postfix VERP howto
<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>

View File

@ -10,6 +10,8 @@ Postfix queue control
.nf
\fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-f\fR
.br
\fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-i \fIqueue_id\fR
.br
\fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-p\fR
.br
\fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
@ -36,6 +38,10 @@ by contacting the Postfix \fBqmgr\fR(8) daemon.
Warning: flushing undeliverable mail frequently will result in
poor delivery performance of all other mail.
.IP "\fB-i \fIqueue_id\fR"
Schedule immediate delivery of mail with the specified queue ID.
This feature uses the \fBflush\fR(8) server, and is available
with Postfix 2.4 and later.
.IP \fB-p\fR
Produce a traditional sendmail-style queue listing.
This option implements the traditional \fBmailq\fR command,

View File

@ -174,6 +174,11 @@ poor delivery performance of all other mail.
.IP "\fB-q\fIinterval\fR (ignored)"
The interval between queue runs. Use the \fBqueue_run_delay\fR
configuration parameter instead.
.IP \fB-qI\fIqueueid\fR
Schedule immediate delivery of mail with the specified queue
ID. This option is implemented by executing the
\fBpostqueue\fR(1) command, and is available with Postfix
version 2.4 and later.
.IP \fB-qR\fIsite\fR
Schedule immediate delivery of all mail that is queued for the named
\fIsite\fR. This option accepts only \fIsite\fR names that are

View File

@ -5408,9 +5408,10 @@ restriction that matches wins.
The following restrictions are specific to client hostname or
client network address information.
.IP "\fBcheck_ccert_access \fItype:table\fR\fR"
When the remote SMTP client certificate is verified successfully,
use the client certificate fingerprint as lookup key for the specified
\fBaccess\fR(5) database. This feature is available with Postfix version 2.2.
Use the client certificate fingerprint as lookup key for the
specified \fBaccess\fR(5) database; with Postfix version 2.2, also require
that the SMTP client certificate is verified successfully. This
feature is available with Postfix version 2.2 and later.
.IP "\fBcheck_client_access \fItype:table\fR\fR"
Search the specified access database for the client hostname,
parent domains, client IP address, or networks obtained by stripping

View File

@ -36,9 +36,11 @@ This server implements the following requests:
.IP "\fBadd\fI sitename queueid\fR"
Inform the \fBflush\fR(8) server that the message with the specified
queue ID is queued for the specified destination.
.IP "\fBsend\fI sitename\fR"
.IP "\fBsend_site\fI sitename\fR"
Request delivery of mail that is queued for the specified
destination.
.IP "\fBsend_file\fI queueid\fR"
Request delivery of the specified deferred message.
.IP \fBrefresh\fR
Refresh non-empty per-destination logfiles that were not read in
\fB$fast_flush_refresh_time\fR hours, by simulating

View File

@ -186,6 +186,7 @@ patterns like this: </p>
/^Received:.* +by +(porcupine\.org)[[:&gt;:]]/
reject forged mail server name in Received: header: $1
endif
/^Message-ID:.* &lt;!&amp;!/ DUNNO
/^Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
@ -198,6 +199,7 @@ patterns like this: </p>
/^[&gt; ]*Received:.* +by +(porcupine\.org)[[:&gt;:]]/
reject forged mail server name in Received: header: $1
endif
/^[&gt; ]*Message-ID:.* &lt;!&amp;!/ DUNNO
/^[&gt; ]*Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
</pre>
@ -226,10 +228,18 @@ see your system documentation. </p>
matching attempts. DO NOT indent lines starting with /pattern/
between the "if" and "endif"! </p>
<li> <p> The two "<tt>Message-ID:.* &lt;!&amp;!</tt>" rules are
workarounds for some versions of Outlook express, as described in
the <a href="#caveats"> caveats </a> section below.
</ul>
<p><a name="caveats"><strong>Caveats</strong></a></p>
<ul>
<li>
<p> Netscape Messenger (and reportedly, Mozilla) sends a HELO name
that is identical to the sender address domain part. If you have
such clients then the above patterns would block legitimate email.
@ -260,6 +270,35 @@ mail to a user on such a host. </p>
masquerading, as described in the ADDRESS_REWRITING_README document.
</p>
<li> <p> Reportedly, Outlook 2003 (perhaps Outlook Express, and
other versions as well) present substantially different Message-ID
headers depending upon whether or not a DSN is requested (via Options
"Request a delivery receipt for this message"). </p>
<p> When a DSN is requested, Outlook 2003 uses a Message-ID string
that ends in the sender's domain name: </p>
<blockquote>
<pre>
Message-ID: &lt;!&amp;! ...very long string... ==@example.com&gt;
</pre>
</blockquote>
<p> where <i>example.com</i> is the domain name part of the email
address specified in Outlook's account settings for the user. Since
many users configure their email addresses as <i>username@example.com</i>,
messages with DSN turned on will trigger the REJECT action in the
previous section. </p>
<p> If you have such clients then you can to exclude their Message-ID
strings with the two "<tt>Message-ID:.* &lt;!&amp;!</tt>" patterns
that are shown in the previous section. Otherwise you will not be
able to use the two backscatter rules to stop forged Message ID
strings. Of course this workaround may break the next time Outlook
is changed. </p>
</ul>
<h3><a name="forged_sender">Blocking backscatter mail with forged
sender information</a></h3>

View File

@ -4577,9 +4577,10 @@ client network address information.
<dt><b><a name="check_ccert_access">check_ccert_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
<dd>When the remote SMTP client certificate is verified successfully,
use the client certificate fingerprint as lookup key for the specified
access(5) database. This feature is available with Postfix version 2.2.</dd>
<dd> Use the client certificate fingerprint as lookup key for the
specified access(5) database; with Postfix version 2.2, also require
that the SMTP client certificate is verified successfully. This
feature is available with Postfix version 2.2 and later.</dd>
<dt><b><a name="check_client_access">check_client_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>

View File

@ -78,6 +78,7 @@ flush.o: ../../include/match_ops.h
flush.o: ../../include/match_parent_style.h
flush.o: ../../include/msg.h
flush.o: ../../include/myflock.h
flush.o: ../../include/safe_open.h
flush.o: ../../include/scan_dir.h
flush.o: ../../include/stringops.h
flush.o: ../../include/sys_defs.h

View File

@ -30,9 +30,11 @@
/* .IP "\fBadd\fI sitename queueid\fR"
/* Inform the \fBflush\fR(8) server that the message with the specified
/* queue ID is queued for the specified destination.
/* .IP "\fBsend\fI sitename\fR"
/* .IP "\fBsend_site\fI sitename\fR"
/* Request delivery of mail that is queued for the specified
/* destination.
/* .IP "\fBsend_file\fI queueid\fR"
/* Request delivery of the specified deferred message.
/* .IP \fBrefresh\fR
/* Refresh non-empty per-destination logfiles that were not read in
/* \fB$fast_flush_refresh_time\fR hours, by simulating
@ -166,6 +168,7 @@
#include <dict.h>
#include <scan_dir.h>
#include <stringops.h>
#include <safe_open.h>
/* Global library. */
@ -210,7 +213,7 @@ static DOMAIN_LIST *flush_domains;
* Silly little macros.
*/
#define STR(x) vstring_str(x)
#define STREQ(x,y) (strcmp(x,y) == 0)
#define STREQ(x,y) ((x) == (y) || strcmp(x,y) == 0)
/*
* Forward declarations resulting from breaking up routines according to
@ -223,9 +226,24 @@ static int flush_send_path(const char *, int);
* Do we only refresh the per-destination logfile, or do we really request
* mail delivery as if someone sent ETRN? If the latter, we must override
* information about unavailable hosts or unavailable transports.
*
* When selectively flushing deferred mail, we need to override the queue
* manager's "dead destination" information and unthrottle transports and
* queues. There are two options:
*
* - Unthrottle all transports and queues before we move mail to the incoming
* queue. This is less accurate, but has the advantage when flushing lots of
* mail, because Postfix can skip delivery of flushed messages after it
* discovers that a destination is (still) unavailable.
*
* - Unthrottle some transports and queues after the queue manager moves mail
* to the active queue. This is more accurate, but has the disadvantage when
* flushing lots of mail, because Postfix cannot skip delivery of flushed
* messages after it discovers that a destination is (still) unavailable.
*/
#define REFRESH_ONLY 0
#define REFRESH_AND_DELIVER 1
#define UNTHROTTLE_BEFORE (1<<0)
#define UNTHROTTLE_AFTER (1<<1)
/* flush_site_to_path - convert domain or [addr] to harmless string */
@ -366,6 +384,86 @@ static int flush_send_service(const char *site, int how)
return (status);
}
/* flush_one_file - move one queue file to incoming queue */
static int flush_one_file(const char *queue_id, VSTRING *queue_file,
struct utimbuf * tbuf, int how)
{
const char *myname = "flush_one_file";
const char *queue_name;
const char *path;
/*
* Some other instance of this program may flush some logfile and may
* just have moved this queue file to the incoming queue.
*/
for (queue_name = MAIL_QUEUE_DEFERRED; /* see below */ ;
queue_name = MAIL_QUEUE_INCOMING) {
path = mail_queue_path(queue_file, queue_name, queue_id);
if (utime(path, tbuf) == 0)
break;
if (errno != ENOENT)
msg_warn("%s: update %s time stamps: %m", myname, path);
if (STREQ(queue_name, MAIL_QUEUE_INCOMING))
return (0);
}
/*
* With the UNTHROTTLE_AFTER strategy, we leave it up to the queue
* manager to unthrottle transports and queues as it reads recipients
* from a queue file. We request this unthrottle operation by setting the
* group read permission bit.
*
* Note: we must avoid using chmod(). It is not only slower than fchmod()
* but it is also less secure. With chmod(), an attacker could repeatedly
* send requests to the flush server and trick it into changing
* permissions of non-queue files, by exploiting a race condition.
*
* We use safe_open() because we don't validate the file content before
* modifying the file status.
*/
if (how & UNTHROTTLE_AFTER) {
VSTRING *why;
struct stat st;
VSTREAM *fp;
for (why = vstring_alloc(1); /* see below */ ;
queue_name = MAIL_QUEUE_INCOMING,
path = mail_queue_path(queue_file, queue_name, queue_id)) {
if ((fp = safe_open(path, O_RDWR, 0, &st, -1, -1, why)) != 0)
break;
if (errno != ENOENT)
msg_warn("%s: open %s: %s", myname, path, STR(why));
if (errno != ENOENT || STREQ(queue_name, MAIL_QUEUE_INCOMING)) {
vstring_free(why);
return (0);
}
}
vstring_free(why);
if ((st.st_mode & MAIL_QUEUE_STAT_READY) != MAIL_QUEUE_STAT_READY) {
(void) vstream_fclose(fp);
return (0);
}
if (fchmod(vstream_fileno(fp), st.st_mode | MAIL_QUEUE_STAT_UNTHROTTLE) < 0)
msg_warn("%s: fchmod %s: %m", myname, path);
(void) vstream_fclose(fp);
}
/*
* Move the file to the incoming queue, if it isn't already there.
*/
if (STREQ(queue_name, MAIL_QUEUE_INCOMING) == 0
&& mail_queue_rename(queue_id, queue_name, MAIL_QUEUE_INCOMING) < 0
&& errno != ENOENT)
msg_warn("%s: rename from %s to %s: %m",
path, queue_name, MAIL_QUEUE_INCOMING);
/*
* If we got here, we achieved something, so let's claim succes.
*/
return (1);
}
/* flush_send_path - flush logfile file */
static int flush_send_path(const char *path, int how)
@ -375,11 +473,10 @@ static int flush_send_path(const char *path, int how)
VSTRING *queue_file;
VSTREAM *log;
struct utimbuf tbuf;
static char qmgr_deliver_trigger[] = {
QMGR_REQ_SCAN_INCOMING, /* scan incoming queue */
static char qmgr_flush_trigger[] = {
QMGR_REQ_FLUSH_DEAD, /* flush dead site/transport cache */
};
static char qmgr_refresh_trigger[] = {
static char qmgr_scan_trigger[] = {
QMGR_REQ_SCAN_INCOMING, /* scan incoming queue */
};
HTABLE *dup_filter;
@ -410,6 +507,23 @@ static int flush_send_path(const char *path, int how)
if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
msg_fatal("%s: lock fast flush logfile %s: %m", myname, path);
/*
* With the UNTHROTTLE_BEFORE strategy, we ask the queue manager to
* unthrottle all transports and queues before we move a deferred queue
* file to the incoming queue. This minimizes a race condition where the
* queue manager seizes a queue file before it knows that we want to
* flush that message.
*
* This reduces the race condition time window to a very small amount (the
* flush server does not really know when the queue manager reads its
* command fifo). But there is a worse race, where the queue manager
* moves a deferred queue file to the active queue before we have a
* chance to expedite its delivery.
*/
if (how & UNTHROTTLE_BEFORE)
mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service,
qmgr_flush_trigger, sizeof(qmgr_flush_trigger));
/*
* This is the part that dominates running time: schedule the listed
* queue files for delivery by updating their file time stamps and by
@ -444,25 +558,7 @@ static int flush_send_path(const char *path, int how)
myname, path, STR(queue_id));
if (dup_filter->used <= FLUSH_DUP_FILTER_SIZE)
htable_enter(dup_filter, STR(queue_id), 0);
mail_queue_path(queue_file, MAIL_QUEUE_DEFERRED, STR(queue_id));
if (utime(STR(queue_file), &tbuf) < 0) {
if (errno != ENOENT)
msg_warn("%s: update %s time stamps: %m",
myname, STR(queue_file));
/* XXX Wart... */
mail_queue_path(queue_file, MAIL_QUEUE_INCOMING, STR(queue_id));
if (utime(STR(queue_file), &tbuf) < 0)
if (errno != ENOENT)
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) {
if (errno != ENOENT)
msg_warn("%s: rename from %s to %s: %m",
STR(queue_file), MAIL_QUEUE_DEFERRED,
MAIL_QUEUE_INCOMING);
}
count += flush_one_file(STR(queue_id), queue_file, &tbuf, how);
} else {
if (msg_verbose)
msg_info("%s: logfile %s: skip queue file %s as duplicate",
@ -489,16 +585,42 @@ static int flush_send_path(const char *path, int how)
if (count > 0) {
if (msg_verbose)
msg_info("%s: requesting delivery for logfile %s", myname, path);
if (how == REFRESH_ONLY)
mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service,
qmgr_refresh_trigger, sizeof(qmgr_refresh_trigger));
else
mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service,
qmgr_deliver_trigger, sizeof(qmgr_deliver_trigger));
mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service,
qmgr_scan_trigger, sizeof(qmgr_scan_trigger));
}
return (FLUSH_STAT_OK);
}
/* flush_send_file_service - flush one queue file */
static int flush_send_file_service(const char *queue_id)
{
const char *myname = "flush_send_file_service";
VSTRING *queue_file;
struct utimbuf tbuf;
static char qmgr_scan_trigger[] = {
QMGR_REQ_SCAN_INCOMING, /* scan incoming queue */
};
/*
* Sanity check.
*/
if (!mail_queue_id_ok(queue_id))
return (FLUSH_STAT_BAD);
if (msg_verbose)
msg_info("%s: requesting delivery for queue_id %s", myname, queue_id);
queue_file = vstring_alloc(30);
tbuf.actime = tbuf.modtime = event_time();
if (flush_one_file(queue_id, queue_file, &tbuf, UNTHROTTLE_AFTER) > 0)
mail_trigger(MAIL_CLASS_PUBLIC, var_queue_service,
qmgr_scan_trigger, sizeof(qmgr_scan_trigger));
vstring_free(queue_file);
return (FLUSH_STAT_OK);
}
/* flush_refresh_service - refresh logfiles beyond some age */
static int flush_refresh_service(int max_age)
@ -633,13 +755,22 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
ATTR_TYPE_END);
} else if (STREQ(STR(request), FLUSH_REQ_SEND)) {
} else if (STREQ(STR(request), FLUSH_REQ_SEND_SITE)) {
site = vstring_alloc(10);
if (attr_scan(client_stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
ATTR_TYPE_END) == 1)
status = flush_send_service(lowercase(STR(site)),
REFRESH_AND_DELIVER);
UNTHROTTLE_BEFORE);
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
ATTR_TYPE_END);
} else if (STREQ(STR(request), FLUSH_REQ_SEND_FILE)) {
queue_id = vstring_alloc(10);
if (attr_scan(client_stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
ATTR_TYPE_END) == 1)
status = flush_send_file_service(STR(queue_id));
attr_print(client_stream, ATTR_FLAG_NONE,
ATTR_TYPE_INT, MAIL_ATTR_STATUS, status,
ATTR_TYPE_END);

View File

@ -12,9 +12,12 @@
/* const char *site;
/* const char *queue_id;
/*
/* int flush_send(site)
/* int flush_send_site(site)
/* const char *site;
/*
/* int flush_send_file(queue_id)
/* const char *queue_id;
/*
/* int flush_refresh()
/*
/* int flush_purge()
@ -30,9 +33,12 @@
/* 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
/* flush_send_site() requests delivery of all mail that is queued for
/* the specified destination.
/*
/* flush_send_file() requests delivery of mail with the specified
/* queue ID.
/*
/* flush_refresh() requests the "fast flush" cache manager to refresh
/* cached information that was not used for some configurable amount
/* time.
@ -153,11 +159,11 @@ int flush_refresh(void)
return (status);
}
/* flush_send - deliver mail queued for site */
/* flush_send_site - deliver mail queued for site */
int flush_send(const char *site)
int flush_send_site(const char *site)
{
const char *myname = "flush_send";
const char *myname = "flush_send_site";
int status;
if (msg_verbose)
@ -173,7 +179,7 @@ int flush_send(const char *site)
status = FLUSH_STAT_DENY;
else
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND,
ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND_SITE,
ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
ATTR_TYPE_END);
@ -183,6 +189,30 @@ int flush_send(const char *site)
return (status);
}
/* flush_send_file - deliver specific message */
int flush_send_file(const char *queue_id)
{
const char *myname = "flush_send_file";
int status;
if (msg_verbose)
msg_info("%s: queue_id %s", myname, queue_id);
/*
* Require that the service is turned on.
*/
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND_FILE,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
ATTR_TYPE_END);
if (msg_verbose)
msg_info("%s: queue_id %s status %d", myname, queue_id, status);
return (status);
}
/* flush_add - inform "fast flush" cache manager */
int flush_add(const char *site, const char *queue_id)

View File

@ -16,7 +16,8 @@
*/
extern void flush_init(void);
extern int flush_add(const char *, const char *);
extern int flush_send(const char *);
extern int flush_send_site(const char *);
extern int flush_send_file(const char *);
extern int flush_refresh(void);
extern int flush_purge(void);
@ -24,7 +25,8 @@ 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_SEND_SITE "send_site" /* flush mail for site */
#define FLUSH_REQ_SEND_FILE "send_file" /* flush one queue file */
#define FLUSH_REQ_REFRESH "rfrsh" /* refresh old logfiles */
#define FLUSH_REQ_PURGE "purge" /* refresh all logfiles */

View File

@ -38,9 +38,17 @@
/*
* Queue file modes.
*
* 4.4BSD-like systems don't allow (sticky AND executable) together, so we use
* group read permission bits instead. These are more portable, but they
* also are more likely to be turned on by accident. It would not be the end
* of the world.
*/
#define MAIL_QUEUE_STAT_READY (S_IRUSR | S_IWUSR | S_IXUSR)
#define MAIL_QUEUE_STAT_CORRUPT (S_IRUSR)
#ifndef MAIL_QUEUE_STAT_UNTHROTTLE
#define MAIL_QUEUE_STAT_UNTHROTTLE (S_IRGRP)
#endif
extern struct VSTREAM *mail_queue_enter(const char *, mode_t, struct timeval *);
extern struct VSTREAM *mail_queue_open(const char *, const char *, int, mode_t);

View File

@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
#define MAIL_RELEASE_DATE "20061210"
#define MAIL_RELEASE_DATE "20061217"
#define MAIL_VERSION_NUMBER "2.4"
#ifdef SNAPSHOT

View File

@ -367,6 +367,8 @@ static void qmgr_trigger_event(char *buf, int len,
* request in order. And as long as we don't have conflicting requests we
* are free to sort them into the most suitable order.
*/
#define QMGR_FLUSH_BEFORE (QMGR_FLUSH_ONCE | QMGR_FLUSH_DFXP)
for (i = 0; i < len; i++) {
if (msg_verbose)
msg_info("request: %d (%c)",
@ -380,8 +382,8 @@ static void qmgr_trigger_event(char *buf, int len,
deferred_flag |= QMGR_SCAN_START;
break;
case QMGR_REQ_FLUSH_DEAD:
deferred_flag |= QMGR_FLUSH_DEAD;
incoming_flag |= QMGR_FLUSH_DEAD;
deferred_flag |= QMGR_FLUSH_BEFORE;
incoming_flag |= QMGR_FLUSH_BEFORE;
break;
case QMGR_REQ_SCAN_ALL:
deferred_flag |= QMGR_SCAN_ALL;

View File

@ -256,7 +256,7 @@ extern int qmgr_recipient_count;
extern void qmgr_message_free(QMGR_MESSAGE *);
extern void qmgr_message_update_warn(QMGR_MESSAGE *);
extern void qmgr_message_kill_record(QMGR_MESSAGE *, long);
extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int);
extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int, mode_t);
extern QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *);
#define QMGR_MSG_STATS(stats, message) \
@ -317,7 +317,9 @@ struct QMGR_SCAN {
*/
#define QMGR_SCAN_START (1<<0) /* start now/restart when done */
#define QMGR_SCAN_ALL (1<<1) /* all queue file time stamps */
#define QMGR_FLUSH_DEAD (1<<2) /* all sites, all transports */
#define QMGR_FLUSH_ONCE (1<<2) /* unthrottle once */
#define QMGR_FLUSH_DFXP (1<<3) /* override defer_transports */
#define QMGR_FLUSH_EACH (1<<4) /* unthrottle per message */
/*
* qmgr_scan.c

View File

@ -226,8 +226,15 @@ int qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id)
* being delivered. In that case (the file is locked), defer delivery by
* a minimal amount of time.
*/
#define QMGR_FLUSH_AFTER (QMGR_FLUSH_EACH | QMGR_FLUSH_DFXP)
if ((message = qmgr_message_alloc(MAIL_QUEUE_ACTIVE, queue_id,
scan_info->flags)) == 0) {
(st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
scan_info->flags | QMGR_FLUSH_AFTER :
scan_info->flags,
(st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
st.st_mode & ~MAIL_QUEUE_STAT_UNTHROTTLE :
0)) == 0) {
qmgr_active_corrupt(queue_id);
return (0);
} else if (message == QMGR_MESSAGE_LOCKED) {

View File

@ -9,10 +9,11 @@
/* int qmgr_message_count;
/* int qmgr_recipient_count;
/*
/* QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags)
/* QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags, mode)
/* const char *class;
/* const char *name;
/* int qflags;
/* mode_t mode;
/*
/* QMGR_MESSAGE *qmgr_message_realloc(message)
/* QMGR_MESSAGE *message;
@ -49,6 +50,7 @@
/* run through the resolver, and are assigned to destination
/* queues. Recipients that cannot be assigned are deferred or
/* bounced. Mail that has bounced twice is silently absorbed.
/* A non-zero mode means change the queue file permissions.
/*
/* qmgr_message_realloc() resumes reading recipients from the queue
/* file, and updates the recipient list and \fIrcpt_offset\fR message
@ -929,9 +931,9 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
for (recipient = list.info; recipient < list.info + list.len; recipient++) {
/*
* Redirect overrides all else. But only once (per entire
* message). For consistency with the remainder of Postfix,
* rewrite the address to canonical form before resolving it.
* Redirect overrides all else. But only once (per entire message).
* For consistency with the remainder of Postfix, rewrite the address
* to canonical form before resolving it.
*/
if (message->redirect_addr) {
if (recipient > list.info) {
@ -1040,7 +1042,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_FLUSH_DEAD) == 0) {
if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DFXP) == 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++)
@ -1061,6 +1063,14 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
queue = 0;
}
/*
* This message is being flushed. If need-be unthrottle the
* transport.
*/
if ((message->qflags & QMGR_FLUSH_EACH) != 0
&& QMGR_TRANSPORT_THROTTLED(transport))
qmgr_transport_unthrottle(transport);
/*
* This transport is dead. Defer delivery to this recipient.
*/
@ -1137,6 +1147,13 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
STR(reply.nexthop));
}
/*
* This message is being flushed. If need-be unthrottle the queue.
*/
if ((message->qflags & QMGR_FLUSH_EACH) != 0
&& QMGR_QUEUE_THROTTLED(queue))
qmgr_queue_unthrottle(queue);
/*
* This queue is dead. Defer delivery to this recipient.
*/
@ -1242,7 +1259,7 @@ void qmgr_message_free(QMGR_MESSAGE *message)
/* qmgr_message_alloc - create in-core message structure */
QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
int qflags)
int qflags, mode_t mode)
{
const char *myname = "qmgr_message_alloc";
QMGR_MESSAGE *message;
@ -1277,6 +1294,13 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
return (0);
} else {
/*
* We have validated the queue file content, so it is safe to modify
* the file properties now.
*/
if (mode != 0 && fchmod(vstream_fileno(message->fp), mode) < 0)
msg_fatal("fchmod %s: %m", VSTREAM_PATH(message->fp));
/*
* Reset the defer log. This code should not be here, but we must
* reset the defer log *after* acquiring the exclusive lock on the

View File

@ -31,12 +31,17 @@
/* qmgr_scan_request() records a request for the next queue scan. The
/* flags argument is the bit-wise OR of zero or more of the following,
/* unrecognized flags being ignored:
/* .IP QMGR_FLUSH_DEAD
/* Forget state information about dead hosts or transports. This
/* request takes effect upon the next queue scan.
/* .IP QMGR_FLUSH_ONCE
/* Forget state information about dead hosts or transports.
/* This request takes effect immediately.
/* .IP QMGR_FLUSH_DFXP
/* Override the defer_transports setting. This takes effect
/* immediately when a queue scan is in progress, and affects
/* the next queue scan.
/* .IP QMGR_SCAN_ALL
/* Ignore queue file time stamps.
/* This flag is passed on to the qmgr_active_feed() routine.
/* Ignore queue file time stamps. This takes effect immediately
/* when a queue scan is in progress, and affects the next queue
/* scan.
/* .IP QMGR_SCAN_START
/* Start a queue scan when none is in progress, or restart the
/* current scan upon completion.
@ -94,12 +99,6 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
scan_info->nflags & QMGR_SCAN_START ? "re" : "",
scan_info->queue);
/*
* Optionally forget all dead host information.
*/
if (scan_info->nflags & QMGR_FLUSH_DEAD)
qmgr_enable_all();
/*
* Start or restart the scan.
*/
@ -113,6 +112,33 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
void qmgr_scan_request(QMGR_SCAN *scan_info, int flags)
{
/*
* Apply "forget all dead destinations" requests immediately. Throttle
* dead transports and queues at the earliest opportunity: preferably
* during an already ongoing queue scan, otherwise the throttling will
* have to wait until a "start scan" trigger arrives.
*
* The QMGR_FLUSH_ONCE request always comes with QMGR_FLUSH_DFXP, and
* sometimes it also comes with QMGR_SCAN_ALL. It becomes a completely
* different story when a flush request is encoded in file permissions.
*/
if (flags & QMGR_FLUSH_ONCE)
qmgr_enable_all();
/*
* Apply "ignore time stamp" requests also towards the scan that is
* already in progress.
*/
if (scan_info->handle != 0 && (flags & QMGR_SCAN_ALL))
scan_info->flags |= QMGR_SCAN_ALL;
/*
* Apply "override defer_transports" requests also towards the scan that
* is already in progress.
*/
if (scan_info->handle != 0 && (flags & QMGR_FLUSH_DFXP))
scan_info->flags |= QMGR_FLUSH_DFXP;
/*
* If a scan is in progress, just record the request.
*/

View File

@ -381,17 +381,12 @@ static const char *check_myhostname(void)
/*
* If the local machine name is not in FQDN form, try to append the
* contents of $mydomain.
*
* XXX Do not complain when running as "postconf -d".
*/
name = get_hostname();
if ((cmd_mode & SHOW_DEFS) == 0 && (dot = strchr(name, '.')) == 0) {
if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0) {
msg_warn("My hostname %s is not a fully qualified name - set %s or %s in %s/main.cf",
name, VAR_MYHOSTNAME, VAR_MYDOMAIN, var_config_dir);
} else {
name = concatenate(name, ".", domain, (char *) 0);
}
if ((dot = strchr(name, '.')) == 0) {
if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0)
domain = DEF_MYDOMAIN;
name = concatenate(name, ".", domain, (char *) 0);
}
return (name);
}
@ -420,7 +415,7 @@ static const char *check_mydomainname(void)
if (var_myhostname == 0)
get_myhostname();
if ((dot = strchr(var_myhostname, '.')) == 0 || strchr(dot + 1, '.') == 0)
return (var_myhostname);
return (DEF_MYDOMAIN);
return (dot + 1);
}

View File

@ -68,6 +68,7 @@ postqueue.o: ../../include/mail_dict.h
postqueue.o: ../../include/mail_flush.h
postqueue.o: ../../include/mail_params.h
postqueue.o: ../../include/mail_proto.h
postqueue.o: ../../include/mail_queue.h
postqueue.o: ../../include/mail_run.h
postqueue.o: ../../include/mail_task.h
postqueue.o: ../../include/msg.h

View File

@ -6,6 +6,8 @@
/* SYNOPSIS
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-f\fR
/* .br
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-i \fIqueue_id\fR
/* .br
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-p\fR
/* .br
/* \fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
@ -30,6 +32,10 @@
/*
/* Warning: flushing undeliverable mail frequently will result in
/* poor delivery performance of all other mail.
/* .IP "\fB-i \fIqueue_id\fR"
/* Schedule immediate delivery of mail with the specified queue ID.
/* This feature uses the \fBflush\fR(8) server, and is available
/* with Postfix 2.4 and later.
/* .IP \fB-p\fR
/* Produce a traditional sendmail-style queue listing.
/* This option implements the traditional \fBmailq\fR command,
@ -186,6 +192,7 @@
#include <mail_task.h>
#include <mail_run.h>
#include <mail_flush.h>
#include <mail_queue.h>
#include <flush_clnt.h>
#include <smtp_stream.h>
#include <user_acl.h>
@ -214,6 +221,7 @@
#define PQ_MODE_MAILQ_LIST 1 /* list mail queue */
#define PQ_MODE_FLUSH_QUEUE 2 /* flush queue */
#define PQ_MODE_FLUSH_SITE 3 /* flush site */
#define PQ_MODE_FLUSH_FILE 4 /* flush message */
/*
* Silly little macros (SLMs).
@ -345,7 +353,7 @@ static void flush_site(const char *site)
flush_init();
switch (status = flush_send(site)) {
switch (status = flush_send_site(site)) {
case FLUSH_STAT_OK:
exit(0);
case FLUSH_STAT_BAD:
@ -363,11 +371,46 @@ static void flush_site(const char *site)
}
}
/* flush_file - flush mail with specific queue ID */
static void flush_file(const char *queue_id)
{
int status;
const char *errstr;
uid_t uid = getuid();
if (uid != 0 && uid != var_owner_uid
&& (errstr = check_user_acl_byuid(var_flush_acl, uid)) != 0)
msg_fatal_status(EX_NOPERM,
"User %s(%ld) is not allowed to flush the mail queue",
errstr, (long) uid);
switch (status = flush_send_file(queue_id)) {
case FLUSH_STAT_OK:
exit(0);
case FLUSH_STAT_BAD:
msg_fatal_status(EX_USAGE, "Invalid request: \"%s\"", queue_id);
case FLUSH_STAT_FAIL:
msg_fatal_status(EX_UNAVAILABLE,
"Cannot flush mail queue - mail system is down");
default:
msg_fatal_status(EX_SOFTWARE,
"Unexpected flush server reply status %d", status);
}
}
/* unavailable - sanitize exit status from library run-time errors */
static void unavailable(void)
{
exit(EX_UNAVAILABLE);
}
/* usage - scream and die */
static NORETURN usage(void)
{
msg_fatal_status(EX_USAGE, "usage: postqueue -f | postqueue -p | postqueue -s site");
msg_fatal_status(EX_USAGE, "usage: postqueue -f | postqueue -i queueid | postqueue -p | postqueue -s site");
}
/* main - the main program */
@ -380,6 +423,7 @@ int main(int argc, char **argv)
int fd;
int mode = PQ_MODE_DEFAULT;
char *site_to_flush = 0;
char *id_to_flush = 0;
ARGV *import_env;
int bad_site;
@ -406,6 +450,7 @@ int main(int argc, char **argv)
if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
argv[0] = slash + 1;
msg_vstream_init(argv[0], VSTREAM_ERR);
msg_cleanup(unavailable);
msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY);
set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
@ -415,7 +460,7 @@ int main(int argc, char **argv)
* mail configuration read routine. Don't do complex things until we have
* completed initializations.
*/
while ((c = GETOPT(argc, argv, "c:fps:v")) > 0) {
while ((c = GETOPT(argc, argv, "c:fi:ps:v")) > 0) {
switch (c) {
case 'c': /* non-default configuration */
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
@ -426,6 +471,12 @@ int main(int argc, char **argv)
usage();
mode = PQ_MODE_FLUSH_QUEUE;
break;
case 'i': /* flush queue file */
if (mode != PQ_MODE_DEFAULT)
usage();
mode = PQ_MODE_FLUSH_FILE;
id_to_flush = optarg;
break;
case 'p': /* traditional mailq */
if (mode != PQ_MODE_DEFAULT)
usage();
@ -489,6 +540,12 @@ int main(int argc, char **argv)
"Cannot flush mail queue - invalid destination: \"%.100s%s\"",
site_to_flush, strlen(site_to_flush) > 100 ? "..." : "");
}
if (id_to_flush != 0) {
if (!mail_queue_id_ok(id_to_flush))
msg_fatal_status(EX_USAGE,
"Cannot flush queue ID - invalid name: \"%.100s%s\"",
id_to_flush, strlen(id_to_flush) > 100 ? "..." : "");
}
/*
* Start processing.
@ -505,6 +562,10 @@ int main(int argc, char **argv)
flush_site(site_to_flush);
exit(0);
break;
case PQ_MODE_FLUSH_FILE:
flush_file(id_to_flush);
exit(0);
break;
case PQ_MODE_FLUSH_QUEUE:
flush_queue();
exit(0);

View File

@ -427,6 +427,8 @@ static void qmgr_trigger_event(char *buf, int len,
* request in order. And as long as we don't have conflicting requests we
* are free to sort them into the most suitable order.
*/
#define QMGR_FLUSH_BEFORE (QMGR_FLUSH_ONCE | QMGR_FLUSH_DFXP)
for (i = 0; i < len; i++) {
if (msg_verbose)
msg_info("request: %d (%c)",
@ -440,8 +442,8 @@ static void qmgr_trigger_event(char *buf, int len,
deferred_flag |= QMGR_SCAN_START;
break;
case QMGR_REQ_FLUSH_DEAD:
deferred_flag |= QMGR_FLUSH_DEAD;
incoming_flag |= QMGR_FLUSH_DEAD;
deferred_flag |= QMGR_FLUSH_BEFORE;
incoming_flag |= QMGR_FLUSH_BEFORE;
break;
case QMGR_REQ_SCAN_ALL:
deferred_flag |= QMGR_SCAN_ALL;

View File

@ -304,7 +304,7 @@ extern int qmgr_recipient_count;
extern void qmgr_message_free(QMGR_MESSAGE *);
extern void qmgr_message_update_warn(QMGR_MESSAGE *);
extern void qmgr_message_kill_record(QMGR_MESSAGE *, long);
extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int);
extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int, mode_t);
extern QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *);
#define QMGR_MSG_STATS(stats, message) \
@ -423,7 +423,9 @@ struct QMGR_SCAN {
*/
#define QMGR_SCAN_START (1<<0) /* start now/restart when done */
#define QMGR_SCAN_ALL (1<<1) /* all queue file time stamps */
#define QMGR_FLUSH_DEAD (1<<2) /* all sites, all transports */
#define QMGR_FLUSH_ONCE (1<<2) /* unthrottle once */
#define QMGR_FLUSH_DFXP (1<<3) /* override defer_transports */
#define QMGR_FLUSH_EACH (1<<4) /* unthrottle per message */
/*
* qmgr_scan.c

View File

@ -226,8 +226,15 @@ int qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id)
* being delivered. In that case (the file is locked), defer delivery by
* a minimal amount of time.
*/
#define QMGR_FLUSH_AFTER (QMGR_FLUSH_EACH | QMGR_FLUSH_DFXP)
if ((message = qmgr_message_alloc(MAIL_QUEUE_ACTIVE, queue_id,
scan_info->flags)) == 0) {
(st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
scan_info->flags | QMGR_FLUSH_AFTER :
scan_info->flags,
(st.st_mode & MAIL_QUEUE_STAT_UNTHROTTLE) ?
st.st_mode & ~MAIL_QUEUE_STAT_UNTHROTTLE :
0)) == 0) {
qmgr_active_corrupt(queue_id);
return (0);
} else if (message == QMGR_MESSAGE_LOCKED) {

View File

@ -9,10 +9,11 @@
/* int qmgr_message_count;
/* int qmgr_recipient_count;
/*
/* QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags)
/* QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags, mode)
/* const char *class;
/* const char *name;
/* int qflags;
/* mode_t mode;
/*
/* QMGR_MESSAGE *qmgr_message_realloc(message)
/* QMGR_MESSAGE *message;
@ -49,6 +50,7 @@
/* run through the resolver, and are assigned to destination
/* queues. Recipients that cannot be assigned are deferred or
/* bounced. Mail that has bounced twice is silently absorbed.
/* A non-zero mode means change the queue file permissions.
/*
/* qmgr_message_realloc() resumes reading recipients from the queue
/* file, and updates the recipient list and \fIrcpt_offset\fR message
@ -749,10 +751,11 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
message->queue_id, orig_rcpt);
myfree(orig_rcpt);
}
/*
* Remember when we have read the last recipient batch. Note that we do
* it here after reading as reading might have used considerable amount of time.
* it here after reading as reading might have used considerable amount
* of time.
*/
message->refill_time = sane_time();
@ -985,16 +988,15 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
for (recipient = list.info; recipient < list.info + list.len; recipient++) {
/*
* Redirect overrides all else. But only once (per entire
* message). For consistency with the remainder of Postfix,
* rewrite the address to canonical form before resolving it.
* Redirect overrides all else. But only once (per entire message).
* For consistency with the remainder of Postfix, rewrite the address
* to canonical form before resolving it.
*/
if (message->redirect_addr) {
if (recipient > list.info) {
recipient->u.queue = 0;
continue;
}
message->rcpt_offset = 0;
message->rcpt_unread = 0;
@ -1099,7 +1101,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_FLUSH_DEAD) == 0) {
if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DFXP) == 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++)
@ -1120,6 +1122,14 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
queue = 0;
}
/*
* This message is being flushed. If need-be unthrottle the
* transport.
*/
if ((message->qflags & QMGR_FLUSH_EACH) != 0
&& QMGR_TRANSPORT_THROTTLED(transport))
qmgr_transport_unthrottle(transport);
/*
* This transport is dead. Defer delivery to this recipient.
*/
@ -1196,6 +1206,13 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
STR(reply.nexthop));
}
/*
* This message is being flushed. If need-be unthrottle the queue.
*/
if ((message->qflags & QMGR_FLUSH_EACH) != 0
&& QMGR_QUEUE_THROTTLED(queue))
qmgr_queue_unthrottle(queue);
/*
* This queue is dead. Defer delivery to this recipient.
*/
@ -1244,7 +1261,7 @@ static void qmgr_message_assign(QMGR_MESSAGE *message)
*/
if ((queue = recipient->u.queue) == 0)
continue;
/*
* Lookup or instantiate the message job if necessary.
*/
@ -1258,10 +1275,10 @@ static void qmgr_message_assign(QMGR_MESSAGE *message)
*/
if (peer == 0 || queue != peer->queue)
peer = qmgr_peer_obtain(job, queue);
/*
* Lookup old or instantiate new recipient entry. We try to reuse
* the last existing entry whenever the recipient limit permits.
* Lookup old or instantiate new recipient entry. We try to reuse the
* last existing entry whenever the recipient limit permits.
*/
entry = peer->entry_list.prev;
if (message->single_rcpt || entry == 0
@ -1363,7 +1380,7 @@ void qmgr_message_free(QMGR_MESSAGE *message)
/* qmgr_message_alloc - create in-core message structure */
QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
int qflags)
int qflags, mode_t mode)
{
const char *myname = "qmgr_message_alloc";
QMGR_MESSAGE *message;
@ -1398,6 +1415,13 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
return (0);
} else {
/*
* We have validated the queue file content, so it is safe to modify
* the file properties now.
*/
if (mode != 0 && fchmod(vstream_fileno(message->fp), mode) < 0)
msg_fatal("fchmod %s: %m", VSTREAM_PATH(message->fp));
/*
* Reset the defer log. This code should not be here, but we must
* reset the defer log *after* acquiring the exclusive lock on the

View File

@ -31,12 +31,17 @@
/* qmgr_scan_request() records a request for the next queue scan. The
/* flags argument is the bit-wise OR of zero or more of the following,
/* unrecognized flags being ignored:
/* .IP QMGR_FLUSH_DEAD
/* Forget state information about dead hosts or transports. This
/* request takes effect upon the next queue scan.
/* .IP QMGR_FLUSH_ONCE
/* Forget state information about dead hosts or transports.
/* This request takes effect immediately.
/* .IP QMGR_FLUSH_DFXP
/* Override the defer_transports setting. This takes effect
/* immediately when a queue scan is in progress, and affects
/* the next queue scan.
/* .IP QMGR_SCAN_ALL
/* Ignore queue file time stamps.
/* This flag is passed on to the qmgr_active_feed() routine.
/* Ignore queue file time stamps. This takes effect immediately
/* when a queue scan is in progress, and affects the next queue
/* scan.
/* .IP QMGR_SCAN_START
/* Start a queue scan when none is in progress, or restart the
/* current scan upon completion.
@ -94,12 +99,6 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
scan_info->nflags & QMGR_SCAN_START ? "re" : "",
scan_info->queue);
/*
* Optionally forget all dead host information.
*/
if (scan_info->nflags & QMGR_FLUSH_DEAD)
qmgr_enable_all();
/*
* Start or restart the scan.
*/
@ -113,6 +112,33 @@ static void qmgr_scan_start(QMGR_SCAN *scan_info)
void qmgr_scan_request(QMGR_SCAN *scan_info, int flags)
{
/*
* Apply "forget all dead destinations" requests immediately. Throttle
* dead transports and queues at the earliest opportunity: preferably
* during an already ongoing queue scan, otherwise the throttling will
* have to wait until a "start scan" trigger arrives.
*
* The QMGR_FLUSH_ONCE request always comes with QMGR_FLUSH_DFXP, and
* sometimes it also comes with QMGR_SCAN_ALL. It becomes a completely
* different story when a flush request is encoded in file permissions.
*/
if (flags & QMGR_FLUSH_ONCE)
qmgr_enable_all();
/*
* Apply "ignore time stamp" requests also towards the scan that is
* already in progress.
*/
if (scan_info->handle != 0 && (flags & QMGR_SCAN_ALL))
scan_info->flags |= QMGR_SCAN_ALL;
/*
* Apply "override defer_transports" requests also towards the scan that
* is already in progress.
*/
if (scan_info->handle != 0 && (flags & QMGR_FLUSH_DFXP))
scan_info->flags |= QMGR_FLUSH_DFXP;
/*
* If a scan is in progress, just record the request.
*/

View File

@ -168,6 +168,11 @@
/* .IP "\fB-q\fIinterval\fR (ignored)"
/* The interval between queue runs. Use the \fBqueue_run_delay\fR
/* configuration parameter instead.
/* .IP \fB-qI\fIqueueid\fR
/* Schedule immediate delivery of mail with the specified queue
/* ID. This option is implemented by executing the
/* \fBpostqueue\fR(1) command, and is available with Postfix
/* version 2.4 and later.
/* .IP \fB-qR\fIsite\fR
/* Schedule immediate delivery of all mail that is queued for the named
/* \fIsite\fR. This option accepts only \fIsite\fR names that are
@ -885,6 +890,13 @@ static void enqueue(const int flags, const char *encoding,
myfree(saved_sender);
}
/* tempfail - sanitize exit status after library run-time error */
static void tempfail(void)
{
exit(EX_TEMPFAIL);
}
/* main - the main program */
int main(int argc, char **argv)
@ -902,6 +914,7 @@ int main(int argc, char **argv)
int n;
int flags = SM_FLAG_DEFAULT;
char *site_to_flush = 0;
char *id_to_flush = 0;
char *encoding = 0;
char *qtime = 0;
const char *errstr;
@ -952,6 +965,7 @@ int main(int argc, char **argv)
if ((slash = strrchr(argv[0], '/')) != 0 && slash[1])
argv[0] = slash + 1;
msg_vstream_init(argv[0], VSTREAM_ERR);
msg_cleanup(tempfail);
msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY);
set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
@ -1175,6 +1189,10 @@ int main(int argc, char **argv)
site_to_flush = optarg + 1;
if (*site_to_flush == 0)
msg_fatal_status(EX_USAGE, "specify: -qRsitename");
} else if (optarg[0] == 'I') {
id_to_flush = optarg + 1;
if (*id_to_flush == 0)
msg_fatal_status(EX_USAGE, "specify: -qIqueueid");
} else {
msg_fatal_status(EX_USAGE, "-q%c is not implemented",
optarg[0]);
@ -1200,6 +1218,9 @@ int main(int argc, char **argv)
if (site_to_flush && mode != SM_MODE_ENQUEUE)
msg_fatal_status(EX_USAGE, "-qR can be used only in delivery mode");
if (id_to_flush && mode != SM_MODE_ENQUEUE)
msg_fatal_status(EX_USAGE, "-qI can be used only in delivery mode");
if (flags & DEL_REQ_FLAG_USR_VRFY) {
if (flags & SM_FLAG_XRCPT)
msg_fatal_status(EX_USAGE, "-t option cannot be used with -bv");
@ -1228,20 +1249,32 @@ int main(int argc, char **argv)
msg_panic("unknown operation mode: %d", mode);
/* NOTREACHED */
case SM_MODE_ENQUEUE:
if (site_to_flush == 0) {
if (site_to_flush) {
if (argv[OPTIND])
msg_fatal_status(EX_USAGE, "flush site requires no recipient");
ext_argv = argv_alloc(2);
argv_add(ext_argv, "postqueue", "-s", site_to_flush, (char *) 0);
for (n = 0; n < msg_verbose; n++)
argv_add(ext_argv, "-v", (char *) 0);
argv_terminate(ext_argv);
mail_run_replace(var_command_dir, ext_argv->argv);
/* NOTREACHED */
} else if (id_to_flush) {
if (argv[OPTIND])
msg_fatal_status(EX_USAGE, "flush queue_id requires no recipient");
ext_argv = argv_alloc(2);
argv_add(ext_argv, "postqueue", "-i", id_to_flush, (char *) 0);
for (n = 0; n < msg_verbose; n++)
argv_add(ext_argv, "-v", (char *) 0);
argv_terminate(ext_argv);
mail_run_replace(var_command_dir, ext_argv->argv);
/* NOTREACHED */
} else {
enqueue(flags, encoding, dsn_envid, dsn_notify,
rewrite_context, sender, full_name, argv + OPTIND);
exit(0);
/* NOTREACHED */
}
if (argv[OPTIND])
msg_fatal_status(EX_USAGE, "flush site requires no recipient");
ext_argv = argv_alloc(2);
argv_add(ext_argv, "postqueue", "-s", site_to_flush, (char *) 0);
for (n = 0; n < msg_verbose; n++)
argv_add(ext_argv, "-v", (char *) 0);
argv_terminate(ext_argv);
mail_run_replace(var_command_dir, ext_argv->argv);
/* NOTREACHED */
break;
case SM_MODE_MAILQ:
if (argv[OPTIND])

View File

@ -1708,6 +1708,11 @@ static int mail_open_stream(SMTPD_STATE *state)
MAIL_ATTR_ACT_HELO_NAME, state->helo_name);
rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%u",
MAIL_ATTR_ACT_CLIENT_AF, state->addr_family);
/*
* Don't send client certificate down the pipeline unless it is
* a) verified or b) just a fingerprint.
*/
}
if (state->verp_delims)
rec_fputs(state->cleanup, REC_TYPE_VERP, state->verp_delims);
@ -2994,7 +2999,7 @@ static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
smtpd_chat_reply(state, "%s", err);
return (-1);
}
switch (flush_send(argv[1].strval)) {
switch (flush_send_site(argv[1].strval)) {
case FLUSH_STAT_OK:
smtpd_chat_reply(state, "250 Queuing started");
return (0);

View File

@ -1221,8 +1221,12 @@ static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
msg_info("Relaying allowed for all verified client certificates");
return (SMTPD_CHECK_OK);
}
if (state->tls_context->peer_verified
&& state->tls_context->peer_fingerprint) {
/*
* When directly checking the fingerprint, it is OK if the issuing CA is
* not trusted.
*/
if (state->tls_context->peer_fingerprint) {
found = maps_find(relay_ccerts, state->tls_context->peer_fingerprint,
DICT_FLAG_NONE);
if (found) {
@ -2578,8 +2582,11 @@ static int check_ccert_access(SMTPD_STATE *state, const char *table,
if (!state->tls_context)
return SMTPD_CHECK_DUNNO;
if (state->tls_context->peer_verified
&& state->tls_context->peer_fingerprint) {
/*
* When directly checking the fingerprint, it is OK if the issuing CA is
* not trusted.
*/
if (state->tls_context->peer_fingerprint) {
if (msg_verbose)
msg_info("%s: %s", myname, state->tls_context->peer_fingerprint);
@ -3335,11 +3342,18 @@ static int check_policy_service(SMTPD_STATE *state, const char *server,
#define IF_VERIFIED(x) \
((state->tls_context && \
state->tls_context->peer_verified && ((x) != 0)) ? (x) : "")
ATTR_TYPE_STR, MAIL_ATTR_CCERT_SUBJECT, subject,
ATTR_TYPE_STR, MAIL_ATTR_CCERT_ISSUER, issuer,
ATTR_TYPE_STR, MAIL_ATTR_CCERT_FINGERPRINT,
IF_VERIFIED(state->tls_context->peer_fingerprint),
#define IF_ENCRYPTED(x, y) ((state->tls_context && ((x) != 0)) ? (x) : (y))
ATTR_TYPE_STR, MAIL_ATTR_CCERT_SUBJECT,
IF_VERIFIED(subject),
ATTR_TYPE_STR, MAIL_ATTR_CCERT_ISSUER,
IF_VERIFIED(issuer),
/*
* When directly checking the fingerprint, it is OK if the issuing CA is
* not trusted.
*/
ATTR_TYPE_STR, MAIL_ATTR_CCERT_FINGERPRINT,
IF_ENCRYPTED(state->tls_context->peer_fingerprint, ""),
ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_PROTOCOL,
IF_ENCRYPTED(state->tls_context->protocol, ""),
ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_CIPHER,