Current Path : /var/www/html/clients/old.e-nkama.ru/e-nkama_bitrix/bitrix/modules/mail/classes/general/ |
Current File : /var/www/html/clients/old.e-nkama.ru/e-nkama_bitrix/bitrix/modules/mail/classes/general/mail.php |
<? ############################################## # Bitrix Site Manager # # Copyright (c) 2002-2007 Bitrix # # http://www.bitrixsoft.com # # mailto:admin@bitrixsoft.com # ############################################## /////////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////////// global $MESS; include(GetLangFileName($_SERVER["DOCUMENT_ROOT"].BX_ROOT."/modules/mail/lang/", "/classes/general/mail.php")); global $BX_MAIL_ERRORs, $B_MAIL_MAX_ALLOWED; $BX_MAIL_ERRORs = Array(); $B_MAIL_MAX_ALLOWED = false; class CMailError { function ResetErrors() { global $BX_MAIL_ERRORs; $BX_MAIL_ERRORs = Array(); } function SetError($ID, $TITLE="", $DESC="") { global $BX_MAIL_ERRORs; $BX_MAIL_ERRORs[] = Array("ID"=>$ID, "TITLE"=>$TITLE, "DESCRIPTION"=>$DESC); return false; } function GetLastError($type=false) { global $BX_MAIL_ERRORs; if($type===false) return $BX_MAIL_ERRORs[count($BX_MAIL_ERRORs)-1]; return $BX_MAIL_ERRORs[count($BX_MAIL_ERRORs)-1][$type]; } function GetErrors() { global $BX_MAIL_ERRORs; return $BX_MAIL_ERRORs; } function GetErrorsText($delim="<br>") { global $BX_MAIL_ERRORs; $str = ""; foreach($BX_MAIL_ERRORs as $err) { if($str!="")$str.=$delim; $str.=$err["TITLE"]; } return $str; } function ErrCount() { global $BX_MAIL_ERRORs; if(!is_array($BX_MAIL_ERRORs)) return 0; return count($BX_MAIL_ERRORs); } } class _CMailBoxDBRes extends CDBResult { function _CMailBoxDBRes($res) { parent::CDBResult($res); } function Fetch() { if($res = parent::Fetch()) { $res["PASSWORD"] = CMailUtil::Decrypt($res["PASSWORD"]); } return $res; } } /////////////////////////////////////////////////////////////////////////////////// // class CMailBox /////////////////////////////////////////////////////////////////////////////////// class CAllMailBox { var $pop3_conn = false; var $mess_count = 0; var $mess_size = 0; var $resp = true; var $last_result = true; var $response = ""; var $response_body = ""; function GetList($arOrder=Array(), $arFilter=Array()) { global $DB; $strSql = "SELECT MB.*, l.CHARSET as LANG_CHARSET, ". " ".$DB->DateToCharFunction("MB.TIMESTAMP_X")." as TIMESTAMP_X ". "FROM b_mail_mailbox MB, b_lang l ". "WHERE MB.LID=l.LID "; if(!is_array($arFilter)) $arFilter = Array(); $arSqlSearch = Array(); $filter_keys = array_keys($arFilter); for($i=0; $i<count($filter_keys); $i++) { $val = $arFilter[$filter_keys[$i]]; if (strlen($val)<=0) continue; $key = strtoupper($filter_keys[$i]); switch($key) { case "ID": $arSqlSearch[] = GetFilterQuery("MB.ID", $val, "N"); break; case "PORT": $arSqlSearch[] = GetFilterQuery("MB.".$key, $val, "N"); break; case "LID": case "LOGIN": case "SERVER": case "NAME": case "DESCRIPTION": case "DOMAINS": case "SERVER_TYPE": $arSqlSearch[] = GetFilterQuery("MB.".$key, $val); break; case "DELETE_MESSAGES": case "ACTIVE": case "USE_MD5": case "RELAY": case "AUTH_RELAY": $arSqlSearch[] = GetFilterQuery("MB.".$key, $val, "N"); break; } } $is_filtered = false; $strSqlSearch = ""; for($i=0; $i<count($arSqlSearch); $i++) { if(strlen($arSqlSearch[$i])>0) { $is_filtered = true; $strSqlSearch .= " AND (".$arSqlSearch[$i].") "; } } $arSqlOrder = Array(); foreach($arOrder as $by=>$order) { $order = strtolower($order); if ($order!="asc") $order = "desc".(strtoupper($DB->type)=="ORACLE"?" NULLS LAST":""); else $order = "asc".(strtoupper($DB->type)=="ORACLE"?" NULLS FIRST":""); switch(strtoupper($by)) { case "TIMESTAMP_X": case "LID": case "ACTIVE": case "NAME": case "SERVER": case "PORT": case "LOGIN": case "USE_MD5": case "DELETE_MESSAGES": case "RELAY": case "AUTH_RELAY": case "SERVER_TYPE": case "PERIOD_CHECK": $arSqlOrder[] = " MB.".$by." ".$order." "; break; default: $arSqlOrder[] = " MB.ID ".$order." "; } } $strSqlOrder = ""; $arSqlOrder = array_unique($arSqlOrder); DelDuplicateSort($arSqlOrder); for ($i=0; $i<count($arSqlOrder); $i++) { if($i==0) $strSqlOrder = " ORDER BY "; else $strSqlOrder .= ","; $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= $strSqlSearch.$strSqlOrder; $res = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $res = new _CMailBoxDBRes($res); $res->is_filtered = $is_filtered; return $res; } function GetByID($ID) { global $DB; return CMailBox::GetList(Array(), Array("ID"=>$ID)); } /********************************************************************* *********************************************************************/ function CheckMail($mailbox_id = false) { global $DB; $mbx = Array(); if($mailbox_id===false) { $strSql = "SELECT MB.ID ". "FROM b_mail_mailbox MB ". "WHERE ACTIVE='Y' "; $dbr = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); while($ar = $dbr->Fetch()) $mbx[] = $ar["ID"]; } else $mbx[] = $mailbox_id; $bNoErrors = true; for($i=0; $i<count($mbx); $i++) { $mb = new CMailbox(); if(!$mb->Connect($mbx[$i])) { $bNoErrors = false; CMailError::SetError("ERR_CHECK_MAIL", GetMessage("MAIL_CL_ERR_CHECK_MAIL")." ".$ar["NAME"].".", ""); } } return $bNoErrors; } function CheckMailAgent($ID) { global $DB, $USER; $bUserCreated = false; if (!isset($USER) || !is_object($USER)) { $USER = new CUser(); $bUserCreated = true; } $ID = IntVal($ID); $strSql = "SELECT MB.ID, MB.PERIOD_CHECK ". "FROM b_mail_mailbox MB ". "WHERE ACTIVE='Y' ". " AND ID=".$ID; $strReturn = ''; $dbr = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); if($ar = $dbr->Fetch()) { $mb = new CMailbox(); $mb->Connect($ID); if(intval($ar["PERIOD_CHECK"])>0) $strReturn = "CMailbox::CheckMailAgent(".$ID.");"; } if ($bUserCreated) { unset($USER); } return $strReturn; } function CheckFields($arFields, $ID=false) { $err_cnt = CMailError::ErrCount(); $arMsg = Array(); if(is_set($arFields, "NAME") && strlen($arFields["NAME"])<1) { CMailError::SetError("B_MAIL_ERR_NAME", GetMessage("MAIL_CL_ERR_NAME")." \"".GetMessage("MAIL_CL_NAME")."\""); $arMsg[] = array("id"=>"NAME", "text"=> GetMessage("MAIL_CL_ERR_NAME")." \"".GetMessage("MAIL_CL_NAME")."\""); } if(strtolower($arFields["SERVER_TYPE"])=="pop3" && is_set($arFields, "LOGIN") && strlen($arFields["LOGIN"])<1) { CMailError::SetError("B_MAIL_ERR_LOGIN", GetMessage("MAIL_CL_ERR_NAME")." \"".GetMessage("MAIL_CL_LOGIN")."\""); $arMsg[] = array("id"=>"LOGIN", "text"=> GetMessage("MAIL_CL_ERR_NAME")." \"".GetMessage("MAIL_CL_LOGIN")."\""); } if(strtolower($arFields["SERVER_TYPE"])=="pop3" && is_set($arFields, "PASSWORD") && strlen($arFields["PASSWORD"])<1) { CMailError::SetError("B_MAIL_ERR_PASSWORD", GetMessage("MAIL_CL_ERR_NAME")." \"".GetMessage("MAIL_CL_PASSWORD")."\""); $arMsg[] = array("id"=>"PASSWORD", "text"=> GetMessage("MAIL_CL_ERR_NAME")." \"".GetMessage("MAIL_CL_PASSWORD")."\""); } if(is_set($arFields, "SERVER") && strlen($arFields["SERVER"])<1) { CMailError::SetError("B_MAIL_ERR_SERVER_NAME", GetMessage("MAIL_CL_ERR_NAME")." \"".GetMessage("MAIL_CL_SERVER")."\""); $arMsg[] = array("id"=>"SERVER", "text"=> GetMessage("MAIL_CL_ERR_NAME")." \"".GetMessage("MAIL_CL_SERVER")."\""); } elseif(strtolower($arFields["SERVER_TYPE"])=="smtp") { $dbres = CMailBox::GetList(array(), array("ACTIVE"=>"Y", "SERVER_TYPE"=>"smtp", "SERVER"=>$arFields["SERVER"], "PORT"=>$arFields["PORT"])); while($arres = $dbres->Fetch()) { if($ID===false || $arres["ID"]!=$ID) { CMailError::SetError("B_MAIL_ERR_SERVER_NAME", GetMessage("B_MAIL_ERR_SN")." \"".GetMessage("MAIL_CL_SERVER")."\""); $arMsg[] = array("id"=>"SERVER", "text"=> GetMessage("B_MAIL_ERR_SN")." (\"".GetMessage("MAIL_CL_SERVER")."\")"); break; } } } if(is_set($arFields, "LID")) { $r = CLang::GetByID($arFields["LID"]); if(!$r->Fetch()) { CMailError::SetError("B_MAIL_ERR_BAD_LANG", GetMessage("MAIL_CL_ERR_BAD_LANG")); $arMsg[] = array("id"=>"LID", "text"=> GetMessage("MAIL_CL_ERR_BAD_LANG")); } } elseif($ID===false) { CMailError::SetError("B_MAIL_ERR_BAD_LANG_NA", GetMessage("MAIL_CL_ERR_BAD_LANG_NX")); $arMsg[] = array("id"=>"LID", "text"=> GetMessage("MAIL_CL_ERR_BAD_LANG_NX")); } if(!empty($arMsg)) { $e = new CAdminException($arMsg); $GLOBALS["APPLICATION"]->ThrowException($e); return false; } return true; //return ($err_cnt == CMailError::ErrCount()); } function Add($arFields) { global $DB; CMailError::ResetErrors(); if($arFields["ACTIVE"]!="Y") $arFields["ACTIVE"]="N"; if($arFields["DELETE_MESSAGES"]!="Y") $arFields["DELETE_MESSAGES"]="N"; if($arFields["USE_MD5"]!="Y") $arFields["USE_MD5"]="N"; if($arFields["USE_TLS"]!="Y") $arFields["USE_TLS"]="N"; if($arFields["SERVER_TYPE"]!="smtp") $arFields["SERVER_TYPE"]="pop3"; if(!CMailBox::CheckFields($arFields)) return false; if(is_set($arFields, "PASSWORD")) $arFields["PASSWORD"]=CMailUtil::Crypt($arFields["PASSWORD"]); $ID = CDatabase::Add("b_mail_mailbox", $arFields); if(intval($arFields["PERIOD_CHECK"])>0 && $arFields["SERVER_TYPE"]=="pop3") CAgent::AddAgent("CMailbox::CheckMailAgent(".$ID.");", "mail", "N", intval($arFields["PERIOD_CHECK"])*60); CMailbox::SMTPReload(); return $ID; } /********************************************************************* *********************************************************************/ function Update($ID, $arFields) { global $DB; $ID = IntVal($ID); CMailError::ResetErrors(); if(is_set($arFields, "ACTIVE") && $arFields["ACTIVE"]!="Y") $arFields["ACTIVE"]="N"; if(is_set($arFields, "DELETE_MESSAGES") && $arFields["DELETE_MESSAGES"]!="Y") $arFields["DELETE_MESSAGES"]="N"; if(is_set($arFields, "USE_MD5") && $arFields["USE_MD5"]!="Y") $arFields["USE_MD5"]="N"; if(is_set($arFields, "USE_TLS") && $arFields["USE_TLS"]!="Y") $arFields["USE_TLS"]="N"; if(is_set($arFields, "SERVER_TYPE") && $arFields["SERVER_TYPE"]!="smtp") $arFields["SERVER_TYPE"]="pop3"; if(!CMailBox::CheckFields($arFields, $ID)) return false; if(is_set($arFields, "PASSWORD")) $arFields["PASSWORD"]=CMailUtil::Crypt($arFields["PASSWORD"]); CAgent::RemoveAgent("CMailbox::CheckMailAgent(".$ID.");", "mail"); if(intval($arFields["PERIOD_CHECK"])>0 && $arFields["SERVER_TYPE"]=="pop3") CAgent::AddAgent("CMailbox::CheckMailAgent(".$ID.");", "mail", "N", intval($arFields["PERIOD_CHECK"])*60); $strUpdate = $DB->PrepareUpdate("b_mail_mailbox", $arFields); $strSql = "UPDATE b_mail_mailbox SET ". $strUpdate." ". "WHERE ID=".$ID; $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); CMailbox::SMTPReload(); return true; } function Delete($ID) { global $DB; $ID = IntVal($ID); $db_msg = CMailMessage::GetList(Array(), Array("MAILBOX_ID"=>$ID)); while($msg = $db_msg->Fetch()) { if(!CMailMessage::Delete($msg["ID"])) return false; } $db_flt = CMailFilter::GetList(Array(), Array("MAILBOX_ID"=>$ID)); while($flt = $db_flt->Fetch()) { if(!CMailFilter::Delete($flt["ID"])) return false; } $db_log = CMailLog::GetList(Array(), Array("MAILBOX_ID"=>$ID)); while($log = $db_log->Fetch()) { if(!CMailLog::Delete($log["ID"])) return false; } CAgent::RemoveAgent("CMailbox::CheckMailAgent(".$ID.");", "mail"); $strSql = "DELETE FROM b_mail_message_uid WHERE MAILBOX_ID=".$ID; if(!$DB->Query($strSql, true)) return false; CMailbox::SMTPReload(); $strSql = "DELETE FROM b_mail_mailbox WHERE ID=".$ID; return $DB->Query($strSql, true); } function SMTPReload() { $f = fopen($_SERVER["DOCUMENT_ROOT"]."/bitrix/cache/smtpd.php", "w+"); fwrite($f, '1'); fclose($f); } /********************************************************************* *********************************************************************/ function SendCommand($command) { fputs($this->pop3_conn, $command."\r\n"); if($this->mailbox_id>0) { CMailLog::AddMessage( Array( "MAILBOX_ID"=>$this->mailbox_id, "STATUS_GOOD"=>"Y", "MESSAGE"=>"> ".nl2br(preg_replace("'PASS .*'", "PASS ******", $command)) ) ); } $this->resp = true; } /********************************************************************* *********************************************************************/ function GetResponse($bMultiline = false, $bSkipFirst = true) { if(!$this->resp) return false; $this->resp = false; socket_set_timeout($this->pop3_conn, 20); $res = rtrim(fgets($this->pop3_conn, 1024), "\r\n"); // socket_set_blocking($this->pop3_conn, false); // socket_set_blocking($this->pop3_conn, true); $this->last_result = ($res[0]=="+"); $this->response = $res; if($this->mailbox_id>0) { CMailLog::AddMessage( Array( "MAILBOX_ID"=>$this->mailbox_id, "STATUS_GOOD"=>($this->last_result?"Y":"N"), "MESSAGE"=>"< ".$res ) ); } if($bMultiline && $res[0]=="+") { if($bSkipFirst) $res = ""; else $res .= "\r\n"; $s = fgets($this->pop3_conn, 1024); while(strlen($s)>0 && $s!=".\r\n") { if(substr($s, 0, 2)=="..") $s = substr($s, 1); $res .= $s; $s = fgets($this->pop3_conn, 1024); } } $this->response_body = $res; return $this->last_result; } function GetResponseBody() { return $this->response_body; } function GetResponseString() { return $this->response_body; } function GetPassword($p) { } function Check($server, $port, $use_tls, $login, $passw) { if($use_tls == 'Y' && strpos($server, 'tls://') === false) $server = 'tls://' . $server; $pop3_conn = &$this->pop3_conn; $pop3_conn = fsockopen($server, $port, $errno, $errstr, COption::GetOptionInt("mail", "connect_timeout", B_MAIL_TIMEOUT)); if(!$pop3_conn) return array(false, GetMessage("MAIL_CL_TIMEOUT")." $errstr ($errno)"); $this->GetResponse(); $greeting = $this->GetResponseString(); $this->SendCommand("USER ".$login); if(!$this->GetResponse()) return array(false, GetMessage("MAIL_CL_ERR_USER").' ('.$this->GetResponseString().')'); $this->SendCommand("PASS ".$passw); if(!$this->GetResponse()) return array(false, GetMessage("MAIL_CL_ERR_PASSWORD").' ('.$this->GetResponseString().')'); $this->SendCommand("STAT"); if(!$this->GetResponse()) return array(false, GetMessage("MAIL_CL_ERR_STAT").' ('.$this->GetResponseString().')'); $stat = trim($this->GetResponseBody()); $arStat = explode(" ", $stat); return array(true, $arStat[1]); } /********************************************************************* *********************************************************************/ function Connect($mailbox_id) { global $DB; $mailbox_id = IntVal($mailbox_id); $strSql = "SELECT MB.*, l.CHARSET as LANG_CHARSET ". "FROM b_mail_mailbox MB, b_lang l ". "WHERE MB.LID=l.LID ". " AND MB.ID=".$mailbox_id; $dbr = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $dbr = new _CMailBoxDBRes($dbr); if(!$arMAILBOX_PARAMS = $dbr->Fetch()) return CMailError::SetError("ERR_MAILBOX_NOT_FOUND", GetMessage("MAIL_CL_ERR_MAILBOX_NOT_FOUND"), GetMessage("MAIL_CL_ERR_MAILBOX_NOT_FOUND")); @set_time_limit(0); $server = $arMAILBOX_PARAMS["SERVER"]; if ($arMAILBOX_PARAMS['USE_TLS'] == 'Y' && strpos($server, 'tls://') === false) { $server = 'tls://' . $server; } $pop3_conn = &$this->pop3_conn; $pop3_conn = @fsockopen($server, $arMAILBOX_PARAMS["PORT"], $errno, $errstr, COption::GetOptionInt("mail", "connect_timeout", B_MAIL_TIMEOUT)); CMailLog::AddMessage( Array( "MAILBOX_ID"=>$mailbox_id, "STATUS_GOOD"=>"Y", "MESSAGE"=>GetMessage("MAIL_CL_CONNECT_TO")." ".$arMAILBOX_PARAMS["SERVER"] ) ); if(!$pop3_conn || !is_resource($pop3_conn)) { CMailLog::AddMessage( Array( "MAILBOX_ID"=>$mailbox_id, "STATUS_GOOD"=>"N", "MESSAGE"=>GetMessage("MAIL_CL_TIMEOUT") ) ); return CMailError::SetError("ERR_CONNECT_TIMEOUT", GetMessage("MAIL_CL_TIMEOUT"), "$errstr ($errno)"); } $this->mailbox_id = $mailbox_id; if($arMAILBOX_PARAMS["CHARSET"]!='') $this->charset = $arMAILBOX_PARAMS["CHARSET"]; else $this->charset = $arMAILBOX_PARAMS["LANG_CHARSET"]; $this->use_md5 = $arMAILBOX_PARAMS["USE_MD5"]; $session_id = md5(uniqid("")); $this->GetResponse(); $greeting = $this->GetResponseString(); if($this->use_md5=="Y" && preg_match("'(<.+>)'", $greeting, $reg)) { $this->SendCommand("APOP ".$arMAILBOX_PARAMS["LOGIN"]." ".md5($reg[1].$arMAILBOX_PARAMS["PASSWORD"])); if(!$this->GetResponse()) return CMailError::SetError("ERR_AFTER_USER", GetMessage("MAIL_CL_ERR_APOP"), $this->GetResponseString()); } else { $this->SendCommand("USER ".$arMAILBOX_PARAMS["LOGIN"]); if(!$this->GetResponse()) return CMailError::SetError("ERR_AFTER_USER", GetMessage("MAIL_CL_ERR_USER"), $this->GetResponseString()); $this->SendCommand("PASS ".$arMAILBOX_PARAMS["PASSWORD"]); if(!$this->GetResponse()) return CMailError::SetError("ERR_AFTER_PASS", GetMessage("MAIL_CL_ERR_PASSWORD"), $this->GetResponseString()); } $this->SendCommand("STAT"); if(!$this->GetResponse()) return CMailError::SetError("ERR_AFTER_STAT", GetMessage("MAIL_CL_ERR_STAT"), $this->GetResponseString()); $stat = trim($this->GetResponseBody()); $arStat = explode(" ", $stat); $this->mess_count = $arStat[1]; if($this->mess_count>0) { $this->mess_size = $arStat[2]; if($arMAILBOX_PARAMS["MAX_MSG_SIZE"]>0) { $this->SendCommand("LIST"); if(!$this->GetResponse(true)) return CMailError::SetError("ERR_AFTER_LIST", "LIST command error", $this->GetResponseString()); $list = $this->GetResponseBody(); preg_match_all("'([0-9]+)[ ]+?(.+)'", $list, $arLIST_temp, PREG_SET_ORDER); $arLIST = Array(); for($i=0; $i<count($arLIST_temp); $i++) $arLIST[IntVal($arLIST_temp[$i][1])] = IntVal($arLIST_temp[$i][2]); } $this->SendCommand("UIDL"); if(!$this->GetResponse(true)) return CMailError::SetError("ERR_AFTER_UIDL", GetMessage("MAIL_CL_ERR_UIDL"), $this->GetResponseString()); $uidl = $this->GetResponseBody(); preg_match_all("'([0-9]+)[ ]+?(.+)'", $uidl, $arUIDL_temp, PREG_SET_ORDER); $arStrIDs = array(); $arUIDL = array(); $cnt = count($arUIDL_temp); for($i=0; $i<$cnt; $i++) { $msguid = md5($arUIDL_temp[$i][2]); $arUIDL[$msguid] = $arUIDL_temp[$i][1]; $arStrIDs[floor($i / 1000)] .= ", '".$DB->ForSQL($msguid)."'"; } if(count($arUIDL) > 0) { $cnt = count($arStrIDs); for ($i = 0; $i < $cnt; ++$i) { $ids = 'ID IN ('.substr($arStrIDs[$i], 2).')'; $strSql = "SELECT ID FROM b_mail_message_uid WHERE MAILBOX_ID=".$mailbox_id." AND ($ids)"; $db_res = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); while($ar_res = $db_res->Fetch()) UnSet($arUIDL[$ar_res["ID"]]); $strSql = "UPDATE b_mail_message_uid SET SESSION_ID = '".$session_id."' WHERE MAILBOX_ID=".$mailbox_id." AND ($ids)"; $db_res = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); } } $strSql = "DELETE FROM b_mail_message_uid WHERE MAILBOX_ID=".$mailbox_id." AND SESSION_ID <> '".$session_id."'"; $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $this->new_mess_count = 0; $this->deleted_mess_count = 0; $session_id = md5(uniqid("")); foreach($arUIDL as $msguid=>$msgnum) { if($arMAILBOX_PARAMS["MAX_MSG_SIZE"]<=0 || $arLIST[$msgnum]<=$arMAILBOX_PARAMS["MAX_MSG_SIZE"]) $this->GetMessage($mailbox_id, $msgnum, $msguid, $session_id); if($arMAILBOX_PARAMS["DELETE_MESSAGES"]=="Y") { $this->DeleteMessage($msgnum); $this->deleted_mess_count++; } $this->new_mess_count++; if($arMAILBOX_PARAMS["MAX_MSG_COUNT"]>0 && $arMAILBOX_PARAMS["MAX_MSG_COUNT"]<=$this->new_mess_count) break; } } $this->SendCommand("QUIT"); if(!$this->GetResponse()) return CMailError::SetError("ERR_AFTER_QUIT", GetMessage("MAIL_CL_ERR_DISCONNECT"), $this->GetResponseString()); fclose($pop3_conn); return true; } /********************************************************************* *********************************************************************/ function GetMessage($mailbox_id, $msgnum, $msguid, $session_id) { global $DB; $this->SendCommand("RETR ".$msgnum); if(!$this->GetResponse(true)) return CMailError::SetError("ERR_AFTER_RETR", GetMessage("MAIL_CL_ERR_RETR"), $this->GetResponseString()); $message = $this->GetResponseBody(); $message_id = CMailMessage::AddMessage($mailbox_id, $message, $this->charset); if($message_id>0) { /* $arFields = array( "ID" => "'".$DB->ForSql($msguid)."'", "MAILBOX_ID" => intval($mailbox_id), "SESSION_ID" => "'".$DB->ForSql($session_id)."'", "DATE_INSERT" => $DB->GetNowFunction(), "MESSAGE_ID" => $message_id ); $DB->Insert("b_mail_message_uid", $arFields, "File: ".__FILE__."<br>Line: ".__LINE__); */ $strSql = "INSERT INTO b_mail_message_uid(ID, MAILBOX_ID, SESSION_ID, DATE_INSERT, MESSAGE_ID) VALUES('".$DB->ForSql($msguid)."', ".IntVal($mailbox_id).", '".$DB->ForSql($session_id)."', ".$DB->GetNowFunction().", ".IntVal($message_id).")"; $DB->Query($strSql); } return $message_id; } // function GetMessage(... /********************************************************************* *********************************************************************/ function DeleteMessage($msgnum) { $this->SendCommand("DELE ".$msgnum); if(!$this->GetResponse()) return CMailError::SetError("ERR_AFTER_DELE", GetMessage("MAIL_CL_ERR_DELE"), $this->GetResponseString()); } } /////////////////////////////////////////////////////////////////////////////////// // class CMailHeader /////////////////////////////////////////////////////////////////////////////////// class CMailHeader { var $arHeader = Array(); var $arHeaderLines = Array(); var $strHeader = ""; var $bMultipart = false; var $content_type, $boundary, $charset, $filename, $MultipartType="mixed"; /********************************************************************* *********************************************************************/ function ConvertHeader($encoding, $type, $str, $charset) { if(strtoupper($type)=="B") $str = base64_decode($str); else $str = quoted_printable_decode(str_replace("_", " ", $str)); $str = CMailUtil::ConvertCharset($str, $encoding, $charset); return $str; } /********************************************************************* *********************************************************************/ function DecodeHeader($str, $charset_to, $charset_document) { while(preg_match('/(=\?[^?]+\?(Q|B)\?[^?]*\?=)(\s)+=\?/i', $str)) $str = preg_replace('/(=\?[^?]+\?(Q|B)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $str); if(!preg_match("'=\?(.*)\?(B|Q)\?(.*)\?='ie", $str)) { if(strlen($charset_document)>0 && $charset_document!=$charset_to) $str = CMailUtil::ConvertCharset($str, $charset_document, $charset_to); } else $str = preg_replace("'=\?(.*?)\?(B|Q)\?(.*?)\?='ie", "CMailHeader::ConvertHeader('\\1', '\\2', '\\3', '".AddSlashes($charset_to)."')", $str); return $str; } /********************************************************************* *********************************************************************/ function Parse($message_header, $charset) { if(preg_match("'content-type:.*?charset=([^\r\n;]+)'is", $message_header, $res)) $this->charset = strtolower(trim($res[1], ' "')); elseif($this->charset=='' && defined("BX_MAIL_DEFAULT_CHARSET")) $this->charset = BX_MAIL_DEFAULT_CHARSET; $ar_message_header_tmp = explode("\r\n", $message_header); $n = -1; $bConvertSubject = false; for($i=0; $i<count($ar_message_header_tmp); $i++) { $line = $ar_message_header_tmp[$i]; if(($line[0]==" " || $line[0]=="\t") && $n>=0) { $line = ltrim($line, " \t"); $bAdd = true; } else $bAdd = false; $line = CMailHeader::DecodeHeader($line, $charset, $this->charset); if($bAdd) $this->arHeaderLines[$n] = $this->arHeaderLines[$n].$line; else { $n++; $this->arHeaderLines[] = $line; } } $this->arHeader = Array(); for($i=0; $i<count($this->arHeaderLines); $i++) { $p = strpos($this->arHeaderLines[$i], ":"); if($p>0) { $header_name = strtoupper(trim(substr($this->arHeaderLines[$i], 0, $p))); $header_value = trim(substr($this->arHeaderLines[$i], $p+1)); $this->arHeader[$header_name] = $header_value; } } $full_content_type = $this->arHeader["CONTENT-TYPE"]; if(strlen($full_content_type)<=0) $full_content_type = "text/plain"; if(!($p = strpos($full_content_type, ";"))) $p = strlen($full_content_type); $this->content_type = trim(substr($full_content_type, 0, $p)); if(strpos(strtolower($this->content_type), "multipart/") === 0) { $this->bMultipart = true; if(!preg_match("'boundary=(.+);'i", $full_content_type, $res)) preg_match("'boundary=(.+)'i", $full_content_type, $res); $this->boundary = trim($res[1], '"'); if($p = strpos($this->content_type, "/")) $this->MultipartType = substr($this->content_type, $p+1); } if($p < strlen($full_content_type)) { $add = substr($full_content_type, $p+1); if(preg_match("'name=(.+)'i", $full_content_type, $res)) $this->filename = trim($res[1], '"'); } $cd = $this->arHeader["CONTENT-DISPOSITION"]; if(strlen($cd)>0 && preg_match("'filename=([^;]+)'i", $cd, $res)) $this->filename = trim($res[1], '"'); if($this->arHeader["CONTENT-ID"]!='') $this->content_id = trim($this->arHeader["CONTENT-ID"], '"<>'); $this->strHeader = implode("\r\n", $this->arHeaderLines); return true; } /********************************************************************* *********************************************************************/ function IsMultipart() { return $this->bMultipart; } /********************************************************************* *********************************************************************/ function MultipartType() { return strtolower($this->MultipartType); } /********************************************************************* *********************************************************************/ function GetBoundary() { return $this->boundary; } /********************************************************************* *********************************************************************/ function GetHeader($type) { return $this->arHeader[strtoupper($type)]; } } /////////////////////////////////////////////////////////////////////////////////// // class CMailMessage /////////////////////////////////////////////////////////////////////////////////// class CAllMailMessage { /********************************************************************* *********************************************************************/ function GetList($arOrder = Array(), $arFilter = Array(), $bCnt = false) { global $DB; if(strtoupper($DB->type)=="MYSQL") $sum = "IF(NEW_MESSAGE='Y', 1, 0)"; else $sum = "case when NEW_MESSAGE='Y' then 1 else 0 end"; $strSql = "SELECT ". ($bCnt? "COUNT('x') as CNT, SUM(".$sum.") as CNT_NEW, COUNT('x')-SUM(".$sum.") as CNT_OLD " : "MS.*, MB.NAME as MAILBOX_NAME, MB.LID, ". " ".$DB->DateToCharFunction("MS.DATE_INSERT")." as DATE_INSERT, ". " ".$DB->DateToCharFunction("MS.FIELD_DATE")." as FIELD_DATE " ). "FROM b_mail_message MS ". ($bCnt? "":" INNER JOIN b_mail_mailbox MB ON MS.MAILBOX_ID=MB.ID "); $arSqlSearch = Array(); $filter_keys = array_keys($arFilter); for($i=0; $i<count($filter_keys); $i++) { $key = $filter_keys[$i]; $val = $arFilter[$key]; $res = CMailUtil::MkOperationFilter($key); $key = strtoupper($res["FIELD"]); $cOperationType = $res["OPERATION"]; if($cOperationType == "?") { if (strlen($val)<=0) continue; switch($key) { case "ID": case "MAILBOX_ID": case "MSGUID": $arSqlSearch[] = GetFilterQuery("MS.".$key, $val, "N"); break; case "FIELD_FROM": case "FIELD_TO": case "FIELD_CC": case "FIELD_BCC": $arSqlSearch[] = GetFilterQuery("MS.".$key, $val, "Y", Array("@", "_", ".", "-")); break; case "NEW_MESSAGE": case "SUBJECT": case "HEADER": case "MSG_ID": case "IN_REPLY_TO": case "BODY": $arSqlSearch[] = GetFilterQuery("MS.".$key, $val); break; case "SENDER": $arSqlSearch[] = GetFilterQuery("MS.FIELD_FROM", $val, "Y", array("@","_",".","-")); break; case "RECIPIENT": $arSqlSearch[] = GetFilterQuery("MS.FIELD_TO, MS.FIELD_CC, MS.FIELD_BCC", $val, "Y", array("@","_",".","-")); break; case "SPAM_RATING": CMailFilter::RecalcSpamRating(); $arSqlSearch[] = GetFilterQuery("MS.SPAM_RATING", $val, "N"); break; case "SPAM": $arSqlSearch[] = GetFilterQuery("MS.SPAM", $val, "Y", array("?")); break; case "ALL": $arSqlSearch[] = GetFilterQuery("MS.HEADER, MS.BODY", $val); break; } } else { switch($key) { case "SPAM": case "NEW_MESSAGE": $arSqlSearch[] = CMailUtil::FilterCreate("MS.".$key, $val, "string_equal", $cOperationType); break; case "ID": case "MAILBOX_ID": $arSqlSearch[] = CMailUtil::FilterCreate("MS.".$key, $val, "number", $cOperationType); break; case "SUBJECT": case "HEADER": case "BODY": case "MSGUID": case "FIELD_FROM": case "FIELD_TO": case "FIELD_CC": case "MSG_ID": case "IN_REPLY_TO": case "FIELD_BCC": $arSqlSearch[] = CMailUtil::FilterCreate("MS.".$key, $val, "string", $cOperationType); break; case "SPAM_RATING": $arSqlSearch[] = CMailUtil::FilterCreate("MS.".$key, $val, "number", $cOperationType); CMailFilter::RecalcSpamRating(); break; /* case "TIMESTAMP_X": $arSqlSearch[] = CIBlock::FilterCreate("BE.TIMESTAMP_X", $val, "date", $cOperationType); break; */ } } } $is_filtered = false; $strSqlSearch = ""; for($i=0; $i<count($arSqlSearch); $i++) if(strlen($arSqlSearch[$i])>0) { $strSqlSearch .= " AND (".$arSqlSearch[$i].") "; $is_filtered = true; } $arSqlOrder = Array(); foreach($arOrder as $by=>$order) { $by = strtolower($by); $order = strtolower($order); if ($order!="asc") $order = "desc".(strtoupper($DB->type)=="ORACLE"?" NULLS LAST":""); else $order = "asc".(strtoupper($DB->type)=="ORACLE"?" NULLS FIRST":""); if ($by == "field_date") $arSqlOrder[] = " MS.FIELD_DATE ".$order." "; elseif ($by == "field_from") $arSqlOrder[] = " MS.FIELD_FROM ".$order." "; elseif ($by == "field_reply_to")$arSqlOrder[] = " MS.FIELD_REPLY_TO ".$order." "; elseif ($by == "field_to") $arSqlOrder[] = " MS.FIELD_TO ".$order." "; elseif ($by == "field_cc") $arSqlOrder[] = " MS.FIELD_CC ".$order." "; elseif ($by == "field_bcc") $arSqlOrder[] = " MS.FIELD_BCC ".$order." "; elseif ($by == "subject") $arSqlOrder[] = " MS.SUBJECT ".$order." "; elseif ($by == "attachments") $arSqlOrder[] = " MS.ATTACHMENTS ".$order." "; elseif ($by == "date_insert") $arSqlOrder[] = " MS.DATE_INSERT ".$order." "; elseif ($by == "msguid") $arSqlOrder[] = " MS.MSGUID ".$order." "; elseif ($by == "mailbox_id") $arSqlOrder[] = " MS.MAILBOX_ID ".$order." "; elseif ($by == "new_message") $arSqlOrder[] = " MS.NEW_MESSAGE ".$order." "; elseif ($by == "mailbox_name" && !$bCnt) $arSqlOrder[] = " MB.NAME ".$order." "; elseif ($by == "spam_rating") {$arSqlOrder[] = " MS.SPAM_RATING ".$order." "; CMailFilter::RecalcSpamRating();} else $arSqlOrder[] = " MS.ID ".$order." "; } $strSqlOrder = ""; $arSqlOrder = array_unique($arSqlOrder); DelDuplicateSort($arSqlOrder); for ($i=0; $i<count($arSqlOrder); $i++) { if($i==0) $strSqlOrder = " ORDER BY "; else $strSqlOrder .= ","; $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= " WHERE 1=1 ".$strSqlSearch.$strSqlOrder; $dbr = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $dbr->is_filtered = $is_filtered; return $dbr; } /********************************************************************* *********************************************************************/ function GetByID($ID) { return CMailMessage::GetList(Array(), Array("=ID"=>$ID)); } function GetSpamRating($msgid, $arRow=false) { global $DB; if(!is_array($arRow)) $res = $DB->Query("SELECT SPAM_RATING, SPAM_LAST_RESULT, FOR_SPAM_TEST FROM b_mail_message WHERE ID=".Intval($msgid)); else $ar = $arRow; if(is_array($arRow) || $ar = $res->Fetch()) { if($ar["SPAM_LAST_RESULT"]=="Y") return $ar["SPAM_RATING"]; $arSpam = CMailFilter::GetSpamRating($ar["FOR_SPAM_TEST"]); $num = Round($arSpam["RATING"], 4); $DB->Query("UPDATE b_mail_message SET SPAM_RATING=".$num.", SPAM_LAST_RESULT='Y', SPAM_WORDS='".$DB->ForSql($arSpam["WORDS"], 255)."' WHERE ID=".Intval($msgid)); return $num; } } /********************************************************************* *********************************************************************/ function ParseHeader($message_header, $charset) { $h = new CMailHeader(); $h->Parse($message_header, $charset); return $h; } /********************************************************************* *********************************************************************/ function AddMessage($mailbox_id, $message, $charset) { global $DB; // replace all /n -> /r/n //$message = str_replace("\r\n", "\n", $message); //$message = str_replace("\n", "\r\n", $message); $header_pos = strpos($message, "\r\n\r\n"); // spliting message to header and body $message_header = substr($message, 0, $header_pos); $message_body = substr($message, $header_pos+4); $message_body_html = false; // parsing header and convert $arMessageParts = Array(); $obHeader = CMailMessage::ParseHeader($message_header, $charset); if($obHeader->IsMultipart()) { //echo 'obHeader="<pre>';print_r($obHeader);echo '/obHeader</pre>'; $arMessagePartsTmp = preg_split("/".preg_quote("--".$obHeader->GetBoundary(), "/")."(--|\r\n)/s", $message_body); $message_body = ""; for($i=0; $i<count($arMessagePartsTmp); $i++) { if(strlen($arMessagePartsTmp[$i])<=0) continue; $message_part = $arMessagePartsTmp[$i]; if(substr($message_part, 0, 2)=="\r\n") $message_part = "\r\n".$message_part; $p = strpos($message_part, "\r\n\r\n"); $message_part_header = substr($message_part, 0, $p); if(strlen(trim($message_part_header))<=0 && count($arMessagePartsTmp)>1) continue; $message_part_body = substr($message_part, $p+4); if(strlen(trim($message_part_body))<=0) continue; $obMPHeader = CMailMessage::ParseHeader($message_part_header, $charset); if(strtolower($obHeader->MultipartType()) == "alternative" && $obMPHeader->IsMultipart()/* && $obHeader->MultipartType() != "mixed"*/) continue; if( //(strtolower($obMPHeader->MultipartType()) == "related" && $obHeader->MultipartType() == "mixed") || (strtolower($obMPHeader->MultipartType()) == "alternative" && $obMPHeader->IsMultipart()) ) { $arMessagePartsRelTmp = preg_split("/".preg_quote("--".$obMPHeader->GetBoundary(), "/")."(--|\r\n)/s", $message_part_body); $bFound = false; $obMPHeaderHTML = false; for($j=0; $j<count($arMessagePartsRelTmp); $j++) { if(strlen(trim($arMessagePartsRelTmp[$j]))<=0) continue; $p = strpos($arMessagePartsRelTmp[$j], "\r\n\r\n"); $message_part_rel_header = substr($arMessagePartsRelTmp[$j], 0, $p); $message_part_rel_body = substr($arMessagePartsRelTmp[$j], $p+4); $obMPRelHeader = CMailMessage::ParseHeader($message_part_rel_header, $charset); $rel_content_type = strtolower($obMPRelHeader->content_type); if($rel_content_type=="text/plain") { $bFound = true; $obMPHeader = $obMPRelHeader; $message_part_body = $message_part_rel_body; break; } elseif($rel_content_type=="text/html" && !is_object($obMPHeaderHTML)) { $obMPHeaderHTML = $obMPRelHeader; $message_part_body_html = $message_part_rel_body; } } // for($j=0; $j<count($arMessagePartsRelTmp); $j++) if(!$bFound && is_object($obMPHeaderHTML)) { $obMPHeader = $obMPHeaderHTML; $message_part_body = HTMLToTxt($message_part_body_html); $bFound = true; } } // if(strtolower($obMPHeader->MultipartType() ... $content_type = strtolower($obMPHeader->content_type); //print_r($obMPHeader); $encoding = strtolower($obMPHeader->GetHeader("CONTENT-TRANSFER-ENCODING")); if($encoding=="base64") $message_part_body = base64_decode($message_part_body); elseif($encoding=="quoted-printable") $message_part_body = quoted_printable_decode($message_part_body); elseif($encoding=="x-uue") $message_part_body = CMailUtil::uue_decode($message_part_body); //? $msg_charset = $obMPHeader->charset; $filename = $obMPHeader->filename; if(strpos($content_type, "plain")!==false || strpos($content_type, "html")!==false || strpos($content_type, "text")!==false) $message_part_body_converted = CMailUtil::ConvertCharset($message_part_body, $msg_charset, $charset); else $message_part_body_converted = $message_part_body; $arMessageParts[] = Array( "CONTENT-TYPE" => $content_type, "CONTENT-ID" => $obMPHeader->content_id, "CHARSET" => $charset, "BODY" => $message_part_body_converted, "FILENAME" => $filename ); } //for($i=0; $i<count($arMessagePartsTmp); $i++) for($i=0; $i<count($arMessageParts); $i++) { if(strlen($arMessageParts[$i]["FILENAME"])<=0 && strpos(strtolower($arMessageParts[$i]["CONTENT-TYPE"]), "text/")===0) { if(strtolower($arMessageParts[$i]["CONTENT-TYPE"])=="text/html") { $message_body_html = $arMessageParts[$i]["BODY"]; $message_body = HTMLToTxt($arMessageParts[$i]["BODY"]); } else $message_body = $arMessageParts[$i]["BODY"]; unset($arMessageParts[$i]); break; } } //print_r($arMessageParts); } else //if($obHeader->IsMultipart()) { $encoding = strtolower($obHeader->GetHeader("CONTENT-TRANSFER-ENCODING")); if($encoding=="base64") $message_body = base64_decode($message_body); elseif($encoding=="quoted-printable") $message_body = quoted_printable_decode($message_body); elseif($encoding=="x-uue") $message_body = CMailUtil::uue_decode($message_body); //? $message_body = CMailUtil::ConvertCharset($message_body, $obHeader->charset, $charset); if(strtolower($obHeader->content_type)=="text/html") { $message_body_html = $message_body; $message_body = HTMLToTxt($message_body); } } //if($obHeader->IsMultipart()) $arFields = Array( "MAILBOX_ID" => $mailbox_id, "HEADER" => $obHeader->strHeader, "FIELD_DATE_ORIGINAL" => $obHeader->GetHeader("DATE"), "NEW_MESSAGE" => "Y", "FIELD_FROM" => $obHeader->GetHeader("FROM"), "FIELD_REPLY_TO" => $obHeader->GetHeader("REPLY-TO"), "FIELD_TO" => $obHeader->GetHeader("TO"), "FIELD_CC" => $obHeader->GetHeader("CC"), "FIELD_BCC" => ($obHeader->GetHeader('X-Original-Rcpt-to')!=''?$obHeader->GetHeader('X-Original-Rcpt-to').($obHeader->GetHeader("BCC")!=''?', ':''):'').$obHeader->GetHeader("BCC"), "MSG_ID" => trim($obHeader->GetHeader("MESSAGE-ID"), " <>"), "IN_REPLY_TO" => trim($obHeader->GetHeader("IN-REPLY-TO"), " <>"), "FIELD_PRIORITY" => IntVal($obHeader->GetHeader("X-PRIORITY")), "MESSAGE_SIZE" => strlen($message), "SUBJECT" => $obHeader->GetHeader("SUBJECT"), "BODY" => RTrim($message_body) ); //print_r($arMessageParts); print_r($arFields); die(); if(COption::GetOptionString("mail", "save_src", B_MAIL_SAVE_SRC)=="Y") $arFields["FULL_TEXT"] = $message; if($message_body_html!==false) $arFields["FOR_SPAM_TEST"] = $obHeader->strHeader." ".$message_body_html; else $arFields["FOR_SPAM_TEST"] = $obHeader->strHeader." ".$message_body; $arFields["SPAM"] = "?"; if(COption::GetOptionString("mail", "spam_check", B_MAIL_CHECK_SPAM)=="Y") { $arSpam = CMailFilter::GetSpamRating($arFields["FOR_SPAM_TEST"]); $arFields["SPAM_RATING"] = $arSpam["RATING"]; $arFields["SPAM_WORDS"] = $arSpam["WORDS"]; $arFields["SPAM_LAST_RESULT"] = "Y"; } if(CMailUtil::IsSizeAllowed(strlen(implode(",", $arFields)))) { $MESSAGE_ID = CMailMessage::Add($arFields); CMailLog::AddMessage( Array( "MAILBOX_ID"=>$mailbox_id, "MESSAGE_ID"=>$MESSAGE_ID, "STATUS_GOOD"=>"Y", "LOG_TYPE"=>"NEW_MESSAGE", "MESSAGE"=>$arFields["SUBJECT"]." (".$arFields["MESSAGE_SIZE"].") ". (COption::GetOptionString("mail", "spam_check", B_MAIL_CHECK_SPAM)=="Y"? "[".Round($arFields["SPAM_RATING"], 3)."]" : "" ) ) ); if(COption::GetOptionString("mail", "save_attachments", B_MAIL_SAVE_ATTACHMENTS)=="Y") { $n=0; foreach($arMessageParts as $part) { $arField = Array( "MESSAGE_ID" => $MESSAGE_ID, "FILE_NAME" => $part["FILENAME"], "CONTENT_TYPE" => $part["CONTENT-TYPE"], "FILE_DATA" => $part["BODY"], "CONTENT_ID" => $part["CONTENT-ID"] ); CMailMessage::AddAttachment($arField); } // foreach($arMessageParts as $part) } CMailFilter::FilterMessage($MESSAGE_ID, "R"); return $MESSAGE_ID; } else CMailLog::AddMessage( Array( "MAILBOX_ID"=>$mailbox_id, "STATUS_GOOD"=>"N", "LOG_TYPE"=>"NEW_MESSAGE", "MESSAGE"=>"Big message size, check mysql max_allow_packet." ) ); } /********************************************************************* *********************************************************************/ function Add($arFields) { global $DB; if(is_set($arFields, "NEW_MESSAGE") && $arFields["NEW_MESSAGE"]!="N") $arFields["NEW_MESSAGE"]="Y"; if(is_set($arFields, "FULL_TEXT") && !is_set($arFields, "MESSAGE_SIZE")) $arFields["MESSAGE_SIZE"] = strlen($arFields["FULL_TEXT"]); if(!is_set($arFields, "DATE_INSERT")) $arFields["~DATE_INSERT"] = $DB->GetNowFunction(); if(is_set($arFields, "FIELD_DATE_ORIGINAL") && !is_set($arFields, "FIELD_DATE")) $arFields["FIELD_DATE"] = $DB->FormatDate(date("d.m.Y H:i:s", strtotime($arFields["FIELD_DATE_ORIGINAL"])), "DD.MM.YYYY HH:MI:SS", CLang::GetDateFormat("FULL")); if (array_key_exists('SUBJECT', $arFields)) { $arFields['SUBJECT'] = strval(substr($arFields['SUBJECT'], 0, 255)); } $ID = $DB->Add("b_mail_message", $arFields, Array("FULL_TEXT", "HEADER", "BODY", "FOR_SPAM_TEST")); return $ID; } /********************************************************************* *********************************************************************/ function Update($ID, $arFields) { global $DB; $ID = Intval($ID); if(is_set($arFields, "FIELD_DATE_ORIGINAL") && !is_set($arFields, "FIELD_DATE")) $arFields["FIELD_DATE"] = $DB->FormatDate(date("m.d.Y H:i:s", strtotime($arFields["FIELD_DATE_ORIGINAL"])), "DD.MM.YYYY HH:MI:SS", CLang::GetDateFormat("FULL")); if (array_key_exists('SUBJECT', $arFields)) { $arFields['SUBJECT'] = strval(substr($arFields['SUBJECT'], 0, 255)); } $strUpdate = $DB->PrepareUpdate("b_mail_message", $arFields); $strSql = "UPDATE b_mail_message SET ".$strUpdate." WHERE ID=".$ID; $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); return true; } function Delete($id) { global $DB; $id = IntVal($id); $strSql = "DELETE FROM b_mail_msg_attachment WHERE MESSAGE_ID=".$id; $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $strSql = "DELETE FROM b_mail_message WHERE ID=".$id; //echo $strSql; $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); return true; } function MarkAsSpam($ID, $bIsSPAM = true, $arRow = false) { global $DB; if(!is_array($arRow)) $res = $DB->Query("SELECT SPAM, FOR_SPAM_TEST, MAILBOX_ID FROM b_mail_message WHERE ID=".Intval($ID)); else $ar = $arRow; if(is_array($arRow) || $ar = $res->Fetch()) { if($bIsSPAM) { if($ar["SPAM"]!="Y") { if($ar["SPAM"]=="N") CMailFilter::DeleteFromSpamBase($ar["FOR_SPAM_TEST"], false); CMailFilter::MarkAsSpam($ar["FOR_SPAM_TEST"], true); CMailMessage::Update($ID, Array("SPAM"=>"Y")); CMailLog::AddMessage( Array( "MAILBOX_ID"=>$ar["MAILBOX_ID"], "MESSAGE_ID"=>$ID, "LOG_TYPE"=>"SPAM" ) ); } } else { if($ar["SPAM"]!="N") { if($ar["SPAM"]=="Y") CMailFilter::DeleteFromSpamBase($ar["FOR_SPAM_TEST"], true); CMailFilter::MarkAsSpam($ar["FOR_SPAM_TEST"], false); CMailMessage::Update($ID, Array("SPAM"=>"N")); CMailLog::AddMessage( Array( "MAILBOX_ID"=>$ar["MAILBOX_ID"], "MESSAGE_ID"=>$ID, "LOG_TYPE"=>"NOTSPAM" ) ); } } $DB->Query("UPDATE b_mail_message SET SPAM_LAST_RESULT='N' WHERE ID=".IntVal($ID)); } } } class CMailAttachment { function GetList($arOrder=Array(), $arFilter=Array()) { global $DB; $strSql = "SELECT * ". "FROM b_mail_msg_attachment MA "; $arSqlSearch = Array(); $filter_keys = array_keys($arFilter); for($i=0; $i<count($filter_keys); $i++) { $key = $filter_keys[$i]; $val = $arFilter[$key]; $res = CMailUtil::MkOperationFilter($key); $key = strtoupper($res["FIELD"]); $cOperationType = $res["OPERATION"]; if($cOperationType == "?") { if (strlen($val)<=0) continue; switch($key) { case "ID": case "MESSAGE_ID": case "FILE_SIZE": case "IMAGE_WIDTH": case "IMAGE_HEIGHT": $arSqlSearch[] = GetFilterQuery("MA.".$key, $val, "N"); break; case "FILE_NAME": case "FILE_DATA": $arSqlSearch[] = GetFilterQuery("MA.".$key, $val); break; case "CONTENT_TYPE": $arSqlSearch[] = GetFilterQuery("MA.".$key, $val, "Y", array("/")); break; } } else { switch($key) { case "ID": case "MESSAGE_ID": case "FILE_SIZE": case "IMAGE_WIDTH": case "IMAGE_HEIGHT": $arSqlSearch[] = CMailUtil::FilterCreate("MA.".$key, $val, "number", $cOperationType); break; case "FILE_NAME": case "CONTENT_TYPE": case "FILE_DATA": $arSqlSearch[] = CMailUtil::FilterCreate("MA.".$key, $val, "string", $cOperationType); break; } } } $is_filtered = false; $strSqlSearch = ""; for($i=0; $i<count($arSqlSearch); $i++) if(strlen($arSqlSearch[$i])>0) { $strSqlSearch .= " AND (".$arSqlSearch[$i].") "; $is_filtered = true; } $arSqlOrder = Array(); foreach($arOrder as $by=>$order) { $by = strtolower($by); $order = strtolower($order); if ($order!="asc") $order = "desc".(strtoupper($DB->type)=="ORACLE"?" NULLS LAST":""); else $order = "asc".(strtoupper($DB->type)=="ORACLE"?" NULLS FIRST":""); if ($by == "message_id") $arSqlOrder[] = " MA.MESSAGE_ID ".$order." "; elseif ($by == "file_name") $arSqlOrder[] = " MA.FILE_NAME ".$order." "; elseif ($by == "file_size") $arSqlOrder[] = " MA.FILE_SIZE ".$order." "; elseif ($by == "content_type") $arSqlOrder[] = " MA.CONTENT_TYPE ".$order." "; elseif ($by == "image_width") $arSqlOrder[] = " MA.IMAGE_WIDTH ".$order." "; elseif ($by == "image_height") $arSqlOrder[] = " MA.IMAGE_HEIGHT ".$order." "; else $arSqlOrder[] = " MA.ID ".$order." "; } $strSqlOrder = ""; $arSqlOrder = array_unique($arSqlOrder); DelDuplicateSort($arSqlOrder); for ($i=0; $i<count($arSqlOrder); $i++) { if($i==0) $strSqlOrder = " ORDER BY "; else $strSqlOrder .= ","; $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= " WHERE 1=1 ".$strSqlSearch.$strSqlOrder; //echo "<pre>".$strSql."</pre>"; $dbr = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $dbr->is_filtered = $is_filtered; return $dbr; } /********************************************************************* *********************************************************************/ function GetByID($ID) { return CMailAttachment::GetList(Array(), Array("=ID"=>$ID)); } function Delete($id) { global $DB; $id = IntVal($id); $strSql = "DELETE FROM b_mail_msg_attachment WHERE ID=".$id; $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); } } /////////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////////// class CAllMailUtil { /********************************************************************* *********************************************************************/ function ConvertCharset($str, $from, $to) { $from = trim(strtolower($from)); $to = trim(strtolower($to)); if(($from=='utf-8' || $to == 'utf-8') || defined('BX_UTF')) return $GLOBALS['APPLICATION']->ConvertCharset($str, $from, $to); if($from=='windows-1251') $from = 'w'; elseif(strpos($from, 'koi8')===0) $from = 'k'; elseif($from=='dos-866') $from = 'd'; elseif($from=='iso-8859-5') $from = 'i'; else $from = ''; if($to=='windows-1251') $to = 'w'; elseif(strpos($to, 'koi8')===0) $to = 'k'; elseif($to=='dos-866') $to = 'd'; elseif($to=='iso-8859-5') $to = 'i'; else $to = ''; if(strlen($from)>0 && strlen($to)>0) { $str = convert_cyr_string($str, $from, $to); } return $str; } function uue_decode($str) { preg_match("/begin [0-7]{3} .+?\r?\n(.+)?\r?\nend/i", $str, $reg); $str = $reg[1]; $res = ''; $str = preg_split("/\r?\n/", trim($str)); $strlen = count($str); for ($i = 0; $i < $strlen; $i++) { $pos = 1; $d = 0; $len= (int)(((ord(substr($str[$i],0,1)) -32) - ' ') & 077); while (($d + 3 <= $len) AND ($pos + 4 <= strlen($str[$i]))) { $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20); $c3 = (ord(substr($str[$i],$pos+3,1)) ^ 0x20); $res .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)). chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2)). chr(((($c2 - ' ') & 077) << 6) | (($c3 - ' ') & 077)); $pos += 4; $d += 3; } if (($d + 2 <= $len) && ($pos + 3 <= strlen($str[$i]))) { $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20); $res .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)). chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2)); $pos += 3; $d += 2; } if (($d + 1 <= $len) && ($pos + 2 <= strlen($str[$i]))) { $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20); $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20); $res .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4)); } } return $res; } function MkOperationFilter($key) { if(substr($key, 0, 1)=="!") { $key = substr($key, 1); $cOperationType = "N"; } elseif(substr($key, 0, 2)==">=") { $key = substr($key, 2); $cOperationType = "GE"; } elseif(substr($key, 0, 1)==">") { $key = substr($key, 1); $cOperationType = "G"; } elseif(substr($key, 0, 2)=="<=") { $key = substr($key, 2); $cOperationType = "LE"; } elseif(substr($key, 0, 1)=="<") { $key = substr($key, 1); $cOperationType = "L"; } elseif(substr($key, 0, 1)=="=") { $key = substr($key, 1); $cOperationType = "E"; } else $cOperationType = "?"; return Array("FIELD"=>$key, "OPERATION"=>$cOperationType); } function FilterCreate($fname, $vals, $type, $cOperationType=false, $bSkipEmpty = true) { return CMailUtil::FilterCreateEx($fname, $vals, $type, $bFullJoin, $cOperationType, $bSkipEmpty); } function FilterCreateEx($fname, $vals, $type, &$bFullJoin, $cOperationType=false, $bSkipEmpty = true) { global $DB; if(!is_array($vals)) $vals=Array($vals); if(count($vals)<1) return ""; if(is_bool($cOperationType)) { if($cOperationType===true) $cOperationType = "N"; else $cOperationType = "E"; } if($cOperationType=="G") $strOperation = ">"; elseif($cOperationType=="GE") $strOperation = ">="; elseif($cOperationType=="LE") $strOperation = "<="; elseif($cOperationType=="L") $strOperation = "<"; else $strOperation = "="; $bFullJoin = false; $bWasLeftJoin = false; $res = Array(); for($i=0; $i<count($vals); $i++) { $val = $vals[$i]; if(!$bSkipEmpty || strlen($val)>0 || (is_bool($val) && $val===false)) { switch ($type) { case "string_equal": if(strlen($val)<=0) $res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL OR ".$DB->Length($fname)."<=0)"; else $res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".CIBlock::_Upper($fname).$strOperation.CIBlock::_Upper("'".$DB->ForSql($val)."'").")"; break; case "string": if(strlen($val)<=0) $res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL OR ".$DB->Length($fname)."<=0)"; else if($strOperation=="=") $res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".(strtoupper($DB->type)=="ORACLE"?CIBlock::_Upper($fname)." LIKE ".CIBlock::_Upper("'".$DB->ForSqlLike($val)."'")." ESCAPE '\\'" : $fname." ".($strOperation=="="?"LIKE":$strOperation)." '".$DB->ForSqlLike($val)."'").")"; else $res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".(strtoupper($DB->type)=="ORACLE"?CIBlock::_Upper($fname)." ".$strOperation." ".CIBlock::_Upper("'".$DB->ForSql($val)."'")." " : $fname." ".$strOperation." '".$DB->ForSql($val)."'").")"; break; case "date": if(strlen($val)<=0) $res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL)"; else $res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".$fname." ".$strOperation." ".$DB->CharToDateFunction($DB->ForSql($val), "FULL").")"; break; case "number": if(strlen($val)<=0) $res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL)"; else $res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".$fname." ".$strOperation." '".DoubleVal($val)."')"; break; case "number_above": if(strlen($val)<=0) $res[] = ($cOperationType=="N"?"NOT":"")."(".$fname." IS NULL)"; else $res[] = ($cOperationType=="N"?" ".$fname." IS NULL OR NOT ":"")."(".$fname." ".$strOperation." '".$DB->ForSql($val)."')"; break; } // ïðè òàêèõ óñëîâèÿõ íóæíî äåëàòü INNER JOIN if(strlen($val)>0 && $cOperationType!="N") $bFullJoin = true; else $bWasLeftJoin = true; } } $strResult = ""; for($i=0; $i<count($res); $i++) { if($i>0) $strResult .= ($cOperationType=="N"?" AND ":" OR "); $strResult .= "(".$res[$i].")"; } if($strResult!="") $strResult = "(".$strResult.")"; if($bFullJoin && $bWasLeftJoin && $cOperationType!="N") $bFullJoin = false; return $strResult; } function ByteXOR($a,$b,$l) { $c=""; for($i=0; $i<$l; $i++) $c .= $a{$i}^$b{$i}; return($c); } function BinMD5($val) { return(pack("H*",md5($val))); } function Decrypt($str, $key=false) { if($key===false) $key = COption::GetOptionString("main", "pwdhashadd", ""); $key1 = CMailUtil::BinMD5($key); $str = base64_decode($str); while($str) { $m = substr($str, 0, 16); $str = substr($str, 16); $m = CMailUtil::ByteXOR($m, $key1, 16); $res .= $m; $key1 = CMailUtil::BinMD5($key.$key1.$m); } return $res; } function Crypt($str, $key=false) { if($key===false) $key = COption::GetOptionString("main", "pwdhashadd", ""); $key1 = CMailUtil::BinMD5($key); while($str) { $m = substr($str, 0, 16); $str = substr($str, 16); $res .= CMailUtil::ByteXOR($m, $key1, 16); $key1 = CMailUtil::BinMD5($key.$key1.$m); } return(base64_encode($res)); } function ExtractAllMailAddresses($emails) { $result = array(); $arEMails = explode(",", $emails); foreach($arEMails as $mail) { $result[] = CMailUtil::ExtractMailAddress($mail); } return $result; } function ExtractMailAddress($email) { $email = trim($email); if(($pos = strpos($email, "<"))!==false) $email = substr($email, $pos+1); if(($pos = strpos($email, ">"))!==false) $email = substr($email, 0, $pos); return strtolower($email); } } global $BX_MAIL_FILTER_CACHE, $BX_MAIL_SPAM_CNT; $BX_MAIL_FILTER_CACHE = Array(); $BX_MAIL_SPAM_CNT = Array(); /////////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////////// class CMailFilter { function GetList($arOrder=Array(), $arFilter=Array(), $bCnt=false) { global $DB; $strSql = "SELECT ". ($bCnt ? " COUNT('x') as CNT " : " MF.*, MB.NAME as MAILBOX_NAME, MB.ID as MAILBOX_ID, MB.SERVER_TYPE as MAILBOX_TYPE, MB.DOMAINS as DOMAINS, ". " ".$DB->DateToCharFunction("MF.TIMESTAMP_X")." as TIMESTAMP_X " ). " ". "FROM b_mail_mailbox MB ".($arFilter["EMPTY"]=="Y"?"LEFT":"INNER")." JOIN b_mail_filter MF ON MB.ID=MF.MAILBOX_ID "; if(!is_array($arFilter)) $arFilter = Array(); $arSqlSearch = Array(); $filter_keys = array_keys($arFilter); for($i=0; $i<count($filter_keys); $i++) { $val = $arFilter[$filter_keys[$i]]; if (strlen($val)<=0) continue; $key = strtoupper($filter_keys[$i]); switch($key) { case "NAME": case "PHP_CONDITION": case "ACTION_PHP": $arSqlSearch[] = GetFilterQuery("MF.".$key, $val); break; case "SERVER_TYPE": $arSqlSearch[] = GetFilterQuery("MB.".$key, $val, "N"); break; case "ID": case "ACTION_TYPE": case "MAILBOX_ID": case "PARENT_FILTER_ID": case "SORT": case "WHEN_MAIL_RECEIVED": case "WHEN_MANUALLY_RUN": case "ACTION_STOP_EXEC": case "ACTION_DELETE_MESSAGE": case "ACTION_READ": case "ACTIVE": $arSqlSearch[] = GetFilterQuery("MF.".$key, $val, "N"); break; } } $is_filtered = false; $strSqlSearch = ""; for($i=0; $i<count($arSqlSearch); $i++) if(strlen($arSqlSearch[$i])>0) { $strSqlSearch .= " AND (".$arSqlSearch[$i].") "; $is_filtered = true; } $arSqlOrder = Array(); foreach($arOrder as $by=>$order) { $order = strtolower($order); if ($order!="asc") $order = "desc".(strtoupper($DB->type)=="ORACLE"?" NULLS LAST":""); else $order = "asc".(strtoupper($DB->type)=="ORACLE"?" NULLS FIRST":""); switch(strtoupper($by)) { case "TIMESTAMP_X": case "MAILBOX_ID": case "ACTIVE": case "NAME": case "SORT": case "PARENT_FILTER_ID": case "WHEN_MAIL_RECEIVED": case "WHEN_MANUALLY_RUN": case "ACTION_STOP_EXEC": case "ACTION_DELETE_MESSAGE": case "ACTION_READ": $arSqlOrder[] = " MF.".$by." ".$order." "; break; case "MAILBOX_NAME": $arSqlOrder[] = " MB.NAME ".$order." "; default: $arSqlOrder[] = " MF.ID ".$order." "; } } $strSqlOrder = ""; $arSqlOrder = array_unique($arSqlOrder); DelDuplicateSort($arSqlOrder); for ($i=0; $i<count($arSqlOrder); $i++) { if($i==0) $strSqlOrder = " ORDER BY "; else $strSqlOrder .= ","; $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= " WHERE 1=1 ".$strSqlSearch.$strSqlOrder; $res = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $res->is_filtered = $is_filtered; return $res; } /********************************************************************* *********************************************************************/ function GetByID($ID) { global $DB; return CMailFilter::GetList(Array(), Array("ID"=>$ID)); } function CheckPHP($code, $field_name) { return true; // not work - E_CODE_ERROR global $php_errormsg; ini_set("track_errors", "on"); $php_errormsg_prev = $php_errormsg; ob_start(); error_reporting(0); @eval($code); ob_end_clean(); if($php_errormsg != "") CMailError::SetError("B_MAIL_ERR_PHP", GetMessage("MAIL_CL_ERR_IN_PHP").$field_name.". (".$php_errormsg.")"); $php_errormsg = $php_errormsg_prev; ini_set("track_errors", $prev); } function CheckFields($arFields, $ID=false) { $err_cnt = CMailError::ErrCount(); $arMsg = Array(); if(is_set($arFields, "NAME") && strlen($arFields["NAME"])<1) { CMailError::SetError("B_MAIL_ERR_NAME", GetMessage("MAIL_CL_ERR_NAME")." \"".GetMessage("MAIL_CL_NAME")."\""); $arMsg[] = array("id"=>"NAME", "text"=> GetMessage("MAIL_CL_ERR_NAME")." \"".GetMessage("MAIL_CL_NAME")."\""); } if(is_set($arFields, "PHP_CONDITION") && strlen(trim($arFields["PHP_CONDITION"]))>0) { if (!CMailFilter::CheckPHP($arFields["PHP_CONDITION"], GetMessage("MAIL_CL_PHP_COND"))) $arMsg[] = array("id"=>"PHP_CONDITION", "text"=> GetMessage("MAIL_CL_ERR_IN_PHP").GetMessage("MAIL_CL_PHP_COND")); } if(is_set($arFields, "ACTION_PHP") && strlen(trim($arFields["ACTION_PHP"]))>0) { if (!CMailFilter::CheckPHP($arFields["ACTION_PHP"], GetMessage("MAIL_CL_PHP_ACT"))) $arMsg[] = array("id"=>"ACTION_PHP", "text"=> GetMessage("MAIL_CL_ERR_IN_PHP").GetMessage("MAIL_CL_PHP_ACT")); } if(is_set($arFields, "MAILBOX_ID")) { $r = CMailBox::GetByID($arFields["MAILBOX_ID"]); if(!$r->Fetch()) { CMailError::SetError("B_MAIL_ERR_BAD_MAILBOX", GetMessage("MAIL_CL_ERR_WRONG_MAILBOX")); $arMsg[] = array("id"=>"MAILBOX_ID", "text"=> GetMessage("MAIL_CL_ERR_WRONG_MAILBOX")); } } elseif($ID===false) { CMailError::SetError("B_MAIL_ERR_BAD_MAILBOX_NA", GetMessage("MAIL_CL_ERR_MAILBOX_NA")); $arMsg[] = array("id"=>"MAILBOX_ID", "text"=> GetMessage("MAIL_CL_ERR_MAILBOX_NA")); } if(!empty($arMsg)) { $e = new CAdminException($arMsg); $GLOBALS["APPLICATION"]->ThrowException($e); return false; } return true; //return ($err_cnt == CMailError::ErrCount()); } /********************************************************************* *********************************************************************/ function Add($arFields) { global $DB; if(is_set($arFields, "ACTIVE") && $arFields["ACTIVE"]!="Y") $arFields["ACTIVE"]="N"; if(is_set($arFields, "ACTION_READ") && $arFields["ACTION_READ"]!="Y" && $arFields["ACTION_READ"]!="N") $arFields["ACTION_READ"] = "-"; if(is_set($arFields, "ACTION_SPAM") && $arFields["ACTION_SPAM"]!="Y" && $arFields["ACTION_SPAM"]!="N") $arFields["ACTION_SPAM"] = "-"; if(is_set($arFields, "ACTION_DELETE_MESSAGE") && $arFields["ACTION_DELETE_MESSAGE"]!="Y") $arFields["ACTION_DELETE_MESSAGE"] ="N"; if(is_set($arFields, "ACTION_STOP_EXEC") && $arFields["ACTION_STOP_EXEC"]!="Y") $arFields["ACTION_STOP_EXEC"] = "N"; if(!CMailFilter::CheckFields($arFields)) return false; $ID = $DB->Add("b_mail_filter", $arFields, Array("PHP_CONDITION", "ACTION_PHP")); if(is_set($arFields, "CONDITIONS")) CMailFilterCondition::SetConditions($ID, $arFields["CONDITIONS"]); CMailbox::SMTPReload(); return $ID; } /********************************************************************* *********************************************************************/ function Update($ID, $arFields) { global $DB; $ID = IntVal($ID); if(is_set($arFields, "ACTIVE") && $arFields["ACTIVE"]!="Y") $arFields["ACTIVE"]="N"; if(is_set($arFields, "WHEN_MAIL_RECEIVED") && $arFields["WHEN_MAIL_RECEIVED"]!="Y") $arFields["WHEN_MAIL_RECEIVED"] = "N"; if(is_set($arFields, "WHEN_MANUALLY_RUN") && $arFields["WHEN_MANUALLY_RUN"]!="Y") $arFields["WHEN_MANUALLY_RUN"] = "N"; if(is_set($arFields, "ACTION_READ") && $arFields["ACTION_READ"]!="Y" && $arFields["ACTION_READ"]!="N") $arFields["ACTION_READ"] = "-"; if(is_set($arFields, "ACTION_SPAM") && $arFields["ACTION_SPAM"]!="Y" && $arFields["ACTION_SPAM"]!="N") $arFields["ACTION_SPAM"] = "-"; if(is_set($arFields, "ACTION_DELETE_MESSAGE") && $arFields["ACTION_DELETE_MESSAGE"]!="Y") $arFields["ACTION_DELETE_MESSAGE"] ="N"; if(is_set($arFields, "ACTION_STOP_EXEC") && $arFields["ACTION_STOP_EXEC"]!="Y") $arFields["ACTION_STOP_EXEC"] = "N"; if(!CMailFilter::CheckFields($arFields, $ID)) return false; $arUpdateBinds = array(); $strUpdate = $DB->PrepareUpdateBind("b_mail_filter", $arFields,"", false, $arUpdateBinds); $strSql = "UPDATE b_mail_filter SET ". $strUpdate." ". "WHERE ID=".$ID; $arBinds = array(); foreach($arUpdateBinds as $field_id) $arBinds[$field_id] = $arFields[$field_id]; $DB->QueryBind($strSql, $arBinds); if(is_set($arFields, "CONDITIONS")) CMailFilterCondition::SetConditions($ID, $arFields["CONDITIONS"]); CMailbox::SMTPReload(); return true; } function Delete($ID) { global $DB; $ID = IntVal($ID); $dbr = CMailFilterCondition::GetList(Array(), Array("FILTER_ID"=>$ID)); while($r = $dbr->Fetch()) { if(!CMailFilterCondition::Delete($r["ID"])) return false; } $strSql = "DELETE FROM b_mail_filter WHERE ID=".$ID; CMailbox::SMTPReload(); return $DB->Query($strSql, true); } function Filter($arFields, $event, $FILTER_ID=false, $PARENT_FILTER_ID = false) { global $BX_MAIL_FILTER_CACHE, $DB; $PARENT_FILTER_ID = IntVal($PARENT_FILTER_ID); $MAILBOX_ID = IntVal($arFields["MAILBOX_ID"]); $MESSAGE_ID = IntVal($arFields["ID"]); $cache_param = $MAILBOX_ID."|".$PARENT_FILTER_ID."|".$event."|".$FILTER_ID; if(is_set($BX_MAIL_FILTER_CACHE, $cache_param)) { $arFilterCond = $BX_MAIL_FILTER_CACHE[$cache_param]["CONDITIONS"]; $arFilter = $BX_MAIL_FILTER_CACHE[$cache_param]["FILTER"]; } else { $strSqlAdd = ""; if($event=="R") $strSqlAdd .= " AND (WHEN_MAIL_RECEIVED='Y')"; else $strSqlAdd .= " AND (WHEN_MANUALLY_RUN='Y' ".(IntVal($FILTER_ID)>0?" AND f.ID='".IntVal($FILTER_ID)."'":"").")"; $strSql = "SELECT f.*, c.*, f.ID, c.ID as CONDITION_ID FROM b_mail_filter f LEFT JOIN b_mail_filter_cond c ON f.ID = c.FILTER_ID WHERE (f.MAILBOX_ID = ".$MAILBOX_ID." OR MAILBOX_ID IS NULL) AND f.ACTIVE = 'Y' AND f.PARENT_FILTER_ID ".($PARENT_FILTER_ID>0?"=".$PARENT_FILTER_ID:" IS NULL "). $strSqlAdd." ORDER BY f.SORT, f.ID"; $dbr = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $arFilter = Array(); $arFilterCond = Array(); $prev_ID = 0; $arr_prev = false; $arConds = Array(); while($arr = $dbr->Fetch()) { $arFilter[$arr["ID"]] = $arr; if($arr["CONDITION_ID"]>0) { if(!is_array($arFilterCond[$arr["ID"]])) $arFilterCond[$arr["ID"]] = Array(); $arFilterCond[$arr["ID"]][] = $arr; } } $BX_MAIL_FILTER_CACHE[$cache_param] = Array("FILTER"=>$arFilter, "CONDITIONS"=>$arFilterCond); } $arFieldsOriginal = $arFields; foreach($arFilter as $filter_id=>$arFilterParams) { $arFields = $arFieldsOriginal; $arFields["MAIL_FILTER"] = $arFilterParams; $arAllConditions = $arFilterCond[$filter_id]; $bCondOK = true; if(!is_array($arAllConditions)) $arAllConditions = Array(); foreach($arAllConditions as $k => $arCondition) { $bCondOK = false; $type = $arCondition["TYPE"]; switch($type) { case "ALL":case "RECIPIENT":case "SENDER": if($type=="ALL") $arFields[$type] = $arFields["HEADER"]."\r\n".$arFields["BODY"]; elseif($type=="RECIPIENT") $arFields[$type] = $arFields["FIELD_CC"]."\r\n".$arFields["FIELD_TO"]."\r\n".$arFields["FIELD_BCC"]; else $arFields[$type] = $arFields["FIELD_FROM"]."\r\n".$arFields["FIELD_REPLY_TO"]; case "HEADER": case "FIELD_FROM": case "FIELD_REPLY_TO": case "FIELD_TO": case "FIELD_CC": case "SUBJECT": case "BODY": $arStrings = explode("\n", $arCondition["STRINGS"]); if($arCondition["COMPARE_TYPE"]=="NOT_EQUAL" || $arCondition["COMPARE_TYPE"]=="NOT_CONTAIN") { $bCondOK = true; for($i=0; $i<count($arStrings); $i++) { $str = strtoupper(Trim($arStrings[$i], "\r")); switch($arCondition["COMPARE_TYPE"]) { case "NOT_CONTAIN": if(strlen($str)>0 && strpos(strtoupper($arFields[$type]), $str)!==false) $bCondOK = false; break; case "NOT_EQUAL": if($str==strtoupper($arFields[$type])) $bCondOK = false; break; } if(!$bCondOK) break; } } else { for($i=0; $i<count($arStrings); $i++) { $str = strtoupper(Trim($arStrings[$i], "\r")); switch($arCondition["COMPARE_TYPE"]) { case "CONTAIN": if(strlen($str)>0 && strpos(strtoupper($arFields[$type]), $str)!==false) $bCondOK = true; break; case "EQUAL": if($str==strtoupper($arFields[$type])) $bCondOK = true; break; case "REGEXP": if(preg_match("'".str_replace("'", "\'", $str)."'i", $arFields[$type])) $bCondOK = true; break; } if($bCondOK) break; } } break; case "ATTACHMENT": $db_att = CMailAttachment::GetList(Array(), Array("MESSAGE_ID"=>$arFields["ID"])); $arStrings = explode("\n", $arCondition["STRINGS"]); if($arCondition["COMPARE_TYPE"]=="NOT_EQUAL" || $arCondition["COMPARE_TYPE"]=="NOT_CONTAIN") { $bCondOK = true; while($arr_att = $db_att->Fetch()) { for($i=0; $i<count($arStrings); $i++) { $str = strtoupper(Trim($arStrings[$i], "\r")); switch($arCondition["COMPARE_TYPE"]) { case "NOT_CONTAIN": if(strlen($str)>0 && strpos(strtoupper($arr_att["FILE_NAME"]), $str)!==false) $bCondOK = false; break; case "NOT_EQUAL": if($str==strtoupper($arr_att["FILE_NAME"])) $bCondOK = false; break; } } if(!$bCondOK) break; } } else { for($i=0; $i<count($arStrings); $i++) { $str = strtoupper(Trim($arStrings[$i], "\r")); while($arr_att = $db_att->Fetch()) { switch($arCondition["COMPARE_TYPE"]) { case "CONTAIN": if(strlen($str)>0 && strpos(strtoupper($arr_att["FILE_NAME"]), $str)!==false) $bCondOK = true; break; case "EQUAL": if($str==strtoupper($arr_att["FILE_NAME"])) $bCondOK = true; break; case "REGEXP": if(preg_match("'".str_replace("'", "\'", $str)."'i", $arr_att["FILE_NAME"])) $bCondOK = true; break; } } if($bCondOK) break; } } break; } //switch if(!$bCondOK) break; } //foreach($arAllConditions as $k => $arCondition) if(!$bCondOK) continue; if($arFilterParams["SPAM_RATING"]>0) { $arFields["SPAM_RATING"] = CMailMessage::GetSpamRating($arFields["ID"], $arFields); if($arFilterParams["SPAM_RATING_TYPE"]==">" && $arFields["SPAM_RATING"]<=$arFilterParams["SPAM_RATING"]) continue; if($arFilterParams["SPAM_RATING_TYPE"]!=">" && $arFields["SPAM_RATING"]>=$arFilterParams["SPAM_RATING"]) continue; } if($arFilterParams["MESSAGE_SIZE"]>0) { $MESSAGE_SIZE = $arFields["MESSAGE_SIZE"]; if($arFilterParams["MESSAGE_SIZE_UNIT"]=="k") $MESSAGE_SIZE = IntVal($MESSAGE_SIZE/1024); elseif($arFilterParams["MESSAGE_SIZE_UNIT"]=="m") $MESSAGE_SIZE = IntVal($MESSAGE_SIZE/1024/1024); if($arFilterParams["MESSAGE_SIZE_TYPE"]==">" && $MESSAGE_SIZE<=$arFilterParams["MESSAGE_SIZE"]) continue; if($arFilterParams["MESSAGE_SIZE_TYPE"]!=">" && $MESSAGE_SIZE>=$arFilterParams["MESSAGE_SIZE"]) continue; } if(strlen($arFilterParams["PHP_CONDITION"])>0) if(!CMailFilter::DoPHPAction("php_cond_".$arFilterParams["ID"]."_", $arFilterParams["PHP_CONDITION"], $arFields)) continue; $arModFilter = false; if($arFilterParams["ACTION_TYPE"]!="") { $res = CMailFilter::GetFilterList($arFilterParams["ACTION_TYPE"]); if($arModFilter = $res->Fetch()) if ( (is_array($arModFilter["CONDITION_FUNC"]) && count($arModFilter["CONDITION_FUNC"]) > 0) || strlen($arModFilter["CONDITION_FUNC"]) > 0 ) if(!call_user_func_array($arModFilter["CONDITION_FUNC"], Array(&$arFields, &$arFilterParams["ACTION_VARS"]))) continue; } CMailLog::AddMessage( Array( "MAILBOX_ID"=>$MAILBOX_ID, "MESSAGE_ID"=>$MESSAGE_ID, "FILTER_ID"=>$filter_id, "STATUS_GOOD"=>"Y", "LOG_TYPE"=>"FILTER_OK", "MESSAGE"=>$event, ) ); if($arModFilter) if ( (is_array($arModFilter["ACTION_FUNC"]) && count($arModFilter["ACTION_FUNC"]) > 0) || strlen($arModFilter["ACTION_FUNC"]) > 0 ) call_user_func_array($arModFilter["ACTION_FUNC"], array(&$arFields, &$arFilterParams["ACTION_VARS"])); if(strlen(Trim($arFilterParams["ACTION_PHP"]))>0) { $res = CMailFilter::DoPHPAction("php_act_".$arFilterParams["ID"]."_", $arFilterParams["ACTION_PHP"], $arFields); CMailLog::AddMessage( Array( "MAILBOX_ID"=>$MAILBOX_ID, "MESSAGE_ID"=>$MESSAGE_ID, "FILTER_ID"=>$filter_id, "LOG_TYPE"=>"DO_PHP", "MESSAGE"=>"" ) ); } if($arFilterParams["ACTION_SPAM"]=="Y" && $arFields["SPAM"]!="Y") { if($arFields["SPAM"]=="N") CMailFilter::DeleteFromSpamBase($arFields["FOR_SPAM_TEST"], false); CMailFilter::MarkAsSpam($arFields["FOR_SPAM_TEST"], true); CMailMessage::Update($MESSAGE_ID, Array("SPAM"=>"Y")); CMailLog::AddMessage( Array( "MAILBOX_ID"=>$MAILBOX_ID, "MESSAGE_ID"=>$MESSAGE_ID, "FILTER_ID"=>$filter_id, "LOG_TYPE"=>"SPAM", "MESSAGE"=>"" ) ); $arFields["SPAM"] = "Y"; } elseif($arFilterParams["ACTION_SPAM"]=="N" && $arFields["SPAM"]!="N") { if($arFields["SPAM"]=="Y") CMailFilter::DeleteFromSpamBase($arFields["FOR_SPAM_TEST"], true); CMailFilter::MarkAsSpam($arFields["FOR_SPAM_TEST"], false); CMailMessage::Update($MESSAGE_ID, Array("SPAM"=>"N")); CMailLog::AddMessage( Array( "MAILBOX_ID"=>$MAILBOX_ID, "MESSAGE_ID"=>$MESSAGE_ID, "FILTER_ID"=>$filter_id, "LOG_TYPE"=>"NOTSPAM", "MESSAGE"=>"" ) ); $arFields["SPAM"] = "N"; } if($arFilterParams["ACTION_READ"]=="Y" && $arFields["NEW_MESSAGE"]=="Y") { $arFields["NEW_MESSAGE"] = "N"; CMailMessage::Update($MESSAGE_ID, Array("NEW_MESSAGE"=>"N")); } elseif($arFilterParams["ACTION_READ"]=="N" && $arFields["NEW_MESSAGE"]!="Y") { $arFields["NEW_MESSAGE"] = "Y"; CMailMessage::Update($MESSAGE_ID, Array("NEW_MESSAGE"=>"Y")); } if($arFilterParams["ACTION_DELETE_MESSAGE"]=="Y") { CMailLog::AddMessage( Array( "MAILBOX_ID"=>$MAILBOX_ID, "MESSAGE_ID"=>$MESSAGE_ID, "FILTER_ID"=>$filter_id, "STATUS_GOOD"=>"Y", "LOG_TYPE"=>"MESSAGE_DELETED", "MESSAGE"=>"" ) ); CMailMessage::Delete($MESSAGE_ID); } if($arFilterParams["ACTION_STOP_EXEC"]=="Y") { CMailLog::AddMessage( Array( "MAILBOX_ID"=>$MAILBOX_ID, "MESSAGE_ID"=>$MESSAGE_ID, "FILTER_ID"=>$filter_id, "STATUS_GOOD"=>"Y", "LOG_TYPE"=>"FILTER_STOP", "MESSAGE"=>"" ) ); return true; } } return true; } function FilterMessage($message_id, $event, $FILTER_ID=false) { $res = CMailMessage::GetByID($message_id); if($arFields = $res->Fetch()) return CMailFilter::Filter($arFields, $event, $FILTER_ID); return false; } function RecalcSpamRating() { $res = $DB->Query("SELECT ID, FOR_SPAM_TEST FROM b_mail_message WHERE SPAM_LAST_RESULT<>'N'"); while($arr = $res->Fetch()) { $arSpam = CMailFilter::GetSpamRating($arr["FOR_SPAM_TEST"]); $DB->Query("UPDATE b_mail_message SET SPAM_RATING=".Round($arSpam["RATING"], 4).", SPAM_LAST_RESULT='Y', SPAM_WORDS='".$DB->ForSql($arSpam["WORDS"], 255)."' WHERE ID=".$arr["ID"]); } } function GetSpamRating($message) { global $DB; $message = Trim($message); if(strlen($message)<=0) return 0; // ðàçáèâàåì íà ñëîâà $arWords = preg_split("/[\x01-\x23\x25-\x3F\x5B-\x5E}{~]+/s", $message); // âûáèðàåì òîëüêî óíèêàëüíûå $arWords = array_unique($arWords); if(count($arWords)>999) $arWords = array_slice($arWords, 0, 999); // äëÿ êàæäîãî ñëîâà íàõîäèì îöåíêó Si $strWords = "''"; foreach($arWords as $word) $strWords .= ",'".md5($word)."'"; global $BX_MAIL_SPAM_CNT; if(!is_set($BX_MAIL_SPAM_CNT, "G")) { $strSql = "SELECT MAX(GOOD_CNT) as G, MAX(BAD_CNT) as B FROM b_mail_spam_weight"; if($res = $DB->Query($strSql)) $BX_MAIL_SPAM_CNT = $res->Fetch(); if(intval($BX_MAIL_SPAM_CNT["G"])<=0) $BX_MAIL_SPAM_CNT["G"] = 1; if(intval($BX_MAIL_SPAM_CNT["B"])<=0) $BX_MAIL_SPAM_CNT["B"] = 1; } $CNT_WORDS = COption::GetOptionInt("mail", "spam_word_count", B_MAIL_WORD_CNT); $MIN_COUNT = COption::GetOptionInt("mail", "spam_min_count", B_MAIL_MIN_CNT); // âûáèðàåì $CNT_WORDS ñëîâ ñ íàèáîëüøåé ïî |Si - 0.5| // åñëè ñëîâî âñòðå÷àëîñü ìåíüøå xxx (5) ðàç, òî èãíîðèðóåì $strSql = "SELECT SW.*, ". " (BAD_CNT/".$BX_MAIL_SPAM_CNT["B"].".0) / (2*GOOD_CNT/".$BX_MAIL_SPAM_CNT["G"].".0 + BAD_CNT/".$BX_MAIL_SPAM_CNT["B"].".0) as RATING, ". " ABS((BAD_CNT/".$BX_MAIL_SPAM_CNT["B"].".0) / (2*GOOD_CNT/".$BX_MAIL_SPAM_CNT["G"].".0 + BAD_CNT/".$BX_MAIL_SPAM_CNT["B"].".0) - 0.5) as MOD_RATING ". "FROM b_mail_spam_weight SW ". "WHERE WORD_ID IN (".$strWords.") ". " AND ABS((BAD_CNT/".$BX_MAIL_SPAM_CNT["B"].".0) / (2*GOOD_CNT/".$BX_MAIL_SPAM_CNT["G"].".0 + BAD_CNT/".$BX_MAIL_SPAM_CNT["B"].".0) - 0.5) > 0.1 ". " AND TOTAL_CNT>".$MIN_COUNT." ". "ORDER BY MOD_RATING DESC ". (strtoupper($DB->type)=="MYSQL"?"LIMIT ".$CNT_WORDS : ""); //echo htmlspecialchars($strSql)."<br>"; $a = 1; $b = 1; $dbr = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $arr = true; $words = ""; for($i=0; $i<$CNT_WORDS; $i++) { if($arr && $arr = $dbr->Fetch()) { //echo "<font size='-3'>".htmlspecialchars($arr["WORD_REAL"])."=".$arr["RATING"]."<br></font> "; $words .= $arr["WORD_REAL"]." ".Round($arr["RATING"]*100, 4)." ".$arr["BAD_CNT"]." ".$arr["GOOD_CNT"]."\n"; $a = $a * ($arr["RATING"]==0?0.00001:$arr["RATING"]); $b = $b * (1 - ($arr["RATING"]==1?0.9999:$arr["RATING"])); } else { // åñëè ñëîâà íåò, òî îöåíêà Si = 0.4 $a = $a * 0.4; $b = $b * (1 - 0.4); } } // ñ÷èòàåì èç íèõ ïî Áàéåñó îöåíêó äëÿ âñåãî ïèñüìà $rating = $a/($a+$b) * 100; return Array("RATING"=>$rating, "WORDS"=>$words); } function DoPHPAction($id, $action, &$arMessageFields) { if(!file_exists($_SERVER["DOCUMENT_ROOT"].BX_PERSONAL_ROOT."/tmp/mailparser/".$id.md5($action).".php")) { CheckDirPath($_SERVER["DOCUMENT_ROOT"].BX_PERSONAL_ROOT."/tmp/mail/"); if(!($f = @fopen($_SERVER["DOCUMENT_ROOT"].BX_PERSONAL_ROOT."/tmp/mail/".$id.md5($action).".php", "wb"))) return false; if(!@fwrite($f, '<'.'?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();?'.'><'.'?'.$action.'?'.'>')) return false; fclose($f); } define("B_PROLOG_INCLUDED", true); return include($_SERVER["DOCUMENT_ROOT"].BX_PERSONAL_ROOT."/tmp/mail/".$id.md5($action).".php"); } function DeleteFromSpamBase($message, $bIsSPAM = true) { return CMailFilter::SpamAction($message, $bIsSPAM, true); } function MarkAsSpam($message, $bIsSPAM = true) { return CMailFilter::SpamAction($message, $bIsSPAM); } function SpamAction($message, $bIsSPAM, $bDelete = false) { global $DB; global $BX_MAIL_SPAM_CNT; if(!is_set($BX_MAIL_SPAM_CNT, "G")) { $strSql = "SELECT MAX(GOOD_CNT) as G, MAX(BAD_CNT) as B FROM b_mail_spam_weight"; if($res = $DB->Query($strSql)) $BX_MAIL_SPAM_CNT = $res->Fetch(); if(intval($BX_MAIL_SPAM_CNT["G"])<=0) $BX_MAIL_SPAM_CNT["G"] = 1; if(intval($BX_MAIL_SPAM_CNT["B"])<=0) $BX_MAIL_SPAM_CNT["B"] = 1; } if($bDelete && $bIsSPAM) $BX_MAIL_SPAM_CNT["B"]--; elseif($bDelete && !$bIsSPAM) $BX_MAIL_SPAM_CNT["G"]--; elseif(!$bDelete && $bIsSPAM) $BX_MAIL_SPAM_CNT["B"]++; elseif(!$bDelete && !$bIsSPAM) $BX_MAIL_SPAM_CNT["G"]++; @set_time_limit(30); // ðàçáèâàåì íà ñëîâà $message = Trim($message); if(strlen($message)<=0) return 0; if(strlen($message)>102400) $message = substr($message, 0, 102400); // ðàçáèâàåì íà ñëîâà $arWords = preg_split("/[\x01-\x23\x25-\x3F\x5B-\x5E}{~]+/s", $message); // âûáèðàåì òîëüêî óíèêàëüíûå $arWords = array_unique($arWords); // äëÿ êàæäîãî ñëîâà íàõîäèì îöåíêó Si $strWords = "''"; foreach($arWords as $word) { $word_md5 = md5($word); // èçìåíÿåì ó íèõ îöåíêó $strSql = "INSERT INTO b_mail_spam_weight(WORD_ID, WORD_REAL, GOOD_CNT, BAD_CNT, TOTAL_CNT) ". "VALUES('".$word_md5."', '".$DB->ForSql($word, 40)."', ".($bIsSPAM?0:1).", ".($bIsSPAM?1:0).", 1)"; if($bDelete || (!$DB->Query($strSql, true))) { if($bDelete) { $strSql = "UPDATE b_mail_spam_weight SET ". " GOOD_CNT = GOOD_CNT - ".($bIsSPAM?0:1).", ". " BAD_CNT = BAD_CNT - ".($bIsSPAM?1:0).", ". " TOTAL_CNT = TOTAL_CNT - 1 ". "WHERE WORD_ID = '".$word_md5."' ". " AND ".($bIsSPAM?"BAD_CNT>0":"GOOD_CNT>0");// AND WORD_REAL = '".$DB->ForSql($word, 40)."'"; } else { $strSql = "UPDATE b_mail_spam_weight SET ". " GOOD_CNT = GOOD_CNT + ".($bIsSPAM?0:1).", ". " BAD_CNT = BAD_CNT + ".($bIsSPAM?1:0).", ". " TOTAL_CNT = TOTAL_CNT + 1 ". "WHERE WORD_ID='".$word_md5."'";// AND WORD_REAL = '".$DB->ForSql($word, 40)."'"; } $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); } } if(COption::GetOptionString("mail", "reset_all_spam_result", "N") == "Y") $DB->Query("UPDATE b_mail_message SET SPAM_LAST_RESULT='N'"); } function GetFilterList($id = "") { global $BX_MAIL_CUST_FILTER_LIST; if($BX_MAIL_CUST_FILTER_LIST===false) { $allResults = Array(); $db_events = GetModuleEvents("mail", "OnGetFilterList"); while($arEvent = $db_events->Fetch()) { $arResult = ExecuteModuleEvent($arEvent); if(is_array($arResult)) $allResults[] = $arResult; } $BX_MAIL_CUST_FILTER_LIST = $allResults; } else $allResults = $BX_MAIL_CUST_FILTER_LIST; if($id!="") { $allResultsTemp = Array(); for($i=0; $i<count($allResults); $i++) { if($allResults[$i]["ID"] == $id) { $allResultsTemp[] = $allResults[$i]; break; } } $allResults = $allResultsTemp; } $db_res = new CDBResult; $db_res->InitFromArray($allResults); return $db_res; } } global $BX_MAIL_CUST_FILTER_LIST; $BX_MAIL_CUST_FILTER_LIST = false; /////////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////////// class CMailFilterCondition { function GetList($arOrder=Array(), $arFilter=Array()) { global $DB; $strSql = "SELECT MFC.* ". "FROM b_mail_filter_cond MFC "; if(!is_array($arFilter)) $arFilter = Array(); $arSqlSearch = Array(); $filter_keys = array_keys($arFilter); for($i=0; $i<count($filter_keys); $i++) { $val = $arFilter[$filter_keys[$i]]; if (strlen($val)<=0) continue; $key = strtoupper($filter_keys[$i]); switch($key) { case "TYPE": case "STRINGS": case "COMPARE_TYPE": $arSqlSearch[] = GetFilterQuery("MFC.".$key, $val); break; case "ID": case "FILTER_ID": $arSqlSearch[] = GetFilterQuery("MFC.".$key, $val, "N"); break; } } $strSqlSearch = ""; for($i=0; $i<count($arSqlSearch); $i++) if(strlen($arSqlSearch[$i])>0) $strSqlSearch .= " AND (".$arSqlSearch[$i].") "; $arSqlOrder = Array(); foreach($arOrder as $by=>$order) { $order = strtolower($order); if ($order!="asc") $order = "desc".(strtoupper($DB->type)=="ORACLE"?" NULLS LAST":""); else $order = "asc".(strtoupper($DB->type)=="ORACLE"?" NULLS FIRST":""); switch(strtoupper($by)) { case "FILTER_ID": case "TYPE": case "STRINGS": case "COMPARE_TYPE": $arSqlOrder[] = " MFC.".$by." ".$order." "; break; default: $arSqlOrder[] = " MFC.ID ".$order." "; } } $strSqlOrder = ""; $arSqlOrder = array_unique($arSqlOrder); DelDuplicateSort($arSqlOrder); for ($i=0; $i<count($arSqlOrder); $i++) { if($i==0) $strSqlOrder = " ORDER BY "; else $strSqlOrder .= ","; $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= " WHERE 1=1 ".$strSqlSearch.$strSqlOrder; $res = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $res->is_filtered = (count($arSqlOrder)>0); return $res; } /********************************************************************* *********************************************************************/ function GetByID($ID) { global $DB; return CMailFilterCondition::GetList(Array(), Array("ID"=>$ID)); } function Delete($ID) { global $DB; $ID = Intval($ID); $strSql = "DELETE FROM b_mail_filter_cond WHERE ID=".$ID; return $DB->Query($strSql, true); } function SetConditions($FILTER_ID, $CONDITIONS, $bClearOther = true) { global $DB; $FILTER_ID = IntVal($FILTER_ID); $strSql= "SELECT ID ". "FROM b_mail_filter_cond ". "WHERE FILTER_ID=".$FILTER_ID; $dbr = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); while($dbr_arr = $dbr->Fetch()) { if(is_set($CONDITIONS, $dbr_arr["ID"]) && is_array($CONDITIONS[$dbr_arr["ID"]]) && strlen($CONDITIONS[$dbr_arr["ID"]]["STRINGS"])>0) { $arFields = $CONDITIONS[$dbr_arr["ID"]]; unset($arFields["ID"]); $arFields["FILTER_ID"] = $FILTER_ID; CMailFilterCondition::Update($dbr_arr["ID"], $arFields); unset($CONDITIONS[$dbr_arr["ID"]]); } elseif($bClearOther) { $DB->Query("DELETE FROM b_mail_filter_cond WHERE ID=".$dbr_arr["ID"]); } } foreach($CONDITIONS as $arFields) { if(is_array($arFields) && strlen($arFields["STRINGS"])>0) { $arFields["FILTER_ID"] = $FILTER_ID; unset($arFields["ID"]); CMailFilterCondition::Add($arFields); } } } /********************************************************************* *********************************************************************/ function Add($arFields) { global $DB; if(is_set($arFields, "COMPARE_TYPE") && $arFields["COMPARE_TYPE"]!="EQUAL" && $arFields["COMPARE_TYPE"]!="NOT_EQUAL" && $arFields["COMPARE_TYPE"]!="NOT_CONTAIN" && $arFields["COMPARE_TYPE"]!="REGEXP") $arFields["COMPARE_TYPE"]="CONTAIN"; $ID = $DB->Add("b_mail_filter_cond", $arFields); return $ID; } /********************************************************************* *********************************************************************/ function Update($ID, $arFields) { global $DB; $ID = IntVal($ID); if(is_set($arFields, "COMPARE_TYPE") && $arFields["COMPARE_TYPE"]!="EQUAL" && $arFields["COMPARE_TYPE"]!="NOT_EQUAL" && $arFields["COMPARE_TYPE"]!="NOT_CONTAIN" && $arFields["COMPARE_TYPE"]!="REGEXP") $arFields["COMPARE_TYPE"]="CONTAIN"; $strUpdate = $DB->PrepareUpdate("b_mail_filter_cond", $arFields); $strSql = "UPDATE b_mail_filter_cond SET ". $strUpdate." ". "WHERE ID=".$ID; $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); return true; } } class CMailLog { function AddMessage($arFields) { global $DB; $arFields["~DATE_INSERT"] = $DB->GetNowFunction(); if(array_key_exists('MESSAGE', $arFields)) $arFields['MESSAGE'] = strval(substr($arFields['MESSAGE'], 0, 255)); else $arFields['MESSAGE'] = ''; return $DB->Add("b_mail_log", $arFields); } function Delete($ID) { global $DB; $ID = IntVal($ID); $strSql = "DELETE FROM b_mail_log WHERE ID=".$ID; return $DB->Query($strSql, true); } function GetList($arOrder=Array(), $arFilter=Array()) { global $DB; $strSql = "SELECT ML.*, MB.NAME as MAILBOX_NAME, ". " MF.NAME as FILTER_NAME, ". " MM.SUBJECT as MESSAGE_SUBJECT, ". " ".$DB->DateToCharFunction("ML.DATE_INSERT")." as DATE_INSERT ". " ". "FROM b_mail_log ML ". " INNER JOIN b_mail_mailbox MB ON MB.ID=ML.MAILBOX_ID ". " LEFT JOIN b_mail_filter MF ON MF.ID=ML.FILTER_ID ". " LEFT JOIN b_mail_message MM ON MM.ID=ML.MESSAGE_ID "; if(!is_array($arFilter)) $arFilter = Array(); $arSqlSearch = Array(); $filter_keys = array_keys($arFilter); for($i=0; $i<count($filter_keys); $i++) { $val = $arFilter[$filter_keys[$i]]; if (strlen($val)<=0) continue; $key = strtoupper($filter_keys[$i]); switch($key) { case "ID": case "MAILBOX_ID": case "FILTER_ID": case "MESSAGE_ID": case "LOG_TYPE": case "STATUS_GOOD": $arSqlSearch[] = GetFilterQuery("ML.".$key, $val, "N"); break; case "MESSAGE": $arSqlSearch[] = GetFilterQuery("ML.".$key, $val); break; case "FILTER_NAME": $arSqlSearch[] = GetFilterQuery("MF.NAME", $val); break; case "MAILBOX_NAME": $arSqlSearch[] = GetFilterQuery("MB.NAME", $val); break; case "MESSAGE_SUBJECT": $arSqlSearch[] = GetFilterQuery("MM.SUBJECT", $val); break; } } $is_filtered = false; $strSqlSearch = ""; for($i=0; $i<count($arSqlSearch); $i++) if(strlen($arSqlSearch[$i])>0) { $strSqlSearch .= " AND (".$arSqlSearch[$i].") "; $is_filtered = true; } $arSqlOrder = Array(); foreach($arOrder as $by=>$order) { $order = strtolower($order); if ($order!="asc") $order = "desc".(strtoupper($DB->type)=="ORACLE"?" NULLS LAST":""); else $order = "asc".(strtoupper($DB->type)=="ORACLE"?" NULLS FIRST":""); switch(strtoupper($by)) { case "ID": case "MAILBOX_ID": case "FILTER_ID": case "MESSAGE_ID": case "DATE_INSERT": case "LOG_TYPE": case "STATUS_GOOD": case "MESSAGE": $arSqlOrder[] = " ML.".$by." ".$order." "; case "MESSAGE_SUBJECT": $arSqlOrder[] = " MM.SUBJECT ".$order." "; case "FILTER_NAME": $arSqlOrder[] = " MF.NAME ".$order." "; case "MAILBOX_NAME": $arSqlOrder[] = " MB.NAME ".$order." "; default: $arSqlOrder[] = " ML.ID ".$order." "; } } $strSqlOrder = ""; $arSqlOrder = array_unique($arSqlOrder); DelDuplicateSort($arSqlOrder); for ($i=0; $i<count($arSqlOrder); $i++) { if($i==0) $strSqlOrder = " ORDER BY "; else $strSqlOrder .= ","; $strSqlOrder .= $arSqlOrder[$i]; } $strSql .= " WHERE 1=1 ".$strSqlSearch.$strSqlOrder; $res = $DB->Query($strSql, false, "File: ".__FILE__."<br>Line: ".__LINE__); $res = new _CMailLogDBRes($res); $res->is_filtered = $is_filtered; return $res; } function ConvertRow($arr_log) { switch($arr_log["LOG_TYPE"]) { case "FILTER_OK": $arr_log["MESSAGE_TEXT"] = GetMessage("MAIL_CL_RULE_RUN")." \"[".$arr_log["FILTER_ID"]."] ".substr($arr_log["FILTER_NAME"], 0, 30).(strlen($arr_log["FILTER_NAME"])>30?"...":"")."\" "; if($arr_log["MESSAGE"]=="R") $arr_log["MESSAGE_TEXT"] .= GetMessage("MAIL_CL_WHEN_CONNECT"); else $arr_log["MESSAGE_TEXT"] .= GetMessage("MAIL_CL_WHEN_MANUAL"); break; case "NEW_MESSAGE": $arr_log["MESSAGE_TEXT"] = GetMessage("MAIL_CL_NEW_MESSAGE")." ".$arr_log["MESSAGE"]; break; case "SPAM": if($arr_log["FILTER_ID"]>0) $arr_log["MESSAGE_TEXT"] = " ".GetMessage("MAIL_CL_RULE_ACT_SPAM"); else $arr_log["MESSAGE_TEXT"] = GetMessage("MAIL_CL_ACT_SPAM"); break; case "NOTSPAM": if($arr_log["FILTER_ID"]>0) $arr_log["MESSAGE_TEXT"] = " ".GetMessage("MAIL_CL_RULE_ACT_NOTSPAM"); else $arr_log["MESSAGE_TEXT"] = GetMessage("MAIL_CL_ACT_NOTSPAM"); break; case "DO_PHP": $arr_log["MESSAGE_TEXT"] = " ".GetMessage("MAIL_CL_RULE_ACT_PHP"); break; case "MESSAGE_DELETED": $arr_log["MESSAGE_TEXT"] = " ".GetMessage("MAIL_CL_RULE_ACT_DEL"); break; case "FILTER_STOP": $arr_log["MESSAGE_TEXT"] = " ".GetMessage("MAIL_CL_RULE_ACT_CANC"); break; default: $arr_log["MESSAGE_TEXT"] = $arr_log["MESSAGE"]; } return $arr_log; } } class _CMailLogDBRes extends CDBResult { function _CMailLogDBRes($res) { parent::CDBResult($res); } function Fetch() { if($arr_log = parent::Fetch()) return CMailLog::ConvertRow($arr_log); return false; } } ?>