* @author Brian Wong * @author Nicolas Peyrussie * @version 04-03-07 * * Copyright (C) 2005 - 2007 MailZu * License: GPL, see LICENSE */ /** * Base directory of application */ @define('BASE_DIR', dirname(__FILE__) . '/..'); /** * CmnFns class */ include_once('lib/CmnFns.class.php'); /** * Include AmavisdEngine class */ include_once('lib/AmavisdEngine.class.php'); /** * PHPMailer */ include_once('lib/PHPMailer.class.php'); /** * Provide quarantine related functions */ /** * Release messages function * @param array $emailaddresses recipient email address(es) * @param array $mail_id_array containing mail_id of messages to be released * @result return array of messages whose release failed */ function releaseMessages($emailaddresses, $mail_id_array) { /*** Array pertaining to the release of messages ***/ // This is an array of array, the key being the $mail_id // and the value being an array containing all the messages info (time, subject, ...) and also the release status. // The reason for this is that we want to keep the ordering of the messages selected for release. $release_messages = array(); // This is an array of array, the key being the host // and the value being an array containing all the release info such as secret_id (one row per message) $hosts = array(); /*** Variables pertaining to the request of release ***/ // This array contains the messages that the logged in user wants the Admins to release $release_req_messages = array(); // Counter for the number of release requests $j = 0; $nb_failure = 0; $db = new DBEngine(); // Set autocommit to false to improve speed of 'RS' flag set up $result = $db->db->autoCommit(false); $db->check_for_error($result, 'PEAR DB autoCommit(false)'); // Fill the arrays foreach ($mail_id_array as $mail_id_recip) { // Get mail_id and recipient email address $temp = preg_split('/_/', $mail_id_recip); $mail_id = str_replace("_" . $temp[(sizeof($temp) - 1)], "", $mail_id_recip); $recip_email = $temp[(sizeof($temp) - 1)]; // Check if logged in user is admin or logged in user is trying to release his own messages if ( Auth::isMailAdmin() || Auth::isDomainAdmin() || in_array($recip_email, $emailaddresses) ) $result = $db->get_message($recip_email, $mail_id); else continue; $rs = $result[0]; // if content type is 'B' or 'V' and the logged in user is not admin // add message to array of release request if ( in_array($rs['content'], array( 'B', 'V')) && (! Auth::isMailAdmin() && ! Auth::isDomainAdmin()) ) { $release_req_messages[ $j ] = array( "mail_id" => $mail_id, "from_addr" => $rs[ 'from_addr' ], "subject" => $rs[ 'subject' ], "time_num" => $rs[ 'time_num' ], "spam_level" => $rs[ 'spam_level' ], "content" => $rs['content'] ); // Try to update the RS flag to 'p' for pending if ( ! $db->update_msgrcpt_rs($mail_id, $recip_email, 'p') ) { $release_req_messages[ $j ]["status"] = "Error: " . $db->get_err(); } else { $release_req_messages[ $j ]["status"] = "Pending"; } $j++; // Other cases where: // - content type is 'B' or 'V' but the logged in user is admin, therefore allowed to release message // - content type is 'S' or 'H' } else { // add message to be released to $hosts array $release_messages[ $mail_id_recip ] = array( "mail_id" => $mail_id, "time" => $rs['time_num'], "subject" => $rs['subject'], "from_addr" => $rs['from_addr'], "spam_level" => $rs['spam_level'], "content" => $rs['content'], ); $hosts[ $rs['host'] ][ $mail_id_recip ] = array( "secret_id" => $rs['secret_id'], "quar_type" => $rs['quar_type'], "quar_loc" => $rs['quar_loc'], "recip_email" => $rs['email'] ); } } global $conf; // If release request needs to be sent to Admins if ( is_array($release_req_messages) && !empty($release_req_messages) && $conf['app']['notifyAdmin'] ) sendMailToAdmin(translate('Request release'), $release_req_messages); // If release needs to be done if ( is_array($hosts) && !empty($hosts) ) { // For each host create socket, connect and release all messages pertaining to that host foreach ($hosts as $host => $message_info ) { // Create new TCP/IP socket and try to connect to $host using this socket $am = new AmavisdEngine($host); if ( ! $am->connected ) foreach ($message_info as $mail_id_recip => $release_info) { $release_messages[ $mail_id_recip ][ 'error_code' ] = 1; $release_messages[ $mail_id_recip ][ 'status' ] = $am->last_error; $nb_failure++; } else { foreach ($message_info as $mail_id_recip => $release_info) { $socket_binding_result = $am->release_message( $release_messages[ $mail_id_recip ][ 'mail_id' ], $release_info[ 'secret_id' ], $release_info[ 'recip_email' ], $release_info[ 'quar_type' ], $release_info[ 'quar_loc' ] ); if (preg_match('/^setreply=250/', $socket_binding_result)) { if ( $db->update_msgrcpt_rs($release_messages[ $mail_id_recip ][ 'mail_id' ], $release_info[ 'recip_email' ], 'R') ) { $release_messages[ $mail_id_recip ][ 'error_code' ] = "0"; CmnFns::write_log('Message Released [' . $release_messages[ $mail_id_recip ][ 'content' ] . ']: ' . $release_messages[ $mail_id_recip ][ 'mail_id' ], $_SESSION['sessionID']); } else { $release_messages[ $mail_id_recip ][ 'error_code' ] = 2; $release_messages[ $mail_id_recip ][ 'status' ] = "Error: " . $db->get_err(); $nb_failure++; } } else { $release_messages[ $mail_id_recip ][ 'error_code' ] = 3; $release_messages[ $mail_id_recip ][ 'status' ] = $am->last_error; $nb_failure++; } } // Shuting down and closing socket $am->disconnect(); } } } // Commit, then set autocommit back to true $result = $db->db->commit(); $db->check_for_error($result, 'PEAR DB commit()'); $result = $db->db->autoCommit(true); $db->check_for_error($result, 'PEAR DB autoCommit(true)'); // Build array of messages whose release failed $failed_array = array(); $i = 0; if ( $nb_failure > 0 ) { foreach ($mail_id_array as $mail_id_recip) { if ($release_messages[ $mail_id_recip ][ 'error_code' ] != 0) { $failed_array[ $i ] = array( "mail_id" => $release_messages[ $mail_id_recip ][ 'mail_id' ], "from_addr" => $release_messages[ $mail_id_recip ][ 'from_addr' ], "subject" => $release_messages[ $mail_id_recip ][ 'subject' ], "time_num" => $release_messages[ $mail_id_recip ][ 'time' ], "spam_level" => $release_messages[ $mail_id_recip ][ 'spam_level' ], "content" => $release_messages[ $mail_id_recip ][ 'content' ], "status" => $release_messages[ $mail_id_recip ][ 'status' ] ); CmnFns::write_log($release_messages[ $mail_id_recip ][ 'status' ], $_SESSION['sessionID']); $i++; } } } // Return array of messages whose release failed return $failed_array; } /** * Update messages function * @param string $content_type 'B', 'S', ... * @param array $emailaddresses recipient email address(es) * @param array $mail_id_array containing mail_id of messages to be deleted * @param bool $all false (default) or true, if true all messages will be deleted * @result return array of messages whose release failed */ function updateMessages($flag, $content_type, $emailaddresses, $mail_id_array, $all = false) { $result_array = array(); $db = new DBEngine(); // Set autocommit to false to improve speed of $flag set $result = $db->db->autoCommit(false); $db->check_for_error($result, 'PEAR DB autoCommit(false)'); if ( $all ) { $res = $db->get_user_messages($content_type, $emailaddresses, 'msgs.time_num', 'DESC', '', false, 0, 0, true); for ($i = 0; is_array($res) && $i < count($res); $i++) { $rs = $res[$i]; if ( Auth::isMailAdmin() || Auth::isDomainAdmin() || in_array($rs['email'], $emailaddresses) ) { if ( ! $db->update_msgrcpt_rs($rs['mail_id'], $rs['email'], $flag ) ) { $rs = $result[0]; $result_array[ $i ] = array( "mail_id" => $mail_id, "from_addr" => $rs[ 'from_addr' ], "subject" => $rs[ 'subject' ], "time_num" => $rs[ 'time_num' ], "spam_level" => $rs[ 'spam_level' ], "status" => "Error: " . $db->get_err() ); } } else { continue; } } } else { $i = 0; foreach ($mail_id_array as $mail_id_recip) { // Get mail_id and recipient email address //$temp = preg_split('/_/', $mail_id_recip, 2); //$mail_id = $temp[0]; //$recip_email = $temp[1]; $mail_id = substr($mail_id_recip, 0, 12); $recip_email = substr($mail_id_recip, 13); // Check if logged in user is admin or logged in user is trying to delete his own messages if ( Auth::isMailAdmin() || Auth::isDomainAdmin() || in_array($recip_email, $emailaddresses) ) { $result = $db->get_message($recip_email, $mail_id); } else { continue; } if ( ! $db->update_msgrcpt_rs($mail_id, $recip_email, $flag) ) { $rs = $result[0]; $result_array[ $i ] = array( "mail_id" => $mail_id, "from_addr" => $rs[ 'from_addr' ], "subject" => $rs[ 'subject' ], "time_num" => $rs[ 'time_num' ], "spam_level" => $rs[ 'spam_level' ], "status" => "Error: " . $db->get_err() ); $i++; } } } // Commit, then set autocommit back to true $result = $db->db->commit(); $db->check_for_error($result, 'PEAR DB commit()'); $result = $db->db->autoCommit(true); $db->check_for_error($result, 'PEAR DB autoCommit(true)'); // Return array of messages whose release failed return $result_array; } /** * @author Mikko Husari * Update white/blaclist function * @param string $flag 'W', 'B' * @param array $emailaddresses recipient email address(es) * @param array $mail_id_array containing mail_id of messages to be whitelisted * @result return array of messages whose release failed */ function updateWblist($flag, $emailaddresses, $mail_id_array, $action) { $result_array = array(); $db = new DBEngine(); $i = 0; foreach ($mail_id_array as $mail_id_recip) { // Get mail_id and recipient email address $temp = preg_split('/_/', $mail_id_recip, 2); $mail_id = $temp[0]; $recip_email = $temp[1]; // Check if logged in user is admin or logged in user is trying to delete his own messages if ( Auth::isMailAdmin() || in_array($recip_email, $emailaddresses) ) { switch ($action) { case translate('Whitelist'): case translate('Blacklist'): case translate('Whitelist by strict addressing'): case translate('Blacklist by strict addressing'): $rid = $db->mail2userid($recip_email); $sid = $db->mailid2sid($mail_id); $db->wbinsert($flag, $rid, $sid); break; case translate('Whitelist by sender domain'): case translate('Blacklist by sender domain'): $rid = $db->mail2userid($recip_email); $sid = $db->mailid2sid($mail_id, true ); $db->wbinsert($flag, $rid, $sid); break; case translate('Whitelist by recipient domain'): case translate('Blacklist by recipient domain'): $rid = $db->mail2userid($recip_email, true); $sid = $db->mailid2sid($mail_id); $db->wbinsert($flag, $rid, $sid); break; case translate('Whitelist by both domains'): case translate('Blacklist by both domains'): $rid = $db->mail2userid($recip_email, true); $sid = $db->mailid2sid($mail_id, true); $db->wbinsert($flag, $rid, $sid); break; } } else { continue; } } // Return array of messages whose release failed return $result_array; } /** * Function that sends: * - an error report if $action = 'Release', 'Delete' or 'Delete All' * - an request if $action = 'Request release' * to $conf['app']['adminEmail'] * @param string $action 'Release', 'Delete', 'Delete All', 'Request release' * @param $messages_array array containing messages info */ function sendMailToAdmin($myaction, $messages_array) { global $conf; $title = $conf['app']['title']; $adminEmail = $conf['app']['adminEmail']; $sub = "[" . $title . "] Notification from '" . $_SESSION['sessionID'] . "'"; $msg = "Mail notification sent by '" . $_SESSION['sessionID'] . "' <" . $_SESSION['sessionMail'][0] . ">.\r\n\r\n"; switch ( $myaction ) { case translate('Release'): case translate('Release/Request release'): $msg .= translate('A problem occured when trying to release the following messages') . ":\r\n\r\n"; break; case translate('Request release'): $msg .= translate('Please release the following messages') . ":\r\n\r\n"; break; case translate('Delete'): case translate('Delete All'): $msg .= translate('A problem occured when trying to delete the following messages') . ":\r\n\r\n"; break; default: CmnFns::do_error_box(translate('Unknown action type'), ''); } for ($i = 0; is_array($messages_array) && $i < count($messages_array); $i++) { $rs = $messages_array[$i]; $msg .= "Message #" . ($i+1) . ":\r\n"; $msg .= "\tmail_id = " . $rs['mail_id'] . "\r\n"; $msg .= "\t" . translate('From') . " = " . $rs['from_addr'] . "\r\n"; $msg .= "\t" . translate('Subject') . " = " . $rs['subject'] . "\r\n"; $msg .= "\t" . translate('Date') . " = " . CmnFns::formatDateTime($rs['time_num']) . "\r\n"; $msg .= "\t" . translate('Score') . " = " . $rs['spam_level'] . "\r\n"; $msg .= "\t" . translate('Status') . " = " . $rs['status'] . "\r\n"; $msg .= "\t" . translate('Content Type') . " = " . $rs['content'] . "\r\n\r\n"; } // Send email $mailer = new PHPMailer(); if ( is_array($adminEmail) ) { foreach ($adminEmail as $email) { $mailer->AddAddress($email, ''); } } else { $mailer->AddAddress($adminEmail, ''); } $mailer->FromName = $_SESSION['sessionID']; $mailer->From = $_SESSION['sessionMail'][0]; $mailer->Subject = $sub; $mailer->Body = $msg; $mailer->Send(); return true; } ?>