diff --git a/include/class.format.php b/include/class.format.php
index 2a9934a6dd1342ca5e9dc80212bec2e0788c5397..c6a45798bb006c7a3be7741a2b4ff4f2410dd6b2 100644
--- a/include/class.format.php
+++ b/include/class.format.php
@@ -217,7 +217,7 @@ class Format {
             'schemes' => 'href: aim, feed, file, ftp, gopher, http, https, irc, mailto, news, nntp, sftp, ssh, telnet; *:file, http, https; src: cid, http, https, data',
             'hook_tag' => function($e, $a=0) { return Format::__html_cleanup($e, $a); },
             'elements' => '*+iframe',
-            'spec' => 'iframe=-*,height,width,type,src(match="`^(https?:)?//(www\.)?(youtube|dailymotion|vimeo)\.com/`i"),frameborder;',
+            'spec' => 'iframe=-*,height,width,type,src(match="`^(https?:)?//(www\.)?(youtube|dailymotion|vimeo)\.com/`i"),frameborder; div=data-mid',
         );
 
         return Format::html($html, $config);
diff --git a/include/class.mailer.php b/include/class.mailer.php
index 1c43398bcf4d3af04540fdbe6c01fbc181d2f2e2..41d82e8c83afb7818633ed102e0d067c26e5aad6 100644
--- a/include/class.mailer.php
+++ b/include/class.mailer.php
@@ -101,7 +101,7 @@ class Mailer {
 
         /* Message ID - generated for each outgoing email */
         $messageId = sprintf('<%s-%s>', Misc::randCode(16),
-                ($this->getEmail()?$this->getEmail()->getEmail():'@osTicketMailer'));
+            ($this->getEmail()?$this->getEmail()->getEmail():'@osTicketMailer'));
 
         $headers = array (
                 'From' => $this->getFromAddress(),
@@ -151,10 +151,17 @@ class Mailer {
         // then assume that it needs html processing to create a valid text
         // body
         $isHtml = true;
+        $mid_token = (isset($options['thread']))
+            ? $options['thread']->asMessageId($to) : '';
         if (!(isset($options['text']) && $options['text'])) {
+            if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()))
+                $message = "<div style=\"display:none\" data-mid=\"$mid_token\">$tag</div>"
+                    .$message;
             // Make sure nothing unsafe has creeped into the message
             $message = Format::safe_html($message); //XXX??
-            $mime->setTXTBody(Format::html2text($message, 90, false));
+            $txtbody = rtrim(Format::html2text($message, 90, false))
+                . ($mid_token ? "\nRef-Mid: $mid_token\n" : '');
+            $mime->setTXTBody($txtbody);
         }
         else {
             $mime->setTXTBody($message);
diff --git a/include/class.thread.php b/include/class.thread.php
index fec7c52c40d9284a18ef3f4a6fca9191db3a0713..35ec91788601d9446f926fdf08136643a81f9670 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -178,13 +178,11 @@ class Thread {
 
     function delete() {
 
-        /* XXX: Leave this out until TICKET_EMAIL_INFO_TABLE has a primary
-         *      key
-        $sql = 'DELETE mid.* FROM '.TICKET_EMAIL_INFO_TABLE.' mid
+        $sql = 'UPDATE '.TICKET_EMAIL_INFO_TABLE.' mid
             INNER JOIN '.TICKET_THREAD_TABLE.' thread ON (thread.id = mid.thread_id)
-            WHERE thread.ticket_id = '.db_input($this->getTicketId());
+            SET mid.headers = null WHERE thread.ticket_id = '
+            .db_input($this->getTicketId());
         db_query($sql);
-         */
 
         $res=db_query('DELETE FROM '.TICKET_THREAD_TABLE.' WHERE ticket_id='.db_input($this->getTicketId()));
         if(!$res || !db_affected_rows())
@@ -854,9 +852,67 @@ Class ThreadEntry {
             }
         }
 
+        // Search for the message-id token in the body
+        if (preg_match('`(?:data-mid="|Ref-Mid: )([^"\s]*)(?:$|")`',
+                $mailinfo['message'], $match))
+            if ($thread = ThreadEntry::lookupByMessageId($match[1]))
+                   return $thread;
+
         return null;
     }
 
+    /**
+     * Find a thread entry from a message-id created from the
+     * ::asMessageId() method
+     */
+    function lookupByMessageId($mid, $from) {
+        $mid = trim($mid, '<>');
+        list($ver, $ids, $mails) = explode('$', $mid, 3);
+
+        // Current version is <null>
+        if ($ver !== '')
+            return false;
+
+        $ids = @unpack('Vthread', base64_decode($ids));
+        if (!$ids || !$ids['thread'])
+            return false;
+
+        $thread = ThreadEntry::lookup($ids['thread']);
+        if (!$thread)
+            return false;
+
+        if (0 === strcasecmp($thread->asMessageId($from, $vers), $mid))
+            return $thread;
+    }
+
+    /**
+     * Get an email message-id that can be used to represent this thread
+     * entry. The same message-id can be passed to ::lookupByMessageId() to
+     * find this thread entry
+     *
+     * Formats:
+     * Initial (version <null>)
+     * <$:b32(thread-id)$:md5(to-addr.ticket-num.ticket-id)@:md5(url)>
+     *      thread-id - thread-id, little-endian INT, packed
+     *      :b32() - base32 encoded
+     *      to-addr - individual email recipient
+     *      ticket-num - external ticket number
+     *      ticket-id - internal ticket id
+     *      :md5() - last 10 hex chars of MD5 sum
+     *      url - helpdesk URL
+     */
+    function asMessageId($to, $version=false) {
+        global $ost;
+
+        $domain = md5($ost->getConfig()->getURL());
+        $ticket = $this->getTicket();
+        return sprintf('$%s$%s@%s',
+            base64_encode(pack('V', $this->getId())),
+            substr(md5($to . $ticket->getNumber() . $ticket->getId()), -10),
+            substr($domain, -10)
+        );
+    }
+
     //new entry ... we're trusting the caller to check validity of the data.
     function create($vars) {
         global $cfg;
diff --git a/include/class.ticket.php b/include/class.ticket.php
index df83644a8da74e58bda87435ab10701eb9adf1a2..124c5ff3b441ef5a078bcb4dc9f20f78d13d0b46 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -874,7 +874,8 @@ class Ticket {
 
         $options = array(
             'inreplyto'=>$message->getEmailMessageId(),
-            'references'=>$message->getEmailReferences());
+            'references'=>$message->getEmailReferences(),
+            'thread'=>$message);
 
         //Send auto response - if enabled.
         if($autorespond
@@ -888,9 +889,6 @@ class Ticket {
                           'signature' => ($dept && $dept->isPublic())?$dept->getSignature():'')
                     );
 
-            if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()))
-                $msg['body'] = "<p style=\"display:none\">$tag<p>".$msg['body'];
-
             $email->sendAutoReply($this->getEmail(), $msg['subj'], $msg['body'],
                 null, $options);
         }
