diff --git a/postfix/HISTORY b/postfix/HISTORY index 4d4512d4e..baeaeb28a 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -8053,13 +8053,14 @@ Apologies for any names omitted. a forbidden "next" sender state after the last recipient. Fix by Vladimir Davydoff. File: lmtp/lmtp_proto.c. - Bugfix: proxymap server did not parse "," as space. - Leandro Santi. File: proxymap/proxymap.c. + Bugfix: "," was not recognized in proxy_read_maps settings. + Fix by Leandro Santi. File: proxymap/proxymap.c. 20030502 Bugfix: defer delivery after .forward etc. file read error. - File: local/token.c. + File: local/token.c. Problem reported by Ben Rosengart, + Panix. 20030503 @@ -8073,16 +8074,20 @@ Apologies for any names omitted. descriptor is writable while write() transfers zero bytes. File: util/vstream.c. -20030519 +20030520 - Feature: new require_{date,from,message_id,received}_header - restriction to reject SMTP mail when some message header - is missing. Only the From: and Date: headers are actually - required by Internet mail standards; the Received: and - Message-ID: headers are optional, but these are often - missing from SPAM email. Files: global/cleanup_user.h, - global/cleanup_strerror.c, smtpd/smtpd_check.c, - cleanup/cleanup_message.c. + Cleanup: future time stamps in Received: headers and negative + delays in delivery agent logging after "postdrop -r", + because deferred queue files had future file modification + times. File: src/postsuper/postsuper.c. + +20030521 + + Cleanup: nqmgr warnings about "recipient count mismatch" + after "postdrop -r", because the cleanup server did not + count the "already done" recipients. Problem reported by + Richard Stockton, Gramma Software. Files: + cleanup/cleanup_envelope.c, cleanup/cleanup_extracted.c. Open problems: diff --git a/postfix/man/man8/cleanup.8 b/postfix/man/man8/cleanup.8 index 67420bea3..fdadfa4a8 100644 --- a/postfix/man/man8/cleanup.8 +++ b/postfix/man/man8/cleanup.8 @@ -121,7 +121,7 @@ this also breaks majordomo approval requests when the included request contains valid 8-bit MIME mail, and it breaks bounces from mailers that do not properly encapsulate 8-bit content (for example, bounces from qmail or from old versions of Postfix). -.IP \fBstrict_mime_encoding_domain\fR +.IP \fBstrict_mime_domain_encoding\fR Reject mail with invalid \fBContent-Transfer-Encoding:\fR information for message/* or multipart/*. This blocks mail from poorly written software. diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c index b26ccc7ed..8cdefbd00 100644 --- a/postfix/src/cleanup/cleanup_envelope.c +++ b/postfix/src/cleanup/cleanup_envelope.c @@ -183,6 +183,8 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, cleanup_addr_recipient(state, buf); myfree(state->orig_rcpt); state->orig_rcpt = 0; + } else if (type == REC_TYPE_DONE) { + /* void */ ; } else if (type == REC_TYPE_WARN) { if ((state->warn_time = atol(buf)) < 0) { state->errs |= CLEANUP_STAT_BAD; diff --git a/postfix/src/cleanup/cleanup_extracted.c b/postfix/src/cleanup/cleanup_extracted.c index faad668a1..2d284b272 100644 --- a/postfix/src/cleanup/cleanup_extracted.c +++ b/postfix/src/cleanup/cleanup_extracted.c @@ -153,8 +153,11 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, myfree(state->orig_rcpt); state->orig_rcpt = 0; return; + } else if (type == REC_TYPE_DONE) { + return; } else if (type == REC_TYPE_ORCP) { state->orig_rcpt = mystrdup(buf); + return; } if (type != REC_TYPE_END) { cleanup_out(state, type, buf, len); diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index f77801565..72a562703 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -493,29 +493,6 @@ static void cleanup_header_callback(void *context, int header_class, } } -/* cleanup_missing - handle missing message header */ - -static void cleanup_missing(CLEANUP_STATE *state, const char *resent, - const char *header) -{ - const char *attr; - - if ((attr = nvtable_find(state->attr, MAIL_ATTR_ORIGIN)) == 0) - attr = "unknown"; - vstring_sprintf(state->temp1, "%s: reject: missing %s%s header from %s;", - state->queue_id, resent, header, attr); - if (state->sender) - vstring_sprintf_append(state->temp1, " from=<%s>", state->sender); - if (state->recip) - vstring_sprintf_append(state->temp1, " to=<%s>", state->recip); - if ((attr = nvtable_find(state->attr, MAIL_ATTR_PROTO_NAME)) != 0) - vstring_sprintf_append(state->temp1, " proto=%s", attr); - if ((attr = nvtable_find(state->attr, MAIL_ATTR_HELO_NAME)) != 0) - vstring_sprintf_append(state->temp1, " helo=<%s>", attr); - msg_info("%s", vstring_str(state->temp1)); - state->errs |= CLEANUP_STAT_MISS_HDR; -} - /* cleanup_header_done_callback - insert missing message headers */ static void cleanup_header_done_callback(void *context) @@ -525,15 +502,6 @@ static void cleanup_header_done_callback(void *context) struct tm *tp; TOK822 *token; - /* - * Postfix prepends a Received: message header, so we should see two when - * one is required. - */ - if ((state->flags & CLEANUP_FLAG_NEED_RCVD) && state->hop_count < 2) { - cleanup_missing(state, "", "Received"); - return; - } - /* * Add a missing (Resent-)Message-Id: header. The message ID gives the * time in GMT units, plus the local queue ID. @@ -545,10 +513,6 @@ static void cleanup_header_done_callback(void *context) */ if ((state->headers_seen & (1 << (state->resent[0] ? HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID))) == 0) { - if (state->flags & CLEANUP_FLAG_NEED_MSGID) { - cleanup_missing(state, state->resent, "Message-Id"); - return; - } tp = gmtime(&state->time); strftime(time_stamp, sizeof(time_stamp), "%Y%m%d%H%M%S", tp); cleanup_out_format(state, REC_TYPE_NORM, "%sMessage-Id: <%s.%s@%s>", @@ -564,10 +528,6 @@ static void cleanup_header_done_callback(void *context) */ if ((state->headers_seen & (1 << (state->resent[0] ? HDR_RESENT_DATE : HDR_DATE))) == 0) { - if (state->flags & CLEANUP_FLAG_NEED_DATE) { - cleanup_missing(state, state->resent, "Date"); - return; - } cleanup_out_format(state, REC_TYPE_NORM, "%sDate: %s", state->resent, mail_date(state->time)); } @@ -577,10 +537,6 @@ static void cleanup_header_done_callback(void *context) */ if ((state->headers_seen & (1 << (state->resent[0] ? HDR_RESENT_FROM : HDR_FROM))) == 0) { - if (state->flags & CLEANUP_FLAG_NEED_FROM) { - cleanup_missing(state, state->resent, "From"); - return; - } quote_822_local(state->temp1, *state->sender ? state->sender : MAIL_ADDR_MAIL_DAEMON); vstring_sprintf(state->temp2, "%sFrom: %s", diff --git a/postfix/src/global/cleanup_strerror.c b/postfix/src/global/cleanup_strerror.c index e763ce950..489093ed9 100644 --- a/postfix/src/global/cleanup_strerror.c +++ b/postfix/src/global/cleanup_strerror.c @@ -51,7 +51,6 @@ static struct cleanup_stat_map cleanup_stat_map[] = { CLEANUP_STAT_BAD, "Internal protocol error", CLEANUP_STAT_RCPT, "No recipients specified", CLEANUP_STAT_HOPS, "Too many hops", - CLEANUP_STAT_MISS_HDR, "Missing message header", CLEANUP_STAT_SIZE, "Message file too big", CLEANUP_STAT_CONT, "Message content rejected", CLEANUP_STAT_WRITE, "Error writing message file", diff --git a/postfix/src/global/cleanup_user.h b/postfix/src/global/cleanup_user.h index 8c988251b..ce4af5851 100644 --- a/postfix/src/global/cleanup_user.h +++ b/postfix/src/global/cleanup_user.h @@ -20,19 +20,13 @@ #define CLEANUP_FLAG_HOLD (1<<2) /* Place message on hold */ #define CLEANUP_FLAG_DISCARD (1<<3) /* Discard message silently */ #define CLEANUP_FLAG_BCC_OK (1<<4) /* Ok to add auto-BCC addresses */ -#define CLEANUP_FLAG_NEED_DATE (1<<5) /* Require (Resent:-)Date: */ -#define CLEANUP_FLAG_NEED_FROM (1<<6) /* Require (Resent:-)From: */ -#define CLEANUP_FLAG_NEED_MSGID (1<<7) /* Require (Resent:-)Message-Id: */ -#define CLEANUP_FLAG_NEED_RCVD (1<<8) /* Require two Received: headers */ /* * These are set on the fly while processing SMTP envelopes or message * content. */ #define CLEANUP_FLAG_MASK_EXTRA \ - (CLEANUP_FLAG_HOLD | CLEANUP_FLAG_DISCARD | CLEANUP_FLAG_NEED_DATE | \ - CLEANUP_FLAG_NEED_FROM | CLEANUP_FLAG_NEED_MSGID | \ - CLEANUP_FLAG_NEED_RCVD) + (CLEANUP_FLAG_HOLD | CLEANUP_FLAG_DISCARD) /* * Diagnostics. @@ -45,7 +39,6 @@ #define CLEANUP_STAT_SIZE (1<<2) /* Message file too big */ #define CLEANUP_STAT_CONT (1<<3) /* Message content rejected */ #define CLEANUP_STAT_HOPS (1<<4) /* Too many hops */ -#define CLEANUP_STAT_MISS_HDR (1<<5) /* Some missing header */ #define CLEANUP_STAT_RCPT (1<<6) /* No recipients found */ /* diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 8c2463b80..2662b1ade 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -607,6 +607,17 @@ void mail_params_init() if (strcasecmp(var_myhostname, var_relayhost) == 0) msg_fatal("myhostname == relayhost"); + /* + * XXX These should be caught by a proper parameter parsing algorithm. + */ + if (var_myorigin[strcspn(var_myorigin, ", \t\r\n")]) + msg_fatal("myorigin parameter setting contains multiple values: %s", + var_myorigin); + + if (var_relayhost[strcspn(var_relayhost, ", \t\r\n")]) + msg_fatal("relayhost parameter setting contains multiple values: %s", + var_relayhost); + /* * One more sanity check. */ diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 4b968416c..3c8021d5d 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1337,11 +1337,6 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`\ abcdefghijklmnopqrstuvwxyz{|}~" extern char *var_smtpd_exp_filter; -#define REQUIRE_DATE_HDR "require_date_header" -#define REQUIRE_FROM_HDR "require_from_header" -#define REQUIRE_MSGID_HDR "require_message_id_header" -#define REQUIRE_RCVD_HDR "require_received_header" - /* * Heuristic to reject unknown local recipients at the SMTP port. */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 744414eff..f649ecd36 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,10 +20,10 @@ * 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 "20030519" +#define MAIL_RELEASE_DATE "20030521" #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "2.0.9-" MAIL_RELEASE_DATE +#define DEF_MAIL_VERSION "2.0.10-" MAIL_RELEASE_DATE extern char *var_mail_version; /* diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index 6d51cec84..28e04f2a6 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -175,6 +175,8 @@ static int copy_segment(VSTREAM *qfile, VSTREAM *cleanup, PICKUP_INFO *info, if ((type = rec_get(qfile, buf, var_line_limit)) < 0 || strchr(expected, type) == 0) return (file_read_error(info, type)); + if (msg_verbose) + msg_info("%s: read %c %s", info->id, type, vstring_str(buf)); if (type == *expected) break; if (type == REC_TYPE_FROM) @@ -191,6 +193,8 @@ static int copy_segment(VSTREAM *qfile, VSTREAM *cleanup, PICKUP_INFO *info, info->rcpt = mystrdup(vstring_str(buf)); if (type == REC_TYPE_TIME) continue; + if (type == REC_TYPE_SIZE) + continue; if (type == REC_TYPE_ATTR) { if ((error_text = split_nameval(vstring_str(buf), &attr_name, &attr_value)) != 0) { diff --git a/postfix/src/postdrop/postdrop.c b/postfix/src/postdrop/postdrop.c index 6832aa9bd..141702406 100644 --- a/postfix/src/postdrop/postdrop.c +++ b/postfix/src/postdrop/postdrop.c @@ -315,9 +315,6 @@ int main(int argc, char **argv) } if (rec_type == REC_TYPE_ERROR) msg_fatal("uid=%ld: malformed input", (long) uid); - if (rec_type == REC_TYPE_TIME) - rec_fprintf(dst->stream, REC_TYPE_TIME, "%ld", - (long) time((time_t *) 0)); if (strchr(*expected, rec_type) == 0) msg_fatal("uid=%ld: unexpected record type: %d", (long) uid, rec_type); if (rec_type == **expected) diff --git a/postfix/src/postsuper/postsuper.c b/postfix/src/postsuper/postsuper.c index 7c8989893..6e986ce49 100644 --- a/postfix/src/postsuper/postsuper.c +++ b/postfix/src/postsuper/postsuper.c @@ -5,7 +5,7 @@ /* Postfix superintendent /* SYNOPSIS /* .fi -/* \fBpostsuper\fR [\fB-psv\fR] +/* \fBpostsuper\fR [\fB-psv\fR] /* [\fB-c \fIconfig_dir\fR] [\fB-d \fIqueue_id\fR] /* [\fB-h \fIqueue_id\fR] [\fB-H \fIqueue_id\fR] /* [\fB-r \fIqueue_id\fR] [\fIdirectory ...\fR] @@ -191,6 +191,7 @@ #include #include #include /* remove() */ +#include /* Utility library. */ @@ -433,6 +434,7 @@ static int requeue_one(const char **queue_names, const char *queue_id) VSTRING *new_path_buf; int found; int tries; + struct utimbuf tbuf; /* * Sanity check. No early returns beyond this point. @@ -459,6 +461,9 @@ static int requeue_one(const char **queue_names, const char *queue_id) continue; (void) mail_queue_path(new_path_buf, MAIL_QUEUE_MAILDROP, queue_id); if (postrename(old_path, STR(new_path_buf)) == 0) { + tbuf.actime = tbuf.modtime = time((time_t *) 0); + if (utime(STR(new_path_buf), &tbuf) < 0) + msg_warn("%s: reset time stamps: %m", STR(new_path_buf)); msg_info("%s: requeued", queue_id); found = 1; break; diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index 2e676001e..28cbbcd68 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -482,9 +482,6 @@ static void qmqpd_send_status(QMQPD_STATE *state) } else if ((state->err & CLEANUP_STAT_RCPT) != 0) { qmqpd_reply(state, DO_LOG, QMQPD_STAT_HARD, "Error: no recipients specified"); - } else if ((state->err & CLEANUP_STAT_MISS_HDR) != 0) { - qmqpd_reply(state, DO_LOG, QMQPD_STAT_HARD, - "Error: missing message header"); } else { qmqpd_reply(state, DO_LOG, QMQPD_STAT_RETRY, "Error: internal error %d", state->err); diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index 93c2677a3..83b7d46ff 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -523,7 +523,6 @@ static void enqueue(const int flags, const char *encoding, const char *sender, * * XXX Should limit the size of envelope records. */ - rec_fprintf(dst, REC_TYPE_TIME, "%ld", (long) time((time_t *) 0)); if (full_name || (full_name = fullname()) != 0) rec_fputs(dst, REC_TYPE_FULL, full_name); rec_fputs(dst, REC_TYPE_FROM, saved_sender); diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 9c93fd0e3..96147559d 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -1141,9 +1141,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) } else if ((state->err & CLEANUP_STAT_WRITE) != 0) { state->error_mask |= MAIL_ERROR_RESOURCE; smtpd_chat_reply(state, "451 Error: queue file write error"); - } else if ((state->err & CLEANUP_STAT_MISS_HDR) != 0) { - state->error_mask |= MAIL_ERROR_POLICY; - smtpd_chat_reply(state, "550 Error: missing message header"); } else { state->error_mask |= MAIL_ERROR_SOFTWARE; smtpd_chat_reply(state, "451 Error: internal error %d", state->err); diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index ee56be523..f3ef3fe4f 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -57,13 +57,6 @@ /* Reject, defer or permit the request unconditionally. This is to be used /* at the end of a restriction list in order to make the default /* action explicit. -/* .IP require_date_header -/* .IP require_from_header -/* .IP require_message_id_header -/* .IP require_received_header -/* Reject the message when it does not contain a Date: etc. -/* message header. Only the Date: header is required by mail -/* standards. The other headers are usually added by MTAs. /* .IP reject_unknown_client /* Reject the request when the client hostname could not be found. /* The \fIunknown_client_reject_code\fR configuration parameter @@ -2757,26 +2750,6 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY, "450 <%s>: %s rejected: defer_if_reject requested", reply_name, reply_class); - } else if (strcasecmp(name, REQUIRE_DATE_HDR) == 0) { -#ifndef TEST - rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", - CLEANUP_FLAG_NEED_DATE); -#endif - } else if (strcasecmp(name, REQUIRE_FROM_HDR) == 0) { -#ifndef TEST - rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", - CLEANUP_FLAG_NEED_FROM); -#endif - } else if (strcasecmp(name, REQUIRE_MSGID_HDR) == 0) { -#ifndef TEST - rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", - CLEANUP_FLAG_NEED_MSGID); -#endif - } else if (strcasecmp(name, REQUIRE_RCVD_HDR) == 0) { -#ifndef TEST - rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", - CLEANUP_FLAG_NEED_RCVD); -#endif } /*