Prereq: "2.5.16"
diff -cr --new-file /var/tmp/postfix-2.5.16/src/global/mail_version.h ./src/global/mail_version.h
*** /var/tmp/postfix-2.5.16/src/global/mail_version.h	Sun Oct 23 19:55:14 2011
--- ./src/global/mail_version.h	Sat Feb  4 20:09:16 2012
***************
*** 20,27 ****
    * Patches change both the patchlevel and the release date. Snapshots have no
    * patchlevel; they change the release date only.
    */
! #define MAIL_RELEASE_DATE	"20111024"
! #define MAIL_VERSION_NUMBER	"2.5.16"
  
  #ifdef SNAPSHOT
  # define MAIL_VERSION_DATE	"-" MAIL_RELEASE_DATE
--- 20,27 ----
    * Patches change both the patchlevel and the release date. Snapshots have no
    * patchlevel; they change the release date only.
    */
! #define MAIL_RELEASE_DATE	"20120204"
! #define MAIL_VERSION_NUMBER	"2.5.17"
  
  #ifdef SNAPSHOT
  # define MAIL_VERSION_DATE	"-" MAIL_RELEASE_DATE
diff -cr --new-file /var/tmp/postfix-2.5.16/HISTORY ./HISTORY
*** /var/tmp/postfix-2.5.16/HISTORY	Thu Oct 20 17:40:57 2011
--- ./HISTORY	Sat Feb  4 16:57:49 2012
***************
*** 14773,14775 ****
--- 14773,14809 ----
  	checks to unknown message subtypes such as message/global*.
  	File: global/mime_state.c.
  
+ 20111024
+ 
+ 	Bugfix (introduced: Postfix 2.3): while the Postfix SMTP
+ 	client's protocol parser uses the last SMTP reply line as
+ 	intended, the error processing routine was taking information
+ 	from the beginning of the response. This was causing "Protocol
+ 	error" bounces with postscreen responses on Postfix < 2.6.
+ 	Reported by Ralf Hildebrandt. File: smtp/smtp_trouble.c.
+ 
+ 20111226
+ 
+ 	Bugfix (introduced 20110426): after lookup error with
+ 	mailbox_transport_maps, mailbox_command_maps or
+ 	fallback_transport_maps, the local delivery agent did not
+ 	log the problem before deferring mail, and produced no defer
+ 	logfile record. Files: local/mailbox.c, local/unknown.c.
+ 
+ 20120130
+ 
+ 	Bugfix (introduced: Postfix 2.3): the trace service did not
+ 	distinguish between DSN SUCCESS notifications for a non-bounce
+ 	or a bounce message, and replied to mail from <>. This code
+ 	pre-dates DSN support and should have been updated when it
+ 	was re-purposed to handle DSN SUCCESS notifications. Problem
+ 	reported by Sabahattin Gucukoglu.  File:
+ 	bounce/bounce_trace_service.c.
+ 
+ 20120202
+ 
+ 	Bugfix (introduced: Postfix 2.3): the "change header" milter
+ 	request could replace the wrong header. A long header name
+ 	could match a shorter one, because a length check was done
+ 	on the wrong string.  Reported by Vladimir Vassiliev.  File:
+ 	cleanup/cleanup_milter.c.
diff -cr --new-file /var/tmp/postfix-2.5.16/src/bounce/bounce_trace_service.c ./src/bounce/bounce_trace_service.c
*** /var/tmp/postfix-2.5.16/src/bounce/bounce_trace_service.c	Mon Jul 10 20:24:10 2006
--- ./src/bounce/bounce_trace_service.c	Sat Feb  4 16:40:04 2012
***************
*** 83,90 ****
      BOUNCE_INFO *bounce_info;
      int     bounce_status = 1;
      VSTREAM *bounce;
!     VSTRING *new_id = vstring_alloc(10);
      int     count;
  
      /*
       * Initialize. Open queue file, bounce log, etc.
--- 83,121 ----
      BOUNCE_INFO *bounce_info;
      int     bounce_status = 1;
      VSTREAM *bounce;
!     int     notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
! 				    var_notify_classes);
!     VSTRING *new_id;
      int     count;
+     const char *sender;
+ 
+     /*
+      * For consistency with fail/delay notifications, send notification for a
+      * non-bounce message as a single-bounce message, send notification for a
+      * single-bounce message as a double-bounce message, and drop requests to
+      * send notification for a double-bounce message.
+      */
+ #define NULL_SENDER		MAIL_ADDR_EMPTY	/* special address */
+ 
+     if (strcasecmp(recipient, mail_addr_double_bounce()) == 0) {
+ 	msg_info("%s: not sending trace/success notification for "
+ 		 "double-bounce message", queue_id);
+ 	return (0);
+     } else if (*recipient == 0) {
+ 	if ((notify_mask & MAIL_ERROR_2BOUNCE) != 0) {
+ 	    recipient = var_2bounce_rcpt;
+ 	    sender = mail_addr_double_bounce();
+ 	} else {
+ 	    msg_info("%s: not sending trace/success notification "
+ 		     "for single-bounce message", queue_id);
+ 	    if (mail_queue_remove(service, queue_id) && errno != ENOENT)
+ 		msg_fatal("remove %s %s: %m", service, queue_id);
+ 	    return (0);
+ 	}
+     } else {
+ 	/* Always send notification for non-bounce message. */
+ 	sender = NULL_SENDER;
+     }
  
      /*
       * Initialize. Open queue file, bounce log, etc.
***************
*** 126,132 ****
  	bounce_mail_free(bounce_info);
  	return (0);
      }
- #define NULL_SENDER		MAIL_ADDR_EMPTY	/* special address */
  #define NULL_TRACE_FLAGS	0
  
      /*
--- 157,162 ----
***************
*** 139,145 ****
       * there are fewer potential left-over files to remove up when we create
       * a new queue file.
       */
