diff --git a/include/api.tickets.php b/include/api.tickets.php
index f0758d5d2ea75324620ce12acbf30fe76222fb06..00d7628b2e06076938a13df268b0a52fe05dbdc3 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'));
             $supported['attachments']['*'][] = 'cid';
         }
 
@@ -144,10 +144,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 21a7d157d68a28191b88e798dade0633d3c15725..f3aa6e43ea9c5f0d8debcf0aaee1e29824d5fa2c 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 7149d44d05da615b7a0a74699ef94cc2842f5e69..e7b039211f71b9c8ff8f472503ca75eed20e3924 100644
--- a/include/class.mailfetch.php
+++ b/include/class.mailfetch.php
@@ -311,7 +311,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);
@@ -345,11 +345,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;
             }
         }
@@ -437,6 +438,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));
@@ -485,9 +526,22 @@ class MailFetcher {
         }
 
         $vars = $mailinfo;
+        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));
+        }
+
         $vars['name']=$this->mime_decode($mailinfo['name']);
         $vars['subject']=$mailinfo['subject']?$this->mime_decode($mailinfo['subject']):'[No Subject]';
-        $vars['message']=Format::stripEmptyLines($this->getBody($mid));
         $vars['emailId']=$mailinfo['emailId']?$mailinfo['emailId']:$this->getEmailId();
 
         //Missing FROM name  - use email address.
diff --git a/include/class.mailparse.php b/include/class.mailparse.php
index 32b0083a6df2c077defd19ac1560627b20ab877c..3356cb9bf1a596272d3e46e9a2cb72dfc0c41ca5 100644
--- a/include/class.mailparse.php
+++ b/include/class.mailparse.php
@@ -169,6 +169,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;
 
@@ -197,7 +231,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);
@@ -213,9 +247,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;
             }
         }
@@ -393,16 +428,27 @@ class EmailDataParser {
             }
         }
 
+        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['emailId'] = $emailId;
 
-        $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 89a5d0af571a9645e39b570c147810ba5065632f..2fda4bcae682487687a6ea162a2f32454a82dd24 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -575,6 +575,7 @@ Class ThreadEntry {
             'ip' =>     '',
             'reply_to' => $this,
         );
+        $errors = array();
 
         if (isset($mailinfo['attachments']))
             $vars['attachments'] = $mailinfo['attachments'];
@@ -591,7 +592,6 @@ Class ThreadEntry {
         elseif ($staff_id = Staff::getIdByEmail($mailinfo['email'])) {
             $vars['staffId'] = $staff_id;
             $poster = Staff::lookup($staff_id);
-            $errors = array();
             $vars['note'] = $body;
             return $ticket->postNote($vars, $errors, $poster);
         }
@@ -599,6 +599,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 {
             $vars['message'] = sprintf("Received From: %s\n\n%s",