Exemple #1
0
 function saveTabInboxAddAction()
 {
     $translate = DevblocksPlatform::getTranslationService();
     @($id = DevblocksPlatform::importGPC($_REQUEST['id'], 'integer', 0));
     @($group_id = DevblocksPlatform::importGPC($_REQUEST['group_id'], 'integer'));
     @($view_id = DevblocksPlatform::importGPC($_REQUEST['view_id'], 'string', ''));
     @($active_worker = CerberusApplication::getActiveWorker());
     if (!$active_worker->isTeamManager($group_id) && !$active_worker->is_superuser) {
         return;
     }
     /*****************************/
     @($name = DevblocksPlatform::importGPC($_POST['name'], 'string', ''));
     @($is_sticky = DevblocksPlatform::importGPC($_POST['is_sticky'], 'integer', 0));
     @($is_stackable = DevblocksPlatform::importGPC($_POST['is_stackable'], 'integer', 0));
     @($rules = DevblocksPlatform::importGPC($_POST['rules'], 'array', array()));
     @($do = DevblocksPlatform::importGPC($_POST['do'], 'array', array()));
     if (empty($name)) {
         $name = $translate->_('mail.inbox_filter');
     }
     $criterion = array();
     $actions = array();
     // Custom fields
     $custom_fields = DAO_CustomField::getAll();
     // Criteria
     if (is_array($rules)) {
         foreach ($rules as $rule) {
             $rule = DevblocksPlatform::strAlphaNumDash($rule);
             @($value = DevblocksPlatform::importGPC($_POST['value_' . $rule], 'string', ''));
             // [JAS]: Allow empty $value (null/blank checking)
             $criteria = array('value' => $value);
             // Any special rule handling
             switch ($rule) {
                 case 'dayofweek':
                     // days
                     $days = DevblocksPlatform::importGPC($_REQUEST['value_dayofweek'], 'array', array());
                     if (in_array(0, $days)) {
                         $criteria['sun'] = 'Sunday';
                     }
                     if (in_array(1, $days)) {
                         $criteria['mon'] = 'Monday';
                     }
                     if (in_array(2, $days)) {
                         $criteria['tue'] = 'Tuesday';
                     }
                     if (in_array(3, $days)) {
                         $criteria['wed'] = 'Wednesday';
                     }
                     if (in_array(4, $days)) {
                         $criteria['thu'] = 'Thursday';
                     }
                     if (in_array(5, $days)) {
                         $criteria['fri'] = 'Friday';
                     }
                     if (in_array(6, $days)) {
                         $criteria['sat'] = 'Saturday';
                     }
                     unset($criteria['value']);
                     break;
                 case 'timeofday':
                     $from = DevblocksPlatform::importGPC($_REQUEST['timeofday_from'], 'string', '');
                     $to = DevblocksPlatform::importGPC($_REQUEST['timeofday_to'], 'string', '');
                     $criteria['from'] = $from;
                     $criteria['to'] = $to;
                     unset($criteria['value']);
                     break;
                 case 'subject':
                     break;
                 case 'from':
                     break;
                 case 'tocc':
                     break;
                 case 'header1':
                 case 'header2':
                 case 'header3':
                 case 'header4':
                 case 'header5':
                     if (null != @($header = DevblocksPlatform::importGPC($_POST[$rule], 'string', null))) {
                         $criteria['header'] = strtolower($header);
                     }
                     break;
                 case 'body':
                     break;
                 case 'attachment':
                     break;
                 default:
                     // ignore invalids
                     // Custom fields
                     if ("cf_" == substr($rule, 0, 3)) {
                         $field_id = intval(substr($rule, 3));
                         if (!isset($custom_fields[$field_id])) {
                             continue;
                         }
                         // [TODO] Operators
                         switch ($custom_fields[$field_id]->type) {
                             case 'S':
                                 // string
                             // string
                             case 'T':
                                 // clob
                             // clob
                             case 'U':
                                 // URL
                                 $oper = DevblocksPlatform::importGPC($_REQUEST['value_cf_' . $field_id . '_oper'], 'string', 'regexp');
                                 $criteria['oper'] = $oper;
                                 break;
                             case 'D':
                                 // dropdown
                             // dropdown
                             case 'M':
                                 // multi-dropdown
                             // multi-dropdown
                             case 'X':
                                 // multi-checkbox
                             // multi-checkbox
                             case 'W':
                                 // worker
                                 $in_array = DevblocksPlatform::importGPC($_REQUEST['value_cf_' . $field_id], 'array', array());
                                 $out_array = array();
                                 // Hash key on the option for quick lookup later
                                 if (is_array($in_array)) {
                                     foreach ($in_array as $k => $v) {
                                         $out_array[$v] = $v;
                                     }
                                 }
                                 $criteria['value'] = $out_array;
                                 break;
                             case 'E':
                                 // date
                                 $from = DevblocksPlatform::importGPC($_REQUEST['value_cf_' . $field_id . '_from'], 'string', '0');
                                 $to = DevblocksPlatform::importGPC($_REQUEST['value_cf_' . $field_id . '_to'], 'string', 'now');
                                 $criteria['from'] = $from;
                                 $criteria['to'] = $to;
                                 unset($criteria['value']);
                                 break;
                             case 'N':
                                 // number
                                 $oper = DevblocksPlatform::importGPC($_REQUEST['value_cf_' . $field_id . '_oper'], 'string', '=');
                                 $criteria['oper'] = $oper;
                                 $criteria['value'] = intval($value);
                                 break;
                             case 'C':
                                 // checkbox
                                 $criteria['value'] = intval($value);
                                 break;
                         }
                     } else {
                         continue;
                     }
                     break;
             }
             $criterion[$rule] = $criteria;
         }
     }
     // Actions
     if (is_array($do)) {
         foreach ($do as $act) {
             $action = array();
             switch ($act) {
                 // Move group/bucket
                 case 'move':
                     @($move_code = DevblocksPlatform::importGPC($_REQUEST['do_move'], 'string', null));
                     if (0 != strlen($move_code)) {
                         list($g_id, $b_id) = CerberusApplication::translateTeamCategoryCode($move_code);
                         $action = array('group_id' => intval($g_id), 'bucket_id' => intval($b_id));
                     }
                     break;
                     // Assign to worker
                 // Assign to worker
                 case 'assign':
                     @($worker_id = DevblocksPlatform::importGPC($_REQUEST['do_assign'], 'string', null));
                     if (0 != strlen($worker_id)) {
                         $action = array('worker_id' => intval($worker_id));
                     }
                     break;
                     // Spam training
                 // Spam training
                 case 'spam':
                     @($is_spam = DevblocksPlatform::importGPC($_REQUEST['do_spam'], 'string', null));
                     if (0 != strlen($is_spam)) {
                         $action = array('is_spam' => !$is_spam ? 0 : 1);
                     }
                     break;
                     // Set status
                 // Set status
                 case 'status':
                     @($status = DevblocksPlatform::importGPC($_REQUEST['do_status'], 'string', null));
                     if (0 != strlen($status)) {
                         $action = array('is_waiting' => 3 == $status ? 1 : 0, 'is_closed' => 0 == $status || 3 == $status ? 0 : 1, 'is_deleted' => 2 == $status ? 1 : 0);
                     }
                     break;
                 default:
                     // ignore invalids
                     // Custom fields
                     if ("cf_" == substr($act, 0, 3)) {
                         $field_id = intval(substr($act, 3));
                         if (!isset($custom_fields[$field_id])) {
                             continue;
                         }
                         $action = array();
                         // [TODO] Operators
                         switch ($custom_fields[$field_id]->type) {
                             case 'S':
                                 // string
                             // string
                             case 'T':
                                 // clob
                             // clob
                             case 'D':
                                 // dropdown
                             // dropdown
                             case 'U':
                                 // URL
                             // URL
                             case 'W':
                                 // worker
                                 $value = DevblocksPlatform::importGPC($_REQUEST['do_cf_' . $field_id], 'string', '');
                                 $action['value'] = $value;
                                 break;
                             case 'M':
                                 // multi-dropdown
                             // multi-dropdown
                             case 'X':
                                 // multi-checkbox
                                 $in_array = DevblocksPlatform::importGPC($_REQUEST['do_cf_' . $field_id], 'array', array());
                                 $out_array = array();
                                 // Hash key on the option for quick lookup later
                                 if (is_array($in_array)) {
                                     foreach ($in_array as $k => $v) {
                                         $out_array[$v] = $v;
                                     }
                                 }
                                 $action['value'] = $out_array;
                                 break;
                             case 'E':
                                 // date
                                 $value = DevblocksPlatform::importGPC($_REQUEST['do_cf_' . $field_id], 'string', '');
                                 $action['value'] = $value;
                                 break;
                             case 'N':
                                 // number
                             // number
                             case 'C':
                                 // checkbox
                                 $value = DevblocksPlatform::importGPC($_REQUEST['do_cf_' . $field_id], 'string', '');
                                 $action['value'] = intval($value);
                                 break;
                         }
                     } else {
                         continue;
                     }
                     break;
             }
             $actions[$act] = $action;
         }
     }
     $fields = array(DAO_GroupInboxFilter::NAME => $name, DAO_GroupInboxFilter::IS_STICKY => $is_sticky, DAO_GroupInboxFilter::CRITERIA_SER => serialize($criterion), DAO_GroupInboxFilter::ACTIONS_SER => serialize($actions));
     // Only sticky filters can manual order and be stackable
     if (!$is_sticky) {
         $fields[DAO_GroupInboxFilter::STICKY_ORDER] = 0;
         $fields[DAO_GroupInboxFilter::IS_STACKABLE] = 0;
     } else {
         // is sticky
         $fields[DAO_GroupInboxFilter::IS_STACKABLE] = $is_stackable;
     }
     // Create
     if (empty($id)) {
         $fields[DAO_GroupInboxFilter::GROUP_ID] = $group_id;
         $fields[DAO_GroupInboxFilter::POS] = 0;
         $id = DAO_GroupInboxFilter::create($fields);
         // Update
     } else {
         DAO_GroupInboxFilter::update($id, $fields);
     }
     $defaults = new C4_AbstractViewModel();
     $defaults->class_name = 'C4_TicketView';
     $defaults->id = $view_id;
     $view = C4_AbstractViewLoader::getView($view_id, $defaults);
     if (!empty($view_id) && null != $view) {
         /* @var $view C4_TicketView */
         // Loop through all the tickets in this inbox
         list($inbox_tickets, $null) = DAO_Ticket::search(null, array(new DevblocksSearchCriteria(SearchFields_Ticket::TICKET_TEAM_ID, '=', $group_id), new DevblocksSearchCriteria(SearchFields_Ticket::TICKET_CATEGORY_ID, '=', '0')), -1, 0, null, null, false);
         if (is_array($inbox_tickets)) {
             foreach ($inbox_tickets as $inbox_ticket) {
                 /* @var $inbox_ticket CerberusTicket */
                 // Run only this new rule against all tickets in the group inbox
                 CerberusApplication::runGroupRouting($group_id, intval($inbox_ticket[SearchFields_Ticket::TICKET_ID]), $id);
             }
         }
         $view->render();
         return;
     }
     DevblocksPlatform::redirect(new DevblocksHttpResponse(array('groups', $group_id, 'inbox')));
 }
