diff -ur sendmail-8.14.4/include/libmilter/mfapi.h sendmail-8.14.4.patched/include/libmilter/mfapi.h
--- sendmail-8.14.4/include/libmilter/mfapi.h	2009-11-06 00:57:08.000000000 +0000
+++ sendmail-8.14.4.patched/include/libmilter/mfapi.h	2010-01-17 17:40:05.000000000 +0000
@@ -422,6 +422,13 @@
 LIBMILTER_API int smfi_setmlreply __P((SMFICTX *, const char *, const char *, ...));
 
 /*
+ **  Alternatively, smfi_setreplies is used for commands, that need multiple
+ **  reply values. Currently applicatable only when PRDR is used.
+ */
+
+ LIBMILTER_API int smfi_setreplies __P((SMFICTX *, char **, char **, char**));
+
+/*
 **  Set the specific reply code to be used in response to the active
 **  command. If not specified, a generic reply code is used.
 **
diff -ur sendmail-8.14.4/libmilter/engine.c sendmail-8.14.4.patched/libmilter/engine.c
--- sendmail-8.14.4/libmilter/engine.c	2009-11-06 00:57:07.000000000 +0000
+++ sendmail-8.14.4.patched/libmilter/engine.c	2010-02-24 11:50:57.000000000 +0000
@@ -658,7 +658,7 @@
 	  case SMFIS_REJECT:
 		if (ctx->ctx_reply != NULL &&
 		    ((r == SMFIS_TEMPFAIL && *ctx->ctx_reply == '4') ||
-		     (r == SMFIS_REJECT && *ctx->ctx_reply == '5')))
+		     (r == SMFIS_REJECT && *ctx->ctx_reply == '5'))
 		{
 			ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_REPLYCODE,
 					ctx->ctx_reply,
diff -ur sendmail-8.14.4/libmilter/smfi.c sendmail-8.14.4.patched/libmilter/smfi.c
--- sendmail-8.14.4/libmilter/smfi.c	2007-04-23 16:44:39.000000000 +0000
+++ sendmail-8.14.4.patched/libmilter/smfi.c	2010-02-24 11:57:15.000000000 +0000
@@ -618,6 +618,86 @@
 	return MI_SUCCESS;
 }
 
+
+/*
+**  SMFI_SETREPLIES -- set multi replies codes for the next reply to the MTA 
+**    (useful with PRDR)
+**
+**      Parameters:
+**              ctx -- Opaque context structure
+**              rcodes -- null terminated array of reply codes
+**              xcodes -- array of DSN
+**              txt -- array of reply strings, \r\n starts a new line
+**
+**      Returns:
+**              MI_SUCCESS/MI_FAILURE
+*/
+int
+#if SM_VA_STD
+smfi_setreplies(SMFICTX *ctx, char** rcodes, char** xcodes, char** text)
+#else /* SM_VA_STD */
+smfi_setreplies(ctx, rcode, xcode, text)
+	SMFICTX *ctx;
+	char** rcodes;
+        char** xcodes;
+        char** text;
+#endif /* SM_VA_STD */
+
+  size_t len = 0;
+  char  *j, *temp;
+  //put the resulting string in ctx->ctx_reply and return MI_SUCCESS;
+  int i = 0, this_line;
+  while (rcodes[i] != NULL) {
+    this_line = strlen(rcodes[i]) + 3;//2 = \r\n, 1 for ' '
+    if (xcodes[i]) this_line+= strlen(xcodes[i])+1;
+    if (text[i++] == NULL) {
+      len += this_line + 6;
+      continue;
+    }
+    j = text[i-1];
+    temp = j;
+    while (j = strchr(temp, '\r')) {
+      len += this_line + j - temp;
+      temp = j+2;
+    }
+    len += this_line + strlen(temp);
+  }
+  i = 0;
+  char *buf = malloc(len);
+  if (buf == NULL)
+    return MI_FAILURE;		/* oops */
+  *buf = '\0';
+  while (rcodes[i] != NULL) {
+    if (text[i] == NULL) {
+      sm_strlcat(buf, rcodes[i], len);
+      if (xcodes[i] != NULL)
+	sm_strlcat2(buf, " ", xcodes[i], len);;
+      sm_strlcat(buf, " OK\r\n", len);
+      i++;
+      continue;
+    }
+    temp = text[i];
+    while( j = strchr(temp, '\r')) {
+      *j = '\0';
+      sm_strlcat2(buf, rcodes[i], "-", len);
+      if (xcodes[i])
+	sm_strlcat2(buf, xcodes[i], " ", len);
+      sm_strlcat2(buf, temp, "\r\n", len);
+      temp = j+2;
+    }
+    sm_strlcat2(buf, rcodes[i], " ", len);
+    if (xcodes[i])
+      sm_strlcat2(buf, xcodes[i], " ", len);
+    sm_strlcat2(buf, temp, "\r\n", len);
+    i++;
+  }
+  if (ctx->ctx_reply != NULL)
+    free(ctx->ctx_reply);
+  ctx->ctx_reply = buf;
+  return MI_SUCCESS;
+}
+
+
 /*
 **  SMFI_SETMLREPLY -- set multiline reply code for the next reply to the MTA
 **
diff -ur sendmail-8.14.4/sendmail/milter.c sendmail-8.14.4.patched/sendmail/milter.c
--- sendmail-8.14.4/sendmail/milter.c	2009-11-06 00:57:06.000000000 +0000
+++ sendmail-8.14.4.patched/sendmail/milter.c	2010-02-24 12:15:42.000000000 +0000
@@ -132,7 +132,7 @@
 	if (response == NULL || \
 	    strlen(response) + 1 != (size_t) rlen || \
 	    rlen < 3 || \
-	    (response[0] != '4' && response[0] != '5') || \
+	    (response[0] != '4' && response[0] != '5' && response[0] != '3')||\
 	    !isascii(response[1]) || !isdigit(response[1]) || \
 	    !isascii(response[2]) || !isdigit(response[2])) \
 	{ \
@@ -2121,9 +2121,16 @@
 	  case SMFIR_REPLYCODE:
 		MILTER_CHECK_REPLYCODE(defresponse);
 		if (MilterLogLevel > 10)
-			sm_syslog(LOG_INFO, e->e_id,
-				  "milter=%s, action=%s, reject=%s",
-				  m->mf_name, action, response);
+		  if (response[0] != '3') {
+		    sm_syslog(LOG_INFO, e->e_id,
+			      "milter=%s, action=%s, reject=%s",
+			      m->mf_name, action, response);
+		  } else {
+		    sm_syslog(LOG_INFO, e->e_id,
+			      "milter=%s, action=%s, prdr=%s",
+			      m->mf_name, action, response);
+		    //*state = SMFIR_CONTINUE;
+		  }
 		*state = rcmd;
 		break;
 
@@ -4451,11 +4458,20 @@
 			switch (rcmd)
 			{
 			  case SMFIR_REPLYCODE:
-				MILTER_CHECK_REPLYCODE("554 5.7.1 Command rejected");
+			        *state = rcmd;
+                                if (response[0] != '3') {
+				  MILTER_CHECK_REPLYCODE("554 5.7.1 Command rejected");
+				} else {
+				  MILTER_CHECK_REPLYCODE(response);
+				  //*state = SMFIR_ACCEPT;
+				}
 				if (MilterLogLevel > 12)
+				  if (response[0] != '3')
 					sm_syslog(LOG_INFO, e->e_id, "milter=%s, reject=%s",
 						  m->mf_name, response);
-				*state = rcmd;
+				  else
+					sm_syslog(LOG_INFO, e->e_id, "milter=%s, prdr=%s",
+						  m->mf_name, response);
 				m->mf_state = SMFS_DONE;
 				break;
 
diff -ur sendmail-8.14.4/sendmail/srvrsmtp.c sendmail-8.14.4.patched/sendmail/srvrsmtp.c
--- sendmail-8.14.4/sendmail/srvrsmtp.c	2009-12-18 17:08:01.000000000 +0000
+++ sendmail-8.14.4.patched/sendmail/srvrsmtp.c	2010-02-24 12:43:54.000000000 +0000
@@ -399,7 +399,7 @@
 			if (MilterLogLevel > 3)				\
 			{						\
 				sm_syslog(LOG_INFO, e->e_id,		\
-					  "Milter: %s=%s, reject=%s",	\
+					  "Milter: %s=%s, prdr/reject=%s",\
 					  str, addr, response);		\
 				LogUsrErrs = false;			\
 			}						\
@@ -415,6 +415,11 @@
 				goto doquit;				\
 			}						\
 			else						\
+			  if (strncmp(response, "353 ", 4) == 0)   {    \
+			    message(response);				\
+			  /*state = SMFIR_CONTINUE;*/			\
+		           milter_cmd_fail = false;			\
+			} else						\
 				usrerr(response);			\
 			break;						\
 									\
