diff --git a/include/api.tickets.php b/include/api.tickets.php
index fb12e623c03328eada3e02bfddba0178c39860c9..4aebd5341ede14d291460400c4352598b24aa4df 100644
--- a/include/api.tickets.php
+++ b/include/api.tickets.php
@@ -39,7 +39,7 @@ class TicketApiController extends ApiController {
         if(!strcasecmp($format, 'email')) {
             $supported = array_merge($supported, array('header', 'mid',
                 'emailId', 'ticketId', 'reply-to', 'reply-to-name',
-                'in-reply-to', 'references',
+                'in-reply-to', 'references', 'thread-type',
                 'recipients' => array('*' => array('name', 'email', 'source'))
                 ));
 
@@ -147,10 +147,6 @@ class TicketApiController extends ApiController {
     function processEmail() {
 
         $data = $this->getEmailRequest();
-        if($data['ticketId'] && ($ticket=Ticket::lookup($data['ticketId']))) {
-            if(($msgid=$ticket->postMessage($data, 'Email')))
-                return $ticket;
-        }
 
         if (($thread = ThreadEntry::lookupByEmailHeaders($data))
                 && $thread->postEmail($data)) {
diff --git a/include/class.mailer.php b/include/class.mailer.php
index f6b83784edd727361e927d195a1c65702759a26d..2ad10dd5a2743936bb1cf5701f0f27422c38ae28 100644
--- a/include/class.mailer.php
+++ b/include/class.mailer.php
@@ -109,7 +109,8 @@ class Mailer {
                 'Subject' => $subject,
                 'Date'=> date('D, d M Y H:i:s O'),
                 'Message-ID' => $messageId,
-                'X-Mailer' =>'osTicket Mailer'
+                'X-Mailer' =>'osTicket Mailer',
+                'Return-Path' => $this->getEmail()->getEmail(),
                );
 
         //Set bulk/auto-response headers.
diff --git a/include/class.mailfetch.php b/include/class.mailfetch.php
index 9184ea8d146f6b1e4c683d8cc159d3d6a12ec27d..fb4d3dd40d4892fe310e5e53bf1d2c0494d2c297 100644
--- a/include/class.mailfetch.php
+++ b/include/class.mailfetch.php
@@ -325,7 +325,7 @@ class MailFetcher {
     }
 
     //search for specific mime type parts....encoding is the desired encoding.
-    function getPart($mid, $mimeType, $encoding=false, $struct=null, $partNumber=false) {
+    function getPart($mid, $mimeType, $encoding=false, $struct=null, $partNumber=false, $recurse=-1) {
 
         if(!$struct && $mid)
             $struct=@imap_fetchstructure($this->mbox, $mid);
@@ -359,11 +359,12 @@ class MailFetcher {
 
         //Do recursive search
         $text='';
-        if($struct && $struct->parts) {
+        if($struct && $struct->parts && $recurse) {
             while(list($i, $substruct) = each($struct->parts)) {
                 if($partNumber)
                     $prefix = $partNumber . '.';
-                if(($result=$this->getPart($mid, $mimeType, $encoding, $substruct, $prefix.($i+1))))
+                if (($result=$this->getPart($mid, $mimeType, $encoding,
+                        $substruct, $prefix.($i+1), $recurse-1)))
                     $text.=$result;
             }
         }
@@ -451,6 +452,46 @@ class MailFetcher {
         return imap_fetchheader($this->mbox, $mid,FT_PREFETCHTEXT);
     }
 
+    function isBounceNotice($mid) {
+        if (!($body = $this->getPart($mid, 'message/delivery-status')))
+            return false;
+
+        $info = Mail_Parse::splitHeaders($body);
+        if (!isset($info['Action']))
+            return false;
+
+        return strcasecmp($info['Action'], 'failed') === 0;
+    }
+
+    function getDeliveryStatusMessage($mid) {
+        if (!($struct = @imap_fetchstructure($this->mbox, $mid)))
+            return false;
+
+        $ctype = $this->getMimeType($struct);
+        if (strtolower($ctype) == 'multipart/report') {
+            foreach ($struct->parameters as $p) {
+                if (strtolower($p->attribute) == 'report-type'
+                        && $p->value == 'delivery-status') {
+                    return sprintf('<pre>%s</pre>',
+                        Format::htmlchars(
+                            $this->getPart($mid, 'text/plain', $this->charset, $struct, false, 1)
+                        ));
+                }
+            }
+        }
+        return false;
+    }
+
+    function getOriginalMessage($mid) {
+        if (!($body = $this->getPart($mid, 'message/rfc822')))
+            return null;
+
+        $msg = new Mail_Parse($body);
+        if (!$msg->decode())
+            return null;
+
+        return $msg->struct;
+    }
 
     function getPriority($mid) {
         return Mail_Parse::parsePriority($this->getHeader($mid));
@@ -501,9 +542,23 @@ class MailFetcher {
         $vars = $mailinfo;
         $vars['name'] = $mailinfo['name'];
         $vars['subject'] = $mailinfo['subject'] ? $mailinfo['subject'] : '[No Subject]';
-        $vars['message'] = Format::stripEmptyLines($this->getBody($mid));
         $vars['emailId'] = $mailinfo['emailId'] ? $mailinfo['emailId'] : $this->getEmailId();
 
+        if ($this->isBounceNotice($mid)) {
+            // Fetch the original References and assign to 'references'
+            if ($msg = $this->getOriginalMessage($mid)) {
+                $vars['references'] = $msg->headers['references'];
+                unset($vars['in-reply-to']);
+            }
+            // Fetch deliver status report
+            $vars['message'] = $this->getDeliveryStatusMessage($mid);
+            $vars['thread-type'] = 'N';
+        }
+        else {
+            $vars['message'] = Format::stripEmptyLines($this->getBody($mid));
+        }
+
+
         //Missing FROM name  - use email address.
         if(!$vars['name'])
             list($vars['name']) = explode('@', $vars['email']);
@@ -658,24 +713,31 @@ class MailFetcher {
             .' WHERE mail_active=1 '
             .'  AND (mail_errors<='.$MAXERRORS.' OR (TIME_TO_SEC(TIMEDIFF(NOW(), mail_lasterror))>'.($TIMEOUT*60).') )'
             .'  AND (mail_lastfetch IS NULL OR TIME_TO_SEC(TIMEDIFF(NOW(), mail_lastfetch))>mail_fetchfreq*60)'
-            .' ORDER BY mail_lastfetch DESC'
-            .' LIMIT 10'; //Processing up to 10 emails at a time.
+            .' ORDER BY mail_lastfetch ASC';
 
-       // echo $sql;
-        if(!($res=db_query($sql)) || !db_num_rows($res))
+        if (!($res=db_query($sql)) || !db_num_rows($res))
             return;  /* Failed query (get's logged) or nothing to do... */
 
-        //TODO: Lock the table here??
+        //Get max execution time so we can figure out how long we can fetch
+        // take fetching emails.
+        if (!($max_time = ini_get('max_execution_time')))
+            $max_time = 300;
+
+        //Start time
+        $start_time = Misc::micro_time();
+        while (list($emailId, $errors)=db_fetch_row($res)) {
+            //Break if we're 80% into max execution time
+            if ((Misc::micro_time()-$start_time) > ($max_time*0.80))
+                break;
 
-        while(list($emailId, $errors)=db_fetch_row($res)) {
             $fetcher = new MailFetcher($emailId);
-            if($fetcher->connect()) {
+            if ($fetcher->connect()) {
                 db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=0, mail_lastfetch=NOW() WHERE email_id='.db_input($emailId));
                 $fetcher->fetchEmails();
                 $fetcher->close();
             } else {
                 db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=mail_errors+1, mail_lasterror=NOW() WHERE email_id='.db_input($emailId));
-                if(++$errors>=$MAXERRORS) {
+                if (++$errors>=$MAXERRORS) {
                     //We've reached the MAX consecutive errors...will attempt logins at delayed intervals
                     $msg="\nosTicket is having trouble fetching emails from the following mail account: \n".
                         "\nUser: ".$fetcher->getUsername().
diff --git a/include/class.mailparse.php b/include/class.mailparse.php
index fc865d4de2c333738ea107f73b450cb1cdcbff30..493603052e75fcf9e916f982428b065b3a43f095 100644
--- a/include/class.mailparse.php
+++ b/include/class.mailparse.php
@@ -180,6 +180,40 @@ class Mail_Parse {
         return Mail_Parse::parseAddressList($header);
     }
 
+    function isBounceNotice() {
+        if (!($body = $this->getPart($this->struct, 'message/delivery-status')))
+            return false;
+
+        $info = self::splitHeaders($body);
+        if (!isset($info['Action']))
+            return false;
+
+        return strcasecmp($info['Action'], 'failed') === 0;
+    }
+
+    function getDeliveryStatusMessage() {
+        $ctype = @strtolower($this->struct->ctype_primary.'/'.$this->struct->ctype_secondary);
+        if ($ctype == 'multipart/report'
+            && isset($this->struct->ctype_parameters['report-type'])
+            && $this->struct->ctype_parameters['report-type'] == 'delivery-status'
+        ) {
+            return sprintf('<pre>%s</pre>',
+                Format::htmlchars(
+                    $this->getPart($this->struct, 'text/plain', 1)
+                ));
+        }
+        return false;
+    }
+
+    function getOriginalMessage() {
+        foreach ($this->struct->parts as $p) {
+            $ctype = $p->ctype_primary.'/'.$p->ctype_secondary;
+            if (strtolower($ctype) === 'message/rfc822')
+                return $p->parts[0];
+        }
+        return null;
+    }
+
     function getBody(){
         global $cfg;
 
@@ -208,7 +242,7 @@ class Mail_Parse {
         return $body;
     }
 
-    function getPart($struct, $ctypepart) {
+    function getPart($struct, $ctypepart, $recurse=-1) {
 
         if($struct && !$struct->parts) {
             $ctype = @strtolower($struct->ctype_primary.'/'.$struct->ctype_secondary);
@@ -224,9 +258,10 @@ class Mail_Parse {
         }
 
         $data='';
-        if($struct && $struct->parts) {
+        if($struct && $struct->parts && $recurse) {
             foreach($struct->parts as $i=>$part) {
-                if($part && !$part->disposition && ($text=$this->getPart($part,$ctypepart)))
+                if($part && !$part->disposition
+                        && ($text=$this->getPart($part,$ctypepart,$recurse - 1)))
                     $data.=$text;
             }
         }
@@ -423,15 +458,26 @@ class EmailDataParser {
             $data['emailId'] = $emailId;
         }
 
+        if ($parser->isBounceNotice()) {
+            // Fetch the original References and assign to 'references'
+            if ($msg = $parser->getOriginalMessage())
+                $data['references'] = $msg->headers['references'];
+            // Fetch deliver status report
+            $data['message'] = $parser->getDeliveryStatusMessage();
+            $data['thread-type'] = 'N';
+        }
+        else {
+            // Typical email
+            $data['message'] = Format::stripEmptyLines($parser->getBody());
+            $data['in-reply-to'] = $parser->struct->headers['in-reply-to'];
+            $data['references'] = $parser->struct->headers['references'];
+        }
+
         $data['subject'] = $parser->getSubject();
-        $data['message'] = Format::stripEmptyLines($parser->getBody());
         $data['header'] = $parser->getHeader();
         $data['mid'] = $parser->getMessageId();
         $data['priorityId'] = $parser->getPriority();
 
-        $data['in-reply-to'] = $parser->struct->headers['in-reply-to'];
-        $data['references'] = $parser->struct->headers['references'];
-
         if (($replyto = $parser->getReplyTo()) && !PEAR::isError($replyto)) {
             $replyto = $replyto[0];
             $data['reply-to'] = $replyto->mailbox.'@'.$replyto->host;
diff --git a/include/class.thread.php b/include/class.thread.php
index c5c1707cd5b2580d93f4c25d7199c941defecace..a05dcedb9446ab36f8241e9e61d846e802f5c467 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -613,6 +613,7 @@ Class ThreadEntry {
             'reply_to' => $this,
             'recipients' => $mailinfo['recipients'],
         );
+        $errors = array();
 
         if (isset($mailinfo['attachments']))
             $vars['attachments'] = $mailinfo['attachments'];
@@ -633,7 +634,6 @@ Class ThreadEntry {
                 || ($mailinfo['staffId'] = Staff::getIdByEmail($mailinfo['email']))) {
             $vars['staffId'] = $mailinfo['staffId'];
             $poster = Staff::lookup($mailinfo['staffId']);
-            $errors = array();
             $vars['note'] = $body;
             return $ticket->postNote($vars, $errors, $poster);
         }
@@ -641,6 +641,15 @@ Class ThreadEntry {
             // Don't process the email -- it came FROM this system
             return true;
         }
+        // Support the mail parsing system declaring a thread-type
+        elseif (isset($mailinfo['thread-type'])) {
+            switch ($mailinfo['thread-type']) {
+            case 'N':
+                $vars['note'] = $body;
+                $poster = $mailinfo['email'];
+                return $ticket->postNote($vars, $errors, $poster);
+            }
+        }
         // TODO: Consider security constraints
         else {
             //XXX: Are we potentially leaking the email address to
diff --git a/scp/autocron.php b/scp/autocron.php
index 1e2460786f13405b24139bb7e4ca6bddc363c579..85e3cfbbb34c55f8085580daac7bd1fdd4e2c0b6 100644
--- a/scp/autocron.php
+++ b/scp/autocron.php
@@ -26,6 +26,12 @@ header('Cache-Control: no-cache, must-revalidate');
 header('Content-Length: '.strlen($data));
 header('Connection: Close');
 print $data;
+// Flush the request buffer
+while(@ob_end_flush());
+flush();
+//Terminate the request
+if (function_exists('fastcgi_finish_request'))
+    fastcgi_finish_request();
 
 ob_start(); //Keep the image output clean. Hide our dirt.
 //TODO: Make cron DB based to allow for better time limits. Direct calls for now sucks big time.
@@ -37,7 +43,7 @@ if($sec>180 && $ost && !$ost->isUpgradePending()): //user can call cron once eve
 require_once(INCLUDE_DIR.'class.cron.php');
 
 $thisstaff = null; //Clear staff obj to avoid false credit internal notes & auto-assignment
-Cron::TicketMonitor(); //Age tickets: We're going to age tickets regardless of cron settings. 
+Cron::TicketMonitor(); //Age tickets: We're going to age tickets regardless of cron settings.
 if($cfg && $cfg->isAutoCronEnabled()) { //ONLY fetch tickets if autocron is enabled!
     Cron::MailFetcher();  //Fetch mail.
     $ost->logDebug('Auto Cron', 'Mail fetcher cron call ['.$caller.']');
@@ -45,6 +51,5 @@ if($cfg && $cfg->isAutoCronEnabled()) { //ONLY fetch tickets if autocron is enab
 
 $_SESSION['lastcroncall']=time();
 endif;
-$output = ob_get_contents();
 ob_end_clean();
 ?>
diff --git a/scp/js/scp.js b/scp/js/scp.js
index 2ad14158f8ed3b23877b9260787b20b1465506ae..30458bcaa9a76c51b02ae1fdc35ae014519a41ef 100644
--- a/scp/js/scp.js
+++ b/scp/js/scp.js
@@ -400,6 +400,13 @@ $(document).ready(function(){
         return false;
     });
 
+    $(document).keydown(function(e) {        
+        if (e.keyCode == 27) {
+            $('div.dialog').hide();
+            $('#overlay').hide();
+        }  
+    });
+
     /* advanced search */
     $('.dialog#advanced-search').css({
         top  : ($(window).height() / 6),