diff -ur sendmail-8.13.8-orig/sendmail/conf.c sendmail-8.13.8-qbexp/sendmail/conf.c
--- sendmail-8.13.8-orig/sendmail/conf.c	2006-03-22 17:49:33.000000000 -0500
+++ sendmail-8.13.8-qbexp/sendmail/conf.c	2006-11-20 15:10:01.000000000 -0500
@@ -6279,6 +6279,14 @@
 	/* Exponential queue delay; disabled in 8.13 since it isn't used. */
 	"_FFR_QUEUEDELAY",
 #endif /* _FFR_QUEUEDELAY */
+#if _FFR_QUEUE_TIMING
+	/* Uses backoff timing */
+	"_FFR_QUEUE_TIMING",
+#endif /* _FFR_QUEUE_TIMING */
+#if _FFR_QUEUE_INITIAL_RETRY
+	/* do initial retry right away, ignoring MinQueueAge and  _FFR_QUEUE_TIMING */
+	"_FFR_QUEUE_INITIAL_RETRY",
+#endif /* _FFR_QUEUE_INITIAL_RETRY */
 #if _FFR_QUEUE_GROUP_SORTORDER
 	/* Allow QueueSortOrder per queue group. */
 /* XXX: Still need to actually use qgrp->qg_sortorder */
diff -ur sendmail-8.13.8-orig/sendmail/queue.c sendmail-8.13.8-qbexp/sendmail/queue.c
--- sendmail-8.13.8-orig/sendmail/queue.c	2006-07-31 17:44:18.000000000 -0400
+++ sendmail-8.13.8-qbexp/sendmail/queue.c	2006-11-20 19:10:00.000000000 -0500
@@ -2472,6 +2472,10 @@
 	QUEUE_CHAR *check;
 	char qd[MAXPATHLEN];
 	char qf[MAXPATHLEN];
+#if _FFR_QUEUE_TIMING || _FFR_QUEUE_INITIAL_RETRY
+	int ntries = 0;
+	time_t age;
+#endif /* _FFR_QUEUE_TIMING || _FFR_QUEUE_INITIAL_RETRY */
 
 	wn = WorkListCount - 1;
 	num_ent = 0;
@@ -2717,7 +2721,9 @@
 				   sizeof lbuf) != NULL)
 		{
 			int c;
+#if !_FFR_QUEUE_TIMING && !_FFR_QUEUE_INITIAL_RETRY
 			time_t age;
+#endif /* !_FFR_QUEUE_TIMING && !_FFR_QUEUE_INITIAL_RETRY */
 
 			p = strchr(lbuf, '\n');
 			if (p != NULL)
@@ -2842,15 +2848,71 @@
 				age = curtime() - (time_t) atol(&lbuf[1]);
 				if (age >= 0 && MinQueueAge > 0 &&
 				    age < MinQueueAge)
+#if _FFR_QUEUE_TIMING || _FFR_QUEUE_INITIAL_RETRY
+				{
+					if (tTd(41, 49))
+						sm_dprintf("retry %s (%x) younger than MinQueueAge %s\n", 
+							w->w_name, i, pintvl(MinQueueAge, true));
 					w->w_tooyoung = true;
+				}
+#else /* _FFR_QUEUE_TIMING || _FFR_QUEUE_INITIAL_RETRY */
+					w->w_tooyoung = true;
+#endif /* _FFR_QUEUE_TIMING || _FFR_QUEUE_INITIAL_RETRY */
 				break;
 
 			  case 'N':
+#if _FFR_QUEUE_TIMING || _FFR_QUEUE_INITIAL_RETRY
+				if ((ntries = atol(&lbuf[1])) == 0)
+#else /* _FFR_QUEUE_TIMING || _FFR_QUEUE_INITIAL_RETRY */
 				if (atol(&lbuf[1]) == 0)
+#endif /* _FFR_QUEUE_TIMING || _FFR_QUEUE_INITIAL_RETRY */
 					w->w_tooyoung = false;
 				break;
 			}
 		}
+
+#if _FFR_QUEUE_TIMING
+		if (bitnset(QD_BACKOFF, Queue[qgrp]->qg_flags))
+		{
+			time_t minqueueage = Queue[qgrp]->qg_minage << ntries;
+			if (minqueueage && Queue[qgrp]->qg_divisor)
+				minqueueage /= Queue[qgrp]->qg_divisor;
+			if (minqueueage > Queue[qgrp]->qg_maxage)
+				minqueueage = Queue[qgrp]->qg_maxage;
+			if (age < minqueueage)
+			{
+				if (tTd(41, 49))
+					sm_dprintf("retry %s (%x) attempt %d, younger than backoff minqueueage %s\n", 
+						w->w_name, i, ntries, pintvl(minqueueage, true));
+				w->w_tooyoung = true;
+			}
+		}
+		else if (!w->w_tooyoung && age < Queue[qgrp]->qg_minage && ntries)
+		{
+			if (tTd(41, 49))
+				sm_dprintf("retry %s (%x) attempt %d, younger than minage %s\n", 
+					w->w_name, i, ntries, pintvl(Queue[qgrp]->qg_minage, true));
+			w->w_tooyoung = true;
+		}
+		if (w->w_tooyoung && age > Queue[qgrp]->qg_maxage && Queue[qgrp]->qg_maxage)
+		{
+			if (tTd(41, 49))
+				sm_dprintf("retry %s (%x) attempt %d, older than maxage %s\n", 
+					w->w_name, i, ntries, pintvl(Queue[qgrp]->qg_maxage, true));
+			w->w_tooyoung = false;
+		}
+#endif /* _FFR_QUEUE_TIMING */
+#if _FFR_QUEUE_INITIAL_RETRY
+		if (ntries <= 1 && w->w_tooyoung && 
+			bitnset(QD_INITIAL_RETRY, Queue[qgrp]->qg_flags))
+		{
+			if (tTd(41, 49))
+				sm_dprintf("never to young for an initial retry %s (%x)\n", 
+					w->w_name, i);
+			w->w_tooyoung = false;
+		}
+#endif /* _FFR_QUEUE_INITIAL_RETRY */
+
 		if (cf != NULL)
 			(void) sm_io_close(cf, SM_TIME_DEFAULT);
 