Exemple #2
0
 function saveAddInboxRulePanelAction()
 {
     $translate = DevblocksPlatform::getTranslationService();
     @($view_id = DevblocksPlatform::importGPC($_REQUEST['view_id'], 'string', ''));
     @($group_id = DevblocksPlatform::importGPC($_REQUEST['group_id'], 'integer'));
     $view = C4_AbstractViewLoader::getView('C4_TicketView', $view_id);
     /* @var $view C4_TicketView */
     if (empty($group_id)) {
         $view->render();
         exit;
     }
     @($name = DevblocksPlatform::importGPC($_POST['name'], 'string', ''));
     @($rules = DevblocksPlatform::importGPC($_POST['rules'], 'array', array()));
     @($do = DevblocksPlatform::importGPC($_POST['do'], 'array', array()));
     if (empty($name)) {
         $name = $translate->_('mail.inbox_filter');
     }
     $criterion = array();
     $actions = array();
     // Criteria
     if (is_array($rules)) {
         foreach ($rules as $rule) {
             $rule = DevblocksPlatform::strAlphaNumDash($rule);
             @($value = DevblocksPlatform::importGPC($_POST['value_' . $rule], 'string', ''));
             // [JAS]: Allow empty $value (null/blank checking)
             $criteria = array('value' => $value);
             // Any special rule handling
             switch ($rule) {
                 case 'subject':
                     break;
                 case 'from':
                     break;
                 case 'tocc':
                     break;
                 case 'header1':
                 case 'header2':
                 case 'header3':
                 case 'header4':
                 case 'header5':
                     if (null != @($header = DevblocksPlatform::importGPC($_POST[$rule], 'string', null))) {
                         $criteria['header'] = strtolower($header);
                     }
                     break;
                 case 'body':
                     break;
                 case 'attachment':
                     break;
                 default:
                     // ignore invalids
                     continue;
                     break;
             }
             $criterion[$rule] = $criteria;
         }
     }
     // Actions
     if (is_array($do)) {
         foreach ($do as $act) {
             $action = array();
             switch ($act) {
                 // Move group/bucket
                 case 'move':
                     @($move_code = DevblocksPlatform::importGPC($_REQUEST['do_move'], 'string', null));
                     if (0 != strlen($move_code)) {
                         list($g_id, $b_id) = CerberusApplication::translateTeamCategoryCode($move_code);
                         $action = array('group_id' => intval($g_id), 'bucket_id' => intval($b_id));
                     }
                     break;
                     // Assign to worker
                 // Assign to worker
                 case 'assign':
                     @($worker_id = DevblocksPlatform::importGPC($_REQUEST['do_assign'], 'string', null));
                     if (0 != strlen($worker_id)) {
                         $action = array('worker_id' => intval($worker_id));
                     }
                     break;
                     // Spam training
                 // Spam training
                 case 'spam':
                     @($is_spam = DevblocksPlatform::importGPC($_REQUEST['do_spam'], 'string', null));
                     if (0 != strlen($is_spam)) {
                         $action = array('is_spam' => !$is_spam ? 0 : 1);
                     }
                     break;
                     // Set status
                 // Set status
                 case 'status':
                     @($status = DevblocksPlatform::importGPC($_REQUEST['do_status'], 'string', null));
                     if (0 != strlen($status)) {
                         $action = array('is_closed' => 0 == $status ? 0 : 1, 'is_deleted' => 2 == $status ? 1 : 0);
                     }
                     break;
                 default:
                     // ignore invalids
                     continue;
                     break;
             }
             $actions[$act] = $action;
         }
     }
     $fields = array(DAO_GroupInboxFilter::NAME => $name, DAO_GroupInboxFilter::GROUP_ID => $group_id, DAO_GroupInboxFilter::CRITERIA_SER => serialize($criterion), DAO_GroupInboxFilter::ACTIONS_SER => serialize($actions), DAO_GroupInboxFilter::POS => 0);
     $routing_id = DAO_GroupInboxFilter::create($fields);
     // Loop through all the tickets in this inbox
     list($inbox_tickets, $null) = DAO_Ticket::search(null, array(new DevblocksSearchCriteria(SearchFields_Ticket::TEAM_ID, '=', $group_id), new DevblocksSearchCriteria(SearchFields_Ticket::TICKET_CATEGORY_ID, '=', '0')), -1, 0, null, null, false);
     if (is_array($inbox_tickets)) {
         foreach ($inbox_tickets as $inbox_ticket) {
             /* @var $inbox_ticket CerberusTicket */
             // Run only this new rule against all tickets in the group inbox
             CerberusApplication::runGroupRouting($group_id, intval($inbox_ticket[SearchFields_Ticket::TICKET_ID]), $routing_id);
         }
     }
     $view->render();
     exit;
 }
