for non-existent addresses. This required re-architecting
the recipient table lookup code. File: smtpd/smtpd_check.c.
+20030410
+
+ Safety: log a fatal error when a net/mask pattern has a
+ non-zero host part, so that mail delivery is deferred.
+ File: util/match_ops.c.
+
+20030411
+
+ Bugfix: extraneous warning about out-of-order original
+ recipient records by Patrik Rak. Files: *qmgr/qmgr_message.c.
+
+10030415
+
+ Workaround: log a warning and reset incoming queue file
+ time stamps when the file system clock is ahead of the
+ local clock, instead of ignoring new mail until the next
+ queue scan. The file system clock drift detection executes
+ only once per process instance, to minimize the performance
+ impact. File: global/mail_stream.c.
+
Open problems:
+ Low: smtp-source may block when sending large test messages.
+
Low: after successful delivery, per-queue window += 1/window,
after failure, queue window -= 1 (Victor).
Be sure to get the quotes right. These details matter a lot.
-Other parameters whose defaults can be specified in this way are:
-
- Macro name default value for
- -------------------------------------
- DEF_COMMAND_DIR command_directory
- DEF_DAEMON_DIR daemon_directory
- DEF_SENDMAIL_PATH sendmail_path
- DEF_MAILQ_PATH mailq_path
- DEF_NEWALIAS_PATH newaliases_path
+Parameters whose defaults can be specified in this way are:
+
+ Macro name default value for typical default
+ -----------------------------------------------------------
+ DEF_COMMAND_DIR command_directory /usr/sbin
+ DEF_CONFIG_DIR config_directory /etc/postfix
+ DEF_DAEMON_DIR daemon_directory /usr/libexec/postfix
+ DEF_MAILQ_PATH mailq_path /usr/bin/mailq
+ DEF_MANPAGE_DIR manpage_directory /usr/local/man
+ DEF_NEWALIAS_PATH newaliases_path /usr/bin/newaliases
+ DEF_README_DIR readme_directory no (do not install)
+ DEF_SAMPLE_DIR sample_directory /etc/postfix
+ DEF_SENDMAIL_PATH sendmail_path /usr/sbin/sendmail
In order to build Postfix for very large applications, where you
expect to run more than 1000 delivery processes, you may need to
date. Snapshots change only the release date, unless they include
the same bugfixes as a patch release.
+Incompatible changes with Postfix version 2.0.8 (released 20030415)
+===================================================================
+
+Too many people mess up their net/mask patterns, causing open
+mail relay problems. Postfix processes now abort when given a
+net/mask pattern with a non-zero host portion (for example,
+168.100.189.2/28), and suggest to specify the proper net/mask
+pattern instead (for example, 168.100.189.0/28).
+
+Major changes with Postfix version 2.0.8 (released 20030415)
+============================================================
+
+Workaround for file system clock drift that caused Postfix to ignore
+new mail (this could happen with file systems mounted from a server).
+Postfix now logs a warning and proceeds with only slightly reduced
+performance, instead of ignoring new mail.
+
Incompatible changes with Postfix version 2.0.6 (released 20030305)
===================================================================
# This file contains example settings for miscellaneous Postfix
# configuration parameters.
+# The allow_min_user parameter specifies whether a recipient address
+# can have a '-' as the first character. By default, this is not
+# allowed, to avoid accidents with software that passes email addresses
+# via the command line.
+#
+allow_min_user = no
+
# The always_bcc parameter specifies an optional address that
# receives a copy of each message that enters the Postfix system,
# not including bounces that are generated locally.
<a name="mynetworks"> <h2> My own networks </h2> </a>
The <b>mynetworks</b> parameter lists all networks that this machine
-somehow trusts. This information can be used by the <a href="uce.html">
-anti-UCE</a> features to recognize trusted SMTP clients that are
-allowed to relay mail through Postfix.
+somehow trusts. This information can be used by the <a
+href="uce.html#smtpd_recipient_restrictions"> anti-UCE</a> features
+to recognize trusted SMTP clients that are allowed to relay mail
+through Postfix.
<p>
<i>user2@virtual-alias.domain</i> <i>address2,</i> <i>address3</i>
The <i>virtual-alias.domain</i> <i>anything</i> entry is required for a
- virtual alias domain. Without this entry, mail is rejected
- with "relay access denied", or bounces with "mail loops
- back to myself".
+ virtual alias domain. <b>Without</b> <b>this</b> <b>entry,</b> <b>mail</b> <b>is</b> <b>rejected</b>
+ <b>with</b> <b>"relay</b> <b>access</b> <b>denied",</b> <b>or</b> <b>bounces</b> <b>with</b> <b>"mail</b> <b>loops</b>
+ <b>back</b> <b>to</b> <b>myself".</b>
Do not specify virtual alias domain names in the <b>main.cf</b>
<b>mydestination</b> or <b>relay</b><i>_</i><b>domains</b> configuration parameters.
.fi
.sp
The \fIvirtual-alias.domain anything\fR entry is required for a
-virtual alias domain. Without this entry, mail is rejected
+virtual alias domain. \fBWithout this entry, mail is rejected
with "relay access denied", or bounces with
-"mail loops back to myself".
+"mail loops back to myself".\fR
Do not specify virtual alias domain names in the \fBmain.cf
mydestination\fR or \fBrelay_domains\fR configuration parameters.
# The built-in default directory name is the current directory.
# This parameter setting is not recorded in the installed main.cf file.
# .IP config_directory
-# The destination directory for Postfix configuration files.
+# The final destination directory for Postfix configuration files.
# The built-in default directory name is /etc/postfix.
-# This parameter setting is not recorded in the installed main.cf file.
+# This parameter setting is not recorded in the installed main.cf file
+# and can be changed only by recompiling Postfix.
# .IP daemon_directory
-# The destination directory for Postfix daemon programs. This directory
-# should not be in the command search path of any users.
+# The final destination directory for Postfix daemon programs. This
+# directory should not be in the command search path of any users.
# The built-in default directory name is /usr/libexec/postfix.
# This parameter setting is recorded in the installed main.cf file.
# .IP command_directory
-# The destination directory for Postfix administrative commands. This
-# directory should be in the command search path of adminstrative users.
-# The built-in default directory name is system dependent.
+# The final destination directory for Postfix administrative commands.
+# This directory should be in the command search path of adminstrative
+# users. The built-in default directory name is system dependent.
# This parameter setting is recorded in the installed main.cf file.
# .IP queue_directory
-# The destination directory for Postfix queues.
+# The final destination directory for Postfix queues.
# The built-in default directory name is /var/spool/postfix.
# This parameter setting is recorded in the installed main.cf file.
# .IP sendmail_path
-# The full destination pathname for the Postfix sendmail command.
+# The final destination pathname for the Postfix sendmail command.
# This is the Sendmail-compatible mail posting interface.
# The built-in default pathname is system dependent.
# This parameter setting is recorded in the installed main.cf file.
# .IP newaliases_path
-# The full destination pathname for the Postfix newaliases command.
+# The final destination pathname for the Postfix newaliases command.
# This is the Sendmail-compatible command to build alias databases
# for the Postfix local delivery agent.
# The built-in default pathname is system dependent.
# This parameter setting is recorded in the installed main.cf file.
# .IP mailq_path
-# The full destination pathname for the Postfix mailq command.
+# The final destination pathname for the Postfix mailq command.
# This is the Sendmail-compatible command to list the mail queue.
# The built-in default pathname is system dependent.
# This parameter setting is recorded in the installed main.cf file.
tempdir_prompt="a directory for scratch files while installing
Postfix. You must have write permission in this directory."
-config_directory_prompt="the destination directory for installed
-Postfix configuration files."
+config_directory_prompt="the final destination directory for
+installed Postfix configuration files."
-daemon_directory_prompt="the destination directory for installed
-Postfix daemon programs. This directory should not be in the
-command search path of any users."
+daemon_directory_prompt="the final destination directory for
+installed Postfix daemon programs. This directory should not be
+in the command search path of any users."
-command_directory_prompt="the destination directory for installed
-Postfix administrative commands. This directory should be in the
-command search path of adminstrative users."
+command_directory_prompt="the final destination directory for
+installed Postfix administrative commands. This directory should
+be in the command search path of adminstrative users."
-queue_directory_prompt="the destination directory for Postfix
+queue_directory_prompt="the final destination directory for Postfix
queues."
-sendmail_path_prompt="the full destination pathname for the installed
-Postfix sendmail command. This is the Sendmail-compatible mail
-posting interface."
+sendmail_path_prompt="the final destination pathname for the
+installed Postfix sendmail command. This is the Sendmail-compatible
+mail posting interface."
-newaliases_path_prompt="the full destination pathname for the
+newaliases_path_prompt="the final destination pathname for the
installed Postfix newaliases command. This is the Sendmail-compatible
command to build alias databases for the Postfix local delivery
agent."
-mailq_path_prompt="the full destination pathname for the installed
+mailq_path_prompt="the final destination pathname for the installed
Postfix mailq command. This is the Sendmail-compatible mail queue
listing command."
# .fi
# .sp
# The \fIvirtual-alias.domain anything\fR entry is required for a
-# virtual alias domain. Without this entry, mail is rejected
+# virtual alias domain. \fBWithout this entry, mail is rejected
# with "relay access denied", or bounces with
-# "mail loops back to myself".
+# "mail loops back to myself".\fR
#
# Do not specify virtual alias domain names in the \fBmain.cf
# mydestination\fR or \fBrelay_domains\fR configuration parameters.
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
+#include <utime.h>
/* Utility library. */
/* mail_stream_cleanup - clean up after success or failure */
-void mail_stream_cleanup(MAIL_STREAM * info)
+void mail_stream_cleanup(MAIL_STREAM *info)
{
FREE_AND_WIPE(info->close, info->stream);
+ FREE_AND_WIPE(myfree, info->queue);
FREE_AND_WIPE(myfree, info->id);
FREE_AND_WIPE(myfree, info->class);
FREE_AND_WIPE(myfree, info->service);
/* mail_stream_finish_file - finish file mail stream */
-static int mail_stream_finish_file(MAIL_STREAM * info, VSTRING *unused_why)
+static int mail_stream_finish_file(MAIL_STREAM *info, VSTRING *unused_why)
{
int status = 0;
static char wakeup[] = {TRIGGER_REQ_WAKEUP};
+ struct stat st;
+ time_t now;
+ struct utimbuf tbuf;
+ char *path_to_reset = 0;
+ static int incoming_fs_clock_ok = 0;
+ static int incoming_clock_warned = 0;
+ int check_incoming_fs_clock;
/*
* Make sure the message makes it to file. Set the execute bit when no
* as are files with unknown record type codes. Every Postfix queue file
* must end with an explicit END record. Postfix queue files without END
* record are discarded.
+ *
+ * Attempt to detect file system clocks that are ahead of local time, but
+ * don't check the file system clock all the time. The effect of file
+ * system clock drift can be difficult to understand (Postfix ignores new
+ * mail until the next queue run).
+ *
+ * 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.
*/
+ check_incoming_fs_clock =
+ (!incoming_fs_clock_ok && !strcmp(info->queue, MAIL_QUEUE_INCOMING));
+
if (vstream_fflush(info->stream)
|| fchmod(vstream_fileno(info->stream), 0700 | info->mode)
#ifdef HAS_FSYNC
|| fsync(vstream_fileno(info->stream))
#endif
+ || (check_incoming_fs_clock
+ && fstat(vstream_fileno(info->stream), &st) < 0)
)
status = (errno == EFBIG ? CLEANUP_STAT_SIZE : CLEANUP_STAT_WRITE);
+#ifdef TEST
+ st.st_mtime += 10;
+#endif
+
+ /*
+ * Work around file system clocks that are ahead of local time.
+ */
+ if (status == CLEANUP_STAT_OK && check_incoming_fs_clock) {
+ if (st.st_mtime <= time(&now)) {
+ incoming_fs_clock_ok = 1;
+ } else {
+ path_to_reset = mystrdup(VSTREAM_PATH(info->stream));
+ if (incoming_clock_warned == 0) {
+ msg_warn("file system clock is %d seconds ahead of local clock",
+ (int) (st.st_mtime - now));
+ msg_warn("resetting file time stamps - this hurts performance");
+ incoming_clock_warned = 1;
+ }
+ }
+ }
+
/*
* Close the queue file and mark it as closed. Be prepared for
* vstream_fclose() to fail even after vstream_fflush() and fsync()
status = (errno == EFBIG ? CLEANUP_STAT_SIZE : CLEANUP_STAT_WRITE);
info->stream = 0;
+ /*
+ * Work around file system clocks that are ahead of local time.
+ */
+ if (path_to_reset != 0) {
+ tbuf.actime = tbuf.modtime = now;
+ if (utime(path_to_reset, &tbuf) < 0 && errno != ENOENT)
+ msg_fatal("%s: update file time stamps: %m", info->id);
+ myfree(path_to_reset);
+ }
+
/*
* When all is well, notify the next service that a new message has been
* queued.
/* mail_stream_finish_ipc - finish IPC mail stream */
-static int mail_stream_finish_ipc(MAIL_STREAM * info, VSTRING *why)
+static int mail_stream_finish_ipc(MAIL_STREAM *info, VSTRING *why)
{
int status = CLEANUP_STAT_WRITE;
/* mail_stream_finish - finish action */
-int mail_stream_finish(MAIL_STREAM * info, VSTRING *why)
+int mail_stream_finish(MAIL_STREAM *info, VSTRING *why)
{
return (info->finish(info, why));
}
info->stream = stream;
info->finish = mail_stream_finish_file;
info->close = vstream_fclose;
+ info->queue = mystrdup(queue);
info->id = mystrdup(basename(VSTREAM_PATH(stream)));
info->class = mystrdup(class);
info->service = mystrdup(service);
info->stream = stream;
info->finish = mail_stream_finish_ipc;
info->close = vstream_fclose;
+ info->queue = 0;
info->id = mystrdup(vstring_str(id_buf));
info->class = 0;
info->service = 0;
info->stream = stream;
info->finish = mail_stream_finish_ipc;
info->close = vstream_pclose;
+ info->queue = 0;
info->id = mystrdup(vstring_str(id_buf));
info->class = 0;
info->service = 0;
struct MAIL_STREAM {
VSTREAM *stream; /* file or pipe or socket */
+ char *queue; /* (initial) queue name */
char *id; /* queue id */
MAIL_STREAM_FINISH_FN finish; /* finish code */
MAIL_STREAM_CLOSE_FN close; /* close stream */
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20030319"
+#define MAIL_RELEASE_DATE "20030415"
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "2.0.7"
+#define DEF_MAIL_VERSION "2.0.8"
extern char *var_mail_version;
/*
message->rcpt_unread--;
}
} else if (rec_type == REC_TYPE_RCPT) {
+ /* See also below for code setting orig_rcpt. */
if (message->rcpt_list.len < recipient_limit) {
message->rcpt_unread--;
qmgr_rcpt_list_add(&message->rcpt_list, curr_offset,
orig_rcpt = 0;
}
if (rec_type == REC_TYPE_ORCP)
- orig_rcpt = mystrdup(start);
+ /* See also above for code clearing orig_rcpt. */
+ if (message->rcpt_offset == 0)
+ orig_rcpt = mystrdup(start);
} while (rec_type > 0 && rec_type != REC_TYPE_END);
/*
"queue %s", message->queue_name);
}
} else if (rec_type == REC_TYPE_RCPT) {
+ /* See also below for code setting orig_rcpt. */
#define FUDGE(x) ((x) * (var_qmgr_fudge / 100.0))
if (message->rcpt_list.len < FUDGE(var_qmgr_rcpt_limit)) {
qmgr_rcpt_list_add(&message->rcpt_list, curr_offset,
orig_rcpt = 0;
}
if (rec_type == REC_TYPE_ORCP)
- orig_rcpt = mystrdup(start);
+ /* See also above for code clearing orig_rcpt. */
+ if (message->rcpt_offset == 0)
+ orig_rcpt = mystrdup(start);
} while (rec_type > 0 && rec_type != REC_TYPE_END);
/*
mydate = mail_date(time((time_t *) 0));
mypid = getpid();
}
+#if SMTP_PRINTF_NO_LONGER_FLUSHES
smtp_printf(session->stream, "From: <%s>", sender);
smtp_printf(session->stream, "To: <%s>", recipient);
smtp_printf(session->stream, "Date: %s", mydate);
mypid, vstream_fileno(session->stream), message_count, var_myhostname);
if (subject)
smtp_printf(session->stream, "Subject: %s", subject);
+#else
+ vstream_fprintf(session->stream, "From: <%s>\r\n", sender);
+ vstream_fprintf(session->stream, "To: <%s>\r\n", recipient);
+ vstream_fprintf(session->stream, "Date: %s\r\n", mydate);
+ vstream_fprintf(session->stream, "Message-Id: <%04x.%04x.%04x@%s>\r\n",
+ mypid, vstream_fileno(session->stream), message_count,
+ var_myhostname);
+ if (subject)
+ vstream_fprintf(session->stream, "Subject: %s\r\n", subject);
+#endif
smtp_fputs("", 0, session->stream);
}
smtp_fputs("La de da de da 3.", 17, session->stream);
smtp_fputs("La de da de da 4.", 17, session->stream);
} else {
+
+ /*
+ * XXX This may cause the process to block with message content
+ * larger than VSTREAM_BUFIZ bytes.
+ */
smtp_fputs(message_data, message_length, session->stream);
}
unsigned long mask_bits;
unsigned long net_bits;
unsigned long addr_bits;
+ struct in_addr net_addr;
if (msg_verbose)
msg_info("%s: %s ~? %s", myname, addr, pattern);
if (addr_bits == INADDR_NONE)
msg_fatal("%s: bad address argument: %s", myname, addr);
mask_bits = htonl((0xffffffff) << (BITS_PER_ADDR - mask_shift));
- return ((addr_bits & mask_bits) == (net_bits & mask_bits));
+ if ((addr_bits & mask_bits) == net_bits)
+ return (1);
+ if (net_bits & ~mask_bits) {
+ net_addr.s_addr = (net_bits & mask_bits);
+ msg_fatal("net/mask pattern %s has a non-null host portion; "
+ "specify %s/%d if this is really what you want",
+ pattern, inet_ntoa(net_addr), mask_shift);
+ }
}
return (0);
}