Subject: Postfix 19990906 Patch04: defer logfile lossage

From: [email-masked] (Wietse Venema)
Date: Wed, 22 Sep 1999 21:32:40 -0400 (EDT)

Problem: as of Postfix 19990906, defer logfiles were being deleted
at the wrong time.

Impact: in some cases, mailq would no longer show why mail is
delayed, and delayed mail could be sent back to the sender with
undeliverable recipients missing from the error report.

Background: the queue manager would throw away defer logs after
deferring mail to known-to-be-dead hosts or message transports.
It should reset the logs before doing so.

The patch below corrects the problem.

A fully-patched version, Postfix-19990906-pl04 will be distributed
from ftp://ftp.porcupine.org/postfix-release/official and mirrors.

Credits to Giulio Orsero @ tiscalinet.it for finding the problem.

	Wietse

Prereq: "Postfix-19990906-pl03"
*** ./global/mail_version.h.orig	Wed Sep 22 12:34:40 1999
--- ./global/mail_version.h	Wed Sep 22 20:13:18 1999
***************
*** 15,21 ****
    * Version of this program.
    */
  #define VAR_MAIL_VERSION	"mail_version"
! #define DEF_MAIL_VERSION	"Postfix-19990906-pl03"
  extern char *var_mail_version;
  
  /* LICENSE
--- 15,21 ----
    * Version of this program.
    */
  #define VAR_MAIL_VERSION	"mail_version"
! #define DEF_MAIL_VERSION	"Postfix-19990906-pl04"
  extern char *var_mail_version;
  
  /* LICENSE
*** ./qmgr/qmgr_active.c.orig	Sun Sep  5 10:51:06 1999
--- ./qmgr/qmgr_active.c	Wed Sep 22 20:12:21 1999
***************
*** 229,236 ****
  		      queue_id, MAIL_QUEUE_DEFER, queue_id);
  
  	/*
  	 * Special case if all recipients were already delivered. Send any
! 	 * bounces and clean up.
  	 */
  	if (message->refcount == 0)
  	    qmgr_active_done(message);
--- 229,243 ----
  		      queue_id, MAIL_QUEUE_DEFER, queue_id);
  
  	/*
+ 	 * Resolve recipient destinations and assign transports. This will
+ 	 * also defer or bounce recipients.
+ 	 */
+ 	qmgr_message_route(message);
+ 
+ 	/*
  	 * Special case if all recipients were already delivered. Send any
! 	 * bounces and clean up. Or, when all recipients were bounced or
! 	 * deferred, go look for more.
  	 */
  	if (message->refcount == 0)
  	    qmgr_active_done(message);
***************
*** 303,308 ****
--- 310,327 ----
  	    qmgr_active_corrupt(message->queue_id);
  	    qmgr_message_free(message);
  	} else {
+ 
+ 	    /*
+ 	     * Resolve recipient destinations and assign transports. This
+ 	     * will also defer or bounce recipients.
+ 	     */
+ 	    qmgr_message_route(message);
+ 
+ 	    /*
+ 	     * Special case if all recipients were already delivered. Send
+ 	     * any bounces and clean up. Or, when all recipients were bounced
+ 	     * or deferred, go look for more.
+ 	     */
  	    if (message->refcount == 0)
  		qmgr_active_done(message);	/* recurse for consistency */
  	}