@@ -1067,13 +1065,10 @@ class Ticket {
                                 'recipient' => $user,
                                 'signature' => ($dept && $dept->isPublic())?$dept->getSignature():''));
 
-            //Reply separator tag.
-            if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()))
-                $msg['body'] = "<p style=\"display:none\">$tag<p>".$msg['body'];
-
             $options = array(
-                'inreplyto' => $message->getEmailMessageId(),
-                'references' => $message->getEmailReferencesForUser($user));
+                'inreplyto'=>$message->getEmailMessageId(),
+                'references' => $message->getEmailReferencesForUser($user),
+                'thread'=>$message);
             $email->sendAutoReply($user->getEmail(), $msg['subj'], $msg['body'],
                 null, $options);
         }
@@ -1130,7 +1125,8 @@ class Ticket {
             $sentlist=array();
             $options = array(
                 'inreplyto'=>$note->getEmailMessageId(),
-                'references'=>$note->getEmailReferences());
+                'references'=>$note->getEmailReferences(),
+                'thread'=>$note);
             foreach( $recipients as $k=>$staff) {
                 if(!is_object($staff) || !$staff->isAvailable() || in_array($staff->getEmail(), $sentlist)) continue;
                 $alert = $this->replaceVars($msg, array('recipient' => $staff));
@@ -1381,7 +1377,8 @@ class Ticket {
             $sentlist=array();
             $options = array(
                 'inreplyto'=>$note->getEmailMessageId(),
-                'references'=>$note->getEmailReferences());
+                'references'=>$note->getEmailReferences(),
+                'thread'=>$note);
             foreach( $recipients as $k=>$staff) {
                 if(!is_object($staff) || !$staff->isAvailable() || in_array($staff->getEmail(), $sentlist)) continue;
                 $alert = $this->replaceVars($msg, array('recipient' => $staff));
@@ -1568,7 +1565,8 @@ class Ticket {
                 );
         $options = array(
                 'inreplyto' => $message->getEmailMessageId(),
-                'references' => $message->getEmailReferences());
+                'references' => $message->getEmailReferences(),
+                'thread'=>$message);
         //If enabled...send alert to staff (New Message Alert)
         if($cfg->alertONNewMessage()
                 && ($email = $cfg->getAlertEmail())
@@ -1643,13 +1641,11 @@ class Ticket {
             $msg = $this->replaceVars($msg->asArray(),
                 array('response' => $response, 'signature' => $signature));
 
-            if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()))
-                $msg['body'] = "<p style=\"display:none\">$tag<p>".$msg['body'];
-
             $attachments =($cfg->emailAttachments() && $files)?$response->getAttachments():array();
             $options = array(
                 'inreplyto'=>$response->getEmailMessageId(),
-                'references'=>$response->getEmailReferences());
+                'references'=>$response->getEmailReferences(),
+                'thread'=>$response);
             $email->sendAutoReply($this->getEmail(), $msg['subj'], $msg['body'], $attachments,
                 $options);
         }
