local/maildir.c, local/mailbox.c, local/command.c, pipe/pipe.c,
virtual/mailbox.c, virtual/maildir.c.
- Bugfix: the bounce daemon broke in case of a non-existing
- message queue file. File: bounce/bounce_notify_util.c.
+ Bugfix: the bounce daemon broke in the unlikely case of a
+ non-existing queue file. File: bounce/bounce_notify_util.c.
+
+20011127
+
+ Feature: added WARN command to header/body_checks files as
+ proposed by Michael Tokarev. File: cleanup/cleanup_message.c.
+
+ Bugfix: the postdrop program was broken after the change
+ of Postfix internal protocols. This broke "sendmail -bs"
+ mail submissions with "secure" maildrop directory. Reported
+ by Craig Loomis, apo.nmsu.edu. File: postdrop/postdrop.c.
+
+ Feature: a first start at fault injection for testing
+ unlikely error scenarios (such as corrupt queue files).
+ Parameter: fault_injection_code, must be left at zero for
+ production use.
Open problems:
Medium: smtpd access maps don't understand the recipient
delimiter setting.
+ Low: generic showq protocol, to allow for more intelligent
+ processing than just mailq. Maybe marry this with postsuper.
+
Low: default domain for appending to unqualified recipients.
Low: The $process_id_directory setting is not used anywhere
mailbox_transport = lmtp:unix:/var/imap/socket/lmtp
+/etc/postfix/master.cf:
+
+ lmtp unix - - n - - lmtp
+
In this case, the Postfix local delivery agent expands aliases
and .forward files, and delegates mailbox delivery to the Cyrus
lmtpd server via the socket "/var/imap/socket/lmtp".
lmtp_sasl_auth_enable = yes
lmtp_sasl_password_maps = hash:/etc/postfix/lmtp_sasl_pass
+/etc/postfix/lmtp_sasl_pass:
+ localhost.my.domain username:password
+
/etc/postfix/master.cf:
lmtp unix - - n - - lmtp
-/etc/postfix/lmtp_sasl_pass:
- localhost.my.domain username:password
-
Instead of "hash", use the map type of your choice. Some systems
use "dbm" instead. Use "postconf -m" to find out what map types
are supported.
+Major changes with snapshot-20011127
+====================================
+
+New parameter smtpd_noop_commands to specify a list of commands
+that the Postfix SMTP server treats as NOOP commands (no syntax
+check, no state change). This is a workaround for misbehaving
+clients that send unsupported commands such as ONEX.
+
+New header/body_check result "WARN" to make Postfix log a warning
+about a header/body line without rejecting the content.
+
Major changes with snapshot-20011125
====================================
# The controls listed here are only a very small subset. See the file
# sample-smtpd.cf for an elaborate list of anti-UCE controls.
-# The header_checks parameter restricts what may appear in message
-# headers. This requires that POSIX or PCRE regular expression support
-# is built-in. Specify "/^header-name: stuff you do not want/ REJECT"
-# in the pattern file. Patterns are case-insensitive by default. Note:
-# specify only patterns ending in REJECT (reject entire message) or
-# IGNORE (silently discard this header). Patterns ending in OK are
-# mostly a waste of cycles.
-#
-#header_checks = regexp:/etc/postfix/filename
-#header_checks = pcre:/etc/postfix/filename
+# The header_checks parameter specifies an optional table with patterns
+# that each logical message header is matched against, including
+# headers that span multiple physical lines. Patterns are matched
+# in the specified order, and the search stops upon the first match.
+# When a pattern matches, what happens next depends on the associated
+# action that is specified in the right-hand side of the table:
+#
+# REJECT the entire message is rejected.
+# REJECT text.... The text is sent to the originator.
+# IGNORE the header line is silently discarded.
+# WARN the header is logged (not rejected) with a warning message.
+#
+# These patterns do not apply to MIME headers in the message body.
+#
+# See also the body_checks example in the sample-filter.cf file.
+#
+#header_checks = regexp:/etc/postfix/header_checks
# FAST ETRN SERVICE
#
# headers that span multiple physical lines. Patterns are matched
# in the specified order, and the search stops upon the first match.
# When a pattern matches, what happens next depends on the associated
-# action:
+# action that is specified in the right-hand side of the table:
#
# REJECT the entire message is rejected.
-#
# REJECT text.... The text is sent to the originator.
-#
# IGNORE the header line is silently discarded.
-#
-# OK Nothing happens. the message will still be rejected when some
-# other header line matches a REJECT pattern.
+# WARN the header is logged (not rejected) with a warning message.
#
# These patterns do not apply to MIME headers in the message body.
#
# The body_checks parameter specifies an optional table with patterns
# that each physical line in the message body is matched against
# (including MIME headers inside the message body - Postfix does not
-# recognize multi-line MIME headers). Lines are matched one at a
-# time. Long lines are matched in chunks of at most $line_length_limit
-# characters. Patterns are matched in the specified order, and the
-# search stops upon the first match. When a pattern matches, what
-# happens next depends on the associated action:
+# recognize multi-line MIME headers in the message body).
+# Lines are matched one at a time. Long lines are matched in chunks
+# of at most $line_length_limit characters. Patterns are matched in
+# the specified order, and the search stops upon the first match.
+# When a pattern matches, what happens next depends on the associated
+# action that is specified in the right-hand side of the table:
#
# REJECT the entire message is rejected.
-#
# REJECT text.... The text is sent to the originator.
-#
# IGNORE the body line is silently discarded.
-#
-# OK Nothing happens. The message will still be rejected when some
-# other body line matches a REJECT pattern.
+# WARN the body line is logged (not rejected) with a warning message.
#
body_checks = regexp:/etc/postfix/body_checks
<dt>Syntax:
<dd>Specify a list of zero or more lookup tables. Whenever a header
-matches a table, a REJECT result means reject the message, and an
-IGNORE result means delete the header from the message.
+matches a table, the action depends on the lookup result:
+
+<p>
+
+<dl>
+
+<dt>REJECT <dd> Reject the message, and log the header.
+
+<dt>REJECT text... <dd> As above, and also send the text to
+the originator.
+
+<dt>IGNORE <dd> Delete the header from the message.
+
+<dt>WARN <dd> Log (but do not reject) the header with a warning.
+
+</dl>
<p>
<dt>Example (header_checks):
-<dd> /^to: *friend@public\.com$/ REJECT
+<dd> <tt>/^to: *friend@public\.com$/ REJECT</tt>
<p>
state->reason);
} else if (strcasecmp(value, "IGNORE") == 0) {
return;
+ } else if (strcasecmp(value, "WARN") == 0) {
+ msg_info("%s: warning: header %.200s; from=<%s> to=<%s>",
+ state->queue_id, header, state->sender,
+ state->recip ? state->recip : "unknown");
}
}
}
state->reason);
} else if (strcasecmp(value, "IGNORE") == 0) {
return;
+ } else if (strcasecmp(value, "WARN") == 0) {
+ msg_info("%s: warning: body %.200s; from=<%s> to=<%s>",
+ state->queue_id, buf, state->sender,
+ state->recip ? state->recip : "unknown");
}
}
}
char *hop_status; /* reason if unavailable */
} DELIVER_REQUEST;
-#define DEL_STAT_OK (0) /* success including bounced */
-#define DEL_STAT_DEFER (-1) /* deferred */
-#define DEL_STAT_CORRUPT (-1) /* corrupt */
-
#define DEL_REQ_FLAG_DEFLT (DEL_REQ_FLAG_SUCCESS | DEL_REQ_FLAG_BOUNCE)
#define DEL_REQ_FLAG_SUCCESS (1<<0) /* delete successful recipients */
#define DEL_REQ_FLAG_BOUNCE (1<<1) /* unimplemented */
+ /*
+ * Delivery status. Note that there are only FINAL and DEFER. This is
+ * because delivery status information can be lost when a delivery agent or
+ * queue manager process terminates prematurely. The only distinctions we
+ * can rely on are "final delivery completed" and "everything else". In the
+ * absence of a definitive statement the queue manager will always have to
+ * be prepared for all possibilities.
+ */
+#define DEL_STAT_FINAL 0 /* delivered or bounced */
+#define DEL_STAT_DEFER (-1) /* not delivered or bounced */
+
typedef struct VSTREAM _deliver_vstream_;
extern DELIVER_REQUEST *deliver_request_read(_deliver_vstream_ *);
extern int deliver_request_done(_deliver_vstream_ *, DELIVER_REQUEST *, int);
#include "rec_type.h"
#include "mail_queue.h"
#include "mail_addr.h"
-#include "mail_copy.h"
#include "mark_corrupt.h"
+#include "mail_params.h"
+#include "mail_copy.h"
/* mail_copy - copy message with extreme prejudice */
prev_type = type;
}
if (vstream_ferror(dst) == 0) {
+ if (var_fault_inj_code == 1)
+ type = 0;
if (type != REC_TYPE_XTRA)
corrupt_error = mark_corrupt(src);
if (prev_type != REC_TYPE_NORM)
if ((flags & MAIL_COPY_TOFILE) != 0)
write_error |= fsync(vstream_fileno(dst));
#endif
+ if (var_fault_inj_code == 2) {
+ read_error = 1;
+ errno = ENOENT;
+ }
+ if (var_fault_inj_code == 3) {
+ write_error = 1;
+ errno = ENOENT;
+ }
#ifndef NO_TRUNCATE
if ((flags & MAIL_COPY_TOFILE) != 0)
if (corrupt_error || read_error || write_error)
/* char *var_debug_peer_list;
/* int var_debug_peer_level;
/* int var_in_flow_delay;
+/* int var_fault_inj_code;
/*
/* void mail_params_init()
/* DESCRIPTION
char *var_export_environ;
char *var_debug_peer_list;
int var_debug_peer_level;
+int var_fault_inj_code;
/* check_myhostname - lookup hostname and validate */
VAR_FORK_TRIES, DEF_FORK_TRIES, &var_fork_tries, 1, 0,
VAR_FLOCK_TRIES, DEF_FLOCK_TRIES, &var_flock_tries, 1, 0,
VAR_DEBUG_PEER_LEVEL, DEF_DEBUG_PEER_LEVEL, &var_debug_peer_level, 1, 0,
+ VAR_FAULT_INJ_CODE, DEF_FAULT_INJ_CODE, &var_fault_inj_code, 0, 0,
0,
};
static CONFIG_TIME_TABLE time_defaults[] = {
#define SMTPD_ACCESS_MAPS "smtpd_access_maps"
+ /*
+ * Run-time fault injection.
+ */
+#define VAR_FAULT_INJ_CODE "fault_injection_code"
+#define DEF_FAULT_INJ_CODE 0
+extern int var_fault_inj_code;
+
/* LICENSE
/* .ad
/* .fi
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-20011126"
+#define DEF_MAIL_VERSION "Snapshot-20011127"
extern char *var_mail_version;
/* LICENSE
if (saved_uid != var_owner_uid)
set_eugid(saved_uid, saved_gid);
- return (DEL_STAT_CORRUPT);
+ return (DEL_STAT_DEFER);
}
"%s", vstring_str(why));
break;
case PIPE_STAT_CORRUPT:
- deliver_status = DEL_STAT_CORRUPT;
+ deliver_status = DEL_STAT_DEFER;
break;
default:
msg_panic("%s: bad status %d", myname, cmd_status);
* As the mail system, bounce, defer delivery, or report success.
*/
if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
- deliver_status = DEL_STAT_CORRUPT;
+ deliver_status = DEL_STAT_DEFER;
} else if (mail_copy_status != 0) {
deliver_status = (errno == EAGAIN || errno == ENOSPC || errno == ESTALE ?
defer_append : bounce_append)
* As the mail system, bounce, defer delivery, or report success.
*/
if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
- deliver_status = DEL_STAT_CORRUPT;
+ deliver_status = DEL_STAT_DEFER;
} else if (mail_copy_status != 0) {
deliver_status = (errno == EAGAIN || errno == ENOSPC || errno == ESTALE ?
defer_append : bounce_append)
* As the mail system, bounce or defer delivery.
*/
if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
- deliver_status = DEL_STAT_CORRUPT;
+ deliver_status = DEL_STAT_DEFER;
} else if (mail_copy_status != 0) {
deliver_status = (errno == ENOSPC || errno == ESTALE ?
defer_append : bounce_append)
}
break;
case PIPE_STAT_CORRUPT:
- result |= DEL_STAT_CORRUPT;
+ result |= DEL_STAT_DEFER;
break;
default:
msg_panic("eval_command_status: bad status %d", command_status);
*/
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
+ ATTR_TYPE_STR, MAIL_ATTR_WHY, "",
ATTR_TYPE_END);
vstream_fflush(VSTREAM_OUT);
exit(status);
/* This parameter uses the same syntax as the right-hand side of
/* a Postfix transport table.
/* .IP \fBsmtpd_noop_commands\fR
-/* List of commands that are treated as NOOP (no operation) commands
-/* without any parameter syntax checking. This list overrides built-in
-/* command definitions.
+/* List of commands that are treated as NOOP (no operation) commands,
+/* without any parameter syntax checking and without any state change.
+/* This list overrides built-in command definitions.
/* .SH "Authentication controls"
/* .IP \fBenable_sasl_authentication\fR
/* Enable per-session authentication as per RFC 2554 (SASL).
* As the mail system, bounce, defer delivery, or report success.
*/
if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
- deliver_status = DEL_STAT_CORRUPT;
+ deliver_status = DEL_STAT_DEFER;
} else if (mail_copy_status != 0) {
deliver_status = (errno == EDQUOT || errno == EFBIG ?
bounce_append : defer_append)
* location possibly under user control.
*/
if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
- deliver_status = DEL_STAT_CORRUPT;
+ deliver_status = DEL_STAT_DEFER;
} else if (mail_copy_status != 0) {
deliver_status = (errno == EDQUOT || errno == EFBIG ?
bounce_append : defer_append)