/** * Main Parse Method * * @param string Raw email contents * @param array Any headers to override * @param bool Can pass true to not actually route */ public static function parse($email, $override = array(), $doNotRoute = FALSE) { $obj = new self(); $obj->raw = $email; //----------------------------------------- // Deconstruct it //----------------------------------------- // It raises strict warnings //@error_reporting( E_NONE ); //@ini_set( 'display_errors', 'off' ); require_once IPS_KERNEL_PATH . 'PEAR/Mail/mimeDecode.php'; /*noLibHook*/ $decoder = new Mail_mimeDecode($email); $mail = $decoder->decode(array('include_bodies' => TRUE, 'decode_bodies' => TRUE, 'decode_headers' => TRUE)); //-------------------------------------- // Parse Headers //-------------------------------------- /* To */ if (isset($override['to'])) { $obj->to = $override['to']; } else { if ($mail->headers['delivered-to']) { $mail->headers['to'] = $mail->headers['delivered-to']; } $to = array(); if (strpos($mail->headers['to'], ',') === FALSE) { $mail->headers['to'] = array($mail->headers['to']); } else { $mail->headers['to'] = explode(',', $mail->headers['to']); } foreach ($mail->headers['to'] as $_to) { if (preg_match("/.+? <(.+?)>/", $_to, $matches)) { $to[] = htmlentities($matches[1]); } else { $to[] = htmlentities(trim($_to, '<>')); } } $obj->to = implode(',', $to); } /* From */ if (isset($override['from'])) { $obj->from = $override['from']; } else { if (preg_match("/.+? <(.+?)>/", $mail->headers['from'], $matches)) { $obj->from = htmlentities($matches[1]); } else { $obj->from = htmlentities(trim($mail->headers['from'], '<>')); } } /* Subject */ if (isset($override['subject'])) { $obj->subject = $override['subject']; } else { $obj->subject = (bool) trim($mail->headers['subject']) ? $mail->headers['subject'] : '(No Subject)'; $obj->subject = htmlentities($obj->subject); } /* CC */ $mail->headers['cc'] = preg_replace('/".+?" <(.+?)>/', '$1', $mail->headers['cc']); if (strpos($mail->headers['cc'], ',') === FALSE) { $mail->headers['cc'] = array($mail->headers['cc']); } else { $mail->headers['cc'] = explode(',', $mail->headers['cc']); } foreach ($mail->headers['cc'] as $_cc) { if (preg_match("/.+? <(.+?)>/", $_cc, $matches)) { $cc[] = $matches[1]; } else { $cc[] = trim($_cc, '<> '); } } $obj->cc = str_replace(array('>', '<'), '', implode(',', $cc)); //----------------------------------------- // Ignore? //----------------------------------------- if (!$obj->debug_mode and !$doNotRoute) { $escapedFrom = $obj->DB->addSlashes($obj->from); $log = $obj->DB->buildAndFetch(array('select' => '*', 'from' => 'core_incoming_email_log', 'where' => "log_email='{$escapedFrom}'")); if ($log['log_id']) { $oneMinuteAgo = time() - 60; if ($log['log_time'] > $oneMinuteAgo && $this->settings['sixty_second_rule']) { $ignore = TRUE; } $obj->DB->update('core_incoming_email_log', array('log_time' => time()), "log_id={$log['log_id']}"); if ($ignore) { return; } } else { $obj->DB->insert('core_incoming_email_log', array('log_email' => $obj->from, 'log_time' => time())); } } //----------------------------------------- // Now destruct the message //----------------------------------------- $obj->message = ''; $obj->_parsePart($mail); //----------------------------------------- // Purify It //----------------------------------------- // sometimes breaks $obj->message = str_replace(' ', ' ', $obj->message); /* Load */ require_once IPS_KERNEL_PATH . 'HTMLPurifier/HTMLPurifier.auto.php'; $config = HTMLPurifier_Config::createDefault(); /* Set Configuration */ $config->set('AutoFormat.Linkify', TRUE); $config->set('Core.Encoding', IPS_DOC_CHAR_SET); $config->set('HTML.TargetBlank', TRUE); $config->set('URI.Munge', ipsRegistry::getClass('output')->buildUrl('app=nexus&module=support§ion=redirect&url=%s&key=%t&resource=%r', 'publicNoSession')); $config->set('URI.MungeResources', TRUE); $config->set('URI.MungeSecretKey', md5(ipsRegistry::$settings['sql_pass'] . ipsRegistry::$settings['board_url'] . ipsRegistry::$settings['sql_database'])); /* Retain collapse data attribute */ $def = $config->getHTMLDefinition(true); $def->addAttribute('blockquote', 'data-author', 'CDATA'); $def->addAttribute('blockquote', 'data-collapsed', 'Number'); /* Purify */ $purifier = new HTMLPurifier($config); $obj->message = $purifier->purify($obj->message); //----------------------------------------- // Route //----------------------------------------- if ($doNotRoute) { return $obj; } $routed = FALSE; /* Try our routing criteria */ $obj->DB->build(array('select' => '*', 'from' => 'core_incoming_emails')); $obj->DB->execute(); while ($row = $obj->DB->fetch()) { // What are we looking for? switch ($row['rule_criteria_field']) { case 'to': $analyse = $obj->to; break; case 'from': $analyse = $obj->from; break; case 'sbjt': $analyse = $obj->subject; break; case 'body': $analyse = $obj->message; break; } // Does it match? $match = false; switch ($row['rule_criteria_type']) { case 'ctns': $match = (bool) (strpos($analyse, $row['rule_criteria_value']) !== FALSE); break; case 'eqls': if (strpos($analyse, ',') !== FALSE) { $match = (bool) in_array($analyse, explode(',', $analyse)); } else { $match = (bool) ($analyse == $row['rule_criteria_value']); } break; case 'regx': $match = (bool) (preg_match("/{$row['rule_criteria_value']}/", $analyse) == 1); break; } // If it matches, give to the app if ($match) { $routed = true; if ($row['rule_app'] != '--') { $appdir = IPSLib::getAppDir($row['rule_app']); if (is_file($appdir . '/extensions/incomingEmails.php')) { $class = 'incomingEmails_' . $row['rule_app']; require_once $appdir . '/extensions/incomingEmails.php'; /*noLibHook*/ $class = new $class(); $class->process($obj); } } break; } } /* Still here? Try all our apps */ if (!$routed) { foreach (ipsRegistry::$applications as $app) { $file = IPSLib::getAppDir($app['app_directory']) . '/extensions/incomingEmails.php'; if (file_exists($file)) { require_once $file; $class = 'incomingEmails_' . $app['app_directory']; $i = new $class(); if ($routed = $i->handleUnrouted($obj)) { break; } } } } /* STILL Here? Throw the unrouted message */ if (!$routed) { $unroutedMessage = @file_get_contents(DOC_IPS_ROOT_PATH . 'interface/email/unrouted.txt'); if ($unroutedMessage) { IPSText::getTextClass('email')->to = $obj->from; IPSText::getTextClass('email')->from = $obj->to; IPSText::getTextClass('email')->subject = "Re: {$obj->subject}"; IPSText::getTextClass('email')->message = nl2br($unroutedMessage); IPSText::getTextClass('email')->setHtmlEmail(TRUE); IPSText::getTextClass('email')->sendMail(); } } }