From 92370560ecda786f3656b7f49a54d7262223cbf7 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Tue, 22 May 2001 00:00:00 -0500 Subject: [PATCH] snapshot-20010522 --- postfix/HISTORY | 36 +++++- postfix/RELEASE_NOTES | 28 +++++ postfix/html/lmtp.8.html | 6 +- postfix/html/postsuper.1.html | 106 ++++++++++++++---- postfix/html/smtp.8.html | 6 +- postfix/html/smtpd.8.html | 2 +- postfix/man/man1/postsuper.1 | 23 +++- postfix/man/man8/lmtp.8 | 1 + postfix/man/man8/smtp.8 | 1 + postfix/man/man8/smtpd.8 | 1 + postfix/src/global/mail_queue.c | 5 + postfix/src/global/mail_version.h | 2 +- postfix/src/global/tok822_parse.c | 3 +- postfix/src/lmtp/lmtp.c | 1 + postfix/src/lmtp/lmtp.h | 2 +- postfix/src/lmtp/lmtp_proto.c | 11 +- postfix/src/lmtp/lmtp_sasl_proto.c | 16 ++- postfix/src/postsuper/postsuper.c | 172 ++++++++++++++++++++++++----- postfix/src/smtp/smtp.c | 1 + postfix/src/smtp/smtp_sasl_proto.c | 6 + postfix/src/smtpd/smtpd.c | 1 + 21 files changed, 358 insertions(+), 72 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index 5b48437ed..ef773ce67 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -5126,8 +5126,16 @@ Apologies for any names omitted. the showq command was extended to safely list the possibly world-writable maildrop directory. File: showq/showq.c. +20010504 + + Feature: postsuper -d will also delete defer and bounce + logfiles when the named queue file is found. + 20010505 + RFC 2821 feature: an SMTP server must reset all buffers + upon receipt of EHLO. File: smtpd/smtpd_check.c. + RFC 2821 feature: an SMTP server must accept a recipient address of "postmaster" without domain name. File: smtpd/smtpd_check.c. @@ -5136,13 +5144,13 @@ Apologies for any names omitted. after 554 greeting. File: smtpd/smtpd.c. RFC 2821 recommendation: if VRFY is enabled, list it in - the EHLO response. + the EHLO response. File: smtpd/smtpd.c. RFC 2821 recommendation: SMTP clients should use EHLO. The default setting of smtp_always_send_ehlo has changed from 0 (send EHLO if server greets with ESMTP) to 1 (always - greet with EHLO). In all cases, Postfix falls back to HELO - if the remote host does not support EHLO. + send EHLO). In all cases, Postfix falls back to HELO if + the server does not support EHLO. File: smtp/smtp_proto.c. 20010507 @@ -5158,9 +5166,9 @@ Apologies for any names omitted. 20010520 - Standard: deleted the "via" portion from Received: headers - generated by Postfix bounce or other notification processes. - File: global/post_mail.c. + Standard: deleted the non-standard "via" portion from + Received: headers generated by Postfix bounce or other + notification processes. File: global/post_mail.c. Robustness: eliminated stack-based recursion from the RFC 822 address parser. File: global/tok822_parse.c. @@ -5168,8 +5176,24 @@ Apologies for any names omitted. Standard: annotated the source code with comments based on RFC 2821 and 2822. Not all the changes make sense. + RFC 2821 recommendation: treat a RCPT 552 reply as if the + server sent 452. Files: smtp/smtp_proto.c, lmtp/lmtp_proto.c. + Cleanup: moved ownership of the debug_peer parameters from the applications to the library, so that a Postfix shared library does not suffer from undefined references. Files: smtp/smtp.c, lmtp/lmtp.c, smtpd/smtpd.c, global/mail_params.c. LaMont Jones, for Debian. + +20010522 + + Feature: "postsuper -r queueID" re-queues a message. The + message is moved to the maildrop queue so that the pickup + daemon will copy it to a new file with the "right" name + that matches the queue file inode number, and so that + address rewriting will be done again. This is useful after + changes of address rewriting or virtual mappings. + + Feature: "postsuper -R" re-queues all mail. This is useful + after restoring a Postfix queue from another machine, or + from backup. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 47940a31d..9fc8bffe8 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -1,3 +1,31 @@ +Incompatible changes with snapshot-20010522 +=========================================== + +The Postfix SMTP server always sends EHLO at the beginning of an +SMTP session. Specify "smtp_always_send_ehlo = no" for the old +behavior, which is to send EHLO only when the server greeting banner +contains the word ESMTP. + +Specifying EHLO in the middle of an SMTP session resets the SMTP +server state just like RSET. This behavior cannot be disabled. + +Major changes with snapshot-20010522 +==================================== + +Revision of some fine details in the light of the new RFC 2821 and +RFC 2822 standards. Changes that may affect interoperability are +listed above under "incompatible changes". + +The postsuper queue maintenance tool was extended with options to +read queue IDs from standard input (which makes it easier to drive +the tool from scripts). + +The postsuper queue maintenance tool has a new -r (requeue) option +for subjecting queue files to another iteration of address rewriting. + +The postsuper -R option requeues all mail. This is necessary after +restoring Postfix queues from another machine or from backups. + Major changes with snapshot-20010502 ==================================== diff --git a/postfix/html/lmtp.8.html b/postfix/html/lmtp.8.html index 653d5d8e4..f6c5cdc6d 100644 --- a/postfix/html/lmtp.8.html +++ b/postfix/html/lmtp.8.html @@ -75,6 +75,7 @@ LMTP(8) LMTP(8) RFC 2033 (LMTP protocol) RFC 2197 (Pipelining) RFC 2554 (AUTH command) + RFC 2821 (SMTP protocol) DIAGNOSTICS Problems and transactions are logged to syslogd(8). Cor- @@ -124,7 +125,6 @@ LMTP(8) LMTP(8) Authentication controls lmtp_enable_sasl_auth Enable per-session authentication as per RFC 2554 - (SASL). By default, Postfix is built without SASL @@ -137,6 +137,7 @@ LMTP(8) LMTP(8) LMTP(8) LMTP(8) + (SASL). By default, Postfix is built without SASL support. lmtp_sasl_password_maps @@ -190,7 +191,6 @@ LMTP(8) LMTP(8) transport_destination_concurrency_limit Limit the number of parallel deliveries to the same - destination via this mail delivery transport. @@ -203,6 +203,7 @@ LMTP(8) LMTP(8) LMTP(8) LMTP(8) + destination via this mail delivery transport. transport is the name of the service as specified in the master.cf file. The default limit is taken from the default_destination_concurrency_limit @@ -259,7 +260,6 @@ LMTP(8) LMTP(8) - 4 diff --git a/postfix/html/postsuper.1.html b/postfix/html/postsuper.1.html index 562450a29..c608c6e01 100644 --- a/postfix/html/postsuper.1.html +++ b/postfix/html/postsuper.1.html @@ -9,13 +9,14 @@ POSTSUPER(1) POSTSUPER(1) postsuper - Postfix super intendent SYNOPSIS - postsuper [-d queue_id] [-p] [-s] [-v] [directory ...] + postsuper [-psv] [-d queue_id] [-r queue_id] [directory + ...] DESCRIPTION - The postsuper command does small maintenance jobs. Use of + The postsuper command does small maintenance jobs. Use of the command is restricted to the super-user. - By default, postsuper performs the operations requested + By default, postsuper performs the operations requested with the -s and -p command-line options on the named Post- fix queue directories (default: all). Directory names are relative to the Postfix top-level queue directory. @@ -23,42 +24,41 @@ POSTSUPER(1) POSTSUPER(1) Options: -d This option ignores any directory argument(s). - Delete one message queue file with the named queue + Delete one message queue file with the named queue ID. Specify multiple -d options to delete multiple queue files by name. Alternatively, if a queue_id of - is specified, the program reads queue IDs from standard input. - The postsuper exit status is non-zero when no mes- + The postsuper exit status is non-zero when no mes- sage queue file was deleted. - There is a very small possibility that postsuper - deletes the wrong message file when it is executed + There is a very small possibility that postsuper + deletes the wrong message file when it is executed while the Postfix mail system is running. The scenario is as follows: - o The Postfix queue manager deletes the file - that postsuper was supposed to delete, - because Postfix was finished with the mes- + o The Postfix queue manager deletes the file + that postsuper was supposed to delete, + because Postfix was finished with the mes- sage. - o New mail arrives, and the new message is - given the same queue ID as the message that + o New mail arrives, and the new message is + given the same queue ID as the message that postsuper was supposed to delete. The prob- - ability for reusing a deleted queue ID is - about 1 in 2**15 (the number of different + ability for reusing a deleted queue ID is + about 1 in 2**15 (the number of different microsecond values that the system clock can - distinguish). + distinguish within a second). o postsuper deletes the new message file, - instead of the old file that should have + instead of the old file that should have been deleted. - -s Structure check. Move queue files that are in the - wrong place in the file system hierarchy and remove - subdirectories that are no longer needed. File + -r This option ignores any directory argument(s). + Requeue one message queue file with the named queue @@ -71,6 +71,26 @@ POSTSUPER(1) POSTSUPER(1) POSTSUPER(1) POSTSUPER(1) + ID. Specify multiple -r options to requeue multi- + ple queue files by name. + + Alternatively, if a queue_id of - is specified, the + program reads queue IDs from standard input. + + The queue file is moved to the maildrop queue, from + where it is copied by the pickup daemon to a new + file whose name is guaranteed to match the queue + file inode number. This feature is useful for queue + files from another machine or for files restored + from backup. The new queue file is subjected again + to address rewriting and substitution. + + The postsuper exit status is non-zero when no mes- + sage queue file was requeued. + + -s Structure check. Move queue files that are in the + wrong place in the file system hierarchy and remove + subdirectories that are no longer needed. File rearrangements are necessary after a change in the hash_queue_names and/or hash_queue_depth configura- tion parameters. It is highly recommended to run @@ -105,6 +125,18 @@ POSTSUPER(1) POSTSUPER(1) AUTHOR(S) Wietse Venema IBM T.J. Watson Research + + + + 2 + + + + + +POSTSUPER(1) POSTSUPER(1) + + P.O. Box 704 Yorktown Heights, NY 10598, USA @@ -128,7 +160,41 @@ POSTSUPER(1) POSTSUPER(1) - 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html index b493e7090..95ae82b63 100644 --- a/postfix/html/smtp.8.html +++ b/postfix/html/smtp.8.html @@ -50,6 +50,7 @@ SMTP(8) SMTP(8) RFC 1870 (Message Size Declaration) RFC 2197 (Pipelining) RFC 2554 (AUTH command) + RFC 2821 (SMTP protocol) DIAGNOSTICS Problems and transactions are logged to syslogd(8). Cor- @@ -58,7 +59,6 @@ SMTP(8) SMTP(8) Depending on the setting of the notify_classes parameter, the postmaster is notified of bounces, protocol problems, - and of other trouble. @@ -71,6 +71,8 @@ SMTP(8) SMTP(8) SMTP(8) SMTP(8) + and of other trouble. + BUGS CONFIGURATION PARAMETERS The following main.cf parameters are especially relevant @@ -126,8 +128,6 @@ SMTP(8) SMTP(8) - - 2 diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 0e96e6860..4ec83ebac 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -44,6 +44,7 @@ SMTPD(8) SMTPD(8) RFC 1870 (Message Size Declaration) RFC 1985 (ETRN command) RFC 2554 (AUTH command) + RFC 2821 (SMTP protocol) DIAGNOSTICS Problems and transactions are logged to syslogd(8). @@ -61,7 +62,6 @@ SMTPD(8) SMTPD(8) - 1 diff --git a/postfix/man/man1/postsuper.1 b/postfix/man/man1/postsuper.1 index ea22b0a98..4b5e83b43 100644 --- a/postfix/man/man1/postsuper.1 +++ b/postfix/man/man1/postsuper.1 @@ -9,8 +9,8 @@ Postfix super intendent .na .nf .fi -\fBpostsuper\fR [\fB-d \fIqueue_id\fR] [\fB-p\fR] -[\fB-s\fR] [\fB-v\fR] [\fIdirectory ...\fR] +\fBpostsuper\fR [\fB-psv\fR] [\fB-d \fIqueue_id\fR] +[\fB-r \fIqueue_id\fR] [\fIdirectory ...\fR] .SH DESCRIPTION .ad .fi @@ -51,11 +51,28 @@ New mail arrives, and the new message is given the same queue ID as the message that \fBpostsuper\fR was supposed to delete. The probability for reusing a deleted queue ID is about 1 in 2**15 (the number of different microsecond values that the system clock -can distinguish). +can distinguish within a second). .IP \(bu \fBpostsuper\fR deletes the new message file, instead of the old file that should have been deleted. .RE +.IP \fB-r \fIqueue_id\fR +This option ignores any \fIdirectory\fR argument(s). +Requeue one message queue file with the named queue ID. Specify +multiple \fB-r\fR options to requeue multiple queue files by name. +.sp +Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified, the +program reads queue IDs from standard input. +.sp +The queue file is moved to the maildrop queue, from where +it is copied by the pickup daemon to a new file whose name +is guaranteed to match the queue file inode number. This +feature is useful for queue files from another machine or +for files restored from backup. The new queue file is +subjected again to address rewriting and substitution. +.sp +The \fBpostsuper\fR exit status is non-zero when no message queue +file was requeued. .IP \fB-s\fR Structure check. Move queue files that are in the wrong place in the file system hierarchy and remove subdirectories that are diff --git a/postfix/man/man8/lmtp.8 b/postfix/man/man8/lmtp.8 index 0521d53e5..51e54e05d 100644 --- a/postfix/man/man8/lmtp.8 +++ b/postfix/man/man8/lmtp.8 @@ -60,6 +60,7 @@ RFC 1870 (Message Size Declaration) RFC 2033 (LMTP protocol) RFC 2197 (Pipelining) RFC 2554 (AUTH command) +RFC 2821 (SMTP protocol) .SH DIAGNOSTICS .ad .fi diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8 index ac6b37604..3fd07aa09 100644 --- a/postfix/man/man8/smtp.8 +++ b/postfix/man/man8/smtp.8 @@ -51,6 +51,7 @@ RFC 1651 (SMTP service extensions) RFC 1870 (Message Size Declaration) RFC 2197 (Pipelining) RFC 2554 (AUTH command) +RFC 2821 (SMTP protocol) .SH DIAGNOSTICS .ad .fi diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 7b5a4ea6e..9c3b9236b 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -48,6 +48,7 @@ RFC 1854 (SMTP Pipelining) RFC 1870 (Message Size Declaration) RFC 1985 (ETRN command) RFC 2554 (AUTH command) +RFC 2821 (SMTP protocol) .SH DIAGNOSTICS .ad .fi diff --git a/postfix/src/global/mail_queue.c b/postfix/src/global/mail_queue.c index d58bade6c..a8c3673c3 100644 --- a/postfix/src/global/mail_queue.c +++ b/postfix/src/global/mail_queue.c @@ -388,6 +388,11 @@ VSTREAM *mail_queue_enter(const char *queue_name, int mode) for (count = 0;; count++) { vstring_sprintf(id_buf, "%05X%s", (int) tv.tv_usec, file_id); mail_queue_path(path_buf, queue_name, STR(id_buf)); + if (access(STR(path_buf), X_OK) == 0) { /* collision. */ + if ((int) ++tv.tv_usec < 0) + tv.tv_usec = 0; + continue; + } if (sane_rename(STR(temp_path), STR(path_buf)) == 0) /* success */ break; if (errno == EPERM || errno == EISDIR) {/* collision. weird. */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 9d866ed9b..7e53c391a 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-20010521" +#define DEF_MAIL_VERSION "Snapshot-20010522" extern char *var_mail_version; /* LICENSE diff --git a/postfix/src/global/tok822_parse.c b/postfix/src/global/tok822_parse.c index 4bb54dc5d..e8c1a9774 100644 --- a/postfix/src/global/tok822_parse.c +++ b/postfix/src/global/tok822_parse.c @@ -467,7 +467,8 @@ static const char *tok822_comment(TOK822 *tp, const char *str) /* * XXX We cheat by storing comments in their external form. Otherwise it * would be a royal pain to preserve \ before (. That would require a - * recursive parser, which could consume unreasonable amounts of memory. + * recursive parser; the easy to implement stack-based recursion would be + * too expensive. */ VSTRING_ADDCH(tp->vstr, '('); diff --git a/postfix/src/lmtp/lmtp.c b/postfix/src/lmtp/lmtp.c index af74d8dd0..62bf023a1 100644 --- a/postfix/src/lmtp/lmtp.c +++ b/postfix/src/lmtp/lmtp.c @@ -50,6 +50,7 @@ /* RFC 2033 (LMTP protocol) /* RFC 2197 (Pipelining) /* RFC 2554 (AUTH command) +/* RFC 2821 (SMTP protocol) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* Corrupted message files are marked so that the queue manager can diff --git a/postfix/src/lmtp/lmtp.h b/postfix/src/lmtp/lmtp.h index 9574b648a..419cb38d5 100644 --- a/postfix/src/lmtp/lmtp.h +++ b/postfix/src/lmtp/lmtp.h @@ -61,7 +61,7 @@ typedef struct LMTP_STATE { #define LMTP_FEATURE_8BITMIME (1<<1) #define LMTP_FEATURE_PIPELINING (1<<2) #define LMTP_FEATURE_SIZE (1<<3) -#define SMTP_FEATURE_AUTH (1<<5) +#define LMTP_FEATURE_AUTH (1<<5) /* * lmtp.c diff --git a/postfix/src/lmtp/lmtp_proto.c b/postfix/src/lmtp/lmtp_proto.c index 93c40d543..b2a01e59f 100644 --- a/postfix/src/lmtp/lmtp_proto.c +++ b/postfix/src/lmtp/lmtp_proto.c @@ -215,7 +215,7 @@ int lmtp_lhlo(LMTP_STATE *state) lines = resp->str; (void) mystrtok(&lines, "\n"); while ((words = mystrtok(&lines, "\n")) != 0) { - if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t")) != 0) { + if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t=")) != 0) { if (strcasecmp(word, "8BITMIME") == 0) state->features |= LMTP_FEATURE_8BITMIME; else if (strcasecmp(word, "PIPELINING") == 0) @@ -232,7 +232,7 @@ int lmtp_lhlo(LMTP_STATE *state) msg_info("server features: 0x%x", state->features); #ifdef USE_SASL_AUTH - if (var_lmtp_sasl_enable && (state->features & SMTP_FEATURE_AUTH)) + if (var_lmtp_sasl_enable && (state->features & LMTP_FEATURE_AUTH)) return (lmtp_sasl_helo_login(state)); #endif @@ -483,9 +483,16 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state) * rejected, ignore RCPT TO responses: all recipients are * dead already. When all recipients are rejected the * receiver may apply a course correction. + * + * XXX 2821: Section 4.5.3.1 says that a 552 RCPT TO reply + * must be treated as if the server replied with 452. */ case LMTP_STATE_RCPT: if (!mail_from_rejected) { +#ifndef RFC821_SYNTAX + if (resp->code == 552) + resp->code = 452; +#endif rcpt = request->rcpt_list.info + recv_rcpt; if (resp->code / 100 == 2) { if (survivors == 0) diff --git a/postfix/src/lmtp/lmtp_sasl_proto.c b/postfix/src/lmtp/lmtp_sasl_proto.c index 8eaeafd14..b8c280c01 100644 --- a/postfix/src/lmtp/lmtp_sasl_proto.c +++ b/postfix/src/lmtp/lmtp_sasl_proto.c @@ -14,14 +14,14 @@ /* LMTP_STATE *state; /* DESCRIPTION /* This module contains random chunks of code that implement -/* the SMTP protocol interface for SASL negotiation. The goal +/* the LMTP protocol interface for SASL negotiation. The goal /* is to reduce clutter in the main LMTP client source code. /* /* lmtp_sasl_helo_auth() processes the AUTH option in the -/* SMTP server's EHLO response. +/* LMTP server's LHLO response. /* /* lmtp_sasl_helo_login() authenticates the LMTP client to the -/* SMTP server, using the authentication mechanism information +/* LMTP server, using the authentication mechanism information /* given by the server. The result is a Postfix delivery status /* code in case of trouble. /* @@ -52,6 +52,10 @@ /* System library. */ #include +#include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif /* Utility library. */ @@ -79,15 +83,17 @@ void lmtp_sasl_helo_auth(LMTP_STATE *state, const char *words) * then pretend that the server doesn't support SASL authentication. */ if (state->sasl_mechanism_list) { + if (strcasecmp(state->sasl_mechanism_list, words) == 0) + return; myfree(state->sasl_mechanism_list); msg_warn("%s offered AUTH option multiple times", state->session->namaddr); state->sasl_mechanism_list = 0; - state->features &= ~SMTP_FEATURE_AUTH; + state->features &= ~LMTP_FEATURE_AUTH; } if (strlen(words) > 0) { state->sasl_mechanism_list = mystrdup(words); - state->features |= SMTP_FEATURE_AUTH; + state->features |= LMTP_FEATURE_AUTH; } else { msg_warn("%s offered null AUTH mechanism list", state->session->namaddr); diff --git a/postfix/src/postsuper/postsuper.c b/postfix/src/postsuper/postsuper.c index daed36206..da6ab3fd9 100644 --- a/postfix/src/postsuper/postsuper.c +++ b/postfix/src/postsuper/postsuper.c @@ -5,8 +5,8 @@ /* Postfix super intendent /* SYNOPSIS /* .fi -/* \fBpostsuper\fR [\fB-d \fIqueue_id\fR] [\fB-p\fR] -/* [\fB-s\fR] [\fB-v\fR] [\fIdirectory ...\fR] +/* \fBpostsuper\fR [\fB-Rpsv\fR] [\fB-d \fIqueue_id\fR] +/* [\fB-r \fIqueue_id\fR] [\fIdirectory ...\fR] /* DESCRIPTION /* The \fBpostsuper\fR command does small maintenance jobs. Use of /* the command is restricted to the super-user. @@ -29,9 +29,9 @@ /* file was deleted. /* .sp /* .ft B -/* There is a very small possibility that postsuper deletes the +/* There is a very small possibility that postsuper deletes the /* wrong message file when it is executed while the Postfix mail -/* system is running. +/* system is running. /* .ft R /* .sp /* The scenario is as follows: @@ -50,6 +50,34 @@ /* \fBpostsuper\fR deletes the new message file, instead of the /* old file that should have been deleted. /* .RE +/* .IP \fB-R\fR +/* This option ignores any \fIdirectory\fR argument(s). +/* Requeue all message queue files. This option is useful for +/* restoring a Postfix queue from another machine or from backup. +/* .sp +/* Each queue file is moved to the maildrop queue, from where +/* it is copied by the pickup daemon to a new file whose name +/* is guaranteed to match the queue file inode number. The +/* new queue file is subjected again to address rewriting and +/* substitution. This is useful when rewriting rules or virtual +/* mappings have changed. +/* .IP \fB-r \fIqueue_id\fR +/* This option ignores any \fIdirectory\fR argument(s). +/* Requeue one message queue file with the named queue ID. Specify +/* multiple \fB-r\fR options to requeue multiple queue files by name. +/* .sp +/* Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified, the +/* program reads queue IDs from standard input. +/* .sp +/* The queue file is moved to the maildrop queue, from where +/* it is copied by the pickup daemon to a new file whose name +/* is guaranteed to match the queue file inode number. The +/* new queue file is subjected again to address rewriting and +/* substitution. This is useful when rewriting rules or virtual +/* mappings have changed. +/* .sp +/* The \fBpostsuper\fR exit status is non-zero when no message queue +/* file was requeued. /* .IP \fB-s\fR /* Structure check. Move queue files that are in the wrong place /* in the file system hierarchy and remove subdirectories that are @@ -110,6 +138,7 @@ #include #include #include +#include /* Global library. */ @@ -127,6 +156,8 @@ #define ACTION_STRUCT (1<<0) /* fix file organization */ #define ACTION_PURGE (1<<1) /* purge old temp files */ #define ACTION_DELETE (1<<2) /* delete named queue file(s) */ +#define ACTION_REQUEUE (1<<3) /* requeue named queue file(s) */ +#define ACTION_REQUEUE_ALL (1<<4) /* requeue all queue file(s) */ #define ACTION_DEFAULT (ACTION_STRUCT | ACTION_PURGE) @@ -173,6 +204,22 @@ static int postunlink(const char *path) return (ret); } +/* postrename - rename file with prejudice */ + +static int postrename(const char *old, const char *new) +{ + int ret; + + if ((ret = sane_rename(old, new)) == 0) { + msg_info("requeued file %s as %s", old, new); + } else if (errno != ENOENT) { + msg_warn("requeue file %s as %s: %m", old, new); + } else if (msg_verbose) { + msg_info("requeue file %s as %s: %m", old, new); + } + return (ret); +} + /* delete_one - delete one message instance and all its associated files */ static int delete_one(const char *queue_id) @@ -218,15 +265,51 @@ static int delete_one(const char *queue_id) return (found); } -/* delete_stream - delete queue IDs given on stream */ +/* requeue_one - requeue one message instance and delete its logfiles */ -static int delete_stream(VSTREAM *fp) +static int requeue_one(const char *queue_id) +{ + const char *msg_queue_names[] = { + MAIL_QUEUE_INCOMING, /* twice, to avoid */ + MAIL_QUEUE_ACTIVE, /* missing a file while */ + MAIL_QUEUE_DEFERRED, /* it is being renamed */ + MAIL_QUEUE_INCOMING, /* this is not 100% */ + MAIL_QUEUE_ACTIVE, /* foolproof but adequate */ + 0, + }; + struct stat st; + const char **msg_qpp; + const char *old_path; + VSTRING *new_path_buf = vstring_alloc(100); + int found = 0; + + /* + * Do not delete defer or bounce logfiles, to avoid losing a race where + * the queue manager decides to bounce mail after all recipients have + * been tried. + */ + for (msg_qpp = msg_queue_names; *msg_qpp != 0; msg_qpp++) { + if (mail_open_ok(*msg_qpp, queue_id, &st, &old_path) != MAIL_OPEN_YES) + continue; + (void) mail_queue_path(new_path_buf, MAIL_QUEUE_MAILDROP, queue_id); + if (postrename(old_path, STR(new_path_buf)) == 0) { + found = 1; + break; + } /* else: lost a race */ + } + vstring_free(new_path_buf); + return (found); +} + +/* operate_stream - operate on queue IDs given on stream */ + +static int operate_stream(VSTREAM *fp, int (*operator) (const char *)) { VSTRING *buf = vstring_alloc(20); int found = 0; while (vstring_get_nonl(buf, fp) != VSTREAM_EOF) - found |= delete_one(STR(buf)); + found |= operator(STR(buf)); vstring_free(buf); return (found); @@ -354,6 +437,30 @@ static void super(char **queues, int action) if (mail_queue_id_ok(path) == 0) continue; + /* + * Requeue this message. This means the pickup daemon will copy + * it to a new queue file, and that address rewriting is applied + * again. XXX Share more code with requeue_one(). Note, that this + * option is intended for large-scale mail queue restore + * operations so that at this stage, the queue file may not even + * be in the "right" place for the current machine. We therefore + * cannot rely on the mail_queue(3) API.() + */ + if ((action & ACTION_REQUEUE_ALL) + && strcmp(queue_name, MAIL_QUEUE_MAILDROP) != 0) { + (void) mail_queue_path(wanted_path, MAIL_QUEUE_MAILDROP, path); + if (rename(STR(actual_path), STR(wanted_path)) < 0) { + if (errno != ENOENT) + msg_fatal("rename %s to %s: %m", STR(actual_path), + STR(wanted_path)); + } else { + if (msg_verbose) + msg_info("rename %s to %s", STR(actual_path), + STR(wanted_path)); + } + continue; + } + /* * See if this file sits in the right place in the file system * hierarchy. Its place may be wrong after a change to the @@ -364,17 +471,19 @@ static void super(char **queues, int action) * to do everything with the postfix owner privileges regardless, * in order to limit the amount of damage that we can do. */ - (void) mail_queue_path(wanted_path, queue_name, path); - if (strcmp(STR(actual_path), STR(wanted_path)) != 0) { - if (rename(STR(actual_path), STR(wanted_path)) < 0) - if (errno != ENOENT - || mail_queue_mkdirs(STR(wanted_path)) < 0 - || rename(STR(actual_path), STR(wanted_path)) < 0) - msg_fatal("rename %s to %s: %m", STR(actual_path), - STR(wanted_path)); - if (msg_verbose) - msg_info("rename %s to %s", STR(actual_path), - STR(wanted_path)); + if (action & ACTION_STRUCT) { + (void) mail_queue_path(wanted_path, queue_name, path); + if (strcmp(STR(actual_path), STR(wanted_path)) != 0) { + if (rename(STR(actual_path), STR(wanted_path)) < 0) + if (errno != ENOENT + || mail_queue_mkdirs(STR(wanted_path)) < 0 + || rename(STR(actual_path), STR(wanted_path)) < 0) + msg_fatal("rename %s to %s: %m", STR(actual_path), + STR(wanted_path)); + if (msg_verbose) + msg_info("rename %s to %s", STR(actual_path), + STR(wanted_path)); + } } } scan_dir_close(info); @@ -473,21 +582,31 @@ int main(int argc, char **argv) while ((c = GETOPT(argc, argv, "d:spv")) > 0) { switch (c) { default: - msg_fatal("usage: %s [-d queue_id] [-p (purge stale files)] [-s (fix structure)]", + msg_fatal("usage: %s [-d queue_id (delete message)] [-p (purge stale files)] [-r queue_id (requeue message)] [-R (requeue all)] [-s (fix structure)]", argv[0]); case 'd': if (strcmp(optarg, "-") == 0) - found |= delete_stream(VSTREAM_IN); + found |= operate_stream(VSTREAM_IN, delete_one); else found |= delete_one(optarg); action |= ACTION_DELETE; break; - case 's': - action |= ACTION_STRUCT; - break; case 'p': action |= ACTION_PURGE; break; + case 'r': + if (strcmp(optarg, "-") == 0) + found |= operate_stream(VSTREAM_IN, requeue_one); + else + found |= requeue_one(optarg); + action |= ACTION_REQUEUE; + break; + case 'R': + action |= ACTION_REQUEUE_ALL; + break; + case 's': + action |= ACTION_STRUCT; + break; case 'v': msg_verbose++; break; @@ -505,8 +624,9 @@ int main(int argc, char **argv) else queues = argv + optind; - if (action & ~ACTION_DELETE) - super(queues, action & ~ACTION_DELETE); +#define ACTIONS_ON_THE_FLY (ACTION_DELETE | ACTION_REQUEUE) - exit((action & ACTION_DELETE) ? !found : 0); + if (action & ~ACTIONS_ON_THE_FLY) + super(queues, action & ~ACTIONS_ON_THE_FLY); + exit((action & ACTIONS_ON_THE_FLY) ? !found : 0); } diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index ab541acce..32c41a8d3 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -41,6 +41,7 @@ /* RFC 1870 (Message Size Declaration) /* RFC 2197 (Pipelining) /* RFC 2554 (AUTH command) +/* RFC 2821 (SMTP protocol) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* Corrupted message files are marked so that the queue manager can diff --git a/postfix/src/smtp/smtp_sasl_proto.c b/postfix/src/smtp/smtp_sasl_proto.c index f38182365..97c2592c0 100644 --- a/postfix/src/smtp/smtp_sasl_proto.c +++ b/postfix/src/smtp/smtp_sasl_proto.c @@ -52,6 +52,10 @@ /* System library. */ #include +#include +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif /* Utility library. */ @@ -79,6 +83,8 @@ void smtp_sasl_helo_auth(SMTP_STATE *state, const char *words) * then pretend that the server doesn't support SASL authentication. */ if (state->sasl_mechanism_list) { + if (strcasecmp(state->sasl_mechanism_list, words) == 0) + return; myfree(state->sasl_mechanism_list); msg_warn("%s offered AUTH option multiple times", state->session->namaddr); diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 1fc3877e3..5b7bc98e2 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -38,6 +38,7 @@ /* RFC 1870 (Message Size Declaration) /* RFC 1985 (ETRN command) /* RFC 2554 (AUTH command) +/* RFC 2821 (SMTP protocol) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /*