Safety: set-gid commands don't trust TZ. File: msg_syslog.c.
+20031027
+
+ Portability: MacOS X Bind8 compatibility. File: makedefs.
+
+20031110
+
+ Cleanup: don't report that $queue_directory/etc/filename
+ differs from /etc/filename when /etc/filename does not
+ exist. File: conf/postfix-script.
+
+20031126
+
+ Bugfix: "panic: mymalloc: requested length 0" when master.cf
+ specified an invalid host name or address. Postfix now
+ logs more specific information. File: master/master_ent.c.
+ Reported by several people.
+
+20031215
+
+ Safety: updated mail_queue_id_ok() for long fast flush
+ logfile names. File: global/mail_queue.c.
+
+ Robustness: save and restore the resolver _res.options
+ settings before and after DNS lookup, to avoid surprises
+ in third-party code. This may eliminate some "localhost
+ not found" problems. File: dns/dns_lookup.c.
+
+20031222
+
+ Cleanup: shaved half the worst-case bits off the cleanup
+ duplicate address filter footprint. After discussion with
+ Victor Duchovni. File: cleanup/cleanup_out_recipient.c.
+
+20031223
+
+ Bugfix: restore errno after write failure in SIGCHLD handler.
+ Leandro Santi. File: master/master_sig.c.
+
+20040104
+
+ Workaround: MacOSX dumps core on the 20030913 TZ censoring
+ code. We explictly set TZ=UTC, which will produce incorrect
+ results when "mailq" formatting is moved from the showq
+ daemon to the postqueue command. File: msg_syslog.c.
+
+ Bugfix: vstring_get() etc. now return VSTREAM_EOF when they
+ terminate prematurely, instead of returning the last
+ character stored. This avoids mis-leading warnings. File:
+ global/vstring_vstream.c.
+
+20040115
+
+ Performance: allow delivery concurrency to increase even
+ while mail is deferred, as long as the delivery agent does
+ not report really serious trouble with the destination.
+ Files: *qmgr/qmgr_deliver.c.
+
Open problems:
Doc: mention the proxy_interfaces parameter everywhere the
[Obsolete 20021209] The "check_relay_domains" restriction is going
away. The SMTP server logs a warning and suggests using the more
-robust "reject_unauth_destination" instead.
+robust "reject_unauth_destination" instead. This means that Postfix
+by default no longer grants relay permissions on the basis of the
+client hostname, and that relay clients must be authorized via
+other means such as permit_mynetworks.
[Obsolete 20020917] In regexp lookup tables, the form /pattern1/!/pattern2/
is going away. Use the cleaner and more flexible "if !/pattern2/..endif"
where inbound mail deliveries could become resource starved in the
presence of a high volume of outbound mail.
-[Feature 20021013] The body_checks_max_size parameter limits the
+[Feature 20021013] The body_checks_size_limit parameter limits the
amount of text per message body segment (or attachment, if you
prefer to use that term) that is subjected to body_checks inspection.
The default limit is 50 kbytes. This speeds up the processing of
IP address blacklisting. Based on code by LaMont Jones. The old
"reject_maps_rbl" is now implemented as a wrapper around the
reject_rbl_client code, and logs a warning that "reject_maps_rbl"
-is going away.
+is going away. To upgrade, specify "reject_rbl_client domainname"
+once for each domain name that is listed in maps_rbl_domains.
[Feature 20020923] "reject_rhsbl_sender rbl.domain.tld" for sender
domain blacklisting. Also: reject_rhsbl_client and reject_rhsbl_recipient
(for headers of attached email messages except MIME headers). By
default, all headers are matched with header_checks.
-[Feature 20021013] The body_checks_max_size parameter limits the
+[Feature 20021013] The body_checks_size_limit parameter limits the
amount of text per message body segment (or attachment, if you
prefer to use that term) that is subjected to body_checks inspection.
The default limit is 50 kbytes. This speeds up the processing of
do
test -d $dir && find $dir -type f -print | while read path
do
- cmp -s $path /$path ||
- $WARN $queue_directory/$path and /$path differ
+ test -e /$path && {
+ cmp -s $path /$path ||
+ $WARN $queue_directory/$path and /$path differ
+ }
done
done
#
body_checks = regexp:/etc/postfix/body_checks
-# The body_checks_max_size parameter controls how much text in a
+# The body_checks_size_limit parameter controls how much text in a
# message body segment (or attachment, if you prefer to use that
# term) is subjected to body_checks inspection.
#
# By default, only the first 50 kbytes of a message body segment are
# inspected with body_checks patterns.
#
-body_checks_max_size = 51200
+body_checks_size_limit = 51200
# $virtual_alias_domains, or $virtual_mailbox_domains.
# - to destinations matching $relay_domains or subdomain thereof,
# except for addresses with sender-specified routing.
-# reject_unauth_destination: reject mail unless it is sent
+# *reject_unauth_destination: reject mail unless it is sent
# - to destinations matching $inet_interfaces, $mydestination,
# $virtual_alias_domains, or $virtual_mailbox_domains.
# - to destinations matching $relay_domains or subdomain thereof,
SYSLIBS="-lresolv -lsocket -lnsl"
;;
Rhapsody.5*|Darwin.*)
- SYSTYPE=RHAPSODY5
+ SYSTYPE=MACOSX
# Use the native compiler by default
: ${CC=cc}
- AWK=gawk
case $RELEASE in
- 1.[0-3]) ;;
+ 1.[0-3]) AWK=gawk
+ ;;
+ [2-6].*) AWK=awk
+ SYSLIBS=-flat_namespace
+ ;;
*) AWK=awk
SYSLIBS=-flat_namespace
+ CCARGS="$CCARGS -DBIND_8_COMPAT -DNO_NETINFO"
;;
esac
;;
* onto the same mailbox. The recipient will use our original recipient
* message header to figure things out.
*/
+#define STREQ(x, y) (strcmp((x), (y)) == 0)
+
if (cleanup_virt_alias_maps == 0) {
- if (been_here(state->dups, "%s\n%s", orcpt, recip) == 0) {
+ if ((STREQ(orcpt, recip) ? been_here(state->dups, "%s", orcpt) :
+ been_here(state->dups, "%s\n%s", orcpt, recip)) == 0) {
cleanup_out_string(state, REC_TYPE_ORCP, orcpt);
cleanup_out_string(state, REC_TYPE_RCPT, recip);
state->rcpt_count++;
argv = cleanup_map1n_internal(state, recip, cleanup_virt_alias_maps,
cleanup_ext_prop_mask & EXT_PROP_VIRTUAL);
for (cpp = argv->argv; *cpp; cpp++) {
- if (been_here(state->dups, "%s\n%s", orcpt, *cpp) == 0) {
+ if ((STREQ(orcpt, *cpp) ? been_here(state->dups, "%s", orcpt) :
+ been_here(state->dups, "%s\n%s", orcpt, *cpp)) == 0) {
cleanup_out_string(state, REC_TYPE_ORCP, orcpt);
cleanup_out_string(state, REC_TYPE_RCPT, *cpp);
state->rcpt_count++;
{
HEADER *reply_header;
int len;
+ unsigned long saved_options = _res.options;
/*
* Initialize the name service.
* only if the name server told us so.
*/
len = res_search((char *) name, C_IN, type, reply->buf, sizeof(reply->buf));
+ _res.options = saved_options;
if (len < 0) {
if (why)
vstring_sprintf(why, "Name service error for name=%s type=%s: %s",
{
const char *cp;
- if (*queue_id == 0 || strlen(queue_id) > 100)
+ if (*queue_id == 0 || strlen(queue_id) > VALID_HOSTNAME_LEN)
return (0);
/*
- * OK if in in time+inum form.
+ * OK if in time+inum form or in host_domain_tld form.
*/
- for (cp = queue_id; /* void */ ; cp++) {
- if (*cp == 0)
- return (1);
- if (!ISALNUM(*cp))
- break;
- }
-
- /*
- * BAD if in time.pid form.
- */
- for (cp = queue_id; /* void */ ; cp++) {
- if (*cp == 0)
+ for (cp = queue_id; *cp; cp++)
+ if (!ISALNUM(*cp) && *cp != '_')
return (0);
- if (!ISDIGIT(*cp) && *cp != '.')
- break;
- }
-
- /*
- * OK if in valid hostname form.
- */
- return (valid_hostname(queue_id, DONT_GRIPE));
+ return (1);
}
/* mail_queue_enter - make mail queue entry with locally-unique name */
* 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 "20030913"
+#define MAIL_RELEASE_DATE "20040119"
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "2.0.16"
+#define DEF_MAIL_VERSION "2.0.17"
extern char *var_mail_version;
/*
MASTER_INET_ADDRLIST(serv) = (INET_ADDR_LIST *)
mymalloc(sizeof(*MASTER_INET_ADDRLIST(serv)));
inet_addr_list_init(MASTER_INET_ADDRLIST(serv));
- inet_addr_host(MASTER_INET_ADDRLIST(serv), host);
+ if (inet_addr_host(MASTER_INET_ADDRLIST(serv), host) == 0)
+ msg_fatal("%s: line %d: bad hostname or network address: %s",
+ VSTREAM_PATH(master_fp), master_line, host);
inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
} else if (strcasecmp(saved_interfaces, DEF_INET_INTERFACES) == 0) {
static void master_sigchld(int unused_sig)
{
+ int saved_errno = errno;
+
+ /*
+ * WARNING WARNING WARNING.
+ *
+ * This code runs at unpredictable moments, as a signal handler. Don't put
+ * any code here other than for setting a global flag, or code that is
+ * intended to be run within a signal handler. Restore errno in case we
+ * are interrupting the epilog of a failed system call.
+ */
if (write(SIG_PIPE_WRITE_FD, "", 1) != 1)
msg_warn("write to SIG_PIPE_WRITE_FD failed: %m");
+ errno = saved_errno;
}
/* master_sig_event - called upon return from select() */
* No problems detected. Mark the transport and queue as alive. The queue
* itself won't go away before we dispose of the current queue entry.
*/
- if (status == 0) {
+ if (VSTRING_LEN(reason) == 0) {
qmgr_transport_unthrottle(transport);
qmgr_queue_unthrottle(queue);
}
* No problems detected. Mark the transport and queue as alive. The queue
* itself won't go away before we dispose of the current queue entry.
*/
- if (status == 0) {
+ if (VSTRING_LEN(reason) == 0) {
qmgr_transport_unthrottle(transport);
qmgr_queue_unthrottle(queue);
}
#endif
#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffff
+#define INADDR_NONE 0xffffffff
#endif
/* Utility library. */
* This scrubbing code is in the wrong place.
*/
if (unsafe())
- putenv("TZ=");
+ putenv("TZ=UTC");
tzset();
openlog(name, LOG_NDELAY | logopt, facility);
if (first_call) {
#define NORETURN void
#define PRINTFLIKE(x,y)
#define SCANFLIKE(x,y)
+#ifndef NO_NETINFO
#define HAS_NETINFO
+#endif
#define NATIVE_SENDMAIL_PATH "/usr/sbin/sendmail"
#define NATIVE_MAILQ_PATH "/usr/bin/mailq"
#define NATIVE_NEWALIAS_PATH "/usr/bin/newaliases"
break;
}
VSTRING_TERMINATE(vp);
- return (VSTRING_GET_RESULT(vp));
+ return (c == VSTREAM_EOF ? c : VSTRING_GET_RESULT(vp));
}
/* vstring_get_nonl - read line from file, strip newline */
while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != '\n')
VSTRING_ADDCH(vp, c);
VSTRING_TERMINATE(vp);
- return (c == '\n' ? c : VSTRING_GET_RESULT(vp));
+ return (c == '\n' || c == VSTREAM_EOF ? c : VSTRING_GET_RESULT(vp));
}
/* vstring_get_null - read null-terminated string from file */
while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
VSTRING_ADDCH(vp, c);
VSTRING_TERMINATE(vp);
- return (c == 0 ? c : VSTRING_GET_RESULT(vp));
+ return (c == 0 || c == VSTREAM_EOF ? c : VSTRING_GET_RESULT(vp));
}
/* vstring_get_bound - read line from file, keep newline, up to bound */
break;
}
VSTRING_TERMINATE(vp);
- return (VSTRING_GET_RESULT(vp));
+ return (c == VSTREAM_EOF ? c : VSTRING_GET_RESULT(vp));
}
/* vstring_get_nonl_bound - read line from file, strip newline, up to bound */
while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != '\n')
VSTRING_ADDCH(vp, c);
VSTRING_TERMINATE(vp);
- return (c == '\n' ? c : VSTRING_GET_RESULT(vp));
+ return (c == '\n' || c == VSTREAM_EOF ? c : VSTRING_GET_RESULT(vp));
}
/* vstring_get_null_bound - read null-terminated string from file */
while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
VSTRING_ADDCH(vp, c);
VSTRING_TERMINATE(vp);
- return (c == 0 ? c : VSTRING_GET_RESULT(vp));
+ return (c == 0 || c == VSTREAM_EOF ? c : VSTRING_GET_RESULT(vp));
}
#ifdef TEST