diff --git a/include/class.client.php b/include/class.client.php
index 36fa13746ca5cfbba82da2577214718e8418eed6..1e82ebe411a214ecbc1e8f94dd33f2e5c120d836 100644
--- a/include/class.client.php
+++ b/include/class.client.php
@@ -82,6 +82,9 @@ implements EmailContact, ITicketUser, TemplateVariable {
 
     function getId() { return ($this->user) ? $this->user->getId() : null; }
     function getEmail() { return ($this->user) ? $this->user->getEmail() : null; }
+    function getName() {
+        return ($this->user) ? $this->user->getName() : null;
+    }
 
     static function lookupByToken($token) {
 
@@ -158,6 +161,11 @@ class TicketOwner extends  TicketUser {
         $this->ticket = $ticket;
     }
 
+    function __toString() {
+        return (string) $this->getName();
+    }
+
+
     function getTicket() {
         return $this->ticket;
     }
@@ -470,12 +478,6 @@ class ClientAccount extends UserAccount {
     }
 }
 
-// Used by the email system
-interface EmailContact {
-    // function getId()
-    // function getName()
-    // function getEmail()
-}
 
 interface ITicketUser {
 /* PHP 5.3 < 5.3.8 will crash with some abstract inheritance issue
diff --git a/include/class.mailer.php b/include/class.mailer.php
index ed1ef55df3f9c1d779ee72f3172b5d3b5a536c6e..51cbab842478edffe874978856699c072cb4cec3 100644
--- a/include/class.mailer.php
+++ b/include/class.mailer.php
@@ -165,8 +165,11 @@ class Mailer {
         case $recipient instanceof Collaborator:
             $utype = 'C';
             break;
+        case  $recipient instanceof MailingList:
+            $utype = 'M';
+            break;
         default:
-            $utype = $options['utype'] ?: '?';
+            $utype = $options['utype'] ?: is_array($recipient) ? 'M' : '?';
         }
 
 
@@ -209,6 +212,7 @@ class Mailer {
      *          'U' - TicketOwner
      *          'S' - Staff
      *          'C' - Collborator
+     *          'M' - Multiple
      *          '?' - Something else
      */
     static function decodeMessageId($mid) {
@@ -294,14 +298,16 @@ class Mailer {
             0, 6);
     }
 
-    function send($recipient, $subject, $message, $options=null, $collabs=array()) {
+    function send($recipients, $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($recipient, $options);
+
+        $messageId = $this->getMessageId($recipients, $options);
+
 
         if (is_object($recipient) && is_callable(array($recipient, 'getEmail'))) {
             // Add personal name if available
@@ -323,7 +329,6 @@ class Mailer {
 
         $headers = array (
             'From' => $this->getFromAddress($options),
-            'To' => $to,
             'Subject' => $subject,
             'Date'=> date('D, d M Y H:i:s O'),
             'Message-ID' => "<{$messageId}>",
@@ -413,13 +418,35 @@ class Mailer {
 
         // Use general failsafe default initially
         $eol = "\n";
-
         // MAIL_EOL setting can be defined in `ost-config.php`
         if (defined('MAIL_EOL') && is_string(MAIL_EOL)) {
             $eol = MAIL_EOL;
         }
+
         $mime = new Mail_mime($eol);
 
+        // Add recipients
+        if (!is_array($recipients) && (!$recipients instanceof MailingList))
+            $recipients =  array($recipients);
+        foreach ($recipients as $recipient) {
+            switch (true) {
+                case $recipient instanceof TicketOwner:
+                case $recipient instanceof Staff:
+                    $mime->addTo(sprintf('%s <%s>',
+                                $recipient->getName(),
+                                $recipient->getEmail()));
+                break;
+                case $recipient instanceof Collaborator:
+                    $mime->addCc(sprintf('%s <%s>',
+                                $recipient->getName(),
+                                $recipient->getEmail()));
+                break;
+                default:
+                    // Assuming email address.
+                    $mime->addTo($recipient);
+            }
+        }
+
         // Add in extra attachments, if any from template variables
         if ($message instanceof TextWithExtras
             && ($files = $message->getFiles())
@@ -508,19 +535,6 @@ class Mailer {
             }
         }
 
-        $cc = array();
-        if($collabs) {
-          if($collabs['cc']) {
-            foreach ($collabs['cc'] as $email) {
-              $mime->addCc($email);
-              $email = preg_replace("/(\r\n|\r|\n)/s",'', trim($email));
-              $cc[] = $email;
-            }
-            $to = $to.', '.implode(', ',$cc);
-          }
-        }
-        $to = ltrim($to, ', ');
-
         //Desired encodings...
         $encodings=array(
                 'head_encoding' => 'quoted-printable',
@@ -534,7 +548,8 @@ class Mailer {
         $body = $mime->get($encodings);
         //encode the headers.
         $headers = $mime->headers($headers, true);
-
+        $to = implode(',', array_filter(array($headers['To'], $headers['Cc'],
+                    $headers['Bcc'])));
         // Cache smtp connections made during this request
         static $smtp_connections = array();
         if(($smtp=$this->getSMTPInfo())) { //Send via SMTP
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 5078b566e1f8c04944cf524ef379ef9b14b37c16..d50180eef7d47461f6ba434121e79f6250e2ddde 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -829,17 +829,17 @@ implements RestrictedAccess, Threadable, Searchable {
         return $entries;
     }
 
-    //UserList of recipients  (owner + collaborators)
+    // MailingList of recipients  (owner + active collaborators)
     function getRecipients() {
-      $list = new UserList();
-      $list->add($this->getOwner());
-      if ($collabs = $this->getThread()->getActiveCollaborators()) {
-          foreach ($collabs as $c) {
-            $list->add($c);
-          }
-      }
-      $this->recipients = $list;
-
+        if (!isset($this->recipients)) {
+            $list = new MailingList();
+            $list->add($this->getOwner());
+            if ($collabs = $this->getActiveCollaborators()) {
+                foreach ($collabs as $c)
+                    $list->add($c);
+            }
+            $this->recipients = $list;
+        }
         return $this->recipients;
     }
 
@@ -1585,6 +1585,7 @@ implements RestrictedAccess, Threadable, Searchable {
         $poster = User::lookup($entry->user_id);
         $posterEmail = $poster->getEmail()->address;
 
+        $recipients = array();
         if($vars['ccs']) {
           foreach ($vars['ccs'] as $cc) {
             $collab = Collaborator::getIdByUserId($cc, $this->getThread()->getId());
@@ -2163,8 +2164,6 @@ implements RestrictedAccess, Threadable, Searchable {
     function replaceVars($input, $vars = array()) {
         global $ost;
 
-        $recipients = $this->getRecipients();
-
         $vars = array_merge($vars, array('ticket' => $this));
         return $ost->replaceTemplateVariables($input, $vars);
     }
@@ -2843,20 +2842,16 @@ implements RestrictedAccess, Threadable, Searchable {
     function postReply($vars, &$errors, $alert=true, $claim=true) {
         global $thisstaff, $cfg;
 
-        if ($collabs = $this->getRecipients()) {
-          $collabIds = array();
-          foreach ($collabs as $collab)
-            $collabIds[] = $collab->user_id;
-        }
-
-        $ticket = Ticket::lookup($vars['id']);
+        // Add new collabs if any.
+        $collabs = $this->getCollaborators();
         if (isset($vars['ccs'])) {
-          foreach ($vars['ccs'] as $uid) {
-            $user = User::lookup($uid);
-            if (!in_array($uid, $collabIds))
-              if (($c2=$ticket->getThread()->addCollaborator($user,array(), $errors)))
-                    $c2->setCc();
-          }
+            foreach ($vars['ccs'] as $uid) {
+                if ($collabs->findFirst(array('user_id' => $uid)))
+                    continue;
+
+                if ($user=User::lookup($uid))
+                    $this->addCollaborator($user, array(), $errors);
+            }
         }
 
         if (!$vars['poster'] && $thisstaff)
@@ -2898,7 +2893,9 @@ implements RestrictedAccess, Threadable, Searchable {
             return $response;
 
         //allow agent to send from different dept email
-        $vars['from_name'] ? $email = Email::lookup($vars['from_name']) : $email = $dept->getEmail();
+        if (!$vars['from_email_id']
+                ||  !($email = Email::lookup($vars['from_email_id'])))
+            $email = $dept->getEmail();
 
         $options = array('thread'=>$response);
         $signature = $from_name = '';
@@ -2932,26 +2929,31 @@ implements RestrictedAccess, Threadable, Searchable {
             'poster' => $thisstaff
         );
 
-        $user = $this->getOwner();
-        if (($email=$email)
+        if ($email
             && ($tpl = $dept->getTemplate())
             && ($msg=$tpl->getReplyMsgTemplate())) {
 
             $msg = $this->replaceVars($msg->asArray(),
-                $variables + array('recipient' => $user)
+                $variables + array('recipient' => $this->getOwner())
             );
 
-            $attachments = $cfg->emailAttachments() ? $response->getAttachments() : array();
-            //Cc collaborators
-            $collabsCc = array();
-            if ($vars['ccs']) {
-                $collabsCc[] = Collaborator::getCollabList($vars['ccs']);
-                $collabsCc['cc'] = $collabsCc[0];
+            // Attachments
+            $attachments = $cfg->emailAttachments() ?
+                $response->getAttachments() : array();
+
+            // Get active recipients
+            $recipients = new MailingList();
+            $recioients->add($this->getOwner());
+            if ($collabs = $this->getActiveCollaborators()) {
+                foreach ($collabs as $c)
+                    if ($vars['ccs'] && in_array($c->getUserId(),
+                                $vars['ccs']))
+                        $recipients->add($c);
             }
 
-            $email->send($user, $msg['subj'], $msg['body'], $attachments,
-                    $options, $collabsCc);
-
+            //Send email to recepients
+            $email->send($recipients, $msg['subj'], $msg['body'],
+                    $attachments, $options);
         }
 
         return $response;
diff --git a/include/class.user.php b/include/class.user.php
index 083e0d5bf2b1853e82d6804a53641d353dbf8fd9..fee13c2ccbc01a215aa8a504f387c42bfefaeb10 100644
--- a/include/class.user.php
+++ b/include/class.user.php
@@ -210,9 +210,12 @@ class UserCdata extends VerySimpleModel {
 class User extends UserModel
 implements TemplateVariable, Searchable {
 
+    var $_email;
     var $_entries;
     var $_forms;
 
+
+
     static function fromVars($vars, $create=true, $update=false) {
         // Try and lookup by email address
         $user = static::lookupByEmail($vars['email']);
@@ -1310,51 +1313,17 @@ class UserAccountStatus {
     }
 }
 
-
 /*
  *  Generic user list.
  */
-class UserList extends ListObject
-implements TemplateVariable {
+class UserList extends MailingList {
 
-    function __toString() {
-        return $this->getNames();
-    }
+   function add($user) {
+        if (!$user instanceof ITicketUser)
+            throw new InvalidArgumentException('User expected');
 
-    function getNames() {
-        $list = array();
-        foreach($this->storage as $user) {
-            if (is_object($user))
-                $list [] = $user->getName();
-        }
-        return $list ? implode(', ', $list) : '';
-    }
-
-    function getFull() {
-        $list = array();
-        foreach($this->storage as $user) {
-            if (is_object($user))
-                $list[] = sprintf("%s <%s>", $user->getName(), $user->getEmail());
-        }
-
-        return $list ? implode(', ', $list) : '';
-    }
-
-    function getEmails() {
-        $list = array();
-        foreach($this->storage as $user) {
-            if (is_object($user))
-                $list[] = $user->getEmail();
-        }
-        return $list ? implode(', ', $list) : '';
-    }
-
-    static function getVarScope() {
-        return array(
-            'names' => __('List of names'),
-            'emails' => __('List of email addresses'),
-            'full' => __('List of names and email addresses'),
-        );
+        return parent::add($user);
     }
 }
+
 ?>
diff --git a/include/class.util.php b/include/class.util.php
index a56f23b2ce70c43f95c3b63c3d90987ab731331b..52035bcb2287a0e204745c504bb8f5c62e2b7f28 100644
--- a/include/class.util.php
+++ b/include/class.util.php
@@ -1,5 +1,14 @@
 <?php
 
+require_once INCLUDE_DIR . 'class.variable.php';
+
+// Used by the email system
+interface EmailContact {
+    function getId();
+    function getName();
+    function getEmail();
+}
+
 abstract class BaseList
 implements IteratorAggregate, Countable {
     protected $storage = array();
@@ -177,3 +186,54 @@ implements ArrayAccess, Serializable {
         $this->storage = unserialize($what);
     }
 }
+
+class MailingList extends ListObject
+implements TemplateVariable {
+
+    function add($contact) {
+        if (!$contact instanceof EmailContact)
+            throw new InvalidArgumentException('Email Contact expected');
+
+        return parent::add($contact);
+    }
+
+    function __toString() {
+        return $this->getNames();
+    }
+
+    function getNames() {
+        $list = array();
+        foreach($this->storage as $user) {
+            if (is_object($user))
+                $list [] = $user->getName();
+        }
+        return $list ? implode(', ', $list) : '';
+    }
+
+    function getFull() {
+        $list = array();
+        foreach($this->storage as $user) {
+            if (is_object($user))
+                $list[] = sprintf("%s <%s>", $user->getName(), $user->getEmail());
+        }
+
+        return $list ? implode(', ', $list) : '';
+    }
+
+    function getEmails() {
+        $list = array();
+        foreach($this->storage as $user) {
+            if (is_object($user))
+                $list[] = $user->getEmail();
+        }
+        return $list ? implode(', ', $list) : '';
+    }
+
+    static function getVarScope() {
+        return array(
+            'names' => __('List of names'),
+            'emails' => __('List of email addresses'),
+            'full' => __('List of names and email addresses'),
+        );
+    }
+}