trivial-rewrite/resolve.c, trivial-rewrite/transport.c,
*qmgr/qmgr_message.c.
- Also: address_verify_sender_dependent_relayhost_maps for completeness.
+ Also: address_verify_sender_dependent_relayhost_maps for
+ completeness.
20051124
- Feature: specify "smtp_sender_dependent_authentication = yes" to
- enable sender-dependent SASL passwords. This disables SMTP
- connection caching to ensure that mail from different senders
- is delivered with the appropriate credentials. This is an
- extended version of a patch by Mathias Hasselmann. Files:
- smtp/smtp_connect.c, smtp/smtp_sasl_glue.c.
+ Feature: specify "smtp_sender_dependent_authentication =
+ yes" to enable sender-dependent SASL passwords. This disables
+ SMTP connection caching to ensure that mail from different
+ senders is delivered with the appropriate credentials. This
+ is an extended version of a patch by Mathias Hasselmann.
+ Files: smtp/smtp_connect.c, smtp/smtp_sasl_glue.c.
20051126
Workaround: log warning when REDIRECT or FILTER are used
in smtpd_end_of_data_restrictions. File: smtpd/smtpd_check.c.
- Log warning when REDIRECT or FILTER are used in
- smtpd_etrn_restrictions. File: smtpd/smtpd_check.c.
+ Log warning when REDIRECT, FILTER, HOLD and DISCARD are
+ used in smtpd_etrn_restrictions. File: smtpd/smtpd_check.c.
20051128
is received. Files: smtpd/smtpd.c, smtpd/smtpd_check.c,
cleanup/cleanup_extracted.c, pickup/pickup.c.
+ Safety: abort if the SMTP or QMQP server runs with non-postfix
+ privileges while it's connected to the network. Files:
+ smtpd/smtpd_peer.c, qmqpd/qmqpd_peer.c.
+
+20051201
+
+ Bugfix: the LMTP client would reuse a session after negative
+ reply to the RSET command (which may happen when client and
+ server somehow get out of sync). Problem found by Christian
+ Theune. Files: lmtp/lmtp.c, lmtp/lmtp_proto.c.
+
+20051202
+
+ Bugfix: the 20051128 code move for "smtpd_end_of_data_restrictions"
+ broke "postsuper -r".
+
Open problems:
"postsuper -r" no longer resets the message arrival time,
* The Postfix smtp(8) client reuses a session for only a limited number of
times. This avoids triggering bugs in implementations that do not correctly
- handle multiple deliveries per session. The use count is limited with the
- smtp_connection_cache_reuse_limit configuration parameter.
+ handle multiple deliveries per session.
+
+ With Postfix 2.2 the use count is limited with the
+ smtp_connection_cache_reuse_limit configuration parameter. With Postfix 2.3
+ this is replaced by a time limit which is specified with the
+ smtp_connection_reuse_time_limit parameter. In addition, Postfix 2.3 logs
+ the use count of multiply-used connections, as shown in the following
+ example:
+
+ Nov 3 16:04:31 myname postfix/smtp[30840]: 19B6B2900FE:
+ to=<wietse@test.example.com>, orig_to=<wietse@test>,
+ relay=mail.example.com[1.2.3.4], c\bco\bon\bnn\bn_\b_u\bus\bse\be=\b=2\b2, delay=0.22,
+ delays=0.04/0.01/0.05/0.1, dsn=2.0.0, status=sent (250 2.0.0 Ok)
* The connection cache explicitly labels each cached connection with
destination domain and IP address information. A connection cache lookup
smtpd.conf (SASL version 2.1.1) you need to specify how the server should
validate client passwords.
+Note: some Postfix distributions are modified and look for the smtpd.conf file
+in /etc/postfix.
+
+Note: some Cyrus SASL distributions are modified and look for the smtpd.conf
+file in /etc/sasl2.
+
In order to authenticate against the UNIX password database, try:
(SASL version 1.5.5)
* The "-o smtpd_proxy_filter=127.0.0.1:10025" tells the before filter SMTP
server that it should give incoming mail to the content filter that listens
- on localhost port 10025.
+ on localhost TCP port 10025.
+
+ * Postfix 2.3 supports both TCP and UNIX-domain filters. The above filter
+ could be specified as "inet:127.0.0.1:10025". To specify a UNIX-domain
+ filter, specify "unix:pathame". A relative pathname is interpreted relative
+ to the Postfix queue directory.
The after-filter SMTP server is a new master.cf entry:
If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
before proceeding.
+Incompatibility with snapshot 20051202
+======================================
+
+The Postfix SMTP daemon will not receive mail from the network if
+it isn't running with postfix mail_owner privileges. This prevents
+surprises when, for example, "sendmail -bs" is configured to run
+as root from xinetd.
+
Incompatibility with snapshot 20051125
======================================
<ul>
-<li> <p> if mail is sent without a relay host: a domain name (the
+<li> <p> if mail is sent without a <a href="postconf.5.html#relayhost">relay host</a>: a domain name (the
right-hand side of an email address, without the [] around a numeric
IP address), </p>
-<li> <p> if mail is sent via a relay host: a relay host name (without
+<li> <p> if mail is sent via a <a href="postconf.5.html#relayhost">relay host</a>: a <a href="postconf.5.html#relayhost">relay host</a> name (without
the [] or non-default TCP port), as specified in main.cf or in the
transport map, </p>
-<li> <p> a /file/name with domain names and/or relay host names as
+<li> <p> a /file/name with domain names and/or <a href="postconf.5.html#relayhost">relay host</a> names as
defined above, </p>
-<li> <p> a "<a href="DATABASE_README.html">type:table</a>" with domain names and/or relay host names
+<li> <p> a "<a href="DATABASE_README.html">type:table</a>" with domain names and/or <a href="postconf.5.html#relayhost">relay host</a> names
on the left-hand side. The right-hand side result from "<a href="DATABASE_README.html">type:table</a>"
lookups is ignored. </p>
<li> <p> The Postfix <a href="smtp.8.html">smtp(8)</a> client reuses a session for only a
limited number of times. This avoids triggering bugs in implementations
-that do not correctly handle multiple deliveries per session. The
-use count is limited with the <a href="postconf.5.html#smtp_connection_cache_reuse_limit">smtp_connection_cache_reuse_limit</a>
-configuration parameter. </p>
+that do not correctly handle multiple deliveries per session. </p>
+
+<p> With Postfix 2.2 the use count is limited with the
+<a href="postconf.5.html#smtp_connection_cache_reuse_limit">smtp_connection_cache_reuse_limit</a> configuration parameter. With
+Postfix 2.3 this is replaced by a time limit which is specified
+with the <a href="postconf.5.html#smtp_connection_reuse_time_limit">smtp_connection_reuse_time_limit</a> parameter. In addition,
+Postfix 2.3 logs the use count of multiply-used connections,
+as shown in the following example: </p>
+
+<blockquote>
+<pre>
+Nov 3 16:04:31 myname postfix/smtp[30840]: 19B6B2900FE:
+to=<wietse@test.example.com>, orig_to=<wietse@test>,
+relay=mail.example.com[1.2.3.4], <b>conn_use=2</b>, delay=0.22,
+delays=0.04/0.01/0.05/0.1, dsn=2.0.0, status=sent (250 2.0.0 Ok)
+</pre>
+</blockquote>
<li> <p> The connection cache explicitly labels each cached connection
with destination domain and IP address information. A connection
/usr/local/lib/sasl2/smtpd.conf (SASL version 2.1.1) you need to
specify how the server should validate client passwords. </p>
+<p> Note: some Postfix distributions are modified and look for
+the smtpd.conf file in /etc/postfix. </p>
+
+<p> Note: some Cyrus SASL distributions are modified and look for
+the smtpd.conf file in /etc/sasl2. </p>
+
<p> In order to authenticate against the UNIX password database, try: </p>
<dl>
<li> <p> The "-o <a href="postconf.5.html#smtpd_client_connection_count_limit">smtpd_client_connection_count_limit</a>=10" prevents
one SMTP client from using up all 20 SMTP server processes.
This limit is not necessary if you receive all mail from a
- trusted relay host. </p>
+ trusted <a href="postconf.5.html#relayhost">relay host</a>. </p>
<p> Note: this setting is ignored by the stable Postfix 2.1
release. The feature will be available only in the experimental
<li> <p> The "-o <a href="postconf.5.html#smtpd_proxy_filter">smtpd_proxy_filter</a>=127.0.0.1:10025" tells the
before filter SMTP server that it should give incoming mail to
- the content filter that listens on localhost port 10025. </p>
+ the content filter that listens on localhost TCP port 10025.
+
+ <li> <p> Postfix 2.3 supports both TCP and UNIX-domain filters.
+ The above filter could be specified as "inet:127.0.0.1:10025".
+ To specify a UNIX-domain filter, specify "unix:<i>pathame</i>".
+ A relative pathname is interpreted relative to the Postfix queue
+ directory. </p>
</ul>
s/^'"$B"' *//
s/^ //
s/^[ ]*$//
+ /^\\"/d
' $i
done | expand
<li> <p> The Postfix smtp(8) client reuses a session for only a
limited number of times. This avoids triggering bugs in implementations
-that do not correctly handle multiple deliveries per session. The
-use count is limited with the smtp_connection_cache_reuse_limit
-configuration parameter. </p>
+that do not correctly handle multiple deliveries per session. </p>
+
+<p> With Postfix 2.2 the use count is limited with the
+smtp_connection_cache_reuse_limit configuration parameter. With
+Postfix 2.3 this is replaced by a time limit which is specified
+with the smtp_connection_reuse_time_limit parameter. In addition,
+Postfix 2.3 logs the use count of multiply-used connections,
+as shown in the following example: </p>
+
+<blockquote>
+<pre>
+Nov 3 16:04:31 myname postfix/smtp[30840]: 19B6B2900FE:
+to=<wietse@test.example.com>, orig_to=<wietse@test>,
+relay=mail.example.com[1.2.3.4], <b>conn_use=2</b>, delay=0.22,
+delays=0.04/0.01/0.05/0.1, dsn=2.0.0, status=sent (250 2.0.0 Ok)
+</pre>
+</blockquote>
<li> <p> The connection cache explicitly labels each cached connection
with destination domain and IP address information. A connection
/usr/local/lib/sasl2/smtpd.conf (SASL version 2.1.1) you need to
specify how the server should validate client passwords. </p>
+<p> Note: some Postfix distributions are modified and look for
+the smtpd.conf file in /etc/postfix. </p>
+
+<p> Note: some Cyrus SASL distributions are modified and look for
+the smtpd.conf file in /etc/sasl2. </p>
+
<p> In order to authenticate against the UNIX password database, try: </p>
<dl>
<li> <p> The "-o smtpd_proxy_filter=127.0.0.1:10025" tells the
before filter SMTP server that it should give incoming mail to
- the content filter that listens on localhost port 10025. </p>
+ the content filter that listens on localhost TCP port 10025.
+
+ <li> <p> Postfix 2.3 supports both TCP and UNIX-domain filters.
+ The above filter could be specified as "inet:127.0.0.1:10025".
+ To specify a UNIX-domain filter, specify "unix:<i>pathame</i>".
+ A relative pathname is interpreted relative to the Postfix queue
+ directory. </p>
</ul>
# REJECT ACTIONS
# .ad
# .fi
-# Postfix version 2.3 and later support enhanced status codes.
-# When no code is specified at the beginning of the \fItext\fR
-# below, Postfix inserts a default enhanced status code of "5.7.1"
-# in the case of reject actions, and "4.7.1" in the case of
-# defer actions. See "ENHANCED STATUS CODES" below.
+# Postfix version 2.3 and later support enhanced status codes.
+# When no code is specified at the beginning of the \fItext\fR
+# below, Postfix inserts a default enhanced status code of "5.7.1"
+# in the case of reject actions, and "4.7.1" in the case of
+# defer actions. See "ENHANCED STATUS CODES" below.
# .IP "\fB4\fINN text\fR"
# .IP "\fB5\fINN text\fR"
# Reject the address etc. that matches the pattern, and respond with
# .IP \fIrestriction...\fR
# Apply the named UCE restriction(s) (\fBpermit\fR, \fBreject\fR,
# \fBreject_unauth_destination\fR, and so on).
+# \" .IP "\fBDELAY \fItime\fR"
+# \" Place the message into the deferred queue, and delay the
+# \" initial delivery attempt by \fItime\fR. The time value may
+# \" be followed by a one-character suffix that specifies the
+# \" time unit: s (seconds), m (minutes), h (hours), d (days),
+# \" w (weeks). The default time unit is s (seconds).
+# \" .sp
+# \" Limitations:
+# \" .RS
+# \" .IP \(bu
+# \" This action affects all the recipients of the message.
+# \" .IP \(bu
+# \" The delay value has no effect with remote file systems that
+# \" don't correctly emulate UNIX local file system semantics.
+# \" In that case, the delay will be half of $queue_run_delay
+# \" on average.
+# \" .IP \(bu
+# \" Mail will still be delivered with "sendmail -q", "postfix
+# \" flush" or "postqueue -f".
+# \" .IP \(bu
+# \" Delayed mail increases the amount of disk I/O during deferred
+# \" queue scans. When large amounts of mail are queued for
+# \" delayed delivery it may be preferable to use the HOLD feature
+# \" instead.
+# \" .RE
+# \" .IP
+# \" This feature is available in Postfix 2.3 and later.
# .IP "\fBDISCARD \fIoptional text...\fR
# Claim successful delivery and silently discard the message.
# Log the optional text if specified, otherwise log a generic
# .fi
# Action names are case insensitive. They are shown in upper case
# for consistency with other Postfix documentation.
+# \" .IP "\fBDELAY \fItime\fR"
+# \" Place the message into the deferred queue, and delay the
+# \" initial delivery attempt by \fItime\fR. The time value may
+# \" be followed by a one-character suffix that specifies the
+# \" time unit: s (seconds), m (minutes), h (hours), d (days),
+# \" w (weeks). The default time unit is s (seconds).
+# \" .sp
+# \" Limitations:
+# \" .RS
+# \" .IP \(bu
+# \" This action affects all the recipients of the message.
+# \" .IP \(bu
+# \" The delay value has no effect with remote file systems that
+# \" don't correctly emulate UNIX local file system semantics.
+# \" In that case, the delay will be half of $queue_run_delay
+# \" on average.
+# \" .IP \(bu
+# \" Mail will still be delivered with "sendmail -q", "postfix
+# \" flush" or "postqueue -f".
+# \" .IP \(bu
+# \" Delayed mail increases the amount of disk I/O during deferred
+# \" queue scans. When large amounts of mail are queued for
+# \" delayed delivery it may be preferable to use the HOLD feature
+# \" instead.
+# \" .RE
+# \" .IP
+# \" This feature is available in Postfix 2.3 and later.
# .IP "\fBDISCARD \fIoptional text...\fR"
# Claim successful delivery and silently discard the message.
# Log the optional text if specified, otherwise log a generic
cleanup_message.o: ../../include/attr.h
cleanup_message.o: ../../include/been_here.h
cleanup_message.o: ../../include/cleanup_user.h
+cleanup_message.o: ../../include/conv_time.h
cleanup_message.o: ../../include/dict.h
cleanup_message.o: ../../include/dsn_util.h
cleanup_message.o: ../../include/ext_prop.h
int dsn_notify; /* DSN never/delay/fail/success */
char *dsn_orcpt; /* DSN original recipient */
char *verp_delims; /* VERP delimiters (optional) */
+#ifdef DELAY_ACTION
+ int defer_delay; /* deferred delivery */
+#endif
} CLEANUP_STATE;
/*
* reporting purposes.
*/
if (state->errs == 0 && (state->flags & CLEANUP_FLAG_DISCARD) == 0) {
- if ((state->flags & CLEANUP_FLAG_HOLD) != 0) {
+ if ((state->flags & CLEANUP_FLAG_HOLD) != 0
+#ifdef DELAY_ACTION
+ || state->defer_delay > 0
+#endif
+ ) {
myfree(state->queue_name);
+#ifdef DELAY_ACTION
+ state->queue_name = mystrdup((state->flags & CLEANUP_FLAG_HOLD) ?
+ MAIL_QUEUE_HOLD : MAIL_QUEUE_DEFERRED);
+#else
state->queue_name = mystrdup(MAIL_QUEUE_HOLD);
+#endif
mail_stream_ctl(state->handle,
- MAIL_STREAM_CTL_QUEUE, MAIL_QUEUE_HOLD,
+ MAIL_STREAM_CTL_QUEUE, state->queue_name,
MAIL_STREAM_CTL_CLASS, 0,
MAIL_STREAM_CTL_SERVICE, 0,
+#ifdef DELAY_ACTION
+ MAIL_STREAM_CTL_DELAY, state->defer_delay,
+#endif
MAIL_STREAM_CTL_END);
junk = cleanup_path;
cleanup_path = mystrdup(VSTREAM_PATH(state->handle->stream));
int mapped_type = type;
const char *mapped_buf = buf;
+#ifdef DELAY_ACTION
+ int defer_delay;
+
+#endif
+
if (msg_verbose)
msg_info("initial envelope %c %.*s", type, (int) len, buf);
return;
}
+#ifdef DELAY_ACTION
+ if (type == REC_TYPE_DELAY) {
+ /* Not part of queue file format. */
+ defer_delay = atoi(buf);
+ if (defer_delay <= 0)
+ msg_warn("%s: ignoring bad delay time: %s", state->queue_id, buf);
+ else
+ state->defer_delay = defer_delay;
+ return;
+ }
+#endif
+
/*
* Map DSN attribute name to pseudo record type so that we don't have to
* pollute the queue file with records that are incompatible with past
int extra_opts;
int junk;
+#ifdef DELAY_ACTION
+ int defer_delay;
+
+#endif
+
if (msg_verbose)
msg_info("extracted envelope %c %.*s", type, (int) len, buf);
return;
}
+#ifdef DELAY_ACTION
+ if (type == REC_TYPE_DELAY) {
+ /* Not part of queue file format. */
+ defer_delay = atoi(buf);
+ if (defer_delay <= 0)
+ msg_warn("%s: ignoring bad delay time: %s", state->queue_id, buf);
+ else
+ state->defer_delay = defer_delay;
+ return;
+ }
+#endif
+
if (strchr(REC_TYPE_EXTRACT, type) == 0) {
msg_warn("%s: message rejected: "
"unexpected record type %d in extracted envelope",
#include <mime_state.h>
#include <lex_822.h>
#include <dsn_util.h>
+#include <conv_time.h>
/* Application-specific. */
const char *optional_text = value + strcspn(value, " \t");
int command_len = optional_text - value;
+#ifdef DELAY_ACTION
+ int defer_delay;
+
+#endif
+
while (*optional_text && ISSPACE(*optional_text))
optional_text++;
return (buf);
}
if (STREQUAL(value, "HOLD", command_len)) {
- if ((state->flags & CLEANUP_FLAG_HOLD) == 0) {
+ if ((state->flags & (CLEANUP_FLAG_HOLD | CLEANUP_FLAG_DISCARD)) == 0) {
cleanup_act_log(state, "hold", context, buf, optional_text);
state->flags |= CLEANUP_FLAG_HOLD;
}
return (buf);
}
+
+ /*
+ * The DELAY feature is disabled because it has too many problems. 1) It
+ * does not work on some remote file systems; 2) mail will be delivered
+ * anyway with "sendmail -q" etc.; 3) while the mail is queued it bogs
+ * down the deferred queue scan with huge amounts of useless disk I/O
+ * operations.
+ */
+#ifdef DELAY_ACTION
+ if (STREQUAL(value, "DELAY", command_len)) {
+ if ((state->flags & (CLEANUP_FLAG_HOLD | CLEANUP_FLAG_DISCARD)) == 0) {
+ if (*optional_text == 0) {
+ msg_warn("missing DELAY argument in %s map", map_class);
+ } else if (conv_time(optional_text, &defer_delay, 's') == 0) {
+ msg_warn("ignoring bad DELAY argument %s in %s map",
+ optional_text, map_class);
+ } else {
+ cleanup_act_log(state, "delay", context, buf, optional_text);
+ state->defer_delay = defer_delay;
+ }
+ }
+ return (buf);
+ }
+#endif
if (STREQUAL(value, "PREPEND", command_len)) {
if (*optional_text == 0) {
msg_warn("PREPEND action without text in %s map", map_class);
/*
* XXX 2821: Appendix B: The return address in the MAIL command SHOULD,
* if possible, be derived from the system's identity for the submitting
- * (local) user, and the "From:" header field otherwise. If there is a
+ * (local) user, and the "From:" header field otherwise. If there is a
* system identity available, it SHOULD also be copied to the Sender
* header field if it is different from the address in the From header
* field. (Any Sender field that was already there SHOULD be removed.)
ehlo_mask.c \
wildcard_inet_addr.c valid_mailhost_addr.c dsn_util.c dsn_mask.c \
dsn_attr_map.c dsn.c dsn_buf.c rcpt_buf.c rcpt_print.c dsn_print.c \
- dsb_scan.c mail_conf_long.c msg_stats_print.c msg_stats_scan.c
+ dsb_scan.c mail_conf_long.c msg_stats_print.c msg_stats_scan.c \
+ conv_time.c
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
clnt_stream.o debug_peer.o debug_process.o defer.o db_common.o \
ehlo_mask.o \
wildcard_inet_addr.o valid_mailhost_addr.o dsn_util.o dsn_mask.o \
dsn_attr_map.o dsn.o dsn_buf.o rcpt_buf.o rcpt_print.o dsn_print.o \
- dsb_scan.o mail_conf_long.o msg_stats_print.o msg_stats_scan.o
+ dsb_scan.o mail_conf_long.o msg_stats_print.o msg_stats_scan.o \
+ conv_time.o
HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
debug_peer.h debug_process.h defer.h deliver_completed.h \
xtext.h scache.h user_acl.h ehlo_mask.h db_common.h \
wildcard_inet_addr.h valid_mailhost_addr.h dsn_util.h dsn_mask.h \
dsn_attr_map.h dsn.h dsn_buf.h rcpt_buf.h rcpt_print.h dsn_print.h \
- dsb_scan.h msg_stats.h
+ dsb_scan.h msg_stats.h conv_time.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
clnt_stream.o: clnt_stream.h
clnt_stream.o: mail_params.h
clnt_stream.o: mail_proto.h
+conv_time.o: ../../include/msg.h
+conv_time.o: ../../include/sys_defs.h
+conv_time.o: conv_time.c
+conv_time.o: conv_time.h
db_common.o: ../../include/argv.h
db_common.o: ../../include/dict.h
db_common.o: ../../include/match_list.h
deliver_request.o: mail_queue.h
deliver_request.o: msg_stats.h
deliver_request.o: recipient_list.h
+dict_ldap.o: ../../include/argv.h
+dict_ldap.o: ../../include/binhash.h
+dict_ldap.o: ../../include/dict.h
+dict_ldap.o: ../../include/match_list.h
+dict_ldap.o: ../../include/match_ops.h
+dict_ldap.o: ../../include/msg.h
+dict_ldap.o: ../../include/mymalloc.h
+dict_ldap.o: ../../include/stringops.h
dict_ldap.o: ../../include/sys_defs.h
+dict_ldap.o: ../../include/vbuf.h
+dict_ldap.o: ../../include/vstream.h
+dict_ldap.o: ../../include/vstring.h
+dict_ldap.o: cfg_parser.h
+dict_ldap.o: db_common.h
dict_ldap.o: dict_ldap.c
+dict_ldap.o: dict_ldap.h
+dict_ldap.o: string_list.h
+dict_mysql.o: ../../include/argv.h
+dict_mysql.o: ../../include/dict.h
+dict_mysql.o: ../../include/events.h
+dict_mysql.o: ../../include/find_inet.h
+dict_mysql.o: ../../include/match_list.h
+dict_mysql.o: ../../include/match_ops.h
+dict_mysql.o: ../../include/msg.h
+dict_mysql.o: ../../include/mymalloc.h
+dict_mysql.o: ../../include/myrand.h
+dict_mysql.o: ../../include/split_at.h
dict_mysql.o: ../../include/sys_defs.h
+dict_mysql.o: ../../include/vbuf.h
+dict_mysql.o: ../../include/vstream.h
+dict_mysql.o: ../../include/vstring.h
+dict_mysql.o: cfg_parser.h
+dict_mysql.o: db_common.h
dict_mysql.o: dict_mysql.c
+dict_mysql.o: dict_mysql.h
+dict_mysql.o: string_list.h
+dict_pgsql.o: ../../include/argv.h
+dict_pgsql.o: ../../include/dict.h
+dict_pgsql.o: ../../include/events.h
+dict_pgsql.o: ../../include/find_inet.h
+dict_pgsql.o: ../../include/match_list.h
+dict_pgsql.o: ../../include/match_ops.h
+dict_pgsql.o: ../../include/msg.h
+dict_pgsql.o: ../../include/mymalloc.h
+dict_pgsql.o: ../../include/myrand.h
+dict_pgsql.o: ../../include/split_at.h
dict_pgsql.o: ../../include/sys_defs.h
+dict_pgsql.o: ../../include/vbuf.h
+dict_pgsql.o: ../../include/vstream.h
+dict_pgsql.o: ../../include/vstring.h
+dict_pgsql.o: cfg_parser.h
+dict_pgsql.o: db_common.h
dict_pgsql.o: dict_pgsql.c
+dict_pgsql.o: dict_pgsql.h
+dict_pgsql.o: string_list.h
dict_proxy.o: ../../include/argv.h
dict_proxy.o: ../../include/attr.h
dict_proxy.o: ../../include/dict.h
mail_conf_time.o: ../../include/vbuf.h
mail_conf_time.o: ../../include/vstream.h
mail_conf_time.o: ../../include/vstring.h
+mail_conf_time.o: conv_time.h
mail_conf_time.o: mail_conf.h
mail_conf_time.o: mail_conf_time.c
mail_connect.o: ../../include/attr.h
--- /dev/null
+/*++
+/* NAME
+/* conv_time 3
+/* SUMMARY
+/* time value conversion
+/* SYNOPSIS
+/* #include <conv_time.h>
+/*
+/* int conv_time(strval, intval, def_unit);
+/* const char *strval;
+/* int *intval;
+/* int def_unit;
+/* DESCRIPTION
+/* conv_time() converts a numerical time value with optional
+/* one-letter suffix that specifies an explicit time unit: s
+/* (seconds), m (minutes), h (hours), d (days) or w (weeks).
+/* Internally, time is represented in seconds.
+/*
+/* Arguments:
+/* .IP strval
+/* Input value.
+/* .IP intval
+/* Result pointer.
+/* .IP def_unit
+/* The default time unit suffix character.
+/* DIAGNOSTICS
+/* The result value is non-zero in case of success, zero in
+/* case of a bad time value or a bad time unit suffix.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <stdio.h> /* sscanf() */
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* Global library. */
+
+#include <conv_time.h>
+
+#define MINUTE (60)
+#define HOUR (60 * MINUTE)
+#define DAY (24 * HOUR)
+#define WEEK (7 * DAY)
+
+/* conv_time - convert time value */
+
+int conv_time(const char *strval, int *intval, int def_unit)
+{
+ char unit;
+ char junk;
+
+ switch (sscanf(strval, "%d%c%c", intval, &unit, &junk)) {
+ case 1:
+ unit = def_unit;
+ case 2:
+ switch (unit) {
+ case 'w':
+ *intval *= WEEK;
+ return (1);
+ case 'd':
+ *intval *= DAY;
+ return (1);
+ case 'h':
+ *intval *= HOUR;
+ return (1);
+ case 'm':
+ *intval *= MINUTE;
+ return (1);
+ case 's':
+ return (1);
+ }
+ }
+ return (0);
+}
--- /dev/null
+#ifndef _CONV_TIME_INCLUDED_
+#define _CONV_TIME_INCLUDED_
+
+/*++
+/* NAME
+/* conv_time 3h
+/* SUMMARY
+/* time value conversion
+/* SYNOPSIS
+/* #include <conv_time.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * External interface.
+ */
+extern int conv_time(const char *, int *, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
/* Global library. */
+#include "conv_time.h"
#include "mail_conf.h"
-#define MINUTE (60)
-#define HOUR (60 * MINUTE)
-#define DAY (24 * HOUR)
-#define WEEK (7 * DAY)
-
/* convert_mail_conf_time - look up and convert integer parameter value */
static int convert_mail_conf_time(const char *name, int *intval, int def_unit)
{
const char *strval;
- char unit;
- char junk;
if ((strval = mail_conf_lookup_eval(name)) == 0)
return (0);
-
- switch (sscanf(strval, "%d%c%c", intval, &unit, &junk)) {
- case 1:
- unit = def_unit;
- case 2:
- switch (unit) {
- case 'w':
- *intval *= WEEK;
- return (1);
- case 'd':
- *intval *= DAY;
- return (1);
- case 'h':
- *intval *= HOUR;
- return (1);
- case 'm':
- *intval *= MINUTE;
- return (1);
- case 's':
- return (1);
- }
- }
- msg_fatal("parameter %s: bad time unit: %s", name, strval);
+ if (conv_time(strval, intval, def_unit) == 0)
+ msg_fatal("parameter %s: bad time unit: %s", name, strval);
+ return (1);
}
/* check_mail_conf_time - validate integer value */
/* .IP "MAIL_STREAM_CTL_MODE (int)"
/* The argument specifies alternate permissions that override
/* the permissions specified with mail_stream_file().
+/* .IP "MAIL_STREAM_CTL_DELAY (int)"
+/* Attempt to postpone initial delivery by advancing the queue
+/* file modification time stamp by this amount. This has
+/* effect only within the deferred mail queue.
+/* This feature may have no effect with remote file systems.
/* LICENSE
/* .ad
/* .fi
* This clock drift detection code may not work with file systems that work
* on a local copy of the file and that update the server only after the
* file is closed.
+ *
+ * Optionally set a cooldown time.
+ *
+ * XXX: We assume that utime() does control the file modification time even
+ * when followed by an fchmod(), fsync(), close() sequence. This may fail
+ * with remote file systems when fsync() actually updates the file. Even
+ * then, we still delay the average message by 1/2 of the
+ * queue_run_delay.
+ *
+ * XXX: Victor does not like running utime() after the close(), since this
+ * creates a race even with local filesystems. But Wietse is not
+ * confident that utime() before fsync() and close() will work reliably
+ * with remote file systems.
*/
check_incoming_fs_clock =
(!incoming_fs_clock_ok && !strcmp(info->queue, MAIL_QUEUE_INCOMING));
+#ifdef DELAY_ACTION
+ if (strcmp(info->queue, MAIL_QUEUE_DEFERRED) != 0)
+ info->delay = 0;
+ if (info->delay > 0)
+ tbuf.actime = tbuf.modtime = time(&now) + info->delay;
+#endif
+
if (vstream_fflush(info->stream)
+#ifdef DELAY_ACTION
+ || (info->delay > 0 && utime(VSTREAM_PATH(info->stream), &tbuf))
+#endif
|| fchmod(vstream_fileno(info->stream), 0700 | info->mode)
#ifdef HAS_FSYNC
|| fsync(vstream_fileno(info->stream))
info->class = mystrdup(class);
info->service = mystrdup(service);
info->mode = mode;
+#ifdef DELAY_ACTION
+ info->delay = 0;
+#endif
info->ctime = tv;
return (info);
}
info->mode = va_arg(ap, int);
break;
+ /*
+ * Advance the (finished) file modification time.
+ */
+#ifdef DELAY_ACTION
+ case MAIL_STREAM_CTL_DELAY:
+ if ((info->delay = va_arg(ap, int)) < 0)
+ msg_panic("%s: bad delay time %d", myname, info->delay);
+ break;
+#endif
+
default:
msg_panic("%s: bad op code %d", myname, op);
}
char *class; /* trigger class */
char *service; /* trigger service */
int mode; /* additional permissions */
+#ifdef DELAY_ACTION
+ int delay; /* deferred delivery */
+#endif
struct timeval ctime; /* creation time */
};
#define MAIL_STREAM_CTL_CLASS 2 /* Change notification class */
#define MAIL_STREAM_CTL_SERVICE 3 /* Change notification service */
#define MAIL_STREAM_CTL_MODE 4 /* Change final queue file mode */
+#ifdef DELAY_ACTION
+#define MAIL_STREAM_CTL_DELAY 5 /* Change final queue file mtime */
+#endif
extern MAIL_STREAM *mail_stream_file(const char *, const char *, const char *, int);
extern MAIL_STREAM *mail_stream_service(const char *, const char *);
extern MAIL_STREAM *mail_stream_command(const char *);
extern void mail_stream_cleanup(MAIL_STREAM *);
extern int mail_stream_finish(MAIL_STREAM *, VSTRING *);
-extern void mail_stream_ctl(MAIL_STREAM *, int, ...);
+extern void mail_stream_ctl(MAIL_STREAM *, int,...);
/* LICENSE
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20051128"
+#define MAIL_RELEASE_DATE "20051202"
#define MAIL_VERSION_NUMBER "2.3"
#ifdef SNAPSHOT
#define REC_TYPE_RDR '>' /* redirect target */
#define REC_TYPE_FLGS 'f' /* cleanup processing flags */
+#define REC_TYPE_DELAY 'd' /* cleanup delay upon arrival */
#define REC_TYPE_MESG 'M' /* start message records */
* Disconnect if RSET can't be sent over an existing connection.
* Discard transcript and status information for sending RSET.
*/
- else if (lmtp_rset(state) != 0) {
+ else if (lmtp_rset(state) != 0
+ || (state->features & LMTP_FEATURE_RSET_REJECTED) != 0) {
lmtp_chat_reset(state);
state->session = lmtp_session_free(state->session);
#ifdef USE_SASL_AUTH
#define LMTP_FEATURE_XFORWARD_HELO (1<<9)
#define LMTP_FEATURE_XFORWARD_DOMAIN (1<<10)
#define LMTP_FEATURE_DSN (1<<11)
+#define LMTP_FEATURE_RSET_REJECTED (1<<12)
/*
* lmtp.c
*/
state->error_mask |= MAIL_ERROR_PROTOCOL;
if (state->features & LMTP_FEATURE_PIPELINING) {
- msg_warn("non-SMTP response from %s: %s",
+ msg_warn("non-LMTP response from %s: %.100s",
session->namaddr, STR(state->buffer));
vstream_longjmp(session->stream, SMTP_ERR_PROTO);
}
/* accordingly.
/*
/* lmtp_rset() sends a lone RSET command and waits for the response.
+/* In case of a negative reply it sets the CANT_RSET_THIS_SESSION flag.
/*
/* lmtp_quit() sends a lone QUIT command and waits for the response
/* only if waiting for QUIT replies is enabled.
#define SENDING_MAIL \
(recv_state <= LMTP_STATE_DOT)
+#define CANT_RSET_THIS_SESSION \
+ (state->features |= LMTP_FEATURE_RSET_REJECTED)
+
/*
* Pipelining support requires two loops: one loop for sending and one
* for receiving. Each loop has its own independent state. Most of the
* Ignore the RSET response.
*/
case LMTP_STATE_RSET:
+ if (resp->code / 100 != 2)
+ CANT_RSET_THIS_SESSION;
recv_state = LMTP_STATE_LAST;
break;
int time_seen = 0;
char *attr_name;
char *attr_value;
+ char *saved_attr;
+ int skip_attr;
/*
* Limit the input record size. All front-end programs should protect the
if (type == REC_TYPE_ERTO)
/* Discard errors-to record after "postsuper -r". */
continue;
- if (type == REC_TYPE_ATTR
- && split_nameval(vstring_str(buf),
- &attr_name, &attr_value) == 0
- && dsn_attr_map(attr_name) == 0)
+ if (type == REC_TYPE_ATTR) {
+ saved_attr = mystrdup(vstring_str(buf));
+ skip_attr = (split_nameval(saved_attr,
+ &attr_name, &attr_value) == 0
+ && dsn_attr_map(attr_name) == 0);
+ myfree(saved_attr);
/* Discard other/header/body action after "postsuper -r". */
- continue;
+ if (skip_attr)
+ continue;
+ }
}
/*
#include <mail_proto.h>
#include <valid_mailhost_addr.h>
+#include <mail_params.h>
/* Application-specific. */
int aierr;
char *colonp;
+ /*
+ * Sorry, but there are some things that we just cannot do while
+ * connected to the network.
+ */
+ if (geteuid() != var_owner_uid || getuid() != var_owner_uid) {
+ msg_error("incorrect QMQP server privileges: uid=%lu euid=%lu",
+ (unsigned long) getuid(), (unsigned long) geteuid());
+ msg_fatal("the Postfix QMQP server must run with $%s privileges",
+ VAR_MAIL_OWNER);
+ }
+
/*
* Convert the client address to printable form.
*/
smtpd_check.o: ../../include/attr.h
smtpd_check.o: ../../include/attr_clnt.h
smtpd_check.o: ../../include/cleanup_user.h
+smtpd_check.o: ../../include/conv_time.h
smtpd_check.o: ../../include/ctable.h
smtpd_check.o: ../../include/deliver_request.h
smtpd_check.o: ../../include/dict.h
state->saved_redirect = 0;
}
state->saved_flags = 0;
+#ifdef DELAY_ACTION
+ state->saved_delay = 0;
+#endif
#ifdef USE_SASL_AUTH
if (var_smtpd_sasl_enable)
smtpd_sasl_mail_reset(state);
if (state->saved_flags)
rec_fprintf(state->cleanup, REC_TYPE_FLGS, "%d",
state->saved_flags);
+#ifdef DELAY_ACTION
+ if (state->saved_delay)
+ rec_fprintf(state->cleanup, REC_TYPE_DELAY, "%d",
+ state->saved_delay);
+#endif
if (vstream_ferror(state->cleanup))
state->err = CLEANUP_STAT_WRITE;
}
char *saved_filter; /* postponed filter action */
char *saved_redirect; /* postponed redirect action */
int saved_flags; /* postponed hold/discard */
+#ifdef DELAY_ACTION
+ int saved_delay; /* postponed deferred delay */
+#endif
VSTRING *expand_buf; /* scratch space for $name expansion */
ARGV *prepend; /* prepended headers */
VSTRING *instance; /* policy query correlation */
#include <rewrite_clnt.h>
#include <valid_mailhost_addr.h>
#include <dsn_util.h>
+#include <conv_time.h>
/* Application-specific. */
static char def_dsn[] = "5.7.1";
DSN_SPLIT dp;
+#ifdef DELAY_ACTION
+ int defer_delay;
+
+#endif
+
/*
* Parse into command and text. Do not change the input.
*/
return (SMTPD_CHECK_DUNNO);
}
+ /*
+ * DELAY means deliver later. But we may still change our mind, and
+ * reject/discard the message for other reasons.
+ *
+ * This feature is deleted because it has too many problems. 1) It does not
+ * work on some remote file systems; 2) mail will be delivered anyway
+ * with "sendmail -q" etc.; 3) while the mail is queued it bogs down the
+ * deferred queue scan with huge amounts of useless disk I/O operations.
+ */
+#ifdef DELAY_ACTION
+ if (STREQUAL(value, "DELAY", cmd_len)) {
+#ifndef TEST
+ if (can_delegate_action(state, table, "DELAY", reply_class) == 0)
+ return (SMTPD_CHECK_DUNNO);
+#endif
+ if (*cmd_text == 0) {
+ msg_warn("access table %s entry \"%s\" has DELAY entry without value",
+ table, datum);
+ return (SMTPD_CHECK_DUNNO);
+ }
+ if (conv_time(cmd_text, &defer_delay, 's') == 0) {
+ msg_warn("access table %s entry \"%s\" has invalid DELAY argument \"%s\"",
+ table, datum, cmd_text);
+ return (SMTPD_CHECK_DUNNO);
+ }
+ vstring_sprintf(error_text, "<%s>: %s %s", reply_name, reply_class,
+ *cmd_text ? cmd_text : "triggers DELAY action");
+ log_whatsup(state, "delay", STR(error_text));
+#ifndef TEST
+ state->saved_delay = defer_delay;
+#endif
+ return (SMTPD_CHECK_DUNNO);
+ }
+#endif
+
/*
* DISCARD means silently discard and claim successful delivery.
*/
static int reject_unauth_sender_login_mismatch(SMTPD_STATE *state, const char *sender)
{
const RESOLVE_REPLY *reply;
- const char *login = 0;
/*
* Reject if the client is not logged in and the sender address has an
int aierr;
char *colonp;
+ /*
+ * Sorry, but there are some things that we just cannot do while
+ * connected to the network.
+ */
+ if (geteuid() != var_owner_uid || getuid() != var_owner_uid) {
+ msg_error("incorrect SMTP server privileges: uid=%lu euid=%lu",
+ (unsigned long) getuid(), (unsigned long) geteuid());
+ msg_fatal("the Postfix SMTP server must run with $%s privileges",
+ VAR_MAIL_OWNER);
+ }
+
/*
* Convert the client address to printable form.
*/
state->saved_filter = 0;
state->saved_redirect = 0;
state->saved_flags = 0;
+#ifdef DELAY_ACTION
+ state->saved_delay = 0;
+#endif
state->instance = vstring_alloc(10);
state->seqno = 0;
state->rewrite_context = 0;