Exemple #3
0
 private function _handleTicketMoved($event)
 {
     @($ticket_ids = $event->params['ticket_ids']);
     @($changed_fields = $event->params['changed_fields']);
     if (!isset($changed_fields[DAO_Ticket::TEAM_ID])) {
         return;
     }
     @($team_id = $changed_fields[DAO_Ticket::TEAM_ID]);
     @($bucket_id = $changed_fields[DAO_Ticket::CATEGORY_ID]);
     $final_moves = array();
     // If we're landing in an inbox we need to check its filters
     if (!empty($ticket_ids) && !empty($team_id) && empty($bucket_id)) {
         // moving to an inbox
         if (is_array($ticket_ids)) {
             foreach ($ticket_ids as $ticket_id) {
                 // Run the new inbox filters
                 $matches = CerberusApplication::runGroupRouting($team_id, $ticket_id);
                 // If we matched no rules, we're stuck in the destination inbox.
                 if (empty($matches)) {
                     $final_moves[] = $ticket_id;
                 } else {
                     // If more inbox rules want to move this ticket don't consider this finished
                     if (is_array($matches)) {
                         foreach ($matches as $match) {
                             if (isset($match->actions['move'])) {
                                 // any moves
                                 break;
                             }
                             $final_moves[] = $ticket_id;
                         }
                     }
                 }
             }
         }
         // Anything dropping into a non-inbox bucket is done chain-moving
     } elseif (!empty($ticket_ids) && !empty($team_id) && !empty($bucket_id)) {
         $final_moves = $ticket_ids;
     }
     // Did we have any tickets finish chain-moving?
     if (!empty($final_moves)) {
         // Trigger an inbound event for all moves
         if (is_array($final_moves)) {
             foreach ($final_moves as $ticket_id) {
                 // Inbound Reply Event
                 $eventMgr = DevblocksPlatform::getEventService();
                 $eventMgr->trigger(new Model_DevblocksEvent('ticket.reply.inbound', array('ticket_id' => $ticket_id)));
             }
         }
     }
 }