@@ -2231,6 +2236,7 @@
 			**	  remember to update 'helpfile'
 			*/
 
+                        message("250-PRDR");
 			message("250-ENHANCEDSTATUSCODES");
 #if PIPELINING
 			if (bitset(SRV_OFFER_PIPE, features))
@@ -3378,7 +3384,7 @@
 			if (MilterLogLevel > 3)
 			{
 				sm_syslog(LOG_INFO, e->e_id,
-					  "Milter: cmd=data, reject=%s",
+					  "Milter: cmd=data, reject/prdr=%s",
 					  response);
 				LogUsrErrs = false;
 			}
@@ -3386,8 +3392,11 @@
 			if (ISSMTPCODE(response))
 				(void) extenhsc(response + 4, ' ', e->e_enhsc);
 #endif /* _FFR_MILTER_ENHSC */
+			if (strncmp(response, "353 ", 4) == 0) {
+			  state = SMFIR_CONTINUE;
+			} else
+			  usrerr(response);
 
-			usrerr(response);
 			if (strncmp(response, "421 ", 4) == 0
 			    || strncmp(response, "421-", 4) == 0)
 			{
@@ -3421,7 +3430,7 @@
 			if (MilterLogLevel > 3)
 			{
 				sm_syslog(LOG_INFO, e->e_id,
-					  "Milter: cmd=data, reject=%s",
+					  "Milter: cmd=data, reject/prdr=%s",
 					  MSG_TEMPFAIL);
 				LogUsrErrs = false;
 			}
@@ -3502,12 +3511,17 @@
 				sm_syslog(LOG_INFO, e->e_id,
 					  "Milter: data, reject=%s",
 					  response);
-			milteraccept = false;
 #if _FFR_MILTER_ENHSC
 			if (ISSMTPCODE(response))
 				(void) extenhsc(response + 4, ' ', e->e_enhsc);
 #endif /* _FFR_MILTER_ENHSC */
-			usrerr(response);
+
+			if (strncmp(response, "353 ", 4) != 0) {
+			  milteraccept = false;
+			  usrerr(response);
+			} else
+			  message(response);
+
 			if (strncmp(response, "421 ", 4) == 0
 			    || strncmp(response, "421-", 4) == 0)
 				rv = false;
@@ -3826,7 +3840,6 @@
 			(void) doworklist(e, true, true);
 		}
 	}
-
   abortmessage:
 	if (tTd(92, 2))
 		sm_dprintf("abortmessage: e_id=%s, EF_LOGSENDER=%d, LogLevel=%d\n",
@@ -3928,7 +3941,7 @@
 			    msg, NULL, (time_t) 0, e);
 	}
 	e->e_to = NULL;
-}
+ }
 /*
 **  CHECKSMTPATTACK -- check for denial-of-service attack by repetition
 **
@@ -4184,6 +4197,7 @@
 	char *vp;
 	ENVELOPE *e;
 {
+        if (sm_strcasecmp(kp, "prdr") == 0) ; else
 	if (sm_strcasecmp(kp, "size") == 0)
 	{
 		if (vp == NULL)