@@ -7195,6 +7257,83 @@
 	qg->qg_maxqrun = all ? MaxRunnersPerQueue : -1;
 	qg->qg_nice = NiceQueueRun;
 }
+
+#if _FFR_QUEUE_TIMING
+/*
+**  MAKEQUEUE_TIMING -- parse queue timing list
+**
+**	Called when reading configuration file.
+**
+**	Parameters:
+**		qg -- the queue group
+**		spec -- the timeout list.
+**
+**	Returns:
+**		none
+*/
+
+static void
+makequeue_timing(qg, spec)
+	QUEUEGRP *qg;	
+	char *spec;
+{
+	char fcode;
+	register char *p;
+
+	p = spec;
+
+	/* now scan through and assign info from the fields */
+	while (*p != '\0')
+	{
+		char *delimptr;
+
+		while (*p != '\0' &&
+		       (*p == ';' || (isascii(*p) && isspace(*p))))
+			p++;
+
+		/* p now points to field code */
+		fcode = *p;
+		while (*p != '\0' && *p != ':')
+			p++;
+		if (*p++ != ':')
+		{
+			syserr("X%s, T=: `:' expected", qg->qg_name);
+			return;
+		}
+		while (isascii(*p) && isspace(*p))
+			p++;
+
+		/* p now points to the field body */
+		p = munchstring(p, &delimptr, ';');
+
+		/* install the field into the filter struct */
+		switch (fcode)
+		{
+		  case 'N':
+			qg->qg_minage = convtime(p, 's');
+			break;
+
+		  case 'X':
+			qg->qg_maxage = convtime(p, 's');
+			break;
+
+		  case 'D':
+			qg->qg_divisor = atof(p);
+			break;
+
+
+		  default:
+			if (tTd(37, 10))
+				sm_dprintf("Q%s: T= %c unknown\n",
+					   qg->qg_name, fcode);
+			syserr("Q%s: unknown queue timing equate %c=",
+			       qg->qg_name, fcode);
+			break;
+		}
+		p = delimptr;
+	}
+}
+#endif /* _FFR_QUEUE_TIMING */
 /*
 **  MAKEQUEUE -- define a new queue.
 **
@@ -7383,6 +7522,11 @@
 			}
 			break;
 #endif /* _FFR_QUEUE_GROUP_SORTORDER */
+#if _FFR_QUEUE_TIMING
+		  case 'T':
+		  	makequeue_timing(qg, p);	
+			break;
+#endif /* _FFR_QUEUE_TIMING */
 
 		  default:
 			syserr("Q%s: unknown queue equate %c=",
diff -ur sendmail-8.13.8-orig/sendmail/sendmail.h sendmail-8.13.8-qbexp/sendmail/sendmail.h
--- sendmail-8.13.8-orig/sendmail/sendmail.h	2006-05-22 21:32:07.000000000 -0400
+++ sendmail-8.13.8-qbexp/sendmail/sendmail.h	2006-11-20 18:56:25.000000000 -0500
@@ -531,11 +531,23 @@
 	long	qg_qfactor;	/* slope of queue function */
 	bool	qg_doqueuerun;	/* XXX flag is it time to do a queuerun */
 #endif /* 0 */
+#if _FFR_QUEUE_TIMING
+	time_t	qg_minage;	/* minimum amount of time an item needs to sit in the queue before retry */
+	time_t	qg_maxage;	/* maximum amount of time an item can sit in the queue before retry */
+	float	qg_divisor;	/* min ((qg->qg_minage<<ntries)/divisor, qg->qg_maxage) for sitting time */
+#endif /* _FFR_QUEUE_TIMING */
 };
 
 /* bits for qg_flags (XXX: unused as of now) */
 #define QD_DEFINED	((char) 1)	/* queue group has been defined */
 #define QD_FORK		'f'	/* fork queue runs */
+#if _FFR_QUEUE_INITIAL_RETRY
+# define QD_INITIAL_RETRY	'i'	/* do an initial retry immediately */
+#endif /* _FFR_QUEUE_INITIAL_RETRY */
+#if _FFR_QUEUE_TIMING
+# define QD_BACKOFF		'b'	/* use a backoff algorithm */
+#endif /* _FFR_QUEUE_TIMING */
+	
 
 extern void	filesys_update __P((void));
 #if _FFR_ANY_FREE_FS