*** ./qmgr/qmgr_message.c.orig	Wed Sep 22 12:50:35 1999
--- ./qmgr/qmgr_message.c	Wed Sep 22 20:12:21 1999
***************
*** 20,25 ****
--- 20,28 ----
  /*	void	qmgr_message_free(message)
  /*	QMGR_MESSAGE *message;
  /*
+ /*	void	qmgr_message_route(message)
+ /*	QMGR_MESSAGE *message;
+ /*
  /*	void	qmgr_message_update_warn(message)
  /*	QMGR_MESSAGE *message;
  /* DESCRIPTION
***************
*** 41,50 ****
  /*	of recipients read from a queue file is limited by the global
  /*	var_qmgr_rcpt_limit configuration parameter. When the limit
  /*	is reached, the \fIrcpt_offset\fR structure member is set to
! /*	the position where the read was terminated. Recipients are
! /*	run through the resolver, and are assigned to destination
! /*	queues. Recipients that cannot be assigned are deferred or
! /*	bounced. Mail that has bounced twice is silently absorbed.
  /*
  /*	qmgr_message_realloc() resumes reading recipients from the queue
  /*	file, and updates the recipient list and \fIrcpt_offset\fR message
--- 44,50 ----
  /*	of recipients read from a queue file is limited by the global
  /*	var_qmgr_rcpt_limit configuration parameter. When the limit
  /*	is reached, the \fIrcpt_offset\fR structure member is set to
! /*	the position where the read was terminated.
  /*
  /*	qmgr_message_realloc() resumes reading recipients from the queue
  /*	file, and updates the recipient list and \fIrcpt_offset\fR message
***************
*** 55,60 ****
--- 55,65 ----
  /*	the resources available for reuse. It is an error to destroy
  /*	a message structure that is still referenced by queue entry structures.
  /*
+ /*	qmgr_message_route() runs message recipients through the resolver,
+ /*	and assigns them to destination queues. Recipients that cannot be
+ /*	assigned are deferred or bounced. Mail that has bounced twice is
+ /*	silently absorbed.
+ /*
  /*	qmgr_message_update_warn() takes a closed message, opens it, updates
  /*	the warning field, and closes it again.
  /* DIAGNOSTICS
***************
*** 700,709 ****
  	qmgr_message_free(message);
  	return (0);
      } else {
- 	qmgr_message_sort(message);
- 	qmgr_message_resolve(message);
- 	qmgr_message_sort(message);
- 	qmgr_message_assign(message);
  	qmgr_message_close(message);
  	return (message);
      }
--- 705,710 ----
***************
*** 736,746 ****
  	qmgr_message_close(message);
  	return (0);
      } else {
- 	qmgr_message_sort(message);
- 	qmgr_message_resolve(message);
- 	qmgr_message_sort(message);
- 	qmgr_message_assign(message);
  	qmgr_message_close(message);
  	return (message);
      }
  }
--- 737,753 ----
  	qmgr_message_close(message);
  	return (0);
      } else {
  	qmgr_message_close(message);
  	return (message);
      }
+ }
+ 
+ /* qmgr_message_route - route recipients to transports */
+ 
+ void    qmgr_message_route(QMGR_MESSAGE *message)
+ {
+     qmgr_message_sort(message);
+     qmgr_message_resolve(message);
+     qmgr_message_sort(message);
+     qmgr_message_assign(message);
  }
*** ./qmgr/qmgr.h.orig	Tue Aug 31 14:08:37 1999
--- ./qmgr/qmgr.h	Wed Sep 22 20:12:21 1999
***************
*** 245,250 ****
--- 245,251 ----
  extern void qmgr_message_update_warn(QMGR_MESSAGE *);
  extern QMGR_MESSAGE *qmgr_message_alloc(const char *, const char *, int);
  extern QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *);
+ extern void qmgr_message_route(QMGR_MESSAGE *);
  
   /*
    * qmgr_defer.c
*** ./HISTORY.orig	Wed Sep 22 13:07:36 1999
--- ./HISTORY	Wed Sep 22 20:37:16 1999
***************
*** 3061,3063 ****
--- 3061,3070 ----
  	order to protect external commands against surprises.
  	Credits to Mads Kiilerich @ Kiilerich.com.  File:
  	qmgr/qmgr_message.c.
+ 
+ 	Bugfix: after 19990831, the queue manager would throw away
+ 	defer logs after deferring mail to known-to-be-dead hosts
+ 	or message transports. This means that in some cases, mailq
+ 	would not show why mail is delayed, and that delayed mail
+ 	could be sent back with recipients missing from the error
+ 	report. Reported by Giulio Orsero @ tiscalinet.it.