Exemple #4
0
 /**
  * Enter description here...
  *
  * @param CerberusParserMessage $message
  * @return integer
  */
 public static function parseMessage(CerberusParserMessage $message, $options = array())
 {
     //		print_r($rfcMessage);
     /*
      * options:
      * 'no_autoreply'
      */
     $logger = DevblocksPlatform::getConsoleLog();
     $settings = CerberusSettings::getInstance();
     $helpdesk_senders = CerberusApplication::getHelpdeskSenders();
     $headers =& $message->headers;
     // To/From/Cc/Bcc
     $sReturnPath = @$headers['return-path'];
     $sReplyTo = @$headers['reply-to'];
     $sFrom = @$headers['from'];
     $sTo = @$headers['to'];
     $bIsNew = true;
     // Overloadable
     $sMask = '';
     $iClosed = 0;
     $enumSpamTraining = '';
     $iDate = time();
     $from = array();
     $to = array();
     if (!empty($sReplyTo)) {
         $from = CerberusParser::parseRfcAddress($sReplyTo);
     } elseif (!empty($sFrom)) {
         $from = CerberusParser::parseRfcAddress($sFrom);
     } elseif (!empty($sReturnPath)) {
         $from = CerberusParser::parseRfcAddress($sReturnPath);
     }
     if (!empty($sTo)) {
         // [TODO] Do we still need this RFC address parser?
         $to = CerberusParser::parseRfcAddress($sTo);
     }
     // Subject
     // Fix quote printable subject (quoted blocks can appear anywhere in subject)
     $sSubject = "";
     if (isset($headers['subject']) && !empty($headers['subject'])) {
         $sSubject = self::fixQuotePrintableString($headers['subject']);
     }
     // The subject can still end up empty after QP decode
     if (empty($sSubject)) {
         $sSubject = "(no subject)";
     }
     // Date
     $iDate = @strtotime($headers['date']);
     // If blank, or in the future, set to the current date
     if (empty($iDate) || $iDate > time()) {
         $iDate = time();
     }
     if (empty($from) || !is_array($from)) {
         $logger->warn("[Parser] Invalid 'From' address: " . $from);
         return NULL;
     }
     @($fromAddress = $from[0]->mailbox . '@' . $from[0]->host);
     @($fromPersonal = $from[0]->personal);
     if (null == ($fromAddressInst = CerberusApplication::hashLookupAddress($fromAddress, true))) {
         $logger->err("[Parser] 'From' address could not be created: " . $fromAddress);
         return NULL;
     } else {
         $fromAddressId = $fromAddressInst->id;
     }
     // Is banned?
     if (1 == $fromAddressInst->is_banned) {
         $logger->info("[Parser] Ignoring ticket from banned address: " . $fromAddressInst->email);
         return NULL;
     }
     // Message Id / References / In-Reply-To
     @($sMessageId = $headers['message-id']);
     $body_append_text = array();
     $body_append_html = array();
     // [mdf]Check attached files before creating the ticket because we may need to overwrite the message-id
     // also store any contents of rfc822 files so we can include them after the body
     foreach ($message->files as $filename => $file) {
         /* @var $file ParserFile */
         switch ($file->mime_type) {
             case 'message/rfc822':
                 $full_filename = $file->tmpname;
                 $mail = mailparse_msg_parse_file($full_filename);
                 $struct = mailparse_msg_get_structure($mail);
                 $msginfo = mailparse_msg_get_part_data($mail);
                 $inline_headers = $msginfo['headers'];
                 if (isset($headers['from']) && (strtolower(substr($headers['from'], 0, 11)) == 'postmaster@' || strtolower(substr($headers['from'], 0, 14)) == 'mailer-daemon@')) {
                     $headers['in-reply-to'] = $inline_headers['message-id'];
                 }
                 break;
         }
     }
     // [JAS] [TODO] References header may contain multiple message-ids to find
     if (null != ($ids = self::findParentMessage($headers))) {
         $bIsNew = false;
         $id = $ids['ticket_id'];
         $msgid = $ids['message_id'];
         // Is it a worker reply from an external client?  If so, proxy
         if (null != ($worker_address = DAO_AddressToWorker::getByAddress($fromAddressInst->email))) {
             $logger->info("[Parser] Handling an external worker response from " . $fromAddressInst->email);
             if (!DAO_Ticket::isTicketRequester($worker_address->address, $id)) {
                 // Watcher Commands [TODO] Document on wiki/etc
                 if (0 != ($matches = preg_match_all("/\\[(.*?)\\]/i", $message->headers['subject'], $commands))) {
                     @($command = strtolower(array_pop($commands[1])));
                     $logger->info("[Parser] Worker command: " . $command);
                     switch ($command) {
                         case 'close':
                             DAO_Ticket::updateTicket($id, array(DAO_Ticket::IS_CLOSED => CerberusTicketStatus::CLOSED));
                             break;
                         case 'take':
                             DAO_Ticket::updateTicket($id, array(DAO_Ticket::NEXT_WORKER_ID => $worker_address->worker_id));
                             break;
                         case 'comment':
                             $comment_id = DAO_TicketComment::create(array(DAO_TicketComment::ADDRESS_ID => $fromAddressId, DAO_TicketComment::CREATED => time(), DAO_TicketComment::TICKET_ID => $id, DAO_TicketComment::COMMENT => $message->body));
                             return $id;
                             break;
                         default:
                             // Typo?
                             break;
                     }
                 }
                 $attachment_files = array();
                 $attachment_files['name'] = array();
                 $attachment_files['type'] = array();
                 $attachment_files['tmp_name'] = array();
                 $attachment_files['size'] = array();
                 $i = 0;
                 foreach ($message->files as $filename => $file) {
                     $attachment_files['name'][$i] = $filename;
                     $attachment_files['type'][$i] = $file->mime_type;
                     $attachment_files['tmp_name'][$i] = $file->tmpname;
                     $attachment_files['size'][$i] = $file->file_size;
                     $i++;
                 }
                 CerberusMail::sendTicketMessage(array('message_id' => $msgid, 'content' => $message->body, 'files' => $attachment_files, 'agent_id' => $worker_address->worker_id));
                 return $id;
             } else {
                 // ... worker is a requester, treat as normal
                 $logger->info("[Parser] The external worker was a ticket requester, so we're not treating them as a watcher.");
             }
         } else {
             // Reply: Not sent by a worker
             /*
              * [TODO] check that this sender is a requester on the matched ticket
              * Otherwise blank out the $id
              */
         }
     }
     @(list($team_id, $matchingToAddress) = CerberusParser::findDestination($headers));
     // Pre-parse mail rules
     if (null != ($pre_filter = self::_checkPreParseRules(empty($id) ? 1 : 0, $fromAddress, $team_id, $message))) {
         // Do something with matching filter's actions
         foreach ($pre_filter->actions as $action_key => $action) {
             switch ($action_key) {
                 case 'blackhole':
                     return NULL;
                     break;
                 case 'redirect':
                     @($to = $action['to']);
                     CerberusMail::reflect($message, $to);
                     return NULL;
                     break;
                 case 'bounce':
                     @($msg = $action['message']);
                     // [TODO] Follow the RFC spec on a true bounce
                     CerberusMail::quickSend($fromAddress, "Delivery failed: " . $sSubject, $msg);
                     return NULL;
                     break;
             }
         }
     }
     if (empty($id)) {
         // New Ticket
         // Are we delivering or bouncing?
         if (empty($team_id)) {
             // Bounce
             return null;
         }
         if (empty($sMask)) {
             $sMask = CerberusApplication::generateTicketMask();
         }
         $fields = array(DAO_Ticket::MASK => $sMask, DAO_Ticket::SUBJECT => $sSubject, DAO_Ticket::IS_CLOSED => $iClosed, DAO_Ticket::FIRST_WROTE_ID => intval($fromAddressId), DAO_Ticket::LAST_WROTE_ID => intval($fromAddressId), DAO_Ticket::CREATED_DATE => $iDate, DAO_Ticket::UPDATED_DATE => $iDate, DAO_Ticket::TEAM_ID => intval($team_id), DAO_Ticket::LAST_ACTION_CODE => CerberusTicketActionCode::TICKET_OPENED);
         $id = DAO_Ticket::createTicket($fields);
     }
     // [JAS]: Add requesters to the ticket
     if (!empty($fromAddressId) && !empty($id)) {
         // Don't add a requester if the sender is a helpdesk address
         if (isset($helpdesk_senders[$fromAddressInst->email])) {
             $logger->info("[Parser] Not adding ourselves as a requester: " . $fromAddressInst->email);
         } else {
             DAO_Ticket::createRequester($fromAddressId, $id);
         }
     }
     // Add the other TO/CC addresses to the ticket
     // [TODO] This should be cleaned up and optimized
     if ($settings->get(CerberusSettings::PARSER_AUTO_REQ, 0)) {
         @($autoreq_exclude_list = $settings->get(CerberusSettings::PARSER_AUTO_REQ_EXCLUDE, ''));
         $destinations = self::getDestinations($headers);
         if (is_array($destinations) && !empty($destinations)) {
             // Filter out any excluded requesters
             if (!empty($autoreq_exclude_list)) {
                 @($autoreq_exclude = DevblocksPlatform::parseCrlfString($autoreq_exclude_list));
                 if (is_array($autoreq_exclude) && !empty($autoreq_exclude)) {
                     foreach ($autoreq_exclude as $excl_pattern) {
                         $excl_regexp = DevblocksPlatform::parseStringAsRegExp($excl_pattern);
                         // Check all destinations for this pattern
                         foreach ($destinations as $idx => $dest) {
                             if (@preg_match($excl_regexp, $dest)) {
                                 unset($destinations[$idx]);
                             }
                         }
                     }
                 }
             }
             foreach ($destinations as $dest) {
                 if (null != ($destInst = CerberusApplication::hashLookupAddress($dest, true))) {
                     // Skip if the destination is one of our senders or the matching TO
                     if (isset($helpdesk_senders[$destInst->email]) || 0 == strcasecmp($matchingToAddress, $destInst->email)) {
                         continue;
                     }
                     DAO_Ticket::createRequester($destInst->id, $id);
                 }
             }
         }
     }
     $attachment_path = APP_STORAGE_PATH . '/attachments/';
     // [TODO] This should allow external attachments (S3)
     $fields = array(DAO_Message::TICKET_ID => $id, DAO_Message::CREATED_DATE => $iDate, DAO_Message::ADDRESS_ID => $fromAddressId);
     $email_id = DAO_Message::create($fields);
     // Content
     DAO_MessageContent::create($email_id, $message->body);
     // Headers
     foreach ($headers as $hk => $hv) {
         DAO_MessageHeader::create($email_id, $id, $hk, $hv);
     }
     // [mdf] Loop through files to insert attachment records in the db, and move temporary files
     if (!empty($email_id)) {
         foreach ($message->files as $filename => $file) {
             /* @var $file ParserFile */
             //[mdf] skip rfc822 messages since we extracted their content above
             if ($file->mime_type == 'message/rfc822') {
                 continue;
             }
             $fields = array(DAO_Attachment::MESSAGE_ID => $email_id, DAO_Attachment::DISPLAY_NAME => $filename, DAO_Attachment::MIME_TYPE => $file->mime_type, DAO_Attachment::FILE_SIZE => intval($file->file_size));
             $file_id = DAO_Attachment::create($fields);
             if (empty($file_id)) {
                 @unlink($file->tmpname);
                 // remove our temp file
                 continue;
             }
             // Make file attachments use buckets so we have a max per directory
             $attachment_bucket = sprintf("%03d/", mt_rand(1, 100));
             $attachment_file = $file_id;
             if (!file_exists($attachment_path . $attachment_bucket)) {
                 @mkdir($attachment_path . $attachment_bucket, 0770, true);
                 // [TODO] Needs error checking
             }
             rename($file->getTempFile(), $attachment_path . $attachment_bucket . $attachment_file);
             // [TODO] Split off attachments into its own DAO
             DAO_Attachment::update($file_id, array(DAO_Attachment::FILEPATH => $attachment_bucket . $attachment_file));
         }
     }
     // First Thread
     if ($bIsNew && !empty($email_id)) {
         // First thread
         DAO_Ticket::updateTicket($id, array(DAO_Ticket::FIRST_MESSAGE_ID => $email_id));
     }
     // New ticket processing
     if ($bIsNew) {
         // Don't replace this with the master event listener
         if (false !== ($rules = CerberusApplication::runGroupRouting($team_id, $id))) {
             /* @var $rule Model_GroupInboxFilter */
             // Check the last match which moved the ticket
             if (is_array($rules)) {
                 foreach ($rules as $rule) {
                     // If a rule changed our destination, replace the scope variable $team_id
                     if (isset($rule->actions['move']) && isset($rule->actions['move']['group_id'])) {
                         $team_id = intval($rule->actions['move']['group_id']);
                     }
                 }
             }
         }
         // Allow spam training overloading
         if (!empty($enumSpamTraining)) {
             if ($enumSpamTraining == CerberusTicketSpamTraining::SPAM) {
                 CerberusBayes::markTicketAsSpam($id);
                 DAO_Ticket::updateTicket($id, array(DAO_Ticket::IS_CLOSED => 1, DAO_Ticket::IS_DELETED => 1));
             } elseif ($enumSpamTraining == CerberusTicketSpamTraining::NOT_SPAM) {
                 CerberusBayes::markTicketAsNotSpam($id);
             }
         } else {
             // No overload
             $out = CerberusBayes::calculateTicketSpamProbability($id);
             // [TODO] Move this group logic to a post-parse event listener
             if (!empty($team_id)) {
                 @($spam_threshold = DAO_GroupSettings::get($team_id, DAO_GroupSettings::SETTING_SPAM_THRESHOLD, 80));
                 @($spam_action = DAO_GroupSettings::get($team_id, DAO_GroupSettings::SETTING_SPAM_ACTION, ''));
                 @($spam_action_param = DAO_GroupSettings::get($team_id, DAO_GroupSettings::SETTING_SPAM_ACTION_PARAM, ''));
                 if ($out['probability'] * 100 >= $spam_threshold) {
                     $enumSpamTraining = CerberusTicketSpamTraining::SPAM;
                     switch ($spam_action) {
                         default:
                         case 0:
                             // do nothing
                             break;
                         case 1:
                             // delete
                             // [TODO] Would have been much nicer to delete before this point
                             DAO_Ticket::updateTicket($id, array(DAO_Ticket::IS_CLOSED => 1, DAO_Ticket::IS_DELETED => 1));
                             break;
                         case 2:
                             // move
                             $buckets = DAO_Bucket::getAll();
                             // Verify bucket exists
                             if (!empty($spam_action_param) && isset($buckets[$spam_action_param])) {
                                 DAO_Ticket::updateTicket($id, array(DAO_Ticket::TEAM_ID => $team_id, DAO_Ticket::CATEGORY_ID => $spam_action_param));
                             }
                             break;
                     }
                 }
             }
         }
         // end spam training
         // Auto reply
         @($autoreply_enabled = DAO_GroupSettings::get($team_id, DAO_GroupSettings::SETTING_AUTO_REPLY_ENABLED, 0));
         @($autoreply = DAO_GroupSettings::get($team_id, DAO_GroupSettings::SETTING_AUTO_REPLY, ''));
         /*
          * Send the group's autoreply if one exists, as long as this ticket isn't spam
          */
         if (!isset($options['no_autoreply']) && $autoreply_enabled && !empty($autoreply) && $enumSpamTraining != CerberusTicketSpamTraining::SPAM) {
             CerberusMail::sendTicketMessage(array('ticket_id' => $id, 'message_id' => $email_id, 'content' => str_replace(array('#ticket_id#', '#mask#', '#subject#', '#timestamp#', '#sender#', '#sender_first#', '#orig_body#'), array($id, $sMask, $sSubject, date('r'), $fromAddress, $fromAddressInst->first_name, ltrim($message->body)), $autoreply), 'is_autoreply' => true, 'dont_keep_copy' => true));
         }
     }
     // end bIsNew
     unset($message);
     // Re-open and update our date on new replies
     if (!$bIsNew) {
         DAO_Ticket::updateTicket($id, array(DAO_Ticket::UPDATED_DATE => time(), DAO_Ticket::IS_WAITING => 0, DAO_Ticket::IS_CLOSED => 0, DAO_Ticket::IS_DELETED => 0, DAO_Ticket::LAST_WROTE_ID => $fromAddressId, DAO_Ticket::LAST_ACTION_CODE => CerberusTicketActionCode::TICKET_CUSTOMER_REPLY));
         // [TODO] The TICKET_CUSTOMER_REPLY should be sure of this message address not being a worker
     }
     // Inbound Reply Event
     $eventMgr = DevblocksPlatform::getEventService();
     $eventMgr->trigger(new Model_DevblocksEvent('ticket.reply.inbound', array('ticket_id' => $id, 'message_id' => $email_id)));
     @imap_errors();
     // Prevent errors from spilling out into STDOUT
     return $id;
 }