!     if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
  					 INT_FILT_BOUNCE,
  					 NULL_TRACE_FLAGS,
  					 new_id)) != 0) {
--- 169,176 ----
       * there are fewer potential left-over files to remove up when we create
       * a new queue file.
       */
!     new_id = vstring_alloc(10);
!     if ((bounce = post_mail_fopen_nowait(sender, recipient,
  					 INT_FILT_BOUNCE,
  					 NULL_TRACE_FLAGS,
  					 new_id)) != 0) {
diff -cr --new-file /var/tmp/postfix-2.5.16/src/cleanup/cleanup_milter.c ./src/cleanup/cleanup_milter.c
*** /var/tmp/postfix-2.5.16/src/cleanup/cleanup_milter.c	Fri Feb  8 18:54:24 2008
--- ./src/cleanup/cleanup_milter.c	Thu Feb  2 10:12:25 2012
***************
*** 520,527 ****
  	     /* Reset the saved PTR record and update last_type. */ ;
  	else if ((header_label == 0
  		  || (strncasecmp(header_label, STR(buf), len) == 0
! 		      && (IS_SPACE_TAB(STR(buf)[len])
! 			  || STR(buf)[len] == ':')))
  		 && --index == 0) {
  	    /* If we have a saved PTR record, it points to start of header. */
  	    break;
--- 520,526 ----
  	     /* Reset the saved PTR record and update last_type. */ ;
  	else if ((header_label == 0
  		  || (strncasecmp(header_label, STR(buf), len) == 0
! 		      && (strlen(header_label) == len)))
  		 && --index == 0) {
  	    /* If we have a saved PTR record, it points to start of header. */
  	    break;
diff -cr --new-file /var/tmp/postfix-2.5.16/src/local/mailbox.c ./src/local/mailbox.c
*** /var/tmp/postfix-2.5.16/src/local/mailbox.c	Tue Apr 26 15:12:46 2011
--- ./src/local/mailbox.c	Sun Dec 25 15:15:55 2011
***************
*** 289,295 ****
      } else if (dict_errno != 0) {
  	/* Details in the logfile. */
  	dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure");
! 	*statusp = DEL_STAT_DEFER;
  	return (YES);
      }
      if (*var_mailbox_transport) {
--- 289,296 ----
      } else if (dict_errno != 0) {
  	/* Details in the logfile. */
  	dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure");
! 	*statusp = defer_append(BOUNCE_FLAGS(state.request),
! 				BOUNCE_ATTR(state.msg_attr));
  	return (YES);
      }
      if (*var_mailbox_transport) {
***************
*** 333,339 ****
      } else if (dict_errno != 0) {
  	/* Details in the logfile. */
  	dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure");
! 	status = DEL_STAT_DEFER;
      } else if (*var_mailbox_command) {
  	status = deliver_command(state, usr_attr, var_mailbox_command);
      } else if (*var_home_mailbox && LAST_CHAR(var_home_mailbox) == '/') {
--- 334,341 ----
      } else if (dict_errno != 0) {
  	/* Details in the logfile. */
  	dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure");
! 	status = defer_append(BOUNCE_FLAGS(state.request),
! 			      BOUNCE_ATTR(state.msg_attr));
      } else if (*var_mailbox_command) {
  	status = deliver_command(state, usr_attr, var_mailbox_command);
      } else if (*var_home_mailbox && LAST_CHAR(var_home_mailbox) == '/') {
diff -cr --new-file /var/tmp/postfix-2.5.16/src/local/unknown.c ./src/local/unknown.c
*** /var/tmp/postfix-2.5.16/src/local/unknown.c	Tue Apr 26 15:11:43 2011
--- ./src/local/unknown.c	Sun Dec 25 15:16:15 2011
***************
*** 120,126 ****
      } else if (dict_errno != 0) {
  	/* Details in the logfile. */
  	dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure");
! 	return (DEL_STAT_DEFER);
      }
      if (*var_fallback_transport) {
  	state.msg_attr.rcpt.offset = -1L;
--- 120,127 ----
      } else if (dict_errno != 0) {
  	/* Details in the logfile. */
  	dsb_simple(state.msg_attr.why, "4.3.0", "table lookup failure");
! 	return (defer_append(BOUNCE_FLAGS(state.request),
! 			     BOUNCE_ATTR(state.msg_attr)));
      }
      if (*var_fallback_transport) {
  	state.msg_attr.rcpt.offset = -1L;
diff -cr --new-file /var/tmp/postfix-2.5.16/src/smtp/smtp_trouble.c ./src/smtp/smtp_trouble.c
*** /var/tmp/postfix-2.5.16/src/smtp/smtp_trouble.c	Thu Dec 13 20:01:56 2007
--- ./src/smtp/smtp_trouble.c	Mon Oct 24 09:44:40 2011
***************
*** 288,294 ****
       * cycles.
       */
      VSTRING_RESET(why->reason);
!     if (mta_name && reply && reply[0] != '4' && reply[0] != '5') {
  	vstring_strcpy(why->reason, "Protocol error: ");
  	status = "5.5.0";
      }
--- 288,294 ----
       * cycles.
       */
      VSTRING_RESET(why->reason);
!     if (mta_name && status && status[0] != '4' && status[0] != '5') {
  	vstring_strcpy(why->reason, "Protocol error: ");
  	status = "5.5.0";
      }