*/ if (defined('__TEST')) { if (isset($__test_options['parameters'])) { $parameters = $__test_options['parameters']; } if (isset($__test_options['mbox'])) { $mime->mbox = $__test_options['mbox']; } if (isset($__test_options['decode_bodies'])) { $mime->decode_bodies = $__test_options['decode_bodies']; } if (isset($__test_options['use_part_file_names'])) { $mime->use_part_file_names = $__test_options['use_part_file_names']; } } if (!$mime->Decode($parameters, $decoded)) { echo 'MIME message decoding error: ' . $mime->error . ' at position ' . $mime->error_position; if ($mime->track_lines && $mime->GetPositionLine($mime->error_position, $line, $column)) { echo ' line ' . $line . ' column ' . $column; } echo "\n"; } else { print_r($decoded); die; echo 'MIME message decoding successful.' . "\n"; echo count($decoded) == 1 ? '1 message was found.' : count($decoded) . ' messages were found.', "\n"; for ($message = 0; $message < count($decoded); $message++) { echo 'Message ', $message + 1, ':', "\n"; var_dump($decoded[$message]); if ($mime->decode_bodies) { if ($mime->Analyze($decoded[$message], $results)) {
//prepare the output buffers ob_end_clean(); ob_start(); //testing show the raw email //echo "Message: \n".$msg."\n"; //includes require 'resources/pop3/mime_parser.php'; require 'resources/pop3/rfc822_addresses.php'; if (file_exists($_SERVER["PROJECT_ROOT"] . "/app/emails/email_translation.php")) { require_once $_SERVER["PROJECT_ROOT"] . "/app/emails/email_translation.php"; } //parse the email message $mime = new mime_parser_class(); $mime->decode_bodies = 1; $parameters = array('Data' => $msg); $success = $mime->Decode($parameters, $decoded); if (!$success) { echo "MIME message decoding error: " . HtmlSpecialChars($mime->error) . "\n"; } else { //get the headers //print_r($decoded[0]); $headers = json_decode($decoded[0]["Headers"]["x-headers:"], true); $subject = $decoded[0]["Headers"]["subject:"]; $from = $decoded[0]["Headers"]["from:"]; $reply_to = $decoded[0]["Headers"]["reply-to:"]; $to = $decoded[0]["Headers"]["to:"]; $date = $decoded[0]["Headers"]["date:"]; //get the body $body = ''; //$parts_array["Parts"][0]["Headers"]["content-type:"]; //get the body
private function get_message($msg_id, $path) { $body = null; $headers = null; if (($error = $this->pop3->RetrieveMessage($msg_id, $headers, $body, -1)) != "") { $this->errors[] = $error; return false; } $message_file = implode("\r\n", $headers) . "\r\n" . implode("\r\n", $body); // ??? $mime = new mime_parser_class(); $mime->decode_bodies = 1; $parameters = array('Data' => $message_file, 'SkipBody' => 0); if (!$mime->Decode($parameters, $decoded)) { $this->errors[] = 'Unknown error when trying to decode MimeMessage'; return false; } if (!isset($decoded['0']['ExtractedAddresses']['from:'][0]['address']) || !isset($decoded['0']['Headers']['subject:']) || !isset($decoded['0']['Parts']) || !is_array($decoded['0']['Parts']) || count($decoded['0']['Parts']) < 1) { $this->errors[] = 'Missing sections in decoded MimeMessage'; return false; } $from = strtolower($decoded['0']['ExtractedAddresses']['from:'][0]['address']); if (!in_array($from, $this->valid_senders)) { $this->errors[] = 'Email processing rejected! Invalid sender: ' . $from; return false; } $subject = $decoded['0']['Headers']['subject:']; $html = array(); $plain = array(); $image = array(); $i = -1; // loop through all MessageParts and collect all Data (without image data) foreach ($decoded['0']['Parts'] as $main_part) { $i++; if (count($main_part['Parts']) > 0) { $n = -1; foreach ($main_part['Parts'] as $sub_part) { $n++; $this->get_message_part("{$i}-{$n}", $sub_part, $html, $plain, $image, false); } } else { $this->get_message_part("{$i}", $main_part, $html, $plain, $image, false); } } // optional checking extra password if (is_string($this->body_password) && strlen(trim($this->body_password)) > 0) { $pass = false; # check for extra security password foreach (array_merge($plain, $html) as $k => $v) { if (false !== strpos($v['Body'], trim($this->body_password))) { $pass = true; break; } } if ($pass !== true) { $this->errors[] = 'Email processing rejected! Required BodyPassword not found in Email: ' . $subject; return false; } } // optional checking and extracting BodyText $BodyText = ''; if (is_string($this->body_txt_start) && strlen(trim($this->body_txt_start)) > 0 && is_string($this->body_txt_end) && strlen(trim($this->body_txt_end)) > 0) { foreach (array_merge($plain, $html) as $k => $v) { if (false !== ($pos1 = strpos($v['Body'], trim($this->body_txt_start)))) { $pos1 += strlen(trim($this->body_txt_start)); if (false !== ($pos2 = strpos($v['Body'], trim($this->body_txt_end), $pos1))) { $BodyText = substr($v['Body'], $pos1, $pos2 - $pos1); break; } } } } // check for image if (count($image) == 0) { $this->errors[] = 'Email processing rejected! No image found in Email: ' . $subject; return false; } // safe all imgdata to filesystem $n = 0; $filenames = array(); foreach ($image as $img) { // $img['size']; // $img['BodyPartId']; // $img['imgname']; // $img['imgextension']; $p = explode('-', $img['BodyPartId']); if (count($p) == 2) { $imgdata =& $decoded['0']['Parts'][$p[0]]['Parts'][$p[1]]['Body']; } else { $imgdata =& $decoded['0']['Parts'][$p[0]]['Body']; } $img_basename = is_string($img['imgname']) ? $img['imgname'] : 'imgfile_' . strval($this->pulled_image_counter++) . '.' . $img['imgextension']; $img_filename = $path . '/' . $img_basename; $this->next_free_imgname($img_filename); $file_saved = file_put_contents($img_filename, $imgdata, LOCK_EX); if ($file_saved === strlen($imgdata)) { $filenames[] = basename($img_filename); } $imgdata = null; } $filenames = is_array($filenames) && count($filenames) > 0 ? $filenames : null; // >>>>>>> if (is_string($this->autorotate_pattern) && !is_null($filenames) && function_exists('exif_read_data')) { foreach ($filenames as $fn) { $fn = $path . '/' . $fn; $exif = @exif_read_data($fn, 'IFD0'); if (!is_array($exif) || !isset($exif['Model']) || preg_match($this->autorotate_pattern, $exif['Model']) !== 1) { continue; } hn_ImageManipulation::jpegfile_auto_correction($fn); } } // <<<<<<< return array('filenames' => $filenames, 'subject' => $subject, 'body' => $BodyText); }
function analyze($tmpfilepath, $tempdir) { $mime = new mime_parser_class(); $mime->mbox = 0; $mime->decode_bodies = 1; $mime->ignore_syntax_errors = 1; $mime->track_lines = 0; $parameters = array('File' => $tmpfilepath, 'SaveBody' => $tempdir); /* only process the first email */ if ($mime->Decode($parameters, $decoded)) { if ($mime->decode_bodies) { if ($mime->Analyze($decoded[0], $results)) { #echo "MIME:\n\n"; #print_r($results); #echo "\nEND MIME\n\n"; return process_results($results, $tempdir); } else { echo 'MIME message analyse error: ' . $mime->error . "\n"; } } } return False; }
function view($id = null) { if (!$id) { exit; } $polid = $this->Session->read('pol'); $solid = $this->Session->read('sol'); $this->set('menu_left', $this->Xplico->leftmenuarray(6)); $this->Nntp_article->recursive = -1; $article = $this->Nntp_article->read(null, $id); if ($polid != $article['Nntp_article']['pol_id'] || $solid != $article['Nntp_article']['sol_id']) { $this->redirect('/users/login'); } $this->Session->write('narticleid', $id); $this->set('article', $article); /* destroy last tmp dir */ $tmp_dir = $this->Session->read('mimedir'); system('rm -rf ' . $tmp_dir); /* create dir to put decoded data */ $tmp_dir = TmpDir(); $this->Session->write('mimedir', $tmp_dir); /* decode mime */ $mime_parser = new mime_parser_class(); $mime_parser->mbox = 0; // single message file $mime_parser->decode_bodies = 1; // decde bodies $mime_parser->ignore_syntax_errors = 1; $mime_parser->extract_addresses = 1; $parse_parameters = array('File' => $article['Nntp_article']['mime_path'], 'SaveBody' => $tmp_dir, 'SkipBody' => 1); if (!$mime_parser->Decode($parse_parameters, $mime_decoded)) { } elseif ($mime_parser->Analyze($mime_decoded[0], $mime_parsed)) { /* add 'to' and 'from' string */ if (isset($mime_parsed['From'])) { $mime_parsed['from'] = AddressList($mime_parsed['From']); } else { $mime_parsed['from'] = '---'; } if (isset($mime_parsed['To'])) { $mime_parsed['to'] = AddressList($mime_parsed['To']); } else { $mime_parsed['to'] = '---'; } $this->set('mailObj', $mime_parsed); //print_r($mime_parsed); // register visualization if (!$article['Nntp_article']['first_visualization_user_id']) { $uid = $this->Session->read('userid'); $article['Nntp_article']['first_visualization_user_id'] = $uid; $article['Nntp_article']['viewed_date'] = date("Y-m-d H:i:s"); $this->Nntp_article->save($article); } } }
function parseMail(&$message, &$decoded, &$results, &$warnings) { $mime = new mime_parser_class(); $mime->mbox = 0; $mime->decode_bodies = 1; $mime->ignore_syntax_errors = 1; $parameters = array('Data' => $message); if ($mime->Decode($parameters, $decoded)) { for ($msg = 0; $msg < count($decoded); $msg++) { $mime->Analyze($decoded[$msg], $results); } for ($warning = 0, Reset($mime->warnings); $warning < count($mime->warnings); Next($mime->warnings), $warning++) { $w = Key($mime->warnings); $warnings[$warning] = 'Warning: ' . $mime->warnings[$w] . ' at position ' . $w . "\n"; } } }
function parseMail(&$message, &$decoded, &$results, &$warnings) { $mime = new mime_parser_class(); $mime->mbox = 0; $mime->decode_bodies = 1; $mime->ignore_syntax_errors = 1; $parameters = array('Data' => $message); if ($mime->Decode($parameters, $decoded)) { for ($msg = 0; $msg < count($decoded); $msg++) { if (isset($decoded[$msg]['Headers'])) { $headers = $decoded[$msg]['Headers']; $address_hdr = array('to:', 'cc:', 'bcc:'); foreach ($address_hdr as $hdr) { if (isset($headers[$hdr]) && strpos($headers[$hdr], ';') !== false) { $headers[$hdr] = str_replace(';', ',', $headers[$hdr]); if (str_ends_with($headers[$hdr], ',')) { $headers[$hdr] = substr($headers[$hdr], 0, -1); } $decoded[$msg]['Headers'] = $headers; } } } $mime->Analyze($decoded[$msg], $results); } for ($warning = 0, Reset($mime->warnings); $warning < count($mime->warnings); Next($mime->warnings), $warning++) { $w = Key($mime->warnings); $warnings[$warning] = 'Warning: ' . $mime->warnings[$w] . ' at position ' . $w . "\n"; } } }
function message_upload() { $mime = new mime_parser_class(); $mime->decode_bodies = 0; $mime->ignore_syntax_errors = 1; $parameters['Data'] = $_POST["message"]; $parameters['SkipBody'] = 1; $decoded = array(); $mime->Decode($parameters, $decoded); $subject = addslashes($decoded[0]["Headers"]["subject:"]); $_POST["message"] = mysql_escape_string2($_POST["message"]); $q = new mysql(); $date = date('Y-m-d H:i:s'); $sql = "\n\tINSERT INTO `amavisd_tests` (`sender`,`recipients`,`message`,`saved_date`,`subject`) \n\tVALUES ('{$_POST["sender"]}','{$_POST["recipients"]}','{$_POST["message"]}','{$date}','{$subject}')"; $q->QUERY_SQL($sql, "artica_backup"); if (!$q->ok) { echo $q->mysql_error; return; } $size = FormatBytes(strlen($_POST["message"]) / 1024); $tpl = new templates(); echo $tpl->javascript_parse_text("{success} {message_size}:{$size}<br>{$subject}"); $sock = new sockets(); $sock->getFrameWork("cmd.php?spamass-test=yes"); }
function check_msg_analyze_content() { $page = CurrentPageName(); $t = $_GET["t"]; if (!is_file("/usr/share/artica-postfix/ressources/logs/check_msg.msg")) { if ($GLOBALS["VERBOSE"]) { echo "ressources/logs/check_msg.msg no such file<br>"; } return; } $mime = new mime_parser_class(); $mime->decode_bodies = 0; $mime->ignore_syntax_errors = 1; $decoded = array(); $parameters = array('File' => "ressources/logs/check_msg.msg", 'SkipBody' => 1); if (!$mime->Decode($parameters, $decoded)) { echo "<span style='color:#d32d2d;font-size:16px'>MIME message decoding error: {$mime->error} at position {$mime->error_position}</span>"; return; } if (!is_array($decoded[0]["Headers"])) { echo "MIME message decoding no Headers found"; return false; } $mime_decoded_headers = $decoded[0]["Headers"]; krsort($mime_decoded_headers["received:"]); $html[] = "<table style='width:99%' class=form>"; $serv["127.0.0.1"] = true; $serv["localhost"] = true; $serv["IPv6:::1"] = true; $serv["::1"] = true; $serv["Debian-exim"] = true; $serv["debian-exim"] = true; if (preg_match("#<(.*?)>#", $mime_decoded_headers["from:"], $re)) { $from[] = $re[1]; } if (preg_match("#<(.*?)>#", $mime_decoded_headers["reply-to:"], $re)) { $from[] = $re[1]; } if (preg_match("#<(.*?)>#", $mime_decoded_headers["reply-to:"], $re)) { $from[] = $re[1]; } if (isset($mime_decoded_headers["envelope-to:"])) { $from[] = $mime_decoded_headers["envelope-to:"]; } if (isset($mime_decoded_headers["x-beenthere:"])) { $from[] = $mime_decoded_headers["x-beenthere:"]; } if (isset($mime_decoded_headers["sender:"])) { $from[] = $mime_decoded_headers["sender:"]; } while (list($num, $ligne) = each($mime_decoded_headers["received:"])) { $ligne = str_replace("\r\n", " ", $ligne); $ligne = str_replace("\r", " ", $ligne); $ligne = str_replace("\n", " ", $ligne); if (preg_match("#with LMTPA#", $ligne)) { continue; } if (preg_match("#envelope-from\\s+(.*?)@(.+?)[\\s|\\(|;]#", $ligne, $re)) { $from[] = $re[1]; } if (preg_match("#from User\\s+\\(.*?\\[(.*?)\\]\\).*?sender:\\s+(.+?)\\)by\\s+(.+?)[\\s|\\(]#", $ligne, $re)) { $re[1] = trim($re[1]); $re[2] = trim($re[2]); $re[3] = trim($re[3]); $sender[] = $re[2]; $server[] = trim($re[3]); $server[] = trim($re[1]); continue; } if (preg_match("#from\\s+User\\s+.*?\\[(.*?)\\].*?by\\s+(.+?)[\\s|\\(|;]#", $ligne, $re)) { $re[1] = trim($re[1]); $re[2] = trim($re[2]); $server[] = trim($re[1]); $server[] = trim($re[2]); continue; } if (preg_match("#from\\s+(.*?)\\s+\\(\\[(.*?)\\]helo=(.*?)\\)by\\s+(.+?)[\\s|\\(|;]#", $ligne, $re)) { $re[1] = trim($re[1]); $re[2] = trim($re[2]); $re[3] = trim($re[3]); $server[] = trim($re[1]); $server[] = trim($re[2]); $server[] = trim($re[3]); continue; } if (preg_match("#from\\s+(.*?)\\s+\\(\\[(.*?)\\]\\s+helo=(.+?)\\)by\\s+(.+?)[\\s+|;]#", $ligne, $re)) { $re[1] = trim($re[1]); $re[2] = trim($re[2]); $re[3] = trim($re[3]); $server[] = trim($re[1]); $server[] = trim($re[2]); $server[] = trim($re[3]); continue; } if (preg_match("#from\\s+(.*?)\\s+by\\s+(.*?)[;|\\s]#", $ligne, $re)) { $re[1] = trim($re[1]); $re[2] = trim($re[2]); $server[] = trim($re[1]); $server[] = trim($re[2]); continue; } if (preg_match("#from\\s+(.*?)\\(.*?\\[(.*?)\\]\\)#", $ligne, $re)) { $re[1] = trim($re[1]); $re[2] = trim($re[2]); $server[] = trim($re[1]); $server[] = trim($re[2]); continue; } if (preg_match("#^by\\s+(.*?)\\s+with#", trim($ligne), $re)) { $re[1] = trim($re[1]); $server[] = trim($re[1]); continue; } if (preg_match("#^from\\s+(.*?)\\s+\\(\\[(.*?)\\].*?\\)by\\s+(.+)\\s+with#", trim($ligne), $re)) { $re[1] = trim($re[1]); $re[2] = trim($re[2]); $re[3] = trim($re[3]); $server[] = trim($re[1]); $server[] = trim($re[2]); $server[] = trim($re[3]); continue; } if (preg_match("#^from\\s+(.*?)\\s+\\((.*?)\\) by(.*?)\\s+\\((.*?)\\)\\s+with#", trim($ligne), $re)) { $re[1] = trim($re[1]); $re[2] = trim($re[2]); $re[3] = trim($re[3]); $server[] = trim($re[1]); $server[] = trim($re[2]); $server[] = trim($re[3]); continue; } //$not[]="<strong style='color:#d32d2d'>Not found: $ligne</strong>"; } while (list($num, $servx) = each($server)) { $servx = strtolower($servx); if (preg_match("#(.*?)\\s+\\(#", $servx, $re)) { $servx = $re[1]; } if (preg_match("#(.*?)\\(#", $servx, $re)) { $servx = $re[1]; } if (isset($serv[$servx])) { continue; } $resv = null; $hostname = null; $ipaddr = null; if (preg_match("#^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+#", $servx)) { $resv = gethostbyaddr($servx); if ($resv != $servx) { $hostname = $resv; $ipaddr = $servx; } } else { $resv = gethostbyname($servx); if ($resv != $servx) { $hostname = $servx; $ipaddr = $resv; } } if ($hostname == null && $ipaddr == null) { $hostname = $servx; } else { $serv[$hostname] = true; $serv[$ipaddr] = true; } $serv[$servx] = true; $textAffich = $hostname; if ($ipaddr != null) { $textAffich = "{$hostname} <span style='font-size:11px'>[{$ipaddr}]</span>"; } $html[] = "<tr>\n\t\t\t\t\t\t<td style='font-size:14px;font-weight:bold'>{server}: {$textAffich}</td>\n\t\t\t\t\t\t<td nowrap>" . button("{add_rule}", "BannServ{$t}('{$hostname}');", "12px") . "</td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t"; } $html[] = "</table>"; $textSrv = @implode("", $html); $html = array(); $html[] = "<table style='width:99%' class=form>"; while (list($num, $email) = each($from)) { if (trim($email) == null) { continue; } if (preg_match("#<(.*?)>#", $email, $re)) { $email = $re[1]; } $email = str_replace("<", "", $email); $email = str_replace(">", "", $email); if (isset($alr[$email])) { continue; } $html[] = "<tr>\n\t\t\t\t\t\t<td style='font-size:14px;font-weight:bold'>{from}: {$email}</td>\n\t\t\t\t\t\t<td nowrap>" . button("{add_rule}", "BannMail{$t}('{$email}');", "12px") . "</td>\n\t\t\t\t\t</tr>\n\t\t\t\t\t"; $alr[$email] = true; } $html[] = "</table>"; $textemail = @implode("", $html); $script = "\n\t\t<script>\n\t\tvar x_BannServ{$t}=function (obj) {\n\t\t\tvar results=obj.responseText;\n\t\t\tif (results.length>3){alert(results);return;}\n\t\t\t\n\t\t}\n\n\t\tfunction BannServ{$t}(pattern){\n\t\t\tvar XHR = new XHRConnection();\n\t\t\tXHR.appendData('banserv',pattern);\n\t\t\tXHR.sendAndLoad('{$page}', 'POST',x_BannServ{$t});\n\t\t\n\t\t}\t\n\n\t\tfunction BannMail{$t}(pattern){\n\t\t\tvar XHR = new XHRConnection();\n\t\t\tXHR.appendData('banmail',pattern);\n\t\t\tXHR.sendAndLoad('{$page}', 'POST',x_BannServ{$t});\n\t\t\n\t\t}\t\t\n\t\t\n\t\t</script>\n\t\t"; $tpl = new templates(); echo $tpl->_ENGINE_parse_body($textSrv . $textemail) . $script; }
/** * Read messages from server and create posts * * @param resource $mbox created by pbm_connect() (by reference) * @param integer the number of messages to process * @return boolean true on success */ function pbm_process_messages(&$mbox, $limit) { global $Settings; global $pbm_item_files, $pbm_messages, $pbm_items, $post_cntr, $del_cntr, $is_cron_mode; // No execution time limit set_max_execution_time(0); // Are we in test mode? $test_mode_on = $Settings->get('eblog_test_mode'); $post_cntr = 0; $del_cntr = 0; for ($index = 1; $index <= $limit; $index++) { pbm_msg('<hr /><h3>Processing message #' . $index . ':</h3>'); $strbody = ''; $hasAttachment = false; $hasRelated = false; $pbm_item_files = array(); // reset the value for each new Item // Save email to hard drive, otherwise attachments may take a lot of RAM if (!($tmpMIME = tempnam(sys_get_temp_dir(), 'b2evoMail'))) { pbm_msg(T_('Could not create temporary file.'), true); continue; } imap_savebody($mbox, $tmpMIME, $index); // Create random temp directory for message parts $tmpDirMIME = pbm_tempdir(sys_get_temp_dir(), 'b2evo_'); $mimeParser = new mime_parser_class(); $mimeParser->mbox = 0; // Set to 0 for parsing a single message file $mimeParser->decode_headers = 1; $mimeParser->ignore_syntax_errors = 1; $mimeParser->extract_addresses = 0; $MIMEparameters = array('File' => $tmpMIME, 'SaveBody' => $tmpDirMIME, 'SkipBody' => 1); if (!$mimeParser->Decode($MIMEparameters, $decodedMIME)) { pbm_msg(sprintf('MIME message decoding error: %s at position %d.', $mimeParser->error, $mimeParser->error_position), true); rmdir_r($tmpDirMIME); unlink($tmpMIME); continue; } else { pbm_msg('MIME message decoding successful'); if (!$mimeParser->Analyze($decodedMIME[0], $parsedMIME)) { pbm_msg(sprintf('MIME message analyse error: %s', $mimeParser->error), true); rmdir_r($tmpDirMIME); unlink($tmpMIME); continue; } // Get message $subject and $post_date from headers (by reference) if (!pbm_process_header($parsedMIME, $subject, $post_date)) { // Couldn't process message headers rmdir_r($tmpDirMIME); unlink($tmpMIME); continue; } // TODO: handle type == "message" recursively // sam2kb> For some reason imap_qprint() demages HTML text... needs more testing if ($parsedMIME['Type'] == 'html') { // Mail is HTML if ($Settings->get('eblog_html_enabled')) { // HTML posting enabled pbm_msg('HTML message part saved as ' . $parsedMIME['DataFile']); $html_body = file_get_contents($parsedMIME['DataFile']); } foreach ($parsedMIME['Alternative'] as $alternative) { // First try to get HTML alternative (when possible) if ($alternative['Type'] == 'html' && $Settings->get('eblog_html_enabled')) { // HTML text pbm_msg('HTML alternative message part saved as ' . $alternative['DataFile']); // sam2kb> TODO: we may need to use $html_body here instead $strbody = file_get_contents($alternative['DataFile']); break; // stop after first alternative } elseif ($alternative['Type'] == 'text') { // Plain text pbm_msg('Text alternative message part saved as ' . $alternative['DataFile']); $strbody = imap_qprint(file_get_contents($alternative['DataFile'])); break; // stop after first alternative } } } elseif ($parsedMIME['Type'] == 'text') { // Mail is plain text pbm_msg('Plain-text message part saved as ' . $parsedMIME['DataFile']); $strbody = imap_qprint(file_get_contents($parsedMIME['DataFile'])); } // Check for attachments if (!empty($parsedMIME['Attachments'])) { $hasAttachment = true; foreach ($parsedMIME['Attachments'] as $file) { pbm_msg('Attachment: ' . $file['FileName'] . ' stored as ' . $file['DataFile']); } } // Check for inline images if (!empty($parsedMIME['Related'])) { $hasRelated = true; foreach ($parsedMIME['Related'] as $file) { pbm_msg('Related file with content ID: ' . $file['ContentID'] . ' stored as ' . $file['DataFile']); } } if (count($mimeParser->warnings) > 0) { pbm_msg(sprintf('<h4>%d warnings during decode:</h4>', count($mimeParser->warnings))); foreach ($mimeParser->warnings as $k => $v) { pbm_msg('Warning: ' . $v . ' at position ' . $k); } } } unlink($tmpMIME); if (empty($html_body)) { // Plain text message pbm_msg('Message type: TEXT'); pbm_msg('Message body: <pre style="font-size:10px">' . htmlspecialchars($strbody) . '</pre>'); // Process body. First fix different line-endings (dos, mac, unix), remove double newlines $content = str_replace(array("\r", "\n\n"), "\n", trim($strbody)); // First see if there's an <auth> tag with login and password if (($auth = pbm_get_auth_tag($content)) === false) { // No <auth> tag, let's detect legacy "username:password" on the first line $a_body = explode("\n", $content, 2); // tblue> splitting only into 2 parts allows colons in the user PW // Note: login and password cannot include '<' ! $auth = explode(':', strip_tags($a_body[0]), 2); // Drop the first line with username and password $content = $a_body[1]; } } else { // HTML message pbm_msg('Message type: HTML'); if (($parsed_message = pbm_prepare_html_message($html_body)) === false) { // No 'auth' tag provided, skip to the next message rmdir_r($tmpDirMIME); continue; } list($auth, $content) = $parsed_message; } // TODO: dh> should the password really get trimmed here?! $user_pass = isset($auth[1]) ? trim(remove_magic_quotes($auth[1])) : NULL; $user_login = trim(evo_strtolower(remove_magic_quotes($auth[0]))); if (empty($user_login) || empty($user_pass)) { pbm_msg(sprintf(T_('Please add username and password in message body in format %s.'), '"<auth>username:password</auth>"'), true); rmdir_r($tmpDirMIME); continue; } // Authenticate user pbm_msg('Authenticating user: «' . $user_login . '»'); $pbmUser =& pbm_validate_user_password($user_login, $user_pass); if (!$pbmUser) { pbm_msg(sprintf(T_('Authentication failed for user «%s»'), htmlspecialchars($user_login)), true); rmdir_r($tmpDirMIME); continue; } $pbmUser->get_Group(); // Load group if (!empty($is_cron_mode)) { // Assign current User if we are in cron mode. This is needed in order to check user permissions global $current_User; $current_User = duplicate($pbmUser); } // Activate User's locale locale_activate($pbmUser->get('locale')); pbm_msg('<b class="green">Success</b>'); if ($post_categories = xmlrpc_getpostcategories($content)) { $main_cat_ID = array_shift($post_categories); $extra_cat_IDs = $post_categories; pbm_msg('Extra categories: ' . implode(', ', $extra_cat_IDs)); } else { $main_cat_ID = $Settings->get('eblog_default_category'); $extra_cat_IDs = array(); } pbm_msg('Main category ID: ' . $main_cat_ID); $ChapterCache =& get_ChapterCache(); $pbmChapter =& $ChapterCache->get_by_ID($main_cat_ID, false, false); if (empty($pbmChapter)) { pbm_msg(sprintf(T_('Requested category %s does not exist!'), $main_cat_ID), true); rmdir_r($tmpDirMIME); continue; } $blog_ID = $pbmChapter->blog_ID; pbm_msg('Blog ID: ' . $blog_ID); $BlogCache =& get_BlogCache(); $pbmBlog =& $BlogCache->get_by_ID($blog_ID, false, false); if (empty($pbmBlog)) { pbm_msg(sprintf(T_('Requested blog %s does not exist!'), $blog_ID), true); rmdir_r($tmpDirMIME); continue; } // Check permission: pbm_msg(sprintf('Checking permissions for user «%s» to post to Blog #%d', $user_login, $blog_ID)); if (!$pbmUser->check_perm('blog_post!published', 'edit', false, $blog_ID)) { pbm_msg(T_('Permission denied.'), true); rmdir_r($tmpDirMIME); continue; } if (($hasAttachment || $hasRelated) && !$pbmUser->check_perm('files', 'add', false, $blog_ID)) { pbm_msg(T_('You have no permission to add/upload files.'), true); rmdir_r($tmpDirMIME); continue; } pbm_msg('<b class="green">Success</b>'); // Remove content after terminator $eblog_terminator = $Settings->get('eblog_body_terminator'); if (!empty($eblog_terminator) && ($os_terminator = evo_strpos($content, $eblog_terminator)) !== false) { $content = evo_substr($content, 0, $os_terminator); } $post_title = pbm_get_post_title($content, $subject); // Remove 'title' and 'category' tags $content = xmlrpc_removepostdata($content); // Remove <br> tags from string start and end // We do it here because there might be extra <br> left after deletion of <auth>, <category> and <title> tags $content = preg_replace(array('~^(\\s*<br[\\s/]*>\\s*){1,}~i', '~(\\s*<br[\\s/]*>\\s*){1,}$~i'), '', $content); if ($hasAttachment || $hasRelated) { // Handle attachments if (isset($GLOBALS['files_Module'])) { if ($mediadir = $pbmBlog->get_media_dir()) { if ($hasAttachment) { pbm_process_attachments($content, $parsedMIME['Attachments'], $mediadir, $pbmBlog->get_media_url(), $Settings->get('eblog_add_imgtag'), 'attach'); } if ($hasRelated) { pbm_process_attachments($content, $parsedMIME['Related'], $mediadir, $pbmBlog->get_media_url(), true, 'related'); } } else { pbm_msg(T_('Unable to access media directory. No attachments processed.'), true); } } else { pbm_msg(T_('Files module is disabled or missing!'), true); } } // CHECK and FORMAT content global $Plugins; $renderer_params = array('Blog' => &$pbmBlog, 'setting_name' => 'coll_apply_rendering'); $renderers = $Plugins->validate_renderer_list($Settings->get('eblog_renderers'), $renderer_params); pbm_msg('Applying the following text renderers: ' . implode(', ', $renderers)); // Do some optional filtering on the content // Typically stuff that will help the content to validate // Useful for code display // Will probably be used for validation also $Plugins_admin =& get_Plugins_admin(); $params = array('object_type' => 'Item', 'object_Blog' => &$pbmBlog); $Plugins_admin->filter_contents($post_title, $content, $renderers, $params); pbm_msg('Filtered post content: <pre style="font-size:10px">' . htmlspecialchars($content) . '</pre>'); $context = $Settings->get('eblog_html_tag_limit') ? 'commenting' : 'posting'; $post_title = check_html_sanity($post_title, $context, $pbmUser); $content = check_html_sanity($content, $context, $pbmUser); global $Messages; if ($Messages->has_errors()) { // Make it easier for user to find and correct the errors pbm_msg("\n" . sprintf(T_('Processing message: %s'), $post_title), true); pbm_msg($Messages->get_string(T_('Cannot post, please correct these errors:'), 'error'), true); $Messages->clear(); rmdir_r($tmpDirMIME); continue; } if ($test_mode_on) { // Test mode pbm_msg('<b class="green">It looks like the post can be successfully saved in the database. However we will not do it in test mode.</b>'); } else { load_class('items/model/_item.class.php', 'Item'); global $pbm_items, $DB, $localtimenow; $post_status = 'published'; pbm_msg(sprintf('<h4>Saving item "%s" in the database</h4>', $post_title)); // INSERT NEW POST INTO DB: $edited_Item = new Item(); $edited_Item->set_creator_User($pbmUser); $edited_Item->set($edited_Item->lasteditor_field, $pbmUser->ID); $edited_Item->set('title', $post_title); $edited_Item->set('content', $content); $edited_Item->set('datestart', $post_date); $edited_Item->set('datemodified', date('Y-m-d H:i:s', $localtimenow)); $edited_Item->set('main_cat_ID', $main_cat_ID); $edited_Item->set('extra_cat_IDs', $extra_cat_IDs); $edited_Item->set('status', $post_status); $edited_Item->set('locale', $pbmUser->locale); $edited_Item->set('renderers', $renderers); // INSERT INTO DB: $edited_Item->dbinsert('through_email'); pbm_msg(sprintf('Item created?: ' . (isset($edited_Item->ID) ? 'yes' : 'no'))); // Execute or schedule notifications & pings: $edited_Item->handle_post_processing(true); if (!empty($pbm_item_files)) { // Attach files $FileCache =& get_FileCache(); $order = 1; foreach ($pbm_item_files as $filename) { pbm_msg(sprintf('Saving file "%s" in the database', $filename)); $pbmFile =& $FileCache->get_by_root_and_path('collection', $pbmBlog->ID, $filename); $pbmFile->meta = 'notfound'; // Save time and don't try to load meta from DB, it's not there anyway $pbmFile->dbsave(); pbm_msg(sprintf('File saved?: ' . (isset($pbmFile->ID) ? 'yes' : 'no'))); pbm_msg(sprintf('Attaching file "%s" to the post', $filename)); // Let's make the link! $pbmLink = new Link(); $pbmLink->set('itm_ID', $edited_Item->ID); $pbmLink->set('file_ID', $pbmFile->ID); $pbmLink->set('position', 'aftermore'); $pbmLink->set('order', $order++); $pbmLink->dbinsert(); pbm_msg(sprintf('File attached?: ' . (isset($pbmLink->ID) ? 'yes' : 'no'))); } } // Save posted items sorted by author user for reports $pbm_items['user_' . $pbmUser->ID][] = $edited_Item; ++$post_cntr; } pbm_msg('Message posting successful'); // Delete temporary directory rmdir_r($tmpDirMIME); if (!$test_mode_on && $Settings->get('eblog_delete_emails')) { pbm_msg('Marking message for deletion from inbox: ' . $index); imap_delete($mbox, $index); ++$del_cntr; } } // Expunge messages marked for deletion imap_expunge($mbox); return true; }
/** * Read messages from server and save returned emails into DB * * @param resource $mbox created by dre_connect() (by reference) * @param integer the number of messages to process * @param boolean TRUE if script is executed by cron * @return boolean true on success */ function dre_process_messages(&$mbox, $limit, $cron = false) { global $Settings, $debug; global $dre_messages, $dre_emails, $email_cntr, $del_cntr, $is_cron_mode; // This may take a very long time if there are many messages; No execution time limit: set_max_execution_time(0); if ($Settings->get('repath_ignore_read')) { // Read status info of all messages in order to know which have already been read: $msg_statuses = imap_fetch_overview($mbox, '1:' . $limit); } $email_cntr = 0; $del_cntr = 0; for ($index = 1; $index <= $limit; $index++) { // Repeat for as many messages as allowed... dre_msg('<hr /><h3>' . sprintf(T_('Processing message %s:'), '#' . $index) . '</h3>', $cron); if ($Settings->get('repath_ignore_read')) { // Check if we can read this message or we should skip this: if (isset($msg_statuses[$index - 1]) && $msg_statuses[$index - 1]->seen == 1) { // Skip this message because it has already been read: dre_msg(T_('Ignoring this message because it has aleady been read.'), $cron); continue; } else { // Mark this message as "Seen" in order to don't read it twice: imap_setflag_full($mbox, $index, '\\Seen'); } } $html_body = ''; $strbody = ''; $hasAttachment = false; $hasRelated = false; // Save email to a temporary file on hard drive, otherwise BIG attachments may take a lot of RAM: if (!($tmpMIME = tempnam(sys_get_temp_dir(), 'b2evoMail'))) { dre_msg(T_('Could not create temporary file.'), $cron); continue; } // Save the whole body of a specific message from the mailbox: imap_savebody($mbox, $tmpMIME, $index); // fp> TODO: soemwhere here we should skip messages that already have the "seen" flag. This should be optional but should be the default. // This will allow to keep the emails in the INBOX without reprocessing them but to easily try them again my marking them unread. // Create random temp directory for message parts: $tmpDirMIME = dre_tempdir(sys_get_temp_dir(), 'b2evo_'); // Instanciate mime_parser.php library: $mimeParser = new mime_parser_class(); $mimeParser->mbox = 0; // Set to 0 for parsing a *single* RFC 2822 message $mimeParser->decode_headers = 1; // Set to 1 if it is necessary to decode message headers that may have non-ASCII characters and use other character set encodings $mimeParser->ignore_syntax_errors = 1; // ignore syntax errors in malformed messages. $mimeParser->extract_addresses = 0; // Associative array to specify parameters for the messagedata parsing and decoding operation. $MIMEparameters = array('File' => $tmpMIME, 'SaveBody' => $tmpDirMIME, 'SkipBody' => 1); // STEP 1: Parse and decode message data and retrieve its structure: if (!$mimeParser->Decode($MIMEparameters, $decodedMIME)) { // error: dre_msg(sprintf(T_('MIME message decoding error: %s at position %d.'), $mimeParser->error, $mimeParser->error_position), $cron); rmdir_r($tmpDirMIME); unlink($tmpMIME); continue; } else { // the specified message data was parsed successfully: dre_msg(T_('MIME message decoding successful'), $cron); // STEP 2: Analyze (the first) parsed message to describe its contents: if (!$mimeParser->Analyze($decodedMIME[0], $parsedMIME)) { // error: dre_msg(sprintf(T_('MIME message analyze error: %s'), $mimeParser->error), $cron); rmdir_r($tmpDirMIME); unlink($tmpMIME); continue; } // Get message $subject and $post_date from headers (by reference) if (!dre_process_header($parsedMIME, $subject, $post_date, $cron)) { // Couldn't process message headers: rmdir_r($tmpDirMIME); unlink($tmpMIME); continue; } // TODO: handle type == "message" recursively // fp> where is type == "message" ??? // yura> I don't find the type == 'message' in dump of $decodedMIME and $parsedMIME // sam2kb> For some reason imap_qprint() demages HTML text... needs more testing // yura> I replaced imap_qprint() with quoted_printable_decode() to avoid notices about invalid quoted-printable sequence // yura> imap_qprint() and quoted_printable_decode() do empty the message text, thus they were deleted. dre_msg(T_('Email Type') . ': ' . $parsedMIME['Type'], $cron); if ($parsedMIME['Type'] == 'html') { // Mail is HTML: if ($debug) { // Display this info only in debug mode: dre_msg(sprintf(T_('HTML message part saved as %s'), $parsedMIME['DataFile']), $cron); } $html_body = file_get_contents($parsedMIME['DataFile']); if (empty($html_body)) { // Try to get a body text from alternative parts if main html body is empty: foreach ($parsedMIME['Alternative'] as $alternative) { // First try to get HTML alternative (when possible) if ($alternative['Type'] == 'html') { // HTML text if ($debug) { // Display this info only in debug mode: dre_msg(sprintf(T_('HTML alternative message part saved as %s'), $alternative['DataFile']), $cron); } $strbody = file_get_contents($alternative['DataFile']); break; // stop after first alternative } elseif ($alternative['Type'] == 'text') { // Plain text if ($debug) { // Display this info only in debug mode: dre_msg(sprintf(T_('Text alternative message part saved as %s'), $alternative['DataFile']), $cron); } $strbody = file_get_contents($alternative['DataFile']); break; // stop after first alternative } } } } elseif ($parsedMIME['Type'] == 'text') { // Mail is plain text: if ($debug) { // Display this info only in debug mode: dre_msg(sprintf(T_('Plain-text message part saved as %s'), $parsedMIME['DataFile']), $cron); } $strbody = file_get_contents($parsedMIME['DataFile']); } elseif ($parsedMIME['Type'] == 'delivery-status') { // Mail is delivery-status: $strbody = $parsedMIME['Response']; } if (count($mimeParser->warnings) > 0) { // Record potential warnings: dre_msg('<h4>' . sprintf(T_('%d warnings during decode:'), count($mimeParser->warnings)) . '</h4>', $cron); foreach ($mimeParser->warnings as $k => $v) { dre_msg(sprintf(T_('Warning: %s at position %s'), $v, $k), $cron); } } } unlink($tmpMIME); if (empty($html_body)) { // Plain-text message dre_msg(sprintf(T_('Message type: %s'), 'TEXT'), $cron); // Process body. First fix different line-endings (dos, mac, unix), remove double newlines $content = str_replace(array("\r", "\n\n"), "\n", trim($strbody)); dre_msg(sprintf(T_('Message body: %s'), '<pre style="font-size:10px">' . htmlspecialchars($strbody) . '</pre>'), $cron); } else { // HTML message dre_msg(sprintf(T_('Message type: %s'), 'HTML'), $cron); dre_msg(sprintf(T_('Message body (original): %s'), '<pre style="font-size:10px">' . htmlspecialchars($html_body) . '</pre>', $cron)); // Prepare html message body text: $content = dre_prepare_html_message($html_body); dre_msg(sprintf(T_('Message body (processed): %s'), '<pre style="font-size:10px">' . htmlspecialchars($content) . '</pre>', $cron)); } dre_msg('<b class="green">' . T_('MIME Decoding Successful') . '</b>', $cron); $message_text = $content; // Remove content after terminators $content = dre_limit_by_terminators($content); global $Messages; if ($Messages->has_errors()) { // Make it easier for user to find and correct the errors dre_msg("\n" . sprintf(T_('Processing message: %s'), $post_title), $cron); dre_msg($Messages->get_string(T_('Cannot post, please correct these errors:'), 'error'), $cron); $Messages->clear(); rmdir_r($tmpDirMIME); continue; } global $dre_emails, $DB, $localtimenow; dre_msg('<h4>' . T_('Saving the returned email in the database') . '</h4>', $cron); // Get Headers from Decoded MIME Data: $email_headers = dre_get_headers($decodedMIME); // Get data of the returned email: $email_data = dre_get_email_data($content, $message_text, $email_headers); dre_msg(T_('Email Address') . ': ' . $email_data['address'], $cron); dre_msg(T_('Error Type') . ': ' . dre_decode_error_type($email_data['errtype']), $cron); dre_msg(T_('Error Message') . ': ' . $email_data['errormsg'], $cron); // Insert a returned email's data into DB if (dre_insert_returned_email($email_data)) { ++$email_cntr; } // Delete temporary directory: rmdir_r($tmpDirMIME); // Mark message to be deleted: if ($Settings->get('repath_delete_emails')) { dre_msg(sprintf(T_('Marking message for deletion from inbox: %s'), $index), $cron); imap_delete($mbox, $index); ++$del_cntr; } } // Expunge messages marked for deletion imap_expunge($mbox); return true; }
function view($id = null) { if (!$id) { exit; } $polid = $this->Session->read('pol'); $solid = $this->Session->read('sol'); $this->set('menu_left', $this->Xplico->leftmenuarray(3)); $this->Email->recursive = -1; $email = $this->Email->read(null, $id); if ($polid != $email['Email']['pol_id'] || $solid != $email['Email']['sol_id']) { $this->redirect('/users/login'); } $this->Session->write('emailid', $id); $this->set('email', $email); /* destroy last tmp dir */ $tmp_dir = $this->Session->read('mimedir'); system('rm -rf ' . $tmp_dir); /* create dir to put decoded data */ $tmp_dir = TmpDir(); $this->Session->write('mimedir', $tmp_dir); /* decode mime */ $mime_parser = new mime_parser_class(); $mime_parser->mbox = 0; // single message file $mime_parser->decode_bodies = 1; // decde bodies $mime_parser->ignore_syntax_errors = 1; $mime_parser->extract_addresses = 0; $parse_parameters = array('File' => $email['Email']['mime_path'], 'SaveBody' => $tmp_dir, 'SkipBody' => 1); if (!$mime_parser->Decode($parse_parameters, $mime_decoded)) { } elseif ($mime_parser->Analyze($mime_decoded[0], $mime_parsed)) { /* add 'to' and 'from' string */ if (isset($mime_parsed['To'])) { $mime_parsed['to'] = AddressList($mime_parsed['To']); } else { $mime_parsed['to'] = '---'; } if (isset($mime_parsed['From'])) { $mime_parsed['from'] = AddressList($mime_parsed['From']); } else { $mime_parsed['from'] = '---'; } $this->set('mailObj', $mime_parsed); //print_r($mime_parsed); die(); // register visualization if (!$email['Email']['first_visualization_user_id']) { $uid = $this->Session->read('userid'); $email['Email']['first_visualization_user_id'] = $uid; $email['Email']['viewed_date'] = date("Y-m-d H:i:s"); $this->Email->save($email); } } if (!$id && empty($this->data)) { $this->flash(__('Invalid Email', true), array('action' => 'index')); } if (!empty($this->data)) { if ($this->Email->save($this->data)) { // $this->flash(__('Changes saved succesfully.', true), array('action' => 'view/'.$id)); // $this->flash(__('Changes saved succesfully.', true)); $this->redirect('/emails/view/' . $id); } else { } } if (empty($this->data)) { $this->data = $this->Email->read(null, $id); } $this->set('relevanceoptions', array('0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5', '100' => __('Unknown', true))); }
private function download_email($account) { $log =& singleton::get(__NAMESPACE__ . '\\log'); $tickets =& singleton::get(__NAMESPACE__ . '\\tickets'); $ticket_notes =& singleton::get(__NAMESPACE__ . '\\ticket_notes'); $users =& singleton::get(__NAMESPACE__ . '\\users'); $storage =& singleton::get(__NAMESPACE__ . '\\storage'); $pop3 = $account['obj']; $pop3->hostname = $account['hostname']; // POP 3 server host name $pop3->port = $account['port']; // POP 3 server host port $pop3->tls = $account['tls']; // Establish secure connections using TLS $pop3->realm = ''; /* Authentication realm or domain */ $pop3->workstation = ''; /* Workstation for NTLM authentication */ $apop = 0; /* Use APOP authentication */ $pop3->authentication_mechanism = 'USER'; /* SASL authentication mechanism */ $pop3->debug = 0; /* Output debug information */ $pop3->html_debug = 0; /* Debug information is in HTML */ $pop3->join_continuation_header_lines = 1; /* Concatenate headers split in multiple lines */ if (($error = $pop3->Open()) == '') { if (($error = $pop3->Login($account['username'], $account['password'], $apop)) == '') { if (($error = $pop3->Statistics($messages, $size)) == '') { if ($messages > 0) { $log_array['event_severity'] = 'notice'; $log_array['event_number'] = E_USER_NOTICE; $log_array['event_description'] = 'Found "' . (int) $messages . '" messages on POP server "' . safe_output($pop3->hostname) . '" for download'; $log_array['event_file'] = __FILE__; $log_array['event_file_line'] = __LINE__; $log_array['event_type'] = 'download_email'; $log_array['event_source'] = 'pop_system'; $log_array['event_version'] = '1'; $log_array['log_backtrace'] = false; $log->add($log_array); $pop3->GetConnectionName($connection_name); for ($index = 1; $index <= $messages; $index++) { $saved_files = array(); $found_subject = false; $message_file = 'pop3://' . $connection_name . '/' . $index; $mime = new \mime_parser_class(); /* * Set to 0 for not decoding the message bodies */ $mime->decode_bodies = 1; $parameters = array('File' => $message_file); $success = $mime->Decode($parameters, $email_message); $email = array(); $email['body'] = ''; $email['html'] = 0; //get the message id $email['message_id'] = ''; if (isset($email_message[0]['Headers']['message-id:'])) { $email['message_id'] = $email_message[0]['Headers']['message-id:']; } //check if already downloaded $import_message = true; if (!empty($email['message_id'])) { $count = $this->count_message(array('message_id' => $email['message_id'])); if ($count > 0) { $import_message = false; } $this->add_message(array('message_id' => $email['message_id'])); } if ($import_message) { if ($mime->Analyze($email_message[0], $results)) { //print_r($results); //exit; if ($results['Type'] == 'html') { $email['type'] = 'html'; if ($account['html_enabled'] == 1) { if (isset($results['Data']) && !empty($results['Data'])) { $email['html'] = 1; $email['body'] = convert_encoding($results['Data'], $results['Encoding']); } else { $email['body'] = convert_encoding($results['Alternative'][0]['Data'], $results['Encoding']); } } else { if (isset($results['Alternative'][0]['Data']) && !empty($results['Alternative'][0]['Data'])) { $email['body'] = convert_encoding($results['Alternative'][0]['Data'], $results['Encoding']); } else { $data = str_replace('<!DOCTYPE', '<DOCTYPE', $results['Data']); $data = preg_replace("'<style[^>]*>.*</style>'siU", '', $data); $data = preg_replace('/</', ' <', $data); $data = preg_replace('/>/', '> ', $data); $data = html_entity_decode(strip_tags($data)); $data = preg_replace('/[\\n\\r\\t]/', ' ', $data); $data = preg_replace('/ /', ' ', $data); $data = trim($data); $email['body'] = convert_encoding($data, $results['Encoding']); } } } elseif ($results['Type'] == 'text') { $email['type'] = 'text'; if (isset($results['Data']) && !empty($results['Data'])) { $email['body'] = convert_encoding($results['Data'], $results['Encoding']); } } //subject if (isset($results['Subject']) && !empty($results['Subject'])) { if (isset($results['Encoding'])) { $email['subject'] = convert_encoding($results['Subject'], $results['Encoding']); } else { $email['subject'] = convert_encoding($results['Subject']); } $found_subject = TRUE; } //save attachments if ($account['download_files'] == 1) { //there are 3 possible places where the file attachments could be if (isset($results['Attachments']) && is_array($results['Attachments'])) { foreach ($results['Attachments'] as $possible_file) { if (isset($possible_file['Type'])) { if (!empty($possible_file['FileName'])) { $save_array['file']['name'] = $possible_file['FileName']; $save_array['file']['data'] = $possible_file['Data']; $save_array['name'] = $possible_file['FileName']; $saved_files[] = $storage->save_data($save_array); } } } } if (isset($results['Data'])) { if (!empty($results['FileName'])) { $save_array['file']['name'] = $results['FileName']; $save_array['file']['data'] = $results['Data']; $save_array['name'] = $results['FileName']; $saved_files[] = $storage->save_data($save_array); } } if (isset($results['Related']) && is_array($results['Related'])) { foreach ($results['Related'] as $possible_file2) { if (isset($possible_file2['Type'])) { if (!empty($possible_file2['FileName'])) { $save_array['file']['name'] = $possible_file2['FileName']; $save_array['file']['data'] = $possible_file2['Data']; $save_array['name'] = $possible_file2['FileName']; $saved_files[] = $storage->save_data($save_array); } } } } } unset($results); } $email['from_address'] = $email_message[0]['ExtractedAddresses']['from:'][0]['address']; $email['from_name'] = $email_message[0]['ExtractedAddresses']['from:'][0]['name']; $email['to_address'] = $email_message[0]['Headers']['to:']; if (!$found_subject) { $email['subject'] = $email_message[0]['Headers']['subject:']; } $email['date'] = $email_message[0]['Headers']['date:']; if (!empty($email['from_address'])) { $clients = $users->get(array('email' => $email['from_address'], 'limit' => 1)); } else { $clients = NULL; } $new_ticket = true; //existing ticket if (strpos($email['body'], '[TID:') !== false) { $temp_id_array = explode('[TID:', $email['body']); $temp_id_array2 = explode(']', $temp_id_array[1]); $tid = $temp_id_array2[0]; if (strpos($tid, '-') !== false) { $t_array = explode('-', $tid); $ticket_id = (int) $t_array[1]; $ticket_key = $t_array[0]; if ($ticket_id != 0) { //now we can check for the actual ticket $ticket_result = $tickets->get(array('id' => $ticket_id)); if (!empty($ticket_result)) { $ticket = $ticket_result[0]; if ($ticket['key'] == $ticket_key) { $ticket_note['date_added'] = datetime(); $ticket_note['description'] = $email['body']; if (count($clients) == 1) { $ticket_note['user_id'] = $clients[0]['id']; } $ticket_note['html'] = (int) $email['html']; $ticket_note['ticket_id'] = $ticket['id']; $ticket_notes->add($ticket_note); $update_ticket['state_id'] = 1; $update_ticket['date_state_changed'] = datetime(); $update_ticket['id'] = $ticket_id; $tickets->edit($update_ticket); $new_ticket = false; //attach files to ticket if ($account['download_files'] == 1) { if (!empty($saved_files)) { foreach ($saved_files as $file_id) { if ($file_id !== false) { $storage->add_file_to_ticket(array('file_id' => $file_id, 'ticket_id' => $ticket['id'])); } } } } unset($ticket_note); } } } } } //adds a new ticket if anything else fails if ($new_ticket) { //new ticket $array['subject'] = $email['subject']; $array['priority_id'] = $account['priority_id']; $array['description'] = $email['body']; $array['date_added'] = datetime(); $array['department_id'] = $account['department_id']; $array['ticket_state_id'] = 1; if (count($clients) == 1) { $array['user_id'] = $clients[0]['id']; } $array['email'] = $email['from_address']; $array['name'] = $email['from_name']; $array['html'] = (int) $email['html']; $array['pop_account_id'] = (int) $account['id']; //print_r($array); $id = $tickets->add($array); //attach files to ticket if ($account['download_files'] == 1) { if (!empty($saved_files)) { foreach ($saved_files as $file_id) { if ($file_id !== false) { $storage->add_file_to_ticket(array('file_id' => $file_id, 'ticket_id' => $id)); } } } } unset($array); } if (!$account['leave_messages']) { //delete email from pop3 server if it has been added to the database (won't delete from gmail, but will stop it being downloaded via pop3 again) $pop3->DeleteMessage($index); } } } } } else { //unable to retrieve mailbox statistics } } else { $log_array['event_severity'] = 'warning'; $log_array['event_number'] = E_USER_WARNING; $log_array['event_description'] = 'Authentication to POP server "' . safe_output($pop3->hostname) . '" failed'; $log_array['event_file'] = __FILE__; $log_array['event_file_line'] = __LINE__; $log_array['event_type'] = 'download_email'; $log_array['event_source'] = 'pop_system'; $log_array['event_version'] = '1'; $log_array['log_backtrace'] = false; $log->add($log_array); } } else { $log_array['event_severity'] = 'warning'; $log_array['event_number'] = E_USER_WARNING; $log_array['event_description'] = 'Unable to connect to POP server "' . safe_output($pop3->hostname) . '", Error "' . safe_output($error) . '"'; $log_array['event_file'] = __FILE__; $log_array['event_file_line'] = __LINE__; $log_array['event_type'] = 'download_email'; $log_array['event_source'] = 'pop_system'; $log_array['event_version'] = '1'; $log_array['log_backtrace'] = false; $log->add($log_array); } $pop3->Close(); }
/** * Read messages from server and save returned emails into DB * * @param resource $mbox created by dre_connect() (by reference) * @param integer the number of messages to process * @return boolean true on success */ function dre_process_messages(&$mbox, $limit) { //return; // Exit, in development... global $Settings; global $dre_messages, $dre_emails, $email_cntr, $del_cntr, $is_cron_mode; // No execution time limit set_max_execution_time(0); $email_cntr = 0; $del_cntr = 0; for ($index = 1; $index <= $limit; $index++) { dre_msg('<hr /><h3>Processing message #' . $index . ':</h3>'); $strbody = ''; $hasAttachment = false; $hasRelated = false; // Save email to hard drive, otherwise attachments may take a lot of RAM if (!($tmpMIME = tempnam(sys_get_temp_dir(), 'b2evoMail'))) { dre_msg(T_('Could not create temporary file.'), true); continue; } imap_savebody($mbox, $tmpMIME, $index); // Create random temp directory for message parts $tmpDirMIME = dre_tempdir(sys_get_temp_dir(), 'b2evo_'); $mimeParser = new mime_parser_class(); $mimeParser->mbox = 0; // Set to 0 for parsing a single message file $mimeParser->decode_headers = 1; $mimeParser->ignore_syntax_errors = 1; $mimeParser->extract_addresses = 0; $MIMEparameters = array('File' => $tmpMIME, 'SaveBody' => $tmpDirMIME, 'SkipBody' => 1); if (!$mimeParser->Decode($MIMEparameters, $decodedMIME)) { dre_msg(sprintf('MIME message decoding error: %s at position %d.', $mimeParser->error, $mimeParser->error_position), true); rmdir_r($tmpDirMIME); unlink($tmpMIME); continue; } else { dre_msg('MIME message decoding successful'); if (!$mimeParser->Analyze($decodedMIME[0], $parsedMIME)) { dre_msg(sprintf('MIME message analyse error: %s', $mimeParser->error), true); rmdir_r($tmpDirMIME); unlink($tmpMIME); continue; } // Get message $subject and $post_date from headers (by reference) if (!dre_process_header($parsedMIME, $subject, $post_date)) { // Couldn't process message headers rmdir_r($tmpDirMIME); unlink($tmpMIME); continue; } // TODO: handle type == "message" recursively // sam2kb> For some reason imap_qprint() demages HTML text... needs more testing if ($parsedMIME['Type'] == 'html') { // Mail is HTML dre_msg('HTML message part saved as ' . $parsedMIME['DataFile']); $html_body = file_get_contents($parsedMIME['DataFile']); foreach ($parsedMIME['Alternative'] as $alternative) { // First try to get HTML alternative (when possible) if ($alternative['Type'] == 'html') { // HTML text dre_msg('HTML alternative message part saved as ' . $alternative['DataFile']); // sam2kb> TODO: we may need to use $html_body here instead $strbody = file_get_contents($alternative['DataFile']); break; // stop after first alternative } elseif ($alternative['Type'] == 'text') { // Plain text dre_msg('Text alternative message part saved as ' . $alternative['DataFile']); $strbody = imap_qprint(file_get_contents($alternative['DataFile'])); break; // stop after first alternative } } } elseif ($parsedMIME['Type'] == 'text') { // Mail is plain text dre_msg('Plain-text message part saved as ' . $parsedMIME['DataFile']); $strbody = imap_qprint(file_get_contents($parsedMIME['DataFile'])); } elseif ($parsedMIME['Type'] == 'delivery-status') { // Mail is delivery-status $strbody = ''; foreach ($decodedMIME[0]['Parts'] as $part) { $strbody .= imap_qprint(file_get_contents($part['BodyFile'])); } } if (count($mimeParser->warnings) > 0) { dre_msg(sprintf('<h4>%d warnings during decode:</h4>', count($mimeParser->warnings))); foreach ($mimeParser->warnings as $k => $v) { dre_msg('Warning: ' . $v . ' at position ' . $k); } } } unlink($tmpMIME); if (empty($html_body)) { // Plain text message dre_msg('Message type: TEXT'); dre_msg('Message body: <pre style="font-size:10px">' . htmlspecialchars($strbody) . '</pre>'); // Process body. First fix different line-endings (dos, mac, unix), remove double newlines $content = str_replace(array("\r", "\n\n"), "\n", trim($strbody)); } else { // HTML message dre_msg('Message type: HTML'); if (($parsed_message = dre_prepare_html_message($html_body)) === false) { // No 'auth' tag provided, skip to the next message rmdir_r($tmpDirMIME); continue; } list($auth, $content) = $parsed_message; } dre_msg('<b class="green">Success</b>'); $message_text = $content; // Remove content after terminators $content = dre_limit_by_terminators($content); global $Messages; if ($Messages->has_errors()) { // Make it easier for user to find and correct the errors dre_msg("\n" . sprintf(T_('Processing message: %s'), $post_title), true); dre_msg($Messages->get_string(T_('Cannot post, please correct these errors:'), 'error'), true); $Messages->clear(); rmdir_r($tmpDirMIME); continue; } global $dre_emails, $DB, $localtimenow; dre_msg(sprintf('<h4>Saving the returned email in the database</h4>')); // Insert a returned email's data into DB if ($returned_email = dre_insert_returned_email($content, $message_text, dre_get_headers($decodedMIME))) { dre_msg('Error Type: ' . dre_decode_error_type($returned_email['errtype'])); dre_msg('Error Message: ' . $returned_email['errormsg']); ++$email_cntr; } // Delete temporary directory rmdir_r($tmpDirMIME); if ($Settings->get('repath_delete_emails')) { dre_msg('Marking message for deletion from inbox: ' . $index); imap_delete($mbox, $index); ++$del_cntr; } } // Expunge messages market for deletion imap_expunge($mbox); return true; }
public static function import_email($ticket_account_id, $import = true, $debug = false) { require_once 'includes/plugin_ticket/cron/rfc822_addresses.php'; require_once 'includes/plugin_ticket/cron/mime_parser.php'; $admins_rel = self::get_ticket_staff_rel(); $created_tickets = array(); $ticket_account_id = (int) $ticket_account_id; $account = self::get_ticket_account($ticket_account_id); if (!$account) { return false; } $email_account_address = $account['email']; $email_username = $account['username']; $email_password = $account['password']; $email_host = $account['host']; $email_port = $account['port']; $reply_from_user_id = $account['default_user_id']; $support_type = (int) $account['default_type']; $subject_regex = $account['subject_regex']; $body_regex = $account['body_regex']; $to_regex = $account['to_regex']; $search_string = $account['search_string']; $mailbox = $account['mailbox']; $imap = (int) $account['imap']; $secure = (int) $account['secure']; $start_date = $account['start_date'] && $account['start_date'] != '0000-00-00' ? $account['start_date'] : false; if (!$email_host || !$email_username) { return false; } // try to connect with ssl first: $ssl = $secure ? '/ssl' : ''; if ($imap) { $host = '{' . $email_host . ':' . $email_port . '/imap' . $ssl . '/novalidate-cert}' . $mailbox; if ($debug) { echo "Connecting to {$host} <br>\n"; } $mbox = imap_open($host, $email_username, $email_password); } else { $host = '{' . $email_host . ':' . $email_port . '/pop3' . $ssl . '/novalidate-cert}' . $mailbox; if ($debug) { echo "Connecting to {$host} <br>\n"; } $mbox = imap_open($host, $email_username, $email_password); } if (!$mbox) { // todo: send email letting them know bounce checking failed? echo 'Failed to connect when checking for support ticket emails.' . imap_last_error(); imap_errors(); return false; } update_insert('ticket_account_id', $account['ticket_account_id'], 'ticket_account', array('last_checked' => time())); $MC = imap_check($mbox); //echo 'Connected'.$MC->Nmsgs; // do a search if $search_results = array(-1); if ($imap && $search_string) { //imap_sort($mbox,SORTARRIVAL,0); // we do a hack to support multiple searches in the imap string. if (strpos($search_string, '||')) { $search_strings = explode('||', $search_string); } else { $search_strings = array($search_string); } $search_results = array(); foreach ($search_strings as $this_search_string) { $this_search_string = trim($this_search_string); if (!$this_search_string) { return false; } if ($debug) { echo "Searching for {$this_search_string} <br>\n"; } $this_search_results = imap_search($mbox, $this_search_string); if ($debug) { echo " -- found " . count($this_search_results) . " results <br>\n"; } $search_results = array_merge($search_results, $this_search_results); } if (!$search_results) { echo "No search results for {$search_string} "; return false; } else { sort($search_results); } } imap_errors(); //print_r($search_results);//imap_close($mbox);return false; $sorted_emails = array(); foreach ($search_results as $search_result) { if ($search_result >= 0) { $result = imap_fetch_overview($mbox, $search_result, 0); } else { //$result = imap_fetch_overview($mbox,"1:100",0); $result = imap_fetch_overview($mbox, "1:" . min(100, $MC->Nmsgs), 0); } foreach ($result as $overview) { if (!isset($overview->subject) && (!isset($overview->date) || !$overview->date)) { continue; } $overview->subject = self::_subject_decode(isset($overview->subject) ? (string) $overview->subject : ''); if ($subject_regex && !preg_match($subject_regex, $overview->subject)) { continue; } if (!isset($overview->date)) { $overview->date = date('Y-m-d H:i:s'); } if ($start_date > 1000) { if (strtotime($overview->date) < strtotime($start_date)) { continue; } } $message_id = isset($overview->message_id) ? (string) $overview->message_id : false; if (!$message_id) { $overview->message_id = $message_id = md5($overview->subject . $overview->date); } //echo "#{$overview->msgno} ({$overview->date}) - From: {$overview->from} <br> {$this_subject} <br>\n"; // check this email hasn't been processed before. // check this message hasn't been processed yet. $ticket = get_single('ticket_message', 'message_id', $message_id); if ($ticket) { continue; } // get ready to sort them. $overview->time = strtotime($overview->date); $sorted_emails[] = $overview; } } if (!function_exists('dtbaker_ticket_import_sort')) { function dtbaker_ticket_import_sort($a, $b) { return $a->time > $b->time; } } uasort($sorted_emails, 'dtbaker_ticket_import_sort'); $message_number = 0; foreach ($sorted_emails as $overview) { $message_number++; $message_id = (string) $overview->message_id; if ($debug) { ?> <div style="padding:5px; border:1px solid #EFEFEF; margin:4px;"> <div> <strong><?php echo $message_number; ?> </strong> Date: <strong><?php echo $overview->date; ?> </strong> <br/> Subject: <strong><?php echo htmlspecialchars($overview->subject); ?> </strong> <br/> From: <strong><?php echo htmlspecialchars($overview->from); ?> </strong> To: <strong><?php echo htmlspecialchars($overview->to); ?> </strong> <!-- <a href="#" onclick="document.getElementById('msg_<?php echo $message_number; ?> ').style.display='block'; return false;">view body</a> </div> <div style="display:none; padding:10px; border:1px solid #CCC;" id="msg_<?php echo $message_number; ?> "> <?php // echo htmlspecialchars($results['Data']); ?> --> </div> </div> <?php } if (!$import) { continue; } $tmp_file = tempnam(_UCM_FOLDER . '/temp/', 'ticket'); imap_savebody($mbox, $tmp_file, $overview->msgno); $mail_content = file_get_contents($tmp_file); $mime = new mime_parser_class(); $mime->mbox = 0; $mime->decode_bodies = 1; $mime->ignore_syntax_errors = 1; $parameters = array('Data' => $mail_content); $parse_success = false; if (!$mime->Decode($parameters, $decoded)) { //echo 'MIME message decoding error: '.$mime->error.' at position '.$mime->error_position."\n"; // TODO - send warning email to admin. send_error("Failed to decode this email: " . $mail_content); $parse_success = true; // so it delets the email below if that account setting is setfalse; } else { for ($message = 0; $message < count($decoded); $message++) { if ($mime->Analyze($decoded[$message], $results)) { if (isset($results['From'][0]['address'])) { $from_address = $results['From'][0]['address']; } else { continue; } /*$results: Array ( [Type] => html [Description] => HTML message [Encoding] => iso-8859-1 [Data] => asdfasdf [Alternative] => Array ( [0] => Array ( [Type] => text [Description] => Text message [Encoding] => iso-8859-1 [Data] => asdfasdf ) ) [Subject] => [TICKET:004372] Re: Testing cc and bcc fields... [Date] => Sun, 24 Mar 2013 22:04:49 +1000 [From] => Array ( [0] => Array ( [address] => email@gmail.com [name] => Dave ) ) [To] => Array ( [0] => Array ( [address] => email@dtbaker. [name] => dtbaker Support ) [1] => Array ( [address] => email+test@gmail.com ) ) [Cc] => Array ( [0] => Array ( [address] => email+testcc@gmail.com ) [1] => Array ( [address] => info@email.com.au [name] => Hayley ) ) ) */ if ($to_regex) { $to_match = false; foreach ($results['To'] as $possible_to_address) { if (preg_match($to_regex, $possible_to_address['address'])) { $to_match = true; } } if (!$to_match) { continue; } } // find out which accout this sender is from. if (preg_match('/@(.*)$/', $from_address, $matches)) { // run a hook now to parse the from address. $domain = $matches[1]; // find this sender in the database. // if we cant find this sender/customer in the database // then we add this customer as a "support user" to the default customer for this ticketing system. // based on the "to" address of this message. //store this as an eamil $email_to = ''; $email_to_first = current($results['To']); if ($email_to_first) { $email_to = $email_to_first['address']; } // work out the from and to users. $from_user_id = 0; $to_user_id = 0; // this is admin. leave blank for now i guess. // try to find a user based on this from email address. $sql = "SELECT * FROM `" . _DB_PREFIX . "user` u WHERE u.`email` LIKE '" . mysql_real_escape_string($from_address) . "' ORDER BY `date_created` DESC"; $ticket_user_account = $from_user = qa1($sql); // convert the name if it's encoded strangely: if (isset($results['From'][0]['name']) && strlen($results['From'][0]['name']) && isset($results['Encoding']) && strtolower($results['Encoding']) != 'utf8' && strtolower($results['Encoding']) != 'utf-8') { //$name_decoded = quoted_printable_decode($results['From'][0]['name']); if (function_exists('mb_convert_encoding')) { $name_decoded = mb_convert_encoding($results['From'][0]['name'], 'UTF-8', $results['Encoding']); if (strlen($name_decoded) > 0) { $results['From'][0]['name'] = $name_decoded; } } } // todo! this user may be in the system twice! // eg: once from submitting a ticket - then again when creating that user as a contact under a different customer. // so we find the latest entry and use that... ^^ done! updated the above to sort by date updated. if ($from_user) { $from_user_id = $from_user['user_id']; // woo!!found a user. assign this customer to the ticket. if ($from_user['customer_id']) { //$account['default_customer_id'] = $from_user['customer_id']; } } else { if (module_config::c('ticket_allow_new_from_email', 1)) { // create a user under this account customer because we allow new emails to be created if ($account['default_customer_id']) { // create a new support user! go go! $ticket_user_account = $from_user = array('name' => isset($results['From'][0]['name']) ? $results['From'][0]['name'] : $from_address, 'customer_id' => $account['default_customer_id'], 'email' => $from_address, 'status_id' => 1, 'password' => substr(md5(time() . mt_rand(0, 600)), 3)); global $plugins; $from_user_id = $plugins['user']->create_user($from_user, 'support'); $ticket_user_account['user_id'] = $from_user_id; } else { $ticket_user_account = $from_user = array('name' => isset($results['From'][0]['name']) ? $results['From'][0]['name'] : $from_address, 'customer_id' => -1, 'email' => $from_address, 'status_id' => 1, 'password' => substr(md5(time() . mt_rand(0, 600)), 3)); global $plugins; $from_user_id = $plugins['user']->create_user($from_user, 'support'); $ticket_user_account['user_id'] = $from_user_id; //echo 'Failed - no from account set'; //continue; } } } if (!$from_user_id) { // creating a new user for this ticket. not allowed for spam reasons sometimes. if (module_config::c('ticket_allow_new_from_email', 1)) { // failed to create a user in the database. echo 'Failed - cannot find the from user id'; echo $from_address . ' to ' . var_export($results['To'], true) . ' : subject: ' . $overview->subject . '<hr>'; continue; } else { // new option to ignore these emails and force people to submit new tickets via the web interface // send an autoreply to this user saying that their ticket was not created. $temp_from_user = array('name' => isset($results['From'][0]['name']) ? $results['From'][0]['name'] : $from_address, 'email' => $from_address); module_ticket::send_customer_rejection_alert($temp_from_user, $overview->subject); echo 'Rejecting new tickets'; $parse_success = true; continue; } } $message_type_id = _TICKET_MESSAGE_TYPE_CREATOR; // from an end user. if (strtolower($from_address) == strtolower($email_account_address)) { $message_type_id = _TICKET_MESSAGE_TYPE_ADMIN; // from an admin replying via email. } else { if (strtolower($from_address) == strtolower(module_config::c('ticket_admin_email_alert'))) { $message_type_id = _TICKET_MESSAGE_TYPE_ADMIN; // from an admin replying via email. } else { if (isset($admins_rel[$from_user_id])) { $message_type_id = _TICKET_MESSAGE_TYPE_ADMIN; // from an admin replying via email. } } } $sql = "SELECT * FROM `" . _DB_PREFIX . "user` u WHERE u.`email` LIKE '" . mysql_real_escape_string($email_to) . "'"; $to_user_temp = qa1($sql); if ($to_user_temp) { $to_user_id = $to_user_temp['user_id']; // hack for BCC support (eg: email invoice, bcc goes to our ticket email address). if ($message_type_id == _TICKET_MESSAGE_TYPE_ADMIN) { // swap these around. the email is coming from us to the customer. $ticket_user_account = array('customer_id' => $to_user_temp['customer_id'], 'user_id' => $to_user_temp['user_id']); } } $ticket_id = false; $new_message = true; // check if the subject matches an existing ticket subject. if (preg_match('#\\[TICKET:(\\d+)\\]#i', $overview->subject, $subject_matches) || preg_match('#\\#(\\d+)#', $overview->subject, $subject_matches)) { // found an existing ticket. // find this ticket in the system. $ticket_id = ltrim($subject_matches[1], '0'); // see if it exists. $existing_ticket = get_single('ticket', 'ticket_id', $ticket_id); if ($existing_ticket) { // woot! // search to see if this "from" address is in any of the past ticket messages. $valid_previous_contact = false; if ($message_type_id == _TICKET_MESSAGE_TYPE_ADMIN) { $valid_previous_contact = true; } else { $past_ticket_messages = self::get_ticket_messages($existing_ticket['ticket_id'], true); //foreach($past_ticket_messages as $past_ticket_message){ while ($past_ticket_message = mysql_fetch_assoc($past_ticket_messages)) { $past_header_cache = @unserialize($past_ticket_message['cache']); $past_to_temp = array(); if ($past_ticket_message['to_user_id']) { $past_to_temp = module_user::get_user($past_ticket_message['to_user_id'], false); } else { if ($past_header_cache && isset($past_header_cache['to_email'])) { $past_to_temp['email'] = $past_header_cache['to_email']; } } if (isset($past_to_temp['email']) && strtolower($past_to_temp['email']) == strtolower($from_address)) { $valid_previous_contact = true; break; } foreach (array('to_emails', 'cc_emails', 'bcc_emails') as $header_cache_key) { if ($past_header_cache && isset($past_header_cache[$header_cache_key]) && is_array($past_header_cache[$header_cache_key])) { foreach ($past_header_cache[$header_cache_key] as $to_email_additional) { if (isset($to_email_additional['address']) && strlen($to_email_additional['address']) && strtolower($to_email_additional['address']) == strtolower($from_address)) { $valid_previous_contact = true; break 3; } } } } } } if ($valid_previous_contact) { update_insert('ticket_id', $ticket_id, 'ticket', array('status_id' => _TICKET_STATUS_IN_PROGRESS_ID, 'last_message_timestamp' => strtotime($overview->date))); $new_message = false; } else { // create new message based on this one. // remove the old ticket ID number from subject $ticket_id = false; $overview->subject = str_replace($subject_matches[0], '', $overview->subject); } } else { // fail.. $ticket_id = false; } } else { // we search for this subject, and this sender, to see if they have sent a follow up // before we started the ticketing system. // handy for importing an existing inbox with replies etc.. // check to see if the subject matches any existing subjects. $search_subject1 = trim(preg_replace('#^Re:?\\s*#i', '', $overview->subject)); $search_subject2 = trim(preg_replace('#^Fwd?:?\\s*#i', '', $overview->subject)); $search_subject3 = trim($overview->subject); // find any threads that match this subject, from this user id. $sql = "SELECT * FROM `" . _DB_PREFIX . "ticket` t "; $sql .= " WHERE t.`user_id` = " . (int) $from_user_id . " "; $sql .= " AND ( t.`subject` LIKE '%" . mysql_real_escape_string($search_subject1) . "%' OR "; $sql .= " t.`subject` LIKE '%" . mysql_real_escape_string($search_subject2) . "%' OR "; $sql .= " t.`subject` LIKE '%" . mysql_real_escape_string($search_subject3) . "%') "; $sql .= " ORDER BY ticket_id DESC;"; $match = qa1($sql); if (count($match) && (int) $match['ticket_id'] > 0) { // found a matching email. stoked! // add it in as a reply from the end user. $ticket_id = $match['ticket_id']; update_insert('ticket_id', $ticket_id, 'ticket', array('status_id' => _TICKET_STATUS_IN_PROGRESS_ID, 'last_message_timestamp' => strtotime($overview->date))); $new_message = false; } if (!$ticket_id) { // now we see if any match the "TO" address, ie: it's us replying to the user. // handly from a gmail import. if ($email_to) { $sql = "SELECT * FROM `" . _DB_PREFIX . "user` u WHERE u.`email` LIKE '" . mysql_real_escape_string($email_to) . "'"; $temp_to_user = qa1($sql); if ($temp_to_user && $temp_to_user['user_id']) { // we have sent emails to this user before... // check to see if the subject matches any existing subjects. $sql = "SELECT * FROM `" . _DB_PREFIX . "ticket` t "; $sql .= " WHERE t.`user_id` = " . (int) $temp_to_user['user_id'] . " "; $sql .= " AND ( t.`subject` LIKE '%" . mysql_real_escape_string($search_subject1) . "%' OR "; $sql .= " t.`subject` LIKE '%" . mysql_real_escape_string($search_subject2) . "%' OR "; $sql .= " t.`subject` LIKE '%" . mysql_real_escape_string($search_subject3) . "%') "; $sql .= " ORDER BY ticket_id DESC;"; $match = qa1($sql); if (count($match) && (int) $match['ticket_id'] > 0) { // found a matching email. stoked! // add it in as a reply from the end user. $ticket_id = $match['ticket_id']; update_insert('ticket_id', $ticket_id, 'ticket', array('status_id' => _TICKET_STATUS_IN_PROGRESS_ID, 'last_message_timestamp' => strtotime($overview->date))); $new_message = false; } } } } } if (!$ticket_id) { $ticket_id = update_insert('ticket_id', 'new', 'ticket', array('subject' => $overview->subject, 'ticket_account_id' => $account['ticket_account_id'], 'status_id' => _TICKET_STATUS_NEW_ID, 'user_id' => $ticket_user_account['user_id'], 'customer_id' => $ticket_user_account['customer_id'], 'assigned_user_id' => $reply_from_user_id, 'ticket_type_id' => $support_type, 'last_message_timestamp' => strtotime($overview->date))); } if (!$ticket_id) { echo 'Error creating ticket'; continue; } module_ticket::mark_as_unread($ticket_id); $cache = array('from_email' => $from_address, 'to_email' => $email_to, 'to_emails' => isset($results['To']) && is_array($results['To']) ? $results['To'] : array(), 'cc_emails' => isset($results['Cc']) && is_array($results['Cc']) ? $results['Cc'] : array()); // pull otu the email bodyu. $body = $results['Data']; //if($from_address=='*****@*****.**'){ if (isset($results['Encoding']) && strtolower($results['Encoding']) != 'utf8' && strtolower($results['Encoding']) != 'utf-8') { //mail('*****@*****.**','Ticket import results: Encoding',$results['Encoding']."\n\n".var_export($results,true)); //$body2 = quoted_printable_decode($body); if (function_exists('mb_convert_encoding')) { $body3 = mb_convert_encoding($body, 'UTF-8', $results['Encoding']); //$body3 = mb_convert_encoding($body,'HTML-ENTITIES',$results['Encoding']); //$body4 = iconv_mime_decode($body,ICONV_MIME_DECODE_CONTINUE_ON_ERROR,"UTF-8"); //mail('*****@*****.**','Ticket import results: Converted',$body . "\n\n\n\n\n ------------ " . $body2 . "\n\n\n\n\n ------------ " . $body3); if (strlen($body3) > 0) { $body = $body3; } } } //} // debug if ($results['Type'] == "html") { $is_html = true; } else { // convert body to html, so we can do wrap. $body = nl2br($body); $is_html = true; } // find the alt body. $altbody = ''; if (isset($results['Alternative']) && is_array($results['Alternative'])) { foreach ($results['Alternative'] as $alt_id => $alt) { if ($alt['Type'] == "text") { $altbody = $alt['Data']; // if($from_address=='*****@*****.**'){ if (isset($results['Encoding']) && strtolower($results['Encoding']) != 'utf8' && strtolower($results['Encoding']) != 'utf-8') { //$altbody2 = quoted_printable_decode($altbody); if (function_exists('mb_convert_encoding')) { $altbody3 = mb_convert_encoding($altbody, 'UTF-8', $results['Encoding']); if (strlen($altbody3) > 0) { $altbody = $altbody3; } } } //} break; } } } if (!$altbody) { // should really never happen, but who knows. // edit - i think this happens with godaddy webmailer. $altbody = $body; // todo: strip any html. $altbody = preg_replace('#<br[^>]*>\\n*#imsU', "\n", $altbody); $altbody = strip_tags($altbody); } // pass the body and altbody through a hook so we can modify it if needed. // eg: for envato tickets we strip the header/footer out and check the link to see if the buyer really bought anything. // run_hook(... //echo "<hr>$body<hr>$altbody<hr><br><br><br>"; // save the message! $ticket_message_id = update_insert('ticket_message_id', 'new', 'ticket_message', array('ticket_id' => $ticket_id, 'message_id' => $message_id, 'content' => $altbody, 'htmlcontent' => $body, 'message_time' => strtotime($overview->date), 'message_type_id' => $message_type_id, 'from_user_id' => $from_user_id, 'to_user_id' => $to_user_id, 'cache' => serialize($cache), 'status_id' => _TICKET_STATUS_IN_PROGRESS_ID)); if (isset($results['Related'])) { foreach ($results['Related'] as $related) { if (isset($related['FileName']) && $related['FileName']) { // save as attachment against this email. $attachment_id = update_insert('ticket_message_attachment_id', 'new', 'ticket_message_attachment', array('ticket_id' => $ticket_id, 'ticket_message_id' => $ticket_message_id, 'file_name' => $related['FileName'], 'content_type' => $related['Type'] . (isset($related['SubType']) ? '/' . $related['SubType'] : ''))); $result = file_put_contents('includes/plugin_ticket/attachments/' . $attachment_id . '', $related['Data']); if (!$result) { send_error("Failed to save attachment (named: " . $related['FileName'] . " for this email: \n\n\n\n" . var_export($related, true) . "\n\n\n" . var_export($results, true) . "\n\n\n" . $mail_content); } } } } if (isset($results['Attachments'])) { foreach ($results['Attachments'] as $related) { if (isset($related['FileName']) && $related['FileName']) { // save as attachment against this email. $attachment_id = update_insert('ticket_message_attachment_id', 'new', 'ticket_message_attachment', array('ticket_id' => $ticket_id, 'ticket_message_id' => $ticket_message_id, 'file_name' => $related['FileName'], 'content_type' => $related['Type'] . (isset($related['SubType']) ? '/' . $related['SubType'] : ''))); $result = file_put_contents('includes/plugin_ticket/attachments/' . $attachment_id . '', $related['Data']); if (!$result) { send_error("Failed to save attachment (named: " . $related['FileName'] . " for this email: \n\n\n\n" . var_export($related, true) . "\n\n\n" . var_export($results, true) . "\n\n\n" . $mail_content); } } } } //$new_message && if (!preg_match('#failure notice#i', $overview->subject)) { // we don't sent ticket autoresponders when the from user and to user are teh same if ($from_user_id && $to_user_id && $from_user_id == $to_user_id) { } else { $created_tickets[$ticket_id] = $ticket_id; } } $parse_success = true; } } } } if ($parse_success && $account['delete']) { // remove email from inbox if needed. imap_delete($mbox, $overview->msgno); } unlink($tmp_file); } imap_errors(); //} imap_expunge($mbox); imap_close($mbox); imap_errors(); return $created_tickets; }