Exemple #5
0
 private function _handleTicketMoved($event)
 {
     @($ticket_ids = $event->params['ticket_ids']);
     @($changed_fields = $event->params['changed_fields']);
     if (!isset($changed_fields[DAO_Ticket::TEAM_ID]) || !isset($changed_fields[DAO_Ticket::CATEGORY_ID])) {
         return;
     }
     @($team_id = $changed_fields[DAO_Ticket::TEAM_ID]);
     @($bucket_id = $changed_fields[DAO_Ticket::CATEGORY_ID]);
     //============ Check Team Inbox Rules ================
     if (!empty($ticket_ids) && !empty($team_id) && empty($bucket_id)) {
         // moving to an inbox
         // [JAS]: Build hashes for our event ([TODO] clean up)
         $tickets = DAO_Ticket::getTickets($ticket_ids);
         $from_ids = array();
         foreach ($tickets as $ticket) {
             /* @var $ticket CerberusTicket */
             $from_ids[$ticket->id] = $ticket->first_wrote_address_id;
         }
         $from_addresses = DAO_Address::getWhere(sprintf("%s IN (%s)", DAO_Address::ID, implode(',', $from_ids)));
         unset($from_ids);
         if (is_array($tickets)) {
             foreach ($tickets as $ticket_id => $ticket) {
                 $matches = CerberusApplication::runGroupRouting($team_id, $ticket_id);
             }
         }
         unset($from_addresses);
     }
 }