@@ -1700,7 +1696,8 @@ class Ticket {
                 'poster' => $thisstaff);
         $options = array(
                 'inreplyto' => $response->getEmailMessageId(),
-                'references' => $response->getEmailReferences());
+                'references' => $response->getEmailReferences(),
+                'thread'=>$response);
 
         if(($email=$dept->getEmail())
                 && ($tpl = $dept->getTemplate())
@@ -1709,8 +1706,6 @@ class Ticket {
             $msg = $this->replaceVars($msg->asArray(),
                     $variables + array('recipient' => $this->getOwner()));
 
-            if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()))
-                $msg['body'] = "<p style=\"display:none\">$tag<p>".$msg['body'];
             $attachments = $cfg->emailAttachments()?$response->getAttachments():array();
             $email->send($this->getEmail(), $msg['subj'], $msg['body'], $attachments,
                 $options);
@@ -1824,7 +1819,8 @@ class Ticket {
 
             $options = array(
                 'inreplyto'=>$note->getEmailMessageId(),
-                'references'=>$note->getEmailReferences());
+                'references'=>$note->getEmailReferences(),
+                'thread'=>$note);
             $sentlist=array();
             foreach( $recipients as $k=>$staff) {
                 if(!is_object($staff)
@@ -2457,13 +2453,13 @@ class Ticket {
                         )
                     );
 
-            if($cfg->stripQuotedReply() && ($tag=trim($cfg->getReplySeparator())))
-                $msg['body'] = "<p style=\"display:none\">$tag<p>".$msg['body'];
-
             $references = $ticket->getLastMessage()->getEmailMessageId();
             if (isset($response))
                 $references = array($response->getEmailMessageId(), $references);
-            $options = array('references' => $references);
+            $options = array(
+                'references' => $references,
+                'thread'=>$this->getLastMessage()
+            );
             $email->send($ticket->getEmail(), $msg['subj'], $msg['body'], $attachments,
                 $options);
         }