diff --git a/include/class.thread.php b/include/class.thread.php
index 6569f72b1302d966b0a2061775baf83bc31c52e4..11005197501f39f61e6733707a98f00d679d49ec 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -625,14 +625,17 @@ Class ThreadEntry {
         // Disambiguate if the user happens also to be a staff member of the
         // system. The current ticket owner should _always_ post messages
         // instead of notes or responses
-        if (strcasecmp($mailinfo['email'], $ticket->getEmail()) == 0) {
+        if ($mailinfo['userId']
+                || strcasecmp($mailinfo['email'], $ticket->getEmail()) == 0) {
             $vars['message'] = $body;
+            $vars['userId'] = $mailinfo['userId'] ? $mailinfo['userId'] : $ticket->getUserId();
             return $ticket->postMessage($vars, 'Email');
         }
         // XXX: Consider collaborator role
-        elseif ($staff_id = Staff::getIdByEmail($mailinfo['email'])) {
-            $vars['staffId'] = $staff_id;
-            $poster = Staff::lookup($staff_id);
+        elseif ($mailinfo['staffId']
+                || ($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);
@@ -643,8 +646,11 @@ Class ThreadEntry {
         }
         // TODO: Consider security constraints
         else {
+            //XXX: Are we potentially leaking the email address to
+            // collaborators?
             $vars['message'] = sprintf("Received From: %s\n\n%s",
                 $mailinfo['email'], $body);
+            $vars['userId'] = 0; //Unknown user! //XXX: Assume ticket owner?
             return $ticket->postMessage($vars, 'Email');
         }
         // Currently impossible, but indicate that this thread object could
@@ -692,10 +698,14 @@ Class ThreadEntry {
 
     /* variables */
 
-    function asVar() {
+    function __toString() {
         return $this->getBody();
     }
 
+    function asVar() {
+        return (string) $this;
+    }
+
     function getVar($tag) {
         global $cfg;
 
@@ -745,7 +755,7 @@ Class ThreadEntry {
      *      previously seen. This is useful if no thread-id is associated
      *      with the email (if it was rejected for instance).
      */
-    function lookupByEmailHeaders($mailinfo, &$seen=false) {
+    function lookupByEmailHeaders(&$mailinfo, &$seen=false) {
         // Search for messages using the References header, then the
         // in-reply-to header
         $search = 'SELECT thread_id, email_mid FROM '.TICKET_EMAIL_INFO_TABLE
@@ -772,10 +782,27 @@ Class ThreadEntry {
             // @see rfc 1036, section 2.2.5
             // @see http://www.jwz.org/doc/threading.html
             foreach (array_reverse($matches[0]) as $mid) {
+                //Try to determine if it's a reply to a tagged email.
+                $ref = null;
+                if (strpos($mid, '+')) {
+                    list($left, $right) = explode('@',$mid);
+                    list($left, $ref) = explode('+', $left);
+                    $mid = "$left@$right";
+                }
                 $res = db_query(sprintf($search, db_input($mid)));
                 while (list($id) = db_fetch_row($res)) {
-                    if ($t = ThreadEntry::lookup($id))
-                        return $t;
+                    if (!($t = ThreadEntry::lookup($id))) continue;
+
+                    //We found a match  - see if we can ID the user.
+                    // XXX: Check access of ref is enough?
+                    if ($ref && ($uid = $t->getUIDFromEmailReference($ref))) {
+                        if ($ref[0] =='s') //staff
+                            $mailinfo['staffId'] = $uid;
+                        else //user or collaborator.
+                            $mailinfo['userId'] = $uid;
+                    }
+
+                    return $t;
                 }
             }
         }
@@ -785,12 +812,23 @@ Class ThreadEntry {
         // injection by third-party.
         $subject = $mailinfo['subject'];
         $match = array();
-        if ($subject && $mailinfo['email']
+        if ($subject
+                && $mailinfo['email']
                 && preg_match("/#(?:[\p{L}-]+)?([0-9]{1,10})/u", $subject, $match)
-                && ($tid = Ticket::getIdByExtId((int)$match[1], $mailinfo['email']))
-                )
-            // Return last message for the thread
-            return Message::lastByTicketId($tid);
+                //Lookup by ticket number
+                && ($ticket = Ticket::lookupByExtId((int)$match[1]))
+                //Lookup the user using the email address
+                && ($user = User::lookup(array('emails__address' => $mailinfo['email'])))) {
+            //We have a valid ticket and user
+            if ($ticket->getUserId() == $user->getId() //owner
+                    ||  ($c = Collaborator::lookup( // check if collaborator
+                            array('userId' => $user->getId(),
+                                  'ticketId' => $ticket->getId())))) {
+
+                $mailinfo['userId'] = $user->getId();
+                return $ticket->getLastMessage();
+            }
+        }
 
         return null;
     }