/**
  * Test that only no duplicates can exist.
  */
 public function testDuplicateEntriesInSameFieldAreOverWritten()
 {
     $list = new Swift_RecipientList();
     $list->addCc(new Swift_Address("*****@*****.**"));
     $list->addCc("*****@*****.**", "Joe");
     $list->addCc("*****@*****.**");
     $list->addCc("*****@*****.**", "Foo");
     $this->assertEqual(3, count($list->getCc()));
 }
Beispiel #2
0
 /**
  * Send a mail, using params passed :
  * 
  * - connection:
  *     type (*)
  *     params
  * - from (*) is an address
  * - reply-to is an address or an array of addresses
  * - return-path is an address
  * - to (*) is an address or an array of addresses
  * - cc is an address or an array of addresses
  * - bcc is an address or an array of addresses
  * - subject-template
  * - subject (*)
  * - body (*) can also be a direct string
  *     content (*)
  *     content-type (default is text/plain)
  *     encoding
  *     charset
  * - parts is an array of bodies
  * - attachments
  * - embed-images
  * 
  * body[content] can be a direct string (which will be the body's content), or an associative array :
  * - type (partial or component)
  * - name is the name of the partial or component, as "module/partialName" or "module/componentName"
  * - vars is an associative array of variables, passed to the view
  * 
  * attachments is an array of attachment, an attachement is either a string (path name), or a list of these options :
  * - path (*) is the real path on filesystem
  * - filename
  * - mime-type
  * 
  * an address can be either :
  * - a string as an email address or in the "name <email>" format
  * - an array of two strings [name, email] or [email, name]
  * 
  * embed-images is an associative array of key => image light path.
  * You can use "%%IMG_name-of-image%%" in the body or in any part to reference the corresponding embedded image.
  *  
  * @param array $options
  * @throws Exception
  * @return int The number of successful recipients
  */
 protected static function _send(array $options)
 {
     $options = array_merge(sfConfig::get('app_mailer_defaults', array()), $options);
     // Mailer
     if (!isset($options['connection'])) {
         throw new Exception('Connection configuration required');
     }
     if (!isset($options['connection']['type'])) {
         throw new Exception('Connection type undefined');
     }
     if (!isset($options['connection']['params'])) {
         $options['connection']['params'] = array();
     }
     $connection = self::getConnection($options['connection']['type'], $options['connection']['params']);
     $mailer = new Swift($connection);
     $to = new Swift_RecipientList();
     $to->addTo(self::getSwiftAddresses($options['to']));
     // Basic elements
     $from = self::getSwiftAddress($options['from']);
     if (!isset($options['subject'])) {
         throw new Exception('Subject required');
     }
     if (!isset($options['subject-template'])) {
         $options['subject-template'] = '%s';
     }
     if (!isset($options['i18n-catalogue'])) {
         $options['i18n-catalogue'] = 'messages';
     }
     $subject = self::getI18NString($options['subject'], $options['subject-template'], $options['i18n-catalogue']);
     // Message to be sent
     $mail = new Swift_Message($subject);
     // Embedded images
     if (isset($options['embed-images'])) {
         $embedded_images = self::embedImages($mail, @$options['embed-images']);
     } else {
         $embedded_images = array();
     }
     // Get body as the main part
     if (!isset($options['body'])) {
         throw new Exception('Body is required');
     }
     if (!is_array($options['body'])) {
         $options['body'] = array('content' => $options['body']);
     }
     $body = self::getPart($options['body'], $embedded_images);
     // Attach files
     if (isset($options['attachments']) && is_array($options['attachments'])) {
         // Known bug : When we have attachments, we must have body declared as a part, or the
         // mail will be received with no body. We fix this here :
         if (!isset($options['parts'])) {
             $options['parts'] = array();
         }
         foreach ($options['attachments'] as $attachment) {
             $mail->attach(self::getAttachment($attachment));
         }
     }
     // Attach parts (body is the first one)
     if (isset($options['parts']) && is_array($options['parts'])) {
         $parts = self::getParts($options['parts'], $embedded_images);
         array_unshift($parts, $body);
         foreach ($parts as $part) {
             $mail->attach($part);
         }
     } else {
         $mail->setBody($body->getData());
         $mail->setCharset($body->getCharset());
         $mail->setEncoding($body->getEncoding());
         $mail->setContentType($body->getContentType());
     }
     // Handle other options
     if (isset($options['bcc'])) {
         $to->addBcc(self::getSwiftAddresses($options['bcc']));
     }
     if (isset($options['cc'])) {
         $to->addCc(self::getSwiftAddresses($options['cc']));
     }
     if (isset($options['reply-to'])) {
         $mail->setReplyTo(self::getSwiftAddresses($options['reply-to']));
     }
     if (isset($options['return-path'])) {
         $mail->setReturnPath(self::getSwiftAddress($options['return-path']));
     }
     try {
         // Try to send the mail
         $result = $mailer->send($mail, $to, $from);
         $mailer->disconnect();
         return $result;
     } catch (Exception $e) {
         // An error occured, disconnect an eventual connection, and forwards the exception
         $mailer->disconnect();
         throw $e;
     }
 }
 private function sendEmail($notificationIds, $swift, $userId, $emailContent, $cc)
 {
     // Use a transaction to allow us to prevent the email sending and marking of notification as done
     // getting out of step
     $this->db->begin();
     try {
         $this->db->set('acknowledged', 't')->from('notifications')->in('id', $notificationIds)->update();
         $email_config = Kohana::config('email');
         $userResults = $this->db->select('people.email_address')->from('people')->join('users', 'users.person_id', 'people.id')->where('users.id', $userId)->limit(1)->get();
         if (!isset($email_config['address'])) {
             self::msg('Email address not provided in email configuration', 'error');
             return;
         }
         foreach ($userResults as $user) {
             $message = new Swift_Message(kohana::lang('misc.notification_subject', kohana::config('email.server_name')), $emailContent, 'text/html');
             $recipients = new Swift_RecipientList();
             $recipients->addTo($user->email_address);
             $cc = explode(',', $cc);
             foreach ($cc as $ccEmail) {
                 $recipients->addCc(trim($ccEmail));
             }
             // send the email
             $swift->send($message, $recipients, $email_config['address']);
             kohana::log('info', 'Email notification sent to ' . $user->email_address);
         }
     } catch (Exception $e) {
         // Email not sent, so undo marking of notification as complete.
         $this->db->rollback();
         throw $e;
     }
     $this->db->commit();
 }
