diff --git a/include/class.mailer.php b/include/class.mailer.php
index b3c8c2111af544e231a564c3556d91bcfd4ffed1..3faae326690d2fe129549da8d4594b4041c0a5e3 100644
--- a/include/class.mailer.php
+++ b/include/class.mailer.php
@@ -290,25 +290,27 @@ class Mailer {
             0, 6);
     }
 
-    function send($to, $subject, $message, $options=null) {
+    function send($recipient, $subject, $message, $options=null) {
         global $ost, $cfg;
 
         //Get the goodies
         require_once (PEAR_DIR.'Mail.php'); // PEAR Mail package
         require_once (PEAR_DIR.'Mail/mime.php'); // PEAR Mail_Mime packge
 
-        $messageId = $this->getMessageId($to, $options);
+        $messageId = $this->getMessageId($recipient, $options);
 
-        if (is_object($to) && is_callable(array($to, 'getEmail'))) {
+        if (is_object($recipient) && is_callable(array($recipient, 'getEmail'))) {
             // Add personal name if available
-            if (is_callable(array($to, 'getName'))) {
+            if (is_callable(array($recipient, 'getName'))) {
                 $to = sprintf('"%s" <%s>',
-                    $to->getName()->getOriginal(), $to->getEmail()
+                    $recipient->getName()->getOriginal(), $recipient->getEmail()
                 );
             }
             else {
-                $to = $to->getEmail();
+                $to = $recipient->getEmail();
             }
+        } else {
+            $to = $recipient;
         }
 
         //do some cleanup
@@ -327,16 +329,58 @@ class Mailer {
         // Add in the options passed to the constructor
         $options = ($options ?: array()) + $this->options;
 
+        // Message Id Token
+        $mid_token = '';
+        // Check if the email is threadable
+        if (isset($options['thread'])
+            && $options['thread'] instanceof ThreadEntry
+            && ($thread = $options['thread']->getThread())) {
+
+            // Add email in-reply-to references if not set
+            if (!isset($options['inreplyto'])) {
+
+                $entry = null;
+                switch (true) {
+                case $recipient instanceof TicketOwner:
+                case $recipient instanceof Collaborator:
+                    $entry = $thread->getLastEmailMessage(array(
+                                'user_id' => $recipient->getUserId()));
+                    break;
+                case $recipient instanceof Staff:
+                    //XXX: is it necessary ??
+                    break;
+                }
+
+                if ($entry && ($mid=$entry->getEmailMessageId())) {
+                    $options['inreplyto'] = $mid;
+                    $options['references'] = $entry->getEmailReferences();
+                }
+            }
+
+            // Embedded message id token
+            $mid_token = $messageId;
+            // Set Reply-Tag
+            if (!isset($options['reply-tag'])) {
+                if ($cfg && $cfg->stripQuotedReply())
+                    $options['reply-tag'] = $cfg->getReplySeparator() . '<br/><br/>';
+                else
+                    $options['reply-tag'] = '';
+            } elseif ($options['reply-tag'] === false) {
+                $options['reply-tag'] = '';
+            }
+        }
+
+        // Return-Path
         if (isset($options['nobounce']) && $options['nobounce'])
             $headers['Return-Path'] = '<>';
         elseif ($this->getEmail() instanceof Email)
             $headers['Return-Path'] = $this->getEmail()->getEmail();
 
-        //Bulk.
+        // Bulk.
         if (isset($options['bulk']) && $options['bulk'])
             $headers+= array('Precedence' => 'bulk');
 
-        //Auto-reply - mark as autoreply and supress all auto-replies
+        // Auto-reply - mark as autoreply and supress all auto-replies
         if (isset($options['autoreply']) && $options['autoreply']) {
             $headers+= array(
                     'Precedence' => 'auto_reply',
@@ -345,51 +389,22 @@ class Mailer {
                     'Auto-Submitted' => 'auto-replied');
         }
 
-        //Notice (sort of automated - but we don't want auto-replies back
+        // Notice (sort of automated - but we don't want auto-replies back
         if (isset($options['notice']) && $options['notice'])
             $headers+= array(
                     'X-Auto-Response-Suppress' => 'OOF, AutoReply',
                     'Auto-Submitted' => 'auto-generated');
-
-        if ($options) {
-            if (isset($options['inreplyto']) && $options['inreplyto'])
-                $headers += array('In-Reply-To' => $options['inreplyto']);
-            if (isset($options['references']) && $options['references']) {
-                if (is_array($options['references']))
-                    $headers += array('References' =>
-                        implode(' ', $options['references']));
-                else
-                    $headers += array('References' => $options['references']);
-            }
-        }
-
-        // Make the best effort to add In-Reply-To and References headers
-        $reply_tag = $mid_token = '';
-        if (isset($options['thread'])
-            && $options['thread'] instanceof ThreadEntry
-        ) {
-            if ($irt = $options['thread']->getEmailMessageId()) {
-                // This is an response from an email, like and autoresponse.
-                // Web posts will not have a email message-id
-                $headers += array(
-                    'In-Reply-To' => $irt,
-                    'References' => $options['thread']->getEmailReferences()
-                );
-            }
-            elseif ($original = $options['thread']->findOriginalEmailMessage()) {
-                // Use the parent item as the email information source. This
-                // will apply for staff replies
-                $headers += array(
-                    'In-Reply-To' => $original->getEmailMessageId(),
-                    'References' => $original->getEmailReferences(),
-                );
-            }
-
-            // Configure the reply tag and embedded message id token
-            $mid_token = $messageId;
-            if ($cfg && $cfg->stripQuotedReply()
-                    && (!isset($options['reply-tag']) || $options['reply-tag']))
-                $reply_tag = $cfg->getReplySeparator() . '<br/><br/>';
+        // In-Reply-To
+        if (isset($options['inreplyto']) && $options['inreplyto'])
+            $headers += array('In-Reply-To' => $options['inreplyto']);
+
+        // References
+        if (isset($options['references']) && $options['references']) {
+            if (is_array($options['references']))
+                $headers += array('References' =>
+                    implode(' ', $options['references']));
+            else
+                $headers += array('References' => $options['references']);
         }
 
         // Use general failsafe default initially
@@ -419,10 +434,14 @@ class Mailer {
         if (!(isset($options['text']) && $options['text'])) {
             // Embed the data-mid in such a way that it should be included
             // in a response
-            if ($reply_tag || $mid_token) {
-                $message = "<div style=\"display:none\"
-                    class=\"mid-$mid_token\">$reply_tag</div>$message";
+            if ($options['reply-tag'] || $mid_token) {
+                $message = sprintf('<div style="display:none"
+                        class="mid-%s">%s</div>%s',
+                        $mid_token,
+                        $options['reply-tag'],
+                        $message);
             }
+
             $txtbody = rtrim(Format::html2text($message, 90, false))
                 . ($messageId ? "\nRef-Mid: $messageId\n" : '');
             $mime->setTXTBody($txtbody);
diff --git a/include/class.task.php b/include/class.task.php
index d86a52ef766d2a89ede2b410a50878116501b0bb..c3b23bb694c92aea9da74c3e48ac7d81069929ae 100644
--- a/include/class.task.php
+++ b/include/class.task.php
@@ -675,10 +675,7 @@ class Task extends TaskModel implements RestrictedAccess, Threadable {
             // Send the alerts.
             $sentlist = array();
             $options = $note instanceof ThreadEntry
-                ? array(
-                    'inreplyto' => $note->getEmailMessageId(),
-                    'references' => $note->getEmailReferences(),
-                    'thread' => $note)
+                ? array('thread' => $note)
                 : array();
 
             foreach ($recipients as $k => $staff) {
@@ -765,10 +762,7 @@ class Task extends TaskModel implements RestrictedAccess, Threadable {
 
             $sentlist = $options = array();
             if ($note instanceof ThreadEntry) {
-                $options += array(
-                    'inreplyto'=>$note->getEmailMessageId(),
-                    'references'=>$note->getEmailReferences(),
-                    'thread'=>$note);
+                $options += array('thread'=>$note);
             }
 
             foreach ($recipients as $k=>$staff) {
@@ -1018,10 +1012,7 @@ class Task extends TaskModel implements RestrictedAccess, Threadable {
         $options = array();
         $staffId = $thisstaff ? $thisstaff->getId() : 0;
         if ($vars['threadentry'] && $vars['threadentry'] instanceof ThreadEntry) {
-            $options = array(
-                'inreplyto' => $vars['threadentry']->getEmailMessageId(),
-                'references' => $vars['threadentry']->getEmailReferences(),
-                'thread' => $vars['threadentry']);
+            $options = array('thread' => $vars['threadentry']);
 
             // Activity details
             if (!$vars['message'])
@@ -1104,8 +1095,7 @@ class Task extends TaskModel implements RestrictedAccess, Threadable {
         $msg = $this->replaceVars($msg->asArray(), $vars);
 
         $attachments = $cfg->emailAttachments()?$entry->getAttachments():array();
-        $options = array('inreplyto' => $entry->getEmailMessageId(),
-                         'thread' => $entry);
+        $options = array('thread' => $entry);
 
         foreach ($recipients as $recipient) {
             // Skip folks who have already been included on this part of
diff --git a/include/class.thread.php b/include/class.thread.php
index 9f32b0f90521fd8682bbdc27350c589c75b2143f..b1e8445211bb52ce6f19d8700dffd12ab0758432 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -53,6 +53,7 @@ class Thread extends VerySimpleModel {
     const MODE_CLIENT = 2;
 
     var $_object;
+    var $_entries;
     var $_collaborators; // Cache for collabs
     var $_participants;
 
@@ -87,7 +88,6 @@ class Thread extends VerySimpleModel {
         return $this->entries->count();
     }
 
-    var $_entries;
     function getEntries($criteria=false) {
         if (!isset($this->_entries)) {
             $this->_entries = $this->entries->annotate(array(
@@ -2399,44 +2399,68 @@ implements TemplateVariable {
         return $this->counts[NoteThreadEntry::ENTRY_TYPE];
     }
 
-    function getMessages() {
-        return $this->entries->filter(array(
-            'type' => MessageThreadEntry::ENTRY_TYPE
-        ));
-    }
 
     function getLastMessage($criteria=false) {
-        $entries = $this->entries->filter(array(
+        $entries = clone $this->getEntries();
+        $entries->filter(array(
             'type' => MessageThreadEntry::ENTRY_TYPE
         ));
+
         if ($criteria)
             $entries->filter($criteria);
 
-        return $entries->order_by('-id')->first();
+        $entries->order_by('-id');
+
+        return $entries->first();
+    }
+
+    function getLastEmailMessage($criteria=array()) {
+
+        $criteria += array(
+                'source' => 'Email',
+                'email_info__headers__isnull' => false);
+
+        return $this->getLastMessage($criteria);
+    }
+
+    function getLastEmailMessageByUser($user) {
+
+        $uid = is_numeric($user) ? $user : 0;
+        if (!$uid && ($user instanceof EmailContact))
+            $uid = $user->getUserId();
+
+        return $uid
+                ? $this->getLastEmailMessage(array('user_id' => $uid))
+                : null;
     }
 
-    function getEntry($var) {
+    function getEntry($criteria) {
         // XXX: PUNT
-        if (is_numeric($var))
-            $id = $var;
-        else {
-            $criteria = array_merge($var, array('limit' => 1));
-            $entries = $this->getEntries($criteria);
-            if ($entries && $entries[0])
-                $id = $entries[0]['id'];
-        }
+        if (is_numeric($criteria))
+            return parent::getEntry($criteria);
 
-        return $id ? parent::getEntry($id) : null;
+        $entries = clone $this->getEntries();
+        $entries->filter($criteria);
+        return $entries->first();
+    }
+
+    function getMessages() {
+        $entries = clone $this->getEntries();
+        return $entries->filter(array(
+            'type' => MessageThreadEntry::ENTRY_TYPE
+        ));
     }
 
     function getResponses() {
-        return $this->entries->filter(array(
+        $entries = clone $this->getEntries();
+        return $entries->filter(array(
             'type' => ResponseThreadEntry::ENTRY_TYPE
         ));
     }
 
     function getNotes() {
-        return $this->entries->filter(array(
+        $entries = clone $this->getEntries();
+        return $entries->filter(array(
             'type' => NoteThreadEntry::ENTRY_TYPE
         ));
     }
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 86bc673892750bde1380ea282878a447d0083474..c97ebbd2e4f9e329f20530047283d992255593d2 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -1306,7 +1306,8 @@ implements RestrictedAccess, Threadable {
         }
 
         $options = array();
-        if ($message instanceof ThreadEntry) {
+        if (($message instanceof ThreadEntry)
+                && $message->getEmailMessageId()) {
             $options += array(
                 'inreplyto'=>$message->getEmailMessageId(),
                 'references'=>$message->getEmailReferences(),
@@ -1494,8 +1495,7 @@ implements RestrictedAccess, Threadable {
         $msg = $this->replaceVars($msg->asArray(), $vars);
 
         $attachments = $cfg->emailAttachments()?$entry->getAttachments():array();
-        $options = array('inreplyto' => $entry->getEmailMessageId(),
-                         'thread' => $entry);
+        $options = array('thread' => $entry);
         foreach ($recipients as $recipient) {
             // Skip folks who have already been included on this part of
             // the conversation
@@ -1583,10 +1583,14 @@ implements RestrictedAccess, Threadable {
                     'signature' => ($dept && $dept->isPublic())?$dept->getSignature():''
                 )
             );
-            $options = array(
-                'inreplyto' => $message->getEmailMessageId(),
-                'thread' => $message
-            );
+            $options = array('thread' => $message);
+            if ($message->getEmailMessageId()) {
+                $options += array(
+                        'inreplyto' => $message->getEmailMessageId(),
+                        'references' => $message->getEmailReferences()
+                        );
+            }
+
             $email->sendAutoReply($user, $msg['subj'], $msg['body'],
                 null, $options);
         }
@@ -1633,10 +1637,7 @@ implements RestrictedAccess, Threadable {
         $options = array();
         $staffId = $thisstaff ? $thisstaff->getId() : 0;
         if ($vars['threadentry'] && $vars['threadentry'] instanceof ThreadEntry) {
-            $options = array(
-                'inreplyto' => $vars['threadentry']->getEmailMessageId(),
-                'references' => $vars['threadentry']->getEmailReferences(),
-                'thread' => $vars['threadentry']);
+            $options = array('thread' => $vars['threadentry']);
 
             // Activity details
             if (!$vars['comments'])
@@ -1731,10 +1732,7 @@ implements RestrictedAccess, Threadable {
             // Send the alerts.
             $sentlist = array();
             $options = $note instanceof ThreadEntry
-                ? array(
-                    'inreplyto'=>$note->getEmailMessageId(),
-                    'references'=>$note->getEmailReferences(),
-                    'thread'=>$note)
+                ? array('thread'=>$note)
                 : array();
             foreach ($recipients as $k=>$staff) {
                 if (!is_object($staff)
@@ -2064,10 +2062,7 @@ implements RestrictedAccess, Threadable {
             }
             $sentlist = $options = array();
             if ($note) {
-                $options += array(
-                    'inreplyto'=>$note->getEmailMessageId(),
-                    'references'=>$note->getEmailReferences(),
-                    'thread'=>$note);
+                $options += array('thread'=>$note);
             }
             foreach ($recipients as $k=>$staff) {
                 if (!is_object($staff)
@@ -2308,7 +2303,7 @@ implements RestrictedAccess, Threadable {
         if ($alerts && $message->isBounceOrAutoReply())
             $alerts = false;
 
-        if ($alerts && $this->getThread()->getLastMessage(array(
+        if ($alerts && $this->getThread()->getLastEmailMessage(array(
             'user_id' => $message->user_id,
             'id__lt' => $message->id,
             'created__gt' => SqlFunction::NOW()->minus(SqlInterval::MINUTE(5)),
@@ -2330,11 +2325,8 @@ implements RestrictedAccess, Threadable {
             'message' => $message,
             'poster' => ($vars['poster'] ? $vars['poster'] : $this->getName())
         );
-        $options = array(
-            'inreplyto' => $message->getEmailMessageId(),
-            'references' => $message->getEmailReferences(),
-            'thread'=>$message
-        );
+
+        $options = array('thread'=>$message);
         // If enabled...send alert to staff (New Message Alert)
         if ($cfg->alertONNewMessage()
             && ($email = $dept->getAlertEmail())
@@ -2443,11 +2435,18 @@ implements RestrictedAccess, Threadable {
             );
             $attachments = ($cfg->emailAttachments() && $files)
                 ? $response->getAttachments() : array();
-            $options = array(
-                'inreplyto'=>$response->getEmailMessageId(),
-                'references'=>$response->getEmailReferences(),
-                'thread'=>$response);
-            $email->sendAutoReply($this, $msg['subj'], $msg['body'], $attachments,
+
+            $options = array('thread' => $response);
+            if (($message instanceof ThreadEntry)
+                    && $message->getUserId() == $this->getUserId()
+                    && ($mid=$message->getEmailMessageId())) {
+                $options += array(
+                        'inreplyto' => $mid,
+                        'references' => $message->getEmailReferences()
+                        );
+            }
+
+            $email->sendAutoReply($this->getOwner(), $msg['subj'], $msg['body'], $attachments,
                 $options);
         }
         return $response;
@@ -2511,21 +2510,19 @@ implements RestrictedAccess, Threadable {
             'staff' => $thisstaff,
             'poster' => $thisstaff
         );
-        $options = array(
-            'inreplyto' => $response->getEmailMessageId(),
-            'references' => $response->getEmailReferences(),
-            'thread'=>$response
-        );
 
+
+        $user = $this->getOwner();
+        $options = array('thread' => $response);
         if (($email=$dept->getEmail())
             && ($tpl = $dept->getTemplate())
             && ($msg=$tpl->getReplyMsgTemplate())
         ) {
             $msg = $this->replaceVars($msg->asArray(),
-                $variables + array('recipient' => $this->getOwner())
+                $variables + array('recipient' => $user)
             );
             $attachments = $cfg->emailAttachments()?$response->getAttachments():array();
-            $email->send($this->getOwner(), $msg['subj'], $msg['body'], $attachments,
+            $email->send($user, $msg['subj'], $msg['body'], $attachments,
                 $options);
         }
 
@@ -3558,14 +3555,8 @@ implements RestrictedAccess, Threadable {
                     'staff'     => $thisstaff,
                 )
             );
-            $references = array();
             $message = $ticket->getLastMessage();
-            if (isset($message))
-                $references[] = $message->getEmailMessageId();
-            if (isset($response))
-                $references[] = $response->getEmailMessageId();
             $options = array(
-                'references' => $references,
                 'thread' => $message ?: $ticket->getThread(),
             );
             $email->send($ticket->getOwner(), $msg['subj'], $msg['body'], $attachments,