go-mailzu/lib/Quarantine.lib.php
Mikko Husari 7f07671b68 Wbl patch
2008-12-10 20:19:59 +02:00

422 lines
14 KiB
PHP

<?php
/**
* Quarantine lib
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @author Brian Wong <bwsource@users.sourceforge.net>
* @author Nicolas Peyrussie <peyrouz@users.sourceforge.net>
* @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('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, 2);
$mail_id = $temp[0];
$recip_email = $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];
// 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;
}
/**
* 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 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;
}
?>