Beispiel #4
0
 function gmail(&$error, $to, $subject, $body, $fromName = "", $html = 0, $repto = "", $from = "", $cc = "", $reptoName = "")
 {
     global $errorReportingLevel;
     require_once GORUM_DIR . "/SwiftMailer/Swift.php";
     $_S =& new AppSettings();
     error_reporting(0);
     $log =& Swift_LogContainer::getLog();
     $log->setLogLevel($_S->swiftLog);
     Swift_Errors::expect($e, "Swift_Exception");
     if ($_S->smtpServer) {
         require_once GORUM_DIR . "/SwiftMailer/Swift/Connection/SMTP.php";
         if ($_S->fallBackNative) {
             require_once GORUM_DIR . "/SwiftMailer/Swift/Connection/NativeMail.php";
             require_once GORUM_DIR . "/SwiftMailer/Swift/Connection/Multi.php";
             $connections = array();
             $conn =& new Swift_Connection_SMTP($_S->smtpServer);
             $conn->setUsername($_S->smtpUser);
             $conn->setPassword($_S->smtpPass);
             $conn->setPort($_S->smtpPort);
             $conn->setPort($_S->smtpPort);
             $conn->setEncryption($_S->smtpSecure);
             if ($e !== null) {
                 $error = $e->getMessage();
                 return;
             }
             $connections[] =& $conn;
             // Fall back to native mail:
             $connections[] =& new Swift_Connection_NativeMail();
             if ($e !== null) {
                 $error = $e->getMessage();
                 return;
             }
             $swift =& new Swift(new Swift_Connection_Multi($connections));
         } else {
             $connection =& new Swift_Connection_SMTP($_S->smtpServer);
             $connection->setUsername($_S->smtpUser);
             $connection->setPassword($_S->smtpPass);
             $connection->setPort($_S->smtpPort);
             $connection->setEncryption($_S->smtpSecure);
             if ($e !== null) {
                 $error = $e->getMessage();
                 return;
             }
             $swift =& new Swift($connection);
         }
     } else {
         require_once GORUM_DIR . "/SwiftMailer/Swift/Connection/NativeMail.php";
         $swift =& new Swift(new Swift_Connection_NativeMail());
     }
     error_reporting($errorReportingLevel);
     if ($e !== null) {
         $error = $e->getMessage();
         return;
     } else {
         $error = "";
         Swift_Errors::clear("Swift_Exception");
     }
     $subject = str_replace(array("&lt;", "&gt;"), array("<", ">"), $subject);
     $charset = "utf-8";
     $message =& new Swift_Message($subject);
     $message->setCharset($charset);
     $part1 =& new Swift_Message_Part($body, "text/html");
     $part1->setCharset($charset);
     $message->attach($part1);
     $part2 =& new Swift_Message_Part(strip_tags($body));
     $part2->setCharset($charset);
     $message->attach($part2);
     if ($repto) {
         $message->setReplyTo(new Swift_Address($repto, $reptoName));
     }
     error_reporting(0);
     Swift_Errors::expect($e, "Swift_Exception");
     $recipients = new Swift_RecipientList();
     $recipients->addTo($to);
     if ($this->cc) {
         $recipients->addCc($this->cc);
     }
     $swift->send($message, $recipients, new Swift_Address($from, $fromName));
     if ($e !== null) {
         $error = $e->getMessage();
     } else {
         $error = "";
         Swift_Errors::clear("Swift_Exception");
     }
     $swift->disconnect();
     error_reporting($errorReportingLevel);
 }
Beispiel #5
0
 static function sendTicketMessage($properties = array())
 {
     $settings = CerberusSettings::getInstance();
     $helpdesk_senders = CerberusApplication::getHelpdeskSenders();
     @($from_addy = $settings->get(CerberusSettings::DEFAULT_REPLY_FROM, $_SERVER['SERVER_ADMIN']));
     @($from_personal = $settings->get(CerberusSettings::DEFAULT_REPLY_PERSONAL, ''));
     // [TODO] If we still don't have a $from_addy we need a graceful failure.
     /*
     	     * [TODO] Move these into constants?
     	    'message_id'
     	    -----'ticket_id'
     'subject'
     	    'to'
     	    'cc'
     	    'bcc'
     	    'content'
     	    'files'
     	    'closed'
     	    'ticket_reopen'
     	    'unlock_date'
     	    'bucket_id'
     	    'agent_id',
     'is_autoreply',
     'dont_save_copy'
     */
     $mail_succeeded = true;
     try {
         // objects
         $mail_service = DevblocksPlatform::getMailService();
         $mailer = $mail_service->getMailer(CerberusMail::getMailerDefaults());
         $mail = $mail_service->createMessage();
         // properties
         @($reply_message_id = $properties['message_id']);
         @($content =& $properties['content']);
         @($files = $properties['files']);
         @($forward_files = $properties['forward_files']);
         @($worker_id = $properties['agent_id']);
         @($subject = $properties['subject']);
         $message = DAO_Ticket::getMessage($reply_message_id);
         $message_headers = DAO_MessageHeader::getAll($reply_message_id);
         $ticket_id = $message->ticket_id;
         $ticket = DAO_Ticket::getTicket($ticket_id);
         // [TODO] Check that message|ticket isn't NULL
         // If this ticket isn't spam trained and our outgoing message isn't an autoreply
         if ($ticket->spam_training == CerberusTicketSpamTraining::BLANK && (!isset($properties['is_autoreply']) || !$properties['is_autoreply'])) {
             CerberusBayes::markTicketAsNotSpam($ticket_id);
         }
         // Allow teams to override the default from/personal
         @($group_reply = DAO_GroupSettings::get($ticket->team_id, DAO_GroupSettings::SETTING_REPLY_FROM, ''));
         @($group_personal = DAO_GroupSettings::get($ticket->team_id, DAO_GroupSettings::SETTING_REPLY_PERSONAL, ''));
         @($group_personal_with_worker = DAO_GroupSettings::get($ticket->team_id, DAO_GroupSettings::SETTING_REPLY_PERSONAL_WITH_WORKER, 0));
         if (!empty($group_reply)) {
             $from_addy = $group_reply;
         }
         if (!empty($group_personal)) {
             $from_personal = $group_personal;
         }
         // Prefix the worker name on the personal line?
         if (!empty($group_personal_with_worker) && null != ($reply_worker = DAO_Worker::getAgent($worker_id))) {
             $from_personal = $reply_worker->getName() . (!empty($from_personal) ? ', ' . $from_personal : "");
         }
         $sendFrom = new Swift_Address($from_addy, $from_personal);
         // Headers
         $mail->setFrom($sendFrom);
         $mail->generateId();
         $mail->headers->set('X-Mailer', 'Cerberus Helpdesk (Build ' . APP_BUILD . ')');
         // Subject
         if (empty($subject)) {
             $subject = $ticket->subject;
         }
         if (!empty($properties['to'])) {
             // forward
             $mail->setSubject($subject);
         } else {
             // reply
             @($group_has_subject = intval(DAO_GroupSettings::get($ticket->team_id, DAO_GroupSettings::SETTING_SUBJECT_HAS_MASK, 0)));
             @($group_subject_prefix = DAO_GroupSettings::get($ticket->team_id, DAO_GroupSettings::SETTING_SUBJECT_PREFIX, ''));
             $prefix = sprintf("[%s#%s] ", !empty($group_subject_prefix) ? $group_subject_prefix . ' ' : '', $ticket->mask);
             $mail->setSubject(sprintf('Re: %s%s', $group_has_subject ? $prefix : '', $subject));
         }
         $sendTo = new Swift_RecipientList();
         // References
         if (!empty($message) && false !== @($in_reply_to = $message_headers['message-id'])) {
             $mail->headers->set('References', $in_reply_to);
             $mail->headers->set('In-Reply-To', $in_reply_to);
         }
         // Auto-reply handling (RFC-3834 compliant)
         if (isset($properties['is_autoreply']) && $properties['is_autoreply']) {
             $mail->headers->set('Auto-Submitted', 'auto-replied');
             if (null == ($first_address = DAO_Address::get($ticket->first_wrote_address_id))) {
                 return;
             }
             // Don't send e-mail to ourselves
             if (isset($helpdesk_senders[$first_address->email])) {
                 return;
             }
             // Make sure we haven't mailed this address an autoreply within 5 minutes
             if ($first_address->last_autoreply > 0 && $first_address->last_autoreply > time() - 300) {
                 return;
             }
             $first_email = strtolower($first_address->email);
             $first_split = explode('@', $first_email);
             if (!is_array($first_split) || count($first_split) != 2) {
                 return;
             }
             // If return-path is blank
             if (isset($message_headers['return-path']) && $message_headers['return-path'] == '<>') {
                 return;
             }
             // Ignore bounces
             if ($first_split[0] == "postmaster" || $first_split[0] == "mailer-daemon") {
                 return;
             }
             // Ignore autoresponses to autoresponses
             if (isset($message_headers['auto-submitted']) && $message_headers['auto-submitted'] != 'no') {
                 return;
             }
             if (isset($message_headers['precedence']) && ($message_headers['precedence'] == 'list' || $message_headers['precedence'] == 'junk' || ($message_headers['precedence'] = 'bulk'))) {
                 return;
             }
             // Set the auto-reply date for this address to right now
             DAO_Address::update($ticket->first_wrote_address_id, array(DAO_Address::LAST_AUTOREPLY => time()));
             // Auto-reply just to the initial requester
             $sendTo->addTo($first_address->email);
             $mail->setTo($first_address->email);
             // Not an auto-reply
         } else {
             // Forwards
             if (!empty($properties['to'])) {
                 $to = array();
                 $aTo = DevblocksPlatform::parseCsvString(str_replace(';', ',', $properties['to']));
                 foreach ($aTo as $addy) {
                     $to[] = new Swift_Address($addy);
                     $sendTo->addTo($addy);
                 }
                 if (!empty($to)) {
                     $mail->setTo($to);
                 }
                 // Replies
             } else {
                 // Recipients
                 $to = array();
                 $requesters = DAO_Ticket::getRequestersByTicket($ticket_id);
                 if (is_array($requesters)) {
                     foreach ($requesters as $requester) {
                         /* @var $requester Model_Address */
                         $to[] = new Swift_Address($requester->email);
                         $sendTo->addTo($requester->email);
                     }
                 }
                 $mail->setTo($to);
             }
             // Ccs
             if (!empty($properties['cc'])) {
                 $ccs = array();
                 $aCc = DevblocksPlatform::parseCsvString(str_replace(';', ',', $properties['cc']));
                 foreach ($aCc as $addy) {
                     $sendTo->addCc($addy);
                     $ccs[] = new Swift_Address($addy);
                 }
                 if (!empty($ccs)) {
                     $mail->setCc($ccs);
                 }
             }
             // Bccs
             if (!empty($properties['bcc'])) {
                 $aBcc = DevblocksPlatform::parseCsvString(str_replace(';', ',', $properties['bcc']));
                 foreach ($aBcc as $addy) {
                     $sendTo->addBcc($addy);
                 }
             }
         }
         /*
          * [IMPORTANT -- Yes, this is simply a line in the sand.]
          * You're welcome to modify the code to meet your needs, but please respect 
          * our licensing.  Buy a legitimate copy to help support the project!
          * http://www.cerberusweb.com/
          */
         $license = CerberusLicense::getInstance();
         if (empty($license) || @empty($license['serial'])) {
             $content .= base64_decode("DQoNCi0tLQ0KQ29tYmF0IHNwYW0gYW5kIGltcHJvdmUgcmVzc" . "G9uc2UgdGltZXMgd2l0aCBDZXJiZXJ1cyBIZWxwZGVzayA0LjAhDQpodHRwOi8vd3d3LmNlc" . "mJlcnVzd2ViLmNvbS8NCg");
         }
         // Body
         $mail->attach(new Swift_Message_Part($content, 'text/plain', 'base64', LANG_CHARSET_CODE));
         // Mime Attachments
         if (is_array($files) && !empty($files)) {
             foreach ($files['tmp_name'] as $idx => $file) {
                 if (empty($file) || empty($files['name'][$idx])) {
                     continue;
                 }
                 $mail->attach(new Swift_Message_Attachment(new Swift_File($file), $files['name'][$idx], $files['type'][$idx]));
             }
         }
         // Forward Attachments
         if (!empty($forward_files) && is_array($forward_files)) {
             $attachments_path = APP_STORAGE_PATH . '/attachments/';
             foreach ($forward_files as $file_id) {
                 $attachment = DAO_Attachment::get($file_id);
                 $attachment_path = $attachments_path . $attachment->filepath;
                 $mail->attach(new Swift_Message_Attachment(new Swift_File($attachment_path), $attachment->display_name, $attachment->mime_type));
             }
         }
         if (!DEMO_MODE) {
             if (!$mailer->send($mail, $sendTo, $sendFrom)) {
                 $mail_succeeded = false;
                 throw new Exception('Mail not sent.');
             }
         }
     } catch (Exception $e) {
         // tag failure, so we can add a note to the message later
         $mail_succeeded = false;
     }
     // Handle post-mail actions
     $change_fields = array();
     $fromAddressInst = CerberusApplication::hashLookupAddress($from_addy, true);
     $fromAddressId = $fromAddressInst->id;
     if ((!isset($properties['dont_keep_copy']) || !$properties['dont_keep_copy']) && (!isset($properties['is_autoreply']) || !$properties['is_autoreply'])) {
         $change_fields[DAO_Ticket::LAST_WROTE_ID] = $fromAddressId;
         $change_fields[DAO_Ticket::UPDATED_DATE] = time();
         if (!empty($worker_id)) {
             $change_fields[DAO_Ticket::LAST_WORKER_ID] = $worker_id;
             $change_fields[DAO_Ticket::LAST_ACTION_CODE] = CerberusTicketActionCode::TICKET_WORKER_REPLY;
         }
         // Only change the subject if not forwarding
         if (!empty($subject) && empty($properties['to'])) {
             $change_fields[DAO_Ticket::SUBJECT] = $subject;
         }
         $fields = array(DAO_Message::TICKET_ID => $ticket_id, DAO_Message::CREATED_DATE => time(), DAO_Message::ADDRESS_ID => $fromAddressId, DAO_Message::IS_OUTGOING => 1, DAO_Message::WORKER_ID => !empty($worker_id) ? $worker_id : 0);
         $message_id = DAO_Message::create($fields);
         // Content
         DAO_MessageContent::create($message_id, $content);
         // Headers
         if (!empty($mail->headers) && method_exists($mail->headers, 'getList')) {
             foreach ($mail->headers->getList() as $hdr => $v) {
                 if (null != ($hdr_val = $mail->headers->getEncoded($hdr))) {
                     if (!empty($hdr_val)) {
                         DAO_MessageHeader::create($message_id, $ticket_id, $hdr, CerberusParser::fixQuotePrintableString($hdr_val));
                     }
                 }
             }
         }
         if (is_array($files) && !empty($files)) {
             $attachment_path = APP_STORAGE_PATH . '/attachments/';
             reset($files);
             foreach ($files['tmp_name'] as $idx => $file) {
                 if (empty($file) || empty($files['name'][$idx]) || !file_exists($file)) {
                     continue;
                 }
                 $fields = array(DAO_Attachment::MESSAGE_ID => $message_id, DAO_Attachment::DISPLAY_NAME => $files['name'][$idx], DAO_Attachment::MIME_TYPE => $files['type'][$idx], DAO_Attachment::FILE_SIZE => filesize($file));
                 $file_id = DAO_Attachment::create($fields);
                 $attachment_bucket = sprintf("%03d/", mt_rand(1, 100));
                 $attachment_file = $file_id;
                 if (!file_exists($attachment_path . $attachment_bucket)) {
                     mkdir($attachment_path . $attachment_bucket, 0775, true);
                 }
                 if (!is_writeable($attachment_path . $attachment_bucket)) {
                     echo "Can't write to " . $attachment_path . $attachment_bucket . "<BR>";
                 }
                 copy($file, $attachment_path . $attachment_bucket . $attachment_file);
                 @unlink($file);
                 DAO_Attachment::update($file_id, array(DAO_Attachment::FILEPATH => $attachment_bucket . $attachment_file));
             }
         }
         // add note to message if email failed
         if ($mail_succeeded === false) {
             $fields = array(DAO_MessageNote::MESSAGE_ID => $message_id, DAO_MessageNote::CREATED => time(), DAO_MessageNote::WORKER_ID => 0, DAO_MessageNote::CONTENT => 'Exception thrown while sending email: ' . $e->getMessage(), DAO_MessageNote::TYPE => Model_MessageNote::TYPE_ERROR);
             DAO_MessageNote::create($fields);
         }
     }
     // Post-Reply Change Properties
     if (isset($properties['closed'])) {
         switch ($properties['closed']) {
             case 0:
                 // open
                 $change_fields[DAO_Ticket::IS_WAITING] = 0;
                 $change_fields[DAO_Ticket::IS_CLOSED] = 0;
                 $change_fields[DAO_Ticket::IS_DELETED] = 0;
                 $change_fields[DAO_Ticket::DUE_DATE] = 0;
                 break;
             case 1:
                 // closed
                 $change_fields[DAO_Ticket::IS_WAITING] = 0;
                 $change_fields[DAO_Ticket::IS_CLOSED] = 1;
                 $change_fields[DAO_Ticket::IS_DELETED] = 0;
                 if (isset($properties['ticket_reopen'])) {
                     @($time = intval(strtotime($properties['ticket_reopen'])));
                     $change_fields[DAO_Ticket::DUE_DATE] = $time;
                 }
                 break;
             case 2:
                 // waiting
                 $change_fields[DAO_Ticket::IS_WAITING] = 1;
                 $change_fields[DAO_Ticket::IS_CLOSED] = 0;
                 $change_fields[DAO_Ticket::IS_DELETED] = 0;
                 if (isset($properties['ticket_reopen'])) {
                     @($time = intval(strtotime($properties['ticket_reopen'])));
                     $change_fields[DAO_Ticket::DUE_DATE] = $time;
                 }
                 break;
         }
     }
     // Who should handle the followup?
     if (isset($properties['next_worker_id'])) {
         $change_fields[DAO_Ticket::NEXT_WORKER_ID] = $properties['next_worker_id'];
     }
     // Allow anybody to reply after
     if (isset($properties['unlock_date']) && !empty($properties['unlock_date'])) {
         $unlock = strtotime($properties['unlock_date']);
         if (intval($unlock) > 0) {
             $change_fields[DAO_Ticket::UNLOCK_DATE] = $unlock;
         }
     }
     // Move
     if (!empty($properties['bucket_id'])) {
         // [TODO] Use API to move, or fire event
         // [TODO] Ensure team/bucket exist
         list($team_id, $bucket_id) = CerberusApplication::translateTeamCategoryCode($properties['bucket_id']);
         $change_fields[DAO_Ticket::TEAM_ID] = $team_id;
         $change_fields[DAO_Ticket::CATEGORY_ID] = $bucket_id;
     }
     if (!empty($ticket_id) && !empty($change_fields)) {
         DAO_Ticket::updateTicket($ticket_id, $change_fields);
     }
     // Outbound Reply Event (not automated reply, etc.)
     if (!empty($worker_id)) {
         $eventMgr = DevblocksPlatform::getEventService();
         $eventMgr->trigger(new Model_DevblocksEvent('ticket.reply.outbound', array('ticket_id' => $ticket_id, 'worker_id' => $worker_id)));
     }
 }
 public function testFailedRecipientsAreReturned()
 {
     $conn = new FullMockConnection();
     $conn->setReturnValueAt(0, "read", "220 xxx ESMTP");
     $conn->setReturnValueAt(1, "read", "250-Hello xxx\r\n250 HELP");
     $conn->setReturnValueAt(2, "read", "250 Ok");
     $conn->setReturnValueAt(3, "read", "550 Denied");
     $conn->setReturnValueAt(4, "read", "250 ok");
     $conn->setReturnValueAt(5, "read", "550 Denied");
     $conn->setReturnValueAt(6, "read", "354 Go ahead");
     $conn->setReturnValueAt(7, "read", "250 ok");
     $log = Swift_LogContainer::getLog();
     $swift = new Swift($conn, "abc", Swift::ENABLE_LOGGING);
     $message = new Swift_Message("My Subject", "my body");
     $recipients = new Swift_RecipientList();
     $recipients->addTo("*****@*****.**", "XXX YYY");
     $recipients->addTo("*****@*****.**");
     $recipients->addCc("*****@*****.**");
     $this->assertEqual(1, $swift->send($message, $recipients, new Swift_Address("*****@*****.**", "Foo Bar")));
     $this->assertEqual(array("*****@*****.**", "*****@*****.**"), $log->getFailedRecipients());
 }