| Current Path : /var/www/cesa.co.za/crons/ |
| Current File : /var/www/cesa.co.za/crons/sendlater.php |
<?php
// No longer used - use ToSendProcess.php instead
exit;
//if ($_GET["override"] != 1) die();
ini_set('max_execution_time', '0'); // 0 = no limit
ini_set('display_errors', 1);
error_reporting(E_ALL);
ob_start();
$maxmsgs = 20;
$loopMax = 10;
if (!isset($_SERVER['DOCUMENT_ROOT']) || strlen($_SERVER['DOCUMENT_ROOT']) <= 0) {
$_SERVER['DOCUMENT_ROOT'] = str_replace('/crons', '', getcwd());
}
// Check if process is running
$lockFile = $_SERVER['DOCUMENT_ROOT'] . '/crons/ToSendProcess.lock';
if (file_exists($lockFile)) {
echo "Process already running. Exiting.\n";
exit;
}
file_put_contents($lockFile, time());
// echo $_SERVER['DOCUMENT_ROOT'];
// exit;
include_once($_SERVER['DOCUMENT_ROOT'] . "/cfg/config.php");
include_once($_SERVER['DOCUMENT_ROOT'] . "/php/includes/maill.php");
include_once($_SERVER['DOCUMENT_ROOT'] . "/php/includes/ErrorLog.php");
/**
* Format and validate a list of email addresses
* Handles comma, semicolon, and space-separated lists
* Returns formatted comma-separated list of valid emails, or false if none valid
*
* @param string $emailList The email list string
* @return string|false Formatted email list or false if no valid emails
*/
function formatEmailList($emailList) {
if (empty($emailList)) {
return false;
}
// Normalize separators: replace semicolons and multiple spaces with commas
$emailList = str_replace(array(';', "\r\n", "\r", "\n", "\t"), ',', $emailList);
// Replace multiple commas with single comma
$emailList = preg_replace('/,+/', ',', $emailList);
// Split by comma
$emails = explode(',', $emailList);
$validEmails = array();
$invalidEmails = array();
foreach ($emails as $email) {
$email = trim($email);
if (empty($email)) {
continue;
}
// Extract email from "Name <email@domain.com>" format if present
if (preg_match('/<(.+?)>/', $email, $matches)) {
$email = trim($matches[1]);
}
// Validate email
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
// Remove duplicates (case-insensitive)
$emailLower = strtolower($email);
if (!isset($validEmails[$emailLower])) {
$validEmails[$emailLower] = $email;
}
} else {
$invalidEmails[] = $email;
}
}
// Log invalid emails if any
if (!empty($invalidEmails)) {
ErrorLog::logError("Invalid email addresses found in list: " . implode(', ', $invalidEmails));
}
// Return formatted list or false if no valid emails
if (empty($validEmails)) {
return false;
}
return implode(', ', array_values($validEmails));
}
$db = mysqli_connect(EW_CONN_HOST, MAILDB_USER, MAILDB_PASS, MAILDB_DB);
$bCanSend = false;
$bSomethingSent = false;
$sql = "SELECT StartSend, EndSend FROM LastSend";
$rsRec = mysqli_query($db, $sql);
// echo 'Selecting last send: ' . $rsRec . "\r\n";
if ($rsR = mysqli_fetch_assoc($rsRec)) {
// echo 'Last send was ' . $rsR["StartSend"] . ' and ' . $rsR["EndSend"] . "\r\n";
// Has 15 seconds passed since the last send?
if ((time() - strtotime($rsR["StartSend"])) >= 15) {
$bCanSend = true;
// Or, was the last start a loooong time ago?
} elseif ((time() - strtotime($rsR["StartSend"])) >= 10) {
$bCanSend = true;
}
}
if ($bCanSend) {
// Get the messages
$sql = "SELECT * "
. "FROM Messages "
. "WHERE FromSchool=0 "
. "AND EXISTS (SELECT * FROM ToSend WHERE ToSend.MessageID=Messages.MessageID AND ToSend.Sent=0) "
. "ORDER BY Messages.Prioritise DESC, Messages.MessageID";
$rsMsg = mysqli_query($db, $sql);
if ($rsM = mysqli_fetch_assoc($rsMsg)) {
} else {
// echo 'Select from messages failed: ' . $sql . ' <br />';
$bCanSend = false;
}
}
if ($bCanSend) {
for ($loopCnt = 1; $loopCnt <= $loopMax; $loopCnt++) {
//Send 20 messages 10 times
// Make sure another instance of this script doesn't start sending!!
$sql = "UPDATE LastSend SET StartSend='" . date("Y-m-d H:i:s") . "', EndSend='2020-01-01'";
mysqli_query($db, $sql);
$iMsgsSent = 0;
$sql = "SELECT ToSend.SendTo, ToSend.Message FROM ToSend WHERE ToSend.MessageID=" . $rsM["MessageID"] . " and ToSend.Sent=0 and ToSend.SendTo LIKE '%@cesa.co.za' "
. "ORDER BY ToSend.SendTo LIMIT 0," . $maxmsgs;
// echo $sql . "\r\n";
$rsRec = mysqli_query($db, $sql);
if (mysqli_num_rows($rsRec) <= 0) {
$sql = "SELECT ToSend.SendTo, ToSend.Message FROM ToSend WHERE ToSend.MessageID=" . $rsM["MessageID"] . " and ToSend.Sent=0 and NOT (ToSend.SendTo LIKE '%@cesa.co.za') "
. "ORDER BY ToSend.SendTo LIMIT 0," . $maxmsgs;
// echo $sql . "\r\n";
$rsRec = mysqli_query($db, $sql);
}
while ($rsR = mysqli_fetch_assoc($rsRec)) {
$sMessage = $rsM["Message"];
if (!empty($rsR["Message"]))
$sMessage = $rsR["Message"];
// Format and validate email list
$formattedEmailList = formatEmailList($rsR["SendTo"]);
if ($formattedEmailList === false) {
echo 'No valid e-mail addresses found in: ' . $rsR["SendTo"] . "\r\n";
ErrorLog::logError("No valid e-mail addresses found in: " . $rsR["SendTo"]);
// Mark as sent with error status (Sent=2)
$sql = "UPDATE ToSend SET Sent=2 WHERE SendTo='" . addslashes($rsR["SendTo"]) . "' AND MessageID=" . $rsM["MessageID"];
mysqli_query($db, $sql);
continue;
}
// Use formatted email list
$sendToEmail = $formattedEmailList;
// If list was reformatted, log it
if ($sendToEmail !== $rsR["SendTo"]) {
echo 'Email list reformatted from "' . $rsR["SendTo"] . '" to "' . $sendToEmail . '"' . "\r\n";
ErrorLog::logInfo("Email list reformatted from \"" . $rsR["SendTo"] . "\" to \"" . $sendToEmail . "\"");
}
ErrorLog::logInfo("Valid e-mail address(es): " . $sendToEmail);
if ($rsM['Headers'] != '') {
// echo 'using built in mail <br />' . "\r\n";
// var_dump($rsM["Headers"]);
// exit;
// mail(stripslashes($rsR["SendTo"]), $rsM["Subject"], $sMessage, $rsM["Headers"]);
//TODO: Send raw message via SMTP server
$messageFile = sys_get_temp_dir() . '/' . $rsM["MessageID"] . '.html';
if (strpos($rsM["MessageFrom"], 'cesa.co.za') !== false) {
$fromAddress = $rsM["MessageFrom"];
} else {
$fromAddress = $smtp_user;
}
$headerValues = explode("\r\n", $rsM["Headers"]);
$contentType = '';
$boundary = '';
foreach ($headerValues as $headerValue) {
echo 'Looking for boundary: ' . $headerValue . ' '
. strpos($headerValue, 'boundary') . "\r\n";
if (strpos($headerValue, 'Content-Type:') === 0) {
$contentType = $headerValue;
} elseif (strpos($headerValue, 'boundary') !== false) {
$boundary = $headerValue;
echo 'Found: ' . $boundary . "\r\n";
}
}
// var_dump($headerValues);
// echo "\r\n\r\n";
$msgPre = "From: " . $smtp_user . "\r\n"
. "Reply-To: " . $fromAddress . "\r\n"
. "To: " . $sendToEmail . "\r\n"
. "Subject: " . $rsM["Subject"] . "\r\n"
. "MIME-Version: 1.0\r\n"
. $contentType . "\r\n" . $boundary . "\r\n\r\n";
// echo $msgPre;
$sMessage = $msgPre . $sMessage;
file_put_contents($messageFile, $sMessage);
// echo 'python3 '
// . $_SERVER['DOCUMENT_ROOT'] . '/python/send-mail.py ' . $messageFile . ' "'
// . $fromAddress . '" "' . $rsR["SendTo"] . '" ' . $smtp_host . ' '
// . $smtp_port . ' "' . $smtp_user . '" "' . $smtp_pass . '"';
$response = shell_exec('python3 '
. $_SERVER['DOCUMENT_ROOT'] . '/python/send-mail.py ' . $messageFile . ' "'
. $fromAddress . '" "' . $sendToEmail . '" ' . $smtp_host . ' '
. $smtp_port . ' "' . $smtp_user . '" "' . $smtp_pass . '"');
if (strpos($response, 'Email sent successfully') !== false) {
echo 'Python send response: ' . $response . "\r\n";
ErrorLog::logInfo("Email sent successfully");
} else {
echo 'Python send response: ' . $response . "\r\n";
ErrorLog::logError("Email sent failed: " . $response);
}
$iMsgsSent++;
$bSomethingSent = true;
} elseif ($rsM['Options'] != '') {
$json_obj = json_decode($rsM['Options'], true);
if (!is_array($json_obj)) {
$json_obj = [];
}
if (!isset($json_obj['from-name'])) {
$json_obj['from-name'] = 'CESA';
}
maill(stripslashes($sendToEmail), $rsM["Subject"], $sMessage, null, $json_obj, true);
}
$iMsgsSent++;
$bSomethingSent = true;
$sql = "UPDATE ToSend SET Sent=1 "
. "WHERE SendTo='" . addslashes($rsR["SendTo"]) . "' "
. "AND MessageID=" . $rsM["MessageID"];
// echo 'Updating ToSend: ' . $sql . "\r\n";
mysqli_query($db, $sql);
echo $sendToEmail . "<br />\r\n";
// echo ".";
flush();
ob_flush();
//wait for a quarter second
// usleep(250);
} //while
mysqli_free_result($rsRec);
$sql = "DELETE ts FROM ToSend ts "
. "INNER JOIN Messages m ON ts.MessageID = m.MessageID "
. "WHERE ts.Sent = 1 AND m.DateSent <= DATE_SUB(NOW(), INTERVAL 21 DAY)";
// echo 'Cleaning out ToSend: ' . $sql . "\r\n";
mysqli_query($db, $sql);
$sql = "SELECT Messages.MessageID, COUNT(ToSend.ToSendID) AS Num FROM Messages LEFT JOIN ToSend USING (MessageID) "
. "WHERE SendComplete=0 GROUP BY Messages.MessageID";
$rsRec = mysqli_query($db, $sql);
while ($rsRow = mysqli_fetch_assoc($rsRec)) {
if ($rsRow["Num"] == 0) {
$sql = "UPDATE Messages SET SendComplete=1, DateComplete='" . date("Y-m-d H:i:s") . "' WHERE MessageID='" . $rsRow["MessageID"] . "'";
mysqli_query($db, $sql);
}
} //while
// Get school mailing list messages
/*
$sql = "SELECT sml_message_archive.subject AS Subject, sml_message_archive.message AS Message, sml_message_archive.id AS MessageID, sml_delivery_queue.email AS SendTo
FROM sml_message_archive, sml_delivery_queue
WHERE sml_message_archive.id=sml_delivery_queue.message_id
AND sml_message_archive.start_send<=UNIX_TIMESTAMP()";
$rsMsg = mysql_query($sql);
echo ".";
flush();
ob_flush();
while (($iMsgsSent <= $maxmsgs) && ($rsM = mysql_fetch_assoc($rsMsg))) {
$bSendFinished = false;
$sql = "DELETE FROM sml_delivery_queue WHERE message_id=".$rsM["MessageID"]." AND email='".$rsM["SendTo"]."'";
mysql_query($sql);
mail(stripslashes($rsM["SendTo"]), $rsM["Subject"], $rsM["Message"], "MIME-Version: 1.0" . "\r\n"."Content-type:text/html;charset=UTF-8" . "\r\n"."From: brenda@cesa.co.za"."\r\n"."Reply-To: brenda@cesa.co.za"."\r\n");
$iMsgsSent++;
$bSomethingSent = true;
$sql = "UPDATE sml_message_archive SET recipients=recipients+1 WHERE id=".$rsM["MessageID"];
mysql_query($sql);
echo $rsM["SendTo"]."<BR>";
echo ".";
flush();
ob_flush();
usleep(100000);
}
*/
//if ($bSomethingSent) {
$sql = "UPDATE LastSend SET EndSend='" . date("Y-m-d H:i:s") . "'";
mysqli_query($db, $sql);
}
//}
} else {
echo "Can't send yet.";
}
flush();
ob_flush();
unlink($lockFile);