src/cleanup/ Canonicalize and enqueue mail
src/discard/ Trivial discard mailer
src/error/ Trivial error mailer
- src/lmtp/ LMTP client
src/local/ Local delivery
src/master/ Postfix resident superserver
src/oqmgr/ Old queue manager
src/qmgr/ Queue manager
src/qmqpd/ QMQPD server
src/showq/ List Postfix queue status
- src/smtp/ SMTP client
+ src/smtp/ SMTP and LMTP client
src/smtpd/ SMTP server
src/spawn/ Run non-Postfix server
+ src/tlsmgr/ TLS session keys and random pool
src/trivial-rewrite/ Address rewriting and resolving
src/verify/ address verification service
src/virtual/ virtual mailbox-only delivery agent
response on a cached SMTP/LMTP connection. Report by Brian
Kantor. Fix by Victor Duchovni. File: smtp/smtp_reuse.c.
+20061113
+
+ Bugfix: the Postfix install/upgrade procedure broke with
+ non-default config_directory. File: conf/post-install.
+
+20061115
+
+ Bugfix: null pointer bug in end-of-header Milter action
+ when the last header line is too large. Reported by Mark
+ Martinec. The root of the problem is that the MIME state
+ engine may execute up to three call-back functions when it
+ reaches the end of the headers, before it returns to the
+ caller; as long as call-backs return no result, each call-back
+ has to check for itself if a previous call-back ran into a
+ problem. File: milter/milter8.c.
+
+ Workaround: reduce effective header_size_limit to 60000
+ when Milter inspection is enabled, to avoid breaking the
+ Milter protocol request length limit. File:
+ cleanup/cleanup_message.c.
+
+20061123
+
+ Workaround: more agressive early refill of in-memory
+ recipients to prevent a worst-case scenario where the queue
+ manager became starved until after the last batch of slow
+ in-memory recipients of jumbo multi-recipient mail. Files:
+ qmgr/qmgr_job.c.
+
+ Safety: don't read more than 5000 recipients at a time, to
+ avoid spending too much time away from interrupts. File:
+ qmgr/qmgr_message.c.
+
+20061201
+
+ Workaround: don't complain in the trivial-rewrite, verify,
+ proxymap or connection cache client when the server exits
+ after the client sends its request. We still complain,
+ however, when the problem persists. Files: global/rewrite_clnt.c,
+ global/resolve_clnt.c, global/verify_clnt.c, global/scache_clnt.c,
+ global/dict_proxy.c.
+
+ Safety: the header_size_limit is now enforced more strictly,
+ to avoid inter-operability problems with the Milter protocol.
+ Long headers are truncated at a line boundary if possible,
+ otherwise they are cut between line boundaries. File:
+ cleanup/cleanup_out.c.
+
Wish list:
+ Investigate if clients of single-instance servers such as
+ tlsmgr, verify, can close sockets earlier.
+
+ REDIRECT should override original recipient info, and
+ probably override DSN as well.
+
Find out if with Sendmail, a Milter "add recipient" request
results in NOTIFY=NONE as Postfix does now.
Content-Description: Notification
Content-Type: text/plain
- This is the Postfix program at host spike.porcupine.org.
+ This is the mail system at host spike.porcupine.org.
Enclosed is the mail delivery report that you requested.
- The Postfix program
+ The mail system
<postfix-users@postfix.org>: delivery via mail.cloud9.net[168.100.1.4]: 250
- Ok
+ 2.1.5 Ok
The second part of the report is in machine-readable form, and includes the
following information:
Reporting-MTA: dns; spike.porcupine.org
X-Postfix-Queue-ID: 84863BC0E5
X-Postfix-Sender: rfc822; wietse@porcupine.org
- Arrival-Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT)
+ Arrival-Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST)
Final-Recipient: rfc822; postfix-users@postfix.org
Action: deliverable
- Status: 2.0.0
+ Status: 2.1.5
Remote-MTA: dns; mail.cloud9.net
- Diagnostic-Code: smtp; 250 Ok
+ Diagnostic-Code: smtp; 250 2.1.5 Ok
The third part of the report contains the message that Postfix would have
delivered, including From: and To: message headers, so that you can see any
Content-Type: message/rfc822
Received: by spike.porcupine.org (Postfix, from userid 1001)
- id 84863BC0E5; Tue, 13 Apr 2004 19:27:43 -0400 (EDT)
+ id 84863BC0E5; id DA77DBC0A9; Sun, 26 Nov 2006 17:01:01 -0500 (EST)
Subject: probe
To: postfix-users@postfix.org
- Message-Id: <20040413232743.84863BC0E5@spike.porcupine.org>
- Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT)
+ Message-Id: <20061126220101.84863BC0E5@spike.porcupine.org>
+ Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST)
From: wietse@porcupine.org (Wietse Venema)
* How do I block backscatter mail to random recipient addresses?
* How do I block backscatter mail to real recipient addresses?
- o Blocking backscatter mail with forged HELO information
+ o Blocking backscatter mail with forged mail server information
o Blocking backscatter mail with forged sender information
o Blocking backscatter mail with other forged information
o Blocking backscatter mail from virus scanners
message headers contain information that you can use to recognize and block
forged mail.
-B\bBl\blo\boc\bck\bki\bin\bng\bg b\bba\bac\bck\bks\bsc\bca\bat\btt\bte\ber\br m\bma\bai\bil\bl w\bwi\bit\bth\bh f\bfo\bor\brg\bge\bed\bd H\bHE\bEL\bLO\bO i\bin\bnf\bfo\bor\brm\bma\bat\bti\bio\bon\bn
+B\bBl\blo\boc\bck\bki\bin\bng\bg b\bba\bac\bck\bks\bsc\bca\bat\btt\bte\ber\br m\bma\bai\bil\bl w\bwi\bit\bth\bh f\bfo\bor\brg\bge\bed\bd m\bma\bai\bil\bl s\bse\ber\brv\bve\ber\br i\bin\bnf\bfo\bor\brm\bma\bat\bti\bio\bon\bn
Although my email address is "wietse@porcupine.org", all my mail systems
announce themselves with the SMTP HELO command as "hostname.porcupine.org".
Received: from host.example.com (HELO porcupine.org) ...
Received: from host.example.com (EHLO porcupine.org) ...
+Some forgeries show up in the way that a mail server reports itself in
+Received: message headers. Keeping in mind that all my systems have a mail
+server name of hostname.porcupine.org, the following is definitely a forgery:
+
+ Received: by porcupine.org ...
+ Received: from host.example.com ( ... ) by porcupine.org ...
+
Another frequent sign of forgery is the Message-ID: header. My systems produce
a Message-ID: of <stuff@hostname.porcupine.org>. The following are forgeries,
especially the first one:
body_checks = regexp:/etc/postfix/body_checks
/etc/postfix/header_checks:
+ if /^Received:/
/^Received: +from +(porcupine\.org) +/
reject forged client name in Received: header: $1
/^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)
(porcupine\.org)\)/
reject forged client name in Received: header: $2
+ /^Received:.* +by +(porcupine\.org)[[:>:]]/
+ reject forged mail server name in Received: header: $1
+ endif
/^Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
/etc/postfix/body_checks:
+ if /^[> ]*Received:/
/^[> ]*Received: +from +(porcupine\.org) /
reject forged client name in Received: header: $1
/^[> ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)
(porcupine\.org)\)/
reject forged client name in Received: header: $2
+ /^[> ]*Received:.* +by +(porcupine\.org)[[:>:]]/
+ reject forged mail server name in Received: header: $1
+ endif
/^[> ]*Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
* The "\(" and "\)" match "(" and ")" literally. Without the "\", the "(" and
")" would be grouping operators.
+ * The "[[:>:]]" matches the end of a word. On some systems you should specify
+ "\>" instead. For details see your system documentation.
+
+ * The "if /pattern/" and "endif" eliminate unnecessary matching attempts. DO
+ NOT indent lines starting with /pattern/ between the "if" and "endif"!
+
C\bCa\bav\bve\bea\bat\bts\bs
Netscape Messenger (and reportedly, Mozilla) sends a HELO name that is
* Making Postfix daemon programs more verbose
* Manually tracing a Postfix daemon process
* Automatically tracing a Postfix daemon process
- * Running daemon programs with the interactive xxgdb debugger
+ * Running daemon programs with the interactive ddd debugger
+ * Running daemon programs with the interactive gdb debugger
* Running daemon programs under a non-interactive debugger
* Unreasonable behavior
* Reporting problems to postfix-users@postfix.org
Type "p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd" and watch the logfile.
-R\bRu\bun\bnn\bni\bin\bng\bg d\bda\bae\bem\bmo\bon\bn p\bpr\bro\bog\bgr\bra\bam\bms\bs w\bwi\bit\bth\bh t\bth\bhe\be i\bin\bnt\bte\ber\bra\bac\bct\bti\biv\bve\be x\bxx\bxg\bgd\bdb\bb d\bde\beb\bbu\bug\bgg\bge\ber\br
+R\bRu\bun\bnn\bni\bin\bng\bg d\bda\bae\bem\bmo\bon\bn p\bpr\bro\bog\bgr\bra\bam\bms\bs w\bwi\bit\bth\bh t\bth\bhe\be i\bin\bnt\bte\ber\bra\bac\bct\bti\biv\bve\be d\bdd\bdd\bd d\bde\beb\bbu\bug\bgg\bge\ber\br
If you have X Windows installed on the Postfix machine, then an interactive
-debugger such as x\bxx\bxg\bgd\bdb\bb can be convenient.
+debugger such as d\bdd\bdd\bd can be convenient.
Edit the debugger_command definition in /etc/postfix/main.cf so that it invokes
-x\bxx\bxg\bgd\bdb\bb:
+d\bdd\bdd\bd:
/etc/postfix/main.cf:
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
- xxgdb $daemon_directory/$process_name $process_id & sleep 5
+ ddd $daemon_directory/$process_name $process_id & sleep 5
Be sure that g\bgd\bdb\bb is in the command search path, and export X\bXA\bAU\bUT\bTH\bHO\bOR\bRI\bIT\bTY\bY so that X
access control works, for example:
Whenever the suspect daemon process is started, a debugger window pops up and
you can watch in detail what happens.
+R\bRu\bun\bnn\bni\bin\bng\bg d\bda\bae\bem\bmo\bon\bn p\bpr\bro\bog\bgr\bra\bam\bms\bs w\bwi\bit\bth\bh t\bth\bhe\be i\bin\bnt\bte\ber\bra\bac\bct\bti\biv\bve\be g\bgd\bdb\bb d\bde\beb\bbu\bug\bgg\bge\ber\br
+
+If you have the screen command installed on the Postfix machine, then you can
+run an interactive debugger such as g\bgd\bdb\bb as follows.
+
+Edit the debugger_command definition in /etc/postfix/main.cf so that it runs
+g\bgd\bdb\bb inside a detached s\bsc\bcr\bre\bee\ben\bn session:
+
+ /etc/postfix/main.cf:
+ debugger_command =
+ PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH; HOME=/root;
+ export HOME; screen -e^tt -dmS $process_name gdb
+ $daemon_directory/$process_name $process_id & sleep 2
+
+Be sure that g\bgd\bdb\bb is in the command search path.
+
+Append a -\b-D\bD option to the suspect daemon definition in /etc/postfix/master.cf,
+for example:
+
+ /etc/postfix/master.cf:
+ smtp inet n - n - - smtpd -D
+
+Execute the command "p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd" and wait until a daemon process is started
+(you can see this in the maillog file).
+
+Then attach to the screen, and debug away:
+
+ # HOME=/root screen -r
+ gdb) continue
+ gdb) where
+
R\bRu\bun\bnn\bni\bin\bng\bg d\bda\bae\bem\bmo\bon\bn p\bpr\bro\bog\bgr\bra\bam\bms\bs u\bun\bnd\bde\ber\br a\ba n\bno\bon\bn-\b-i\bin\bnt\bte\ber\bra\bac\bct\bti\biv\bve\be d\bde\beb\bbu\bug\bgg\bge\ber\br
If you do not have X Windows installed on the Postfix machine, or if you are
# This safety net is also documented in LOCAL_RECIPIENT_README.
unknown_local=unknown_local_recipient_reject_code
- has_lrm=`$POSTCONF -n local_recipient_maps`
- has_lrjc=`$POSTCONF -n $unknown_local`
+ has_lrm=`$POSTCONF -c $config_directory -n local_recipient_maps`
+ has_lrjc=`$POSTCONF -c $config_directory -n $unknown_local`
if [ -z "$has_lrm" -a -z "$has_lrjc" ]
then
echo SAFETY: editing main.cf, setting $unknown_local=450.
echo See the LOCAL_RECIPIENT_README file for details.
- $POSTCONF -e "$unknown_local = 450" || exit 1
+ $POSTCONF -c $config_directory -e "$unknown_local = 450" || exit 1
fi
# Add missing proxymap service to master.cf.
test -n "$first_install_reminder" && {
- ALIASES=`$POSTCONF -h alias_database | sed 's/^[^:]*://'`
- NEWALIASES_PATH=`$POSTCONF -h newaliases_path`
+ ALIASES=`$POSTCONF -c $config_directory -h alias_database | sed 's/^[^:]*://'`
+ NEWALIASES_PATH=`$POSTCONF -c $config_directory -h newaliases_path`
cat <<EOF | ${FMT}
Warning: you still need to edit myorigin/mydestination/mynetworks
Content-Description: Notification
Content-Type: text/plain
-This is the Postfix program at host spike.porcupine.org.
+This is the mail system at host spike.porcupine.org.
Enclosed is the mail delivery report that you requested.
- The Postfix program
+ The mail system
-<postfix-users@postfix.org>: delivery via mail.cloud9.net[168.100.1.4]: 250 Ok
+<postfix-users@postfix.org>: delivery via mail.cloud9.net[168.100.1.4]: 250 2.1.5 Ok
</pre>
</blockquote>
Reporting-MTA: dns; spike.porcupine.org
X-Postfix-Queue-ID: 84863BC0E5
X-Postfix-Sender: rfc822; wietse@porcupine.org
-Arrival-Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT)
+Arrival-Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST)
Final-Recipient: rfc822; postfix-users@postfix.org
Action: deliverable
-Status: 2.0.0
+Status: 2.1.5
Remote-MTA: dns; mail.cloud9.net
-Diagnostic-Code: smtp; 250 Ok
+Diagnostic-Code: smtp; 250 2.1.5 Ok
</pre>
</blockquote>
Content-Type: message/rfc822
Received: by spike.porcupine.org (Postfix, from userid 1001)
- id 84863BC0E5; Tue, 13 Apr 2004 19:27:43 -0400 (EDT)
+ id 84863BC0E5; id DA77DBC0A9; Sun, 26 Nov 2006 17:01:01 -0500 (EST)
Subject: probe
To: postfix-users@postfix.org
-Message-Id: <20040413232743.84863BC0E5@spike.porcupine.org>
-Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT)
+Message-Id: <20061126220101.84863BC0E5@spike.porcupine.org>
+Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST)
From: wietse@porcupine.org (Wietse Venema)
</pre>
</blockquote>
<ul>
<li><a href="#forged_helo">Blocking backscatter mail with forged
-HELO information</a>
+mail server information</a>
<li><a href="#forged_sender">Blocking backscatter mail with forged
sender information</a>
</p>
<h3><a name="forged_helo">Blocking backscatter mail with forged
-HELO information</a></h3>
+mail server information</a></h3>
<p> Although my email address is "wietse@porcupine.org", all my
mail systems announce themselves with the SMTP HELO command as
</pre>
</blockquote>
+<p> Some forgeries show up in the way that a mail server reports
+itself in Received: message headers. Keeping in mind that all my
+systems have a mail server name of <i>hostname</i>.porcupine.org,
+the following is definitely a forgery:</p>
+
+<blockquote>
+<pre>
+Received: by porcupine.org ...
+Received: from host.example.com ( ... ) by porcupine.org ...
+</pre>
+</blockquote>
+
<p> Another frequent sign of forgery is the Message-ID: header. My
systems produce a Message-ID: of
<<i>stuff</i>@<i>hostname</i>.porcupine.org>. The following
<a href="postconf.5.html#body_checks">body_checks</a> = <a href="regexp_table.5.html">regexp</a>:/etc/postfix/body_checks
/etc/postfix/header_checks:
+ if /^Received:/
/^Received: +from +(porcupine\.org) +/
reject forged client name in Received: header: $1
/^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
reject forged client name in Received: header: $2
+ /^Received:.* +by +(porcupine\.org)[[:>:]]/
+ reject forged mail server name in Received: header: $1
+ endif
/^Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
/etc/postfix/body_checks:
+ if /^[> ]*Received:/
/^[> ]*Received: +from +(porcupine\.org) /
reject forged client name in Received: header: $1
/^[> ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
reject forged client name in Received: header: $2
+ /^[> ]*Received:.* +by +(porcupine\.org)[[:>:]]/
+ reject forged mail server name in Received: header: $1
+ endif
/^[> ]*Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
</pre>
and "<tt>)</tt>" literally. Without the "<tt>\</tt>", the "<tt>(</tt>"
and "<tt>)</tt>" would be grouping operators. </p>
+<li> <p> The "<tt>[[:>:]]</tt>" matches the end of a word. On
+some systems you should specify "<tt>\></tt>" instead. For details
+see your system documentation. </p>
+
+<li> <p> The "if /pattern/" and "endif" eliminate unnecessary
+matching attempts. DO NOT indent lines starting with /pattern/
+between the "if" and "endif"! </p>
+
</ul>
<p><a name="caveats"><strong>Caveats</strong></a></p>
<li> <p> The "<tt>[[:<:]]</tt>" and "<tt>[[:>:]]</tt>" match
the beginning and end of a word, respectively. On some systems you
should specify "<tt>\<</tt>" and "<tt>\></tt>" instead. For
-details see your system documentation.
+details see your system documentation. </p>
<li> <p> The "<tt>\.</tt>" matches "<tt>.</tt>" literally. Without
the "<tt>\</tt>", the "<tt>.</tt>" would match any character. </p>
vary from making Postfix log a lot of detail, to running some daemon
processes under control of a call tracer or debugger. </p>
-<p> The text assumes that the Postfix main.cf and master.cf
+<p> The text assumes that the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a>
configuration files are stored in directory /etc/postfix. You can
use the command "<b>postconf <a href="postconf.5.html#config_directory">config_directory</a></b>" to find out the
actual location of this directory on your machine. </p>
<li><a href="#auto_trace">Automatically tracing a Postfix daemon
process</a>
-<li><a href="#xxgdb">Running daemon programs with the interactive
-xxgdb debugger</a>
+<li><a href="#ddd">Running daemon programs with the interactive
+ddd debugger</a>
+
+<li><a href="#screen">Running daemon programs with the interactive
+gdb debugger</a>
<li><a href="#gdb">Running daemon programs under a non-interactive
debugger</a>
<h2><a name="no_chroot">Try turning off chroot operation in master.cf</a></h2>
-<p> A common mistake is to turn on chroot operation in the master.cf
+<p> A common mistake is to turn on chroot operation in the <a href="master.5.html">master.cf</a>
file without going through all the necessary steps to set up a
chroot environment. This causes Postfix daemon processes to fail
due to all kinds of missing files. </p>
<blockquote>
<pre>
-/etc/postfix/master.cf:
+/etc/postfix/<a href="master.5.html">master.cf</a>:
# =============================================================
# service type private unpriv <b>chroot</b> wakeup maxproc command
# (yes) (yes) <b>(yes)</b> (never) (100)
</pre>
</blockquote>
-<p> Inspect master.cf for any processes that have chroot operation
-not turned off. If you find any, save a copy of the master.cf file,
+<p> Inspect <a href="master.5.html">master.cf</a> for any processes that have chroot operation
+not turned off. If you find any, save a copy of the <a href="master.5.html">master.cf</a> file,
and edit the entries in question. After executing the command
"<b>postfix reload</b>", see if the problem has gone away. </p>
<h2><a name="debug_peer">Verbose logging for specific SMTP
connections</a></h2>
-<p> In /etc/postfix/main.cf, list the remote site name or address
+<p> In /etc/postfix/<a href="postconf.5.html">main.cf</a>, list the remote site name or address
in the <a href="postconf.5.html#debug_peer_list">debug_peer_list</a> parameter. For example, in order to make
the software log a lot of information to the syslog daemon for
connections from or to the loopback interface: </p>
<blockquote>
<pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#debug_peer_list">debug_peer_list</a> = 127.0.0.1
</pre>
</blockquote>
<h2><a name="verbose">Making Postfix daemon programs more verbose</a></h2>
<p> Append one or more "<b>-v</b>" options to selected daemon
-definitions in /etc/postfix/master.cf and type "<b>postfix reload</b>".
+definitions in /etc/postfix/<a href="master.5.html">master.cf</a> and type "<b>postfix reload</b>".
This will cause a lot of activity to be logged to the syslog daemon.
Example: </p>
<blockquote>
<pre>
-/etc/postfix/master.cf:
+/etc/postfix/<a href="master.5.html">master.cf</a>:
smtp inet n - n - - smtpd -v
</pre>
</blockquote>
</ol>
<p> Append a <b>-D</b> option to the suspect command in
-/etc/postfix/master.cf, for example: </p>
+/etc/postfix/<a href="master.5.html">master.cf</a>, for example: </p>
<blockquote>
<pre>
-/etc/postfix/master.cf:
+/etc/postfix/<a href="master.5.html">master.cf</a>:
smtp inet n - n - - smtpd -D
</pre>
</blockquote>
-<p> Edit the <a href="postconf.5.html#debugger_command">debugger_command</a> definition in /etc/postfix/main.cf
+<p> Edit the <a href="postconf.5.html#debugger_command">debugger_command</a> definition in /etc/postfix/<a href="postconf.5.html">main.cf</a>
so that it invokes the call tracer of your choice, for example:
</p>
<blockquote>
<pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#debugger_command">debugger_command</a> =
PATH=/bin:/usr/bin:/usr/local/bin;
(truss -p $<a href="postconf.5.html#process_id">process_id</a> 2>&1 | logger -p mail.info) & sleep 5
<p> Type "<b>postfix reload</b>" and watch the logfile. </p>
-<h2><a name="xxgdb">Running daemon programs with the interactive
-xxgdb debugger</a></h2>
+<h2><a name="ddd">Running daemon programs with the interactive
+ddd debugger</a></h2>
<p> If you have X Windows installed on the Postfix machine, then
-an interactive debugger such as <b>xxgdb</b> can be convenient.
+an interactive debugger such as <b>ddd</b> can be convenient.
</p>
-<p> Edit the <a href="postconf.5.html#debugger_command">debugger_command</a> definition in /etc/postfix/main.cf
-so that it invokes <b>xxgdb</b>: </p>
+<p> Edit the <a href="postconf.5.html#debugger_command">debugger_command</a> definition in /etc/postfix/<a href="postconf.5.html">main.cf</a>
+so that it invokes <b>ddd</b>: </p>
<blockquote>
<pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#debugger_command">debugger_command</a> =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
- xxgdb $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/$<a href="postconf.5.html#process_name">process_name</a> $<a href="postconf.5.html#process_id">process_id</a> & sleep 5
+ ddd $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/$<a href="postconf.5.html#process_name">process_name</a> $<a href="postconf.5.html#process_id">process_id</a> & sleep 5
</pre>
</blockquote>
</blockquote>
<p> Append a <b>-D</b> option to the suspect daemon definition in
-/etc/postfix/master.cf, for example: </p>
+/etc/postfix/<a href="master.5.html">master.cf</a>, for example: </p>
<blockquote>
<pre>
-/etc/postfix/master.cf:
+/etc/postfix/<a href="master.5.html">master.cf</a>:
smtp inet n - n - - smtpd -D
</pre>
</blockquote>
<p> Whenever the suspect daemon process is started, a debugger
window pops up and you can watch in detail what happens. </p>
+<h2><a name="screen">Running daemon programs with the interactive
+gdb debugger</a></h2>
+
+<p> If you have the screen command installed on the Postfix machine, then
+you can run an interactive debugger such as <b>gdb</b> as follows. </p>
+
+<p> Edit the <a href="postconf.5.html#debugger_command">debugger_command</a> definition in /etc/postfix/<a href="postconf.5.html">main.cf</a>
+so that it runs <b>gdb</b> inside a detached <b>screen</b> session:
+</p>
+
+<blockquote>
+<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#debugger_command">debugger_command</a> =
+ PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH; HOME=/root;
+ export HOME; screen -e^tt -dmS $<a href="postconf.5.html#process_name">process_name</a> gdb
+ $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/$<a href="postconf.5.html#process_name">process_name</a> $<a href="postconf.5.html#process_id">process_id</a> & sleep 2
+</pre>
+</blockquote>
+
+<p> Be sure that <b>gdb</b> is in the command search path. </p>
+
+<p> Append a <b>-D</b> option to the suspect daemon definition in
+/etc/postfix/<a href="master.5.html">master.cf</a>, for example: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/<a href="master.5.html">master.cf</a>:
+ smtp inet n - n - - smtpd -D
+</pre>
+</blockquote>
+
+<p> Execute the command "<b>postfix reload</b>" and wait until a
+daemon process is started (you can see this in the maillog file).
+</p>
+
+<p> Then attach to the screen, and debug away: </p>
+
+<blockquote>
+<pre>
+# HOME=/root screen -r
+gdb) continue
+gdb) where
+</pre>
+</blockquote>
+
<h2><a name="gdb">Running daemon programs under a non-interactive
debugger</a></h2>
can try to run <b>gdb</b> in non-interactive mode, and have it
print a stack trace when the process crashes. </p>
-<p> Edit the <a href="postconf.5.html#debugger_command">debugger_command</a> definition in /etc/postfix/main.cf
+<p> Edit the <a href="postconf.5.html#debugger_command">debugger_command</a> definition in /etc/postfix/<a href="postconf.5.html">main.cf</a>
so that it invokes the <b>gdb</b> debugger: </p>
<blockquote>
<pre>
-/etc/postfix/main.cf:
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#debugger_command">debugger_command</a> =
PATH=/bin:/usr/bin:/usr/local/bin; export PATH; (echo cont; echo
where; sleep 8640000) | gdb $<a href="postconf.5.html#daemon_directory">daemon_directory</a>/$<a href="postconf.5.html#process_name">process_name</a>
</blockquote>
<p> Append a <b>-D</b> option to the suspect daemon in
-/etc/postfix/master.cf, for example: </p>
+/etc/postfix/<a href="master.5.html">master.cf</a>, for example: </p>
<blockquote>
<pre>
-/etc/postfix/master.cf:
+/etc/postfix/<a href="master.5.html">master.cf</a>:
smtp inet n - n - - smtpd -D
</pre>
</blockquote>
</p>
<li> <p> Output from "<b>postconf -n</b>". Please do not send your
-main.cf file or 400+ lines of <b>postconf</b> output. </p>
+<a href="postconf.5.html">main.cf</a> file or 400+ lines of <b>postconf</b> output. </p>
<li> <p> Better, provide output from the <b>postfinger</b> tool.
This can be found at <a href="http://ftp.wl0.org/SOURCES/postfinger">http://ftp.wl0.org/SOURCES/postfinger</a>. </p>
update: $(DAEMONS) $(COMMANDS) $(CONFIG) $(OTHER)
-Makefile: Makefile.in
- (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../src/makedefs; cat $?) >$@
-
clean:
echo clean
<p>
The maximum amount of time that an idle Postfix daemon process
waits for the next service request before exiting. This parameter
-is ignored by the Postfix queue manager.
+is ignored by the Postfix queue manager and by other long-lived
+Postfix daemon processes.
</p>
<p>
(default: empty)</b></DT><DD>
<p> A sender-dependent override for the global <a href="postconf.5.html#relayhost">relayhost</a> parameter
-setting. The tables are searched by the sender address and by the
+setting. The tables are searched by the envelope sender address and
@domain. This information is overruled with <a href="postconf.5.html#relay_transport">relay_transport</a>,
<a href="postconf.5.html#default_transport">default_transport</a> and with the <a href="transport.5.html">transport(5)</a> table. </p>
update: $(DAEMONS) $(COMMANDS) $(CONFIG) $(TOOLS)
-Makefile: Makefile.in
- (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../src/makedefs; cat $?) >$@
-
clean:
rm -f cat?/*
.SH max_idle (default: 100s)
The maximum amount of time that an idle Postfix daemon process
waits for the next service request before exiting. This parameter
-is ignored by the Postfix queue manager.
+is ignored by the Postfix queue manager and by other long-lived
+Postfix daemon processes.
.PP
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
.ft R
.SH sender_dependent_relayhost_maps (default: empty)
A sender-dependent override for the global relayhost parameter
-setting. The tables are searched by the sender address and by the
+setting. The tables are searched by the envelope sender address and
@domain. This information is overruled with relay_transport,
default_transport and with the \fBtransport\fR(5) table.
.PP
Content-Description: Notification
Content-Type: text/plain
-This is the Postfix program at host spike.porcupine.org.
+This is the mail system at host spike.porcupine.org.
Enclosed is the mail delivery report that you requested.
- The Postfix program
+ The mail system
-<postfix-users@postfix.org>: delivery via mail.cloud9.net[168.100.1.4]: 250 Ok
+<postfix-users@postfix.org>: delivery via mail.cloud9.net[168.100.1.4]: 250 2.1.5 Ok
</pre>
</blockquote>
Reporting-MTA: dns; spike.porcupine.org
X-Postfix-Queue-ID: 84863BC0E5
X-Postfix-Sender: rfc822; wietse@porcupine.org
-Arrival-Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT)
+Arrival-Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST)
Final-Recipient: rfc822; postfix-users@postfix.org
Action: deliverable
-Status: 2.0.0
+Status: 2.1.5
Remote-MTA: dns; mail.cloud9.net
-Diagnostic-Code: smtp; 250 Ok
+Diagnostic-Code: smtp; 250 2.1.5 Ok
</pre>
</blockquote>
Content-Type: message/rfc822
Received: by spike.porcupine.org (Postfix, from userid 1001)
- id 84863BC0E5; Tue, 13 Apr 2004 19:27:43 -0400 (EDT)
+ id 84863BC0E5; id DA77DBC0A9; Sun, 26 Nov 2006 17:01:01 -0500 (EST)
Subject: probe
To: postfix-users@postfix.org
-Message-Id: <20040413232743.84863BC0E5@spike.porcupine.org>
-Date: Tue, 13 Apr 2004 19:27:43 -0400 (EDT)
+Message-Id: <20061126220101.84863BC0E5@spike.porcupine.org>
+Date: Sun, 26 Nov 2006 17:01:01 -0500 (EST)
From: wietse@porcupine.org (Wietse Venema)
</pre>
</blockquote>
<ul>
<li><a href="#forged_helo">Blocking backscatter mail with forged
-HELO information</a>
+mail server information</a>
<li><a href="#forged_sender">Blocking backscatter mail with forged
sender information</a>
</p>
<h3><a name="forged_helo">Blocking backscatter mail with forged
-HELO information</a></h3>
+mail server information</a></h3>
<p> Although my email address is "wietse@porcupine.org", all my
mail systems announce themselves with the SMTP HELO command as
</pre>
</blockquote>
+<p> Some forgeries show up in the way that a mail server reports
+itself in Received: message headers. Keeping in mind that all my
+systems have a mail server name of <i>hostname</i>.porcupine.org,
+the following is definitely a forgery:</p>
+
+<blockquote>
+<pre>
+Received: by porcupine.org ...
+Received: from host.example.com ( ... ) by porcupine.org ...
+</pre>
+</blockquote>
+
<p> Another frequent sign of forgery is the Message-ID: header. My
systems produce a Message-ID: of
<<i>stuff</i>@<i>hostname</i>.porcupine.org>. The following
body_checks = regexp:/etc/postfix/body_checks
/etc/postfix/header_checks:
+ if /^Received:/
/^Received: +from +(porcupine\.org) +/
reject forged client name in Received: header: $1
/^Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
reject forged client name in Received: header: $2
+ /^Received:.* +by +(porcupine\.org)[[:>:]]/
+ reject forged mail server name in Received: header: $1
+ endif
/^Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
/etc/postfix/body_checks:
+ if /^[> ]*Received:/
/^[> ]*Received: +from +(porcupine\.org) /
reject forged client name in Received: header: $1
/^[> ]*Received: +from +[^ ]+ +\(([^ ]+ +[he]+lo=|[he]+lo +)(porcupine\.org)\)/
reject forged client name in Received: header: $2
+ /^[> ]*Received:.* +by +(porcupine\.org)[[:>:]]/
+ reject forged mail server name in Received: header: $1
+ endif
/^[> ]*Message-ID:.*@(porcupine\.org)/
reject forged domain name in Message-ID: header: $1
</pre>
and "<tt>)</tt>" literally. Without the "<tt>\</tt>", the "<tt>(</tt>"
and "<tt>)</tt>" would be grouping operators. </p>
+<li> <p> The "<tt>[[:>:]]</tt>" matches the end of a word. On
+some systems you should specify "<tt>\></tt>" instead. For details
+see your system documentation. </p>
+
+<li> <p> The "if /pattern/" and "endif" eliminate unnecessary
+matching attempts. DO NOT indent lines starting with /pattern/
+between the "if" and "endif"! </p>
+
</ul>
<p><a name="caveats"><strong>Caveats</strong></a></p>
<li> <p> The "<tt>[[:<:]]</tt>" and "<tt>[[:>:]]</tt>" match
the beginning and end of a word, respectively. On some systems you
should specify "<tt>\<</tt>" and "<tt>\></tt>" instead. For
-details see your system documentation.
+details see your system documentation. </p>
<li> <p> The "<tt>\.</tt>" matches "<tt>.</tt>" literally. Without
the "<tt>\</tt>", the "<tt>.</tt>" would match any character. </p>
<li><a href="#auto_trace">Automatically tracing a Postfix daemon
process</a>
-<li><a href="#xxgdb">Running daemon programs with the interactive
-xxgdb debugger</a>
+<li><a href="#ddd">Running daemon programs with the interactive
+ddd debugger</a>
+
+<li><a href="#screen">Running daemon programs with the interactive
+gdb debugger</a>
<li><a href="#gdb">Running daemon programs under a non-interactive
debugger</a>
<p> Type "<b>postfix reload</b>" and watch the logfile. </p>
-<h2><a name="xxgdb">Running daemon programs with the interactive
-xxgdb debugger</a></h2>
+<h2><a name="ddd">Running daemon programs with the interactive
+ddd debugger</a></h2>
<p> If you have X Windows installed on the Postfix machine, then
-an interactive debugger such as <b>xxgdb</b> can be convenient.
+an interactive debugger such as <b>ddd</b> can be convenient.
</p>
<p> Edit the debugger_command definition in /etc/postfix/main.cf
-so that it invokes <b>xxgdb</b>: </p>
+so that it invokes <b>ddd</b>: </p>
<blockquote>
<pre>
/etc/postfix/main.cf:
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
- xxgdb $daemon_directory/$process_name $process_id & sleep 5
+ ddd $daemon_directory/$process_name $process_id & sleep 5
</pre>
</blockquote>
<p> Whenever the suspect daemon process is started, a debugger
window pops up and you can watch in detail what happens. </p>
+<h2><a name="screen">Running daemon programs with the interactive
+gdb debugger</a></h2>
+
+<p> If you have the screen command installed on the Postfix machine, then
+you can run an interactive debugger such as <b>gdb</b> as follows. </p>
+
+<p> Edit the debugger_command definition in /etc/postfix/main.cf
+so that it runs <b>gdb</b> inside a detached <b>screen</b> session:
+</p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+ debugger_command =
+ PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH; HOME=/root;
+ export HOME; screen -e^tt -dmS $process_name gdb
+ $daemon_directory/$process_name $process_id & sleep 2
+</pre>
+</blockquote>
+
+<p> Be sure that <b>gdb</b> is in the command search path. </p>
+
+<p> Append a <b>-D</b> option to the suspect daemon definition in
+/etc/postfix/master.cf, for example: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/master.cf:
+ smtp inet n - n - - smtpd -D
+</pre>
+</blockquote>
+
+<p> Execute the command "<b>postfix reload</b>" and wait until a
+daemon process is started (you can see this in the maillog file).
+</p>
+
+<p> Then attach to the screen, and debug away: </p>
+
+<blockquote>
+<pre>
+# HOME=/root screen -r
+gdb) continue
+gdb) where
+</pre>
+</blockquote>
+
<h2><a name="gdb">Running daemon programs under a non-interactive
debugger</a></h2>
update: $(CONFIG) $(HTML) $(README) $(MAN)
-Makefile: Makefile.in
- (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../makedefs; cat $?) >$@
-
clean:
:
<p>
The maximum amount of time that an idle Postfix daemon process
waits for the next service request before exiting. This parameter
-is ignored by the Postfix queue manager.
+is ignored by the Postfix queue manager and by other long-lived
+Postfix daemon processes.
</p>
<p>
%PARAM sender_dependent_relayhost_maps empty
<p> A sender-dependent override for the global relayhost parameter
-setting. The tables are searched by the sender address and by the
+setting. The tables are searched by the envelope sender address and
@domain. This information is overruled with relay_transport,
default_transport and with the transport(5) table. </p>
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
TOK822 *token;
time_t tv;
+ /*
+ * XXX Workaround: when we reach the end of headers, mime_state_update()
+ * may execute up to three call-backs before returning to the caller:
+ * head_out(), head_end(), and body_out() or body_end(). As long as
+ * call-backs don't return a result, each call-back has to check for
+ * itself if the previous call-back experienced a problem.
+ */
+ if (CLEANUP_OUT_OK(state) == 0)
+ return;
+
/*
* Add a missing (Resent-)Message-Id: header. The message ID gives the
* time in GMT units, plus the local queue ID.
{
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
+ /*
+ * XXX Workaround: when we reach the end of headers, mime_state_update()
+ * may execute up to three call-backs before returning to the caller:
+ * head_out(), head_end(), and body_out() or body_end(). As long as
+ * call-backs don't return a result, each call-back has to check for
+ * itself if the previous call-back experienced a problem.
+ */
+ if (CLEANUP_OUT_OK(state) == 0)
+ return;
+
/*
* Crude message body content filter for emergencies. This code has
* several problems: it sees one line at a time; it looks at long lines
cleanup_mime_error_callback,
(void *) state);
+ /*
+ * XXX Workaround: truncate a long message header so that we don't exceed
+ * the Milter request size limit of 65535.
+ */
+#define KLUDGE_HEADER_LIMIT 60000
+ if ((cleanup_milters || state->milters)
+ && var_header_limit > KLUDGE_HEADER_LIMIT)
+ var_header_limit = KLUDGE_HEADER_LIMIT;
+
/*
* Pass control to the header processing routine.
*/
msg_vstream_init(argv[0], VSTREAM_ERR);
var_line_limit = DEF_LINE_LIMIT;
+ var_header_limit = DEF_HEADER_LIMIT;
for (;;) {
ARGV *argv;
* of such header lines. NB: This code destroys the header. We could try
* to avoid clobbering it, but we're not going to use the data any
* further.
+ *
+ * XXX We prefer to truncate a header at the last line boundary before the
+ * header size limit. If this would undershoot the limit by more than
+ * 10%, we truncate between line boundaries to avoid losing too much
+ * text. This "unkind cut" may result in syntax errors and may trigger
+ * warnings from down-stream MTAs.
*/
for (line = start; line; line = next_line) {
next_line = split_at(line, '\n');
+ if ((next_line ? next_line - 1 : line + strlen(line))
+ > start + var_header_limit) {
+ if (line - start > 0.9 * var_header_limit) /* nice cut */
+ break;
+ start[var_header_limit] = 0; /* unkind cut */
+ next_line = 0;
+ }
if (line == start || IS_SPACE_TAB(*line)) {
cleanup_out_string(state, REC_TYPE_NORM, line);
} else {
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
fsstone: fsstone.o $(LIBS)
$(CC) $(CFLAGS) -o $@ fsstone.o $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
DICT_PROXY *dict_proxy = (DICT_PROXY *) dict;
VSTREAM *stream;
int status;
+ int count = 0;
/*
* The client and server live in separate processes that may start and
for (;;) {
stream = clnt_stream_access(proxy_stream);
errno = 0;
+ count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_REQ, PROXY_REQ_LOOKUP,
ATTR_TYPE_STR, MAIL_ATTR_TABLE, dict->name,
ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
ATTR_TYPE_STR, MAIL_ATTR_VALUE, dict_proxy->result,
ATTR_TYPE_END) != 2) {
- if (msg_verbose || (errno != EPIPE && errno != ENOENT))
+ if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
} else {
if (msg_verbose)
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20061019"
+#define MAIL_RELEASE_DATE "20061201"
#define MAIL_VERSION_NUMBER "2.4"
#ifdef SNAPSHOT
/* .IP state
/* MIME parser state created with mime_state_alloc().
/* BUGS
+/* NOTE: when the end of headers is reached, mime_state_update()
+/* may execute up to three call-backs before returning to the
+/* caller: head_out(), head_end(), and body_out() or body_end().
+/* As long as call-backs return no result, it is up to the
+/* call-back routines to check if a previous call-back experienced
+/* an error.
+/*
/* Different mail user agents treat malformed message boundary
/* strings in different ways. The Postfix MIME processor cannot
/* be bug-compatible with everything.
const char *myname = "resolve_clnt";
VSTREAM *stream;
int server_flags;
+ int count = 0;
/*
* One-entry cache.
for (;;) {
stream = clnt_stream_access(rewrite_clnt_stream);
errno = 0;
+ count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_REQ, class,
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, reply->recipient,
ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &reply->flags,
ATTR_TYPE_END) != 5) {
- if (msg_verbose || (errno != EPIPE && errno != ENOENT))
+ if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("problem talking to service %s: %m",
var_rewrite_service);
} else {
{
VSTREAM *stream;
int server_flags;
+ int count = 0;
/*
* One-entry cache.
for (;;) {
stream = clnt_stream_access(rewrite_clnt_stream);
errno = 0;
+ count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_REQ, REWRITE_ADDR,
ATTR_TYPE_STR, MAIL_ATTR_RULE, rule,
ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &server_flags,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, result,
ATTR_TYPE_END) != 2) {
- if (msg_verbose || (errno != EPIPE && errno != ENOENT))
+ if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("problem talking to service %s: %m",
var_rewrite_service);
} else {
VSTREAM *stream;
int status;
int tries;
+ int count = 0;
if (msg_verbose)
msg_info("%s: endp=%s prop=%s fd=%d",
for (tries = 0; sp->auto_clnt != 0; tries++) {
if ((stream = auto_clnt_access(sp->auto_clnt)) != 0) {
errno = 0;
+ count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_REQ, SCACHE_REQ_SAVE_ENDP,
ATTR_TYPE_INT, MAIL_ATTR_TTL, endp_ttl,
|| attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
ATTR_TYPE_END) != 1) {
- if (msg_verbose || (errno != EPIPE && errno != ENOENT))
+ if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("problem talking to service %s: %m",
VSTREAM_PATH(stream));
/* Give up or recover. */
myname, status);
break;
}
- }
+ }
/* Give up or recover. */
if (tries >= SCACHE_MAX_TRIES - 1) {
msg_warn("disabling connection caching");
{
VSTREAM *stream;
int request_status;
+ int count = 0;
/*
* Do client-server plumbing.
for (;;) {
stream = clnt_stream_access(vrfy_clnt);
errno = 0;
+ count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_REQ, VRFY_REQ_QUERY,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
ATTR_TYPE_INT, MAIL_ATTR_ADDR_STATUS, addr_status,
ATTR_TYPE_STR, MAIL_ATTR_WHY, why,
ATTR_TYPE_END) != 3) {
- if (msg_verbose || (errno != EPIPE && errno != ENOENT))
+ if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("problem talking to service %s: %m",
var_verify_service);
} else {
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS) $(LIB_OBJ): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
int skip_reply,
ARGV *macros,...)
{
+ const char *myname = "milter8_event";
va_list ap;
ssize_t data_len;
int err;
#define DONT_SKIP_REPLY 0
+ /*
+ * Sanity check.
+ */
+ if (milter->fp == 0 || milter->def_reply != 0) {
+ msg_warn("%s: attempt to send event %s to milter %s after error",
+ myname,
+ (smfic_name = str_name_code(smfic_table, event)) != 0 ?
+ smfic_name : "(unknown MTA event)", milter->m.name);
+ return (milter->def_reply);
+ }
+
/*
* Skip this event if it doesn't exist in the protocol that I announced.
*/
(ssize_t) index,
STR(milter->buf));
if (edit_resp)
- return (milter8_def_reply(milter, edit_resp));
+ return (edit_resp);
continue;
#endif
STR(milter->buf),
STR(milter->body));
if (edit_resp)
- return (milter8_def_reply(milter, edit_resp));
+ return (edit_resp);
continue;
/*
STR(milter->buf),
STR(milter->body));
if (edit_resp)
- return (milter8_def_reply(milter, edit_resp));
+ return (edit_resp);
continue;
#endif
edit_resp = parent->add_rcpt(parent->chg_context,
STR(milter->buf));
if (edit_resp)
- return (milter8_def_reply(milter, edit_resp));
+ return (edit_resp);
continue;
/*
edit_resp = parent->del_rcpt(parent->chg_context,
STR(milter->buf));
if (edit_resp)
- return (milter8_def_reply(milter, edit_resp));
+ return (edit_resp);
continue;
/*
edit_resp = parent->repl_body(parent->chg_context,
milter->body);
if (edit_resp)
- return (milter8_def_reply(milter, edit_resp));
+ return (edit_resp);
continue;
#endif
}
char *cp;
int skip_reply;
+ /*
+ * XXX Workaround: mime_state_update() may invoke multiple call-backs
+ * before returning to the caller.
+ */
+#define MILTER8_MESSAGE_DONE(milter, msg_ctx) \
+ ((milter)->state != MILTER8_STAT_MESSAGE || (msg_ctx)->resp != 0)
+
+ if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
+ return;
+
/*
* XXX Sendmail compatibility. Don't expose our first (received) header
* to mail filter applications. See also cleanup_milter.c for code to
MILTER_MSG_CONTEXT *msg_ctx = (MILTER_MSG_CONTEXT *) ptr;
MILTER8 *milter = msg_ctx->milter;
+ if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
+ return;
if (msg_verbose)
msg_info("%s: eoh milter %s", myname, milter->m.name);
msg_ctx->resp =
ssize_t space;
ssize_t count;
+ if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
+ return;
+
/*
* XXX Sendmail compatibility: don't expose our first body line.
*/
MILTER_MSG_CONTEXT *msg_ctx = (MILTER_MSG_CONTEXT *) ptr;
MILTER8 *milter = msg_ctx->milter;
+ if (MILTER8_MESSAGE_DONE(milter, msg_ctx))
+ return;
if (msg_verbose)
msg_info("%s: eob milter %s", myname, milter->m.name);
msg_ctx->resp =
msg_ctx.resp = "450 4.3.0 Queue file write error";
break;
}
- if (msg_ctx.resp != 0)
- break;
- if (milter->state != MILTER8_STAT_MESSAGE)
+ if (MILTER8_MESSAGE_DONE(milter, &msg_ctx))
break;
if (rec_type != REC_TYPE_NORM && rec_type != REC_TYPE_CONT)
break;
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
#define FUDGE(x) ((x) * (var_qmgr_fudge / 100.0))
message->refcount--;
if (message->rcpt_offset > 0
- && qmgr_recipient_count < FUDGE(var_qmgr_rcpt_limit))
+ && qmgr_recipient_count < FUDGE(var_qmgr_rcpt_limit) - 100)
qmgr_message_realloc(message);
if (message->refcount == 0)
qmgr_active_done(message);
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
update: ../../bin/$(PROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
update: ../../bin/$(PROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
QMGR_PEER *peer;
QMGR_MESSAGE *message = job->message;
+ /*
+ * Workaround to prevent queue manager starvation until the last slow
+ * batch of multi-recipient mail is finished. Postfix 2.4 has a final
+ * solution, but that involves major changes.
+ */
+ if (message->rcpt_offset != 0
+ && message->rcpt_limit > message->rcpt_count - 100
+ && message->refcount > 0) {
+ qmgr_message_realloc(message);
+ }
if (HAS_ENTRIES(job) && (peer = qmgr_peer_select(job)) != 0)
return (peer);
if (recipient_limit < message->rcpt_limit)
recipient_limit = message->rcpt_limit;
}
+ /* Keep interrupt latency in check. */
+ if (recipient_limit > 5000)
+ recipient_limit = 5000;
if (recipient_limit <= 0)
msg_panic("%s: no recipient slots available", message->queue_id);
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
smtp-sink: smtp-sink.o $(LIBS)
$(CC) $(CFLAGS) -o $@ smtp-sink.o $(LIBS) $(SYSLIBS)
qmqp-source.o: ../../include/vstream.h
qmqp-source.o: ../../include/vstring.h
qmqp-source.o: qmqp-source.c
+smtp-sink.o: ../../include/chroot_uid.h
smtp-sink.o: ../../include/events.h
smtp-sink.o: ../../include/get_hostname.h
smtp-sink.o: ../../include/inet_proto.h
smtp-sink.o: ../../include/iostuff.h
smtp-sink.o: ../../include/listen.h
+smtp-sink.o: ../../include/mail_date.h
+smtp-sink.o: ../../include/make_dirs.h
smtp-sink.o: ../../include/msg.h
smtp-sink.o: ../../include/msg_vstream.h
+smtp-sink.o: ../../include/myaddrinfo.h
smtp-sink.o: ../../include/mymalloc.h
+smtp-sink.o: ../../include/myrand.h
smtp-sink.o: ../../include/sane_accept.h
smtp-sink.o: ../../include/smtp_stream.h
smtp-sink.o: ../../include/stringops.h
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
$(OBJS): ../../conf/makedefs.out
Makefile: Makefile.in
- (cat ../../conf/makedefs.out $?) >$@
+ cat ../../conf/makedefs.out $? >$@
test: $(TESTPROG)
const char **result,
unsigned *len)
{
- const char *myname = "xsasl_cyrus_get_user";
+ const char *myname = "xsasl_cyrus_client_get_user";
XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) context;
if (msg_verbose)
static int xsasl_cyrus_client_get_passwd(sasl_conn_t *conn, void *context,
int id, sasl_secret_t **psecret)
{
- const char *myname = "xsasl_cyrus_get_passwd";
+ const char *myname = "xsasl_cyrus_client_get_passwd";
XSASL_CYRUS_CLIENT *client = (XSASL_CYRUS_CLIENT *) context;
int len;