"0205" && $timeNow < "0300") exit(); // Set max processing limits $maxTime = 10 * 60 - 20; $sleepTime = 10; // Set start time $timeNow = time(); $endTime = $timeNow + $maxTime; $lockFile = "{$BASEDIR}/email.cron.lock"; if (file_exists($lockFile)) { // cronjob is already running for this domain // check the age of the lockfile... if it's more than 10 minutes old, // the other cronjob probably crashed and we can ignore it $t = filemtime($lockFile); if (time() - $t > 60*10) touch($lockFile); else { error_log("cronEmailSend.php ($CurrentDomain): skipped, lock held since " . date("Y-m-d H:i:s",$t)); exit(); } } else { touch($lockFile); } // Ensure the lock is always released, even on a fatal error, uncaught // exception, or execution timeout - otherwise one bad run permanently // blocks the queue until the lock is removed by hand. register_shutdown_function(function() use ($lockFile) { @unlink($lockFile); }); $ValidAccess = 2010; include "$BASEDIR/include/globals.php"; // startLog("cronEmailSend"); // ---------- WILL BE A SERVER-WIDE SCRIPT ---------- if (!is_file("$BASEDIR/include/sendmail2.php")) { echo("ERROR: $BASEDIR/include/sendmail2.php not found\n"); writeLog("ERROR: $BASEDIR/include/sendmail2.php not found"); @unlink($lockFile); exit(); } include "$BASEDIR/include/sendmail2.php"; // Open the log file $today = date("Y-m-d",time()); $fp = fopen("$BASEDIR/logs/cron/$today.log","a"); fprintf($fp,"Start: %s\n",date("Y-m-d H:i:s",time())); $logText = ""; $numSent = 0; // Recover any rows left stuck in 'Processing' by a prior run that crashed // or was killed before it could update their status (e.g. today's outage // where the lock file was never released). Only touch rows old enough // that they can't belong to a run that's still legitimately in progress. $staleProcessingTime = time() - 60*10; $query = "UPDATE email_queue SET status = 'Queued' " . "WHERE status = 'Processing' AND processing_start_time < $staleProcessingTime"; writeLog($query); db_query($query); writeLog("timeNow: $timeNow"); writeLog("endTime: $endTime"); // Loop until end processing time while ($timeNow < ($endTime - $sleepTime * 5)) { writeLog("endTime: $endTime"); // Exit when MySQL is being backed up $currentTime = date("Hi",time()); if ($currentTime > "0210" && $currentTime < "0230") exit(); // Get set of queued messages db_query("START TRANSACTION"); $query = "SELECT * FROM email_queue " . "WHERE status = 'Queued' " . "AND delay < 15 " . "ORDER BY delay,posted_time,record_num LIMIT 0,50"; writeLog($query); $results = db_query($query); // Get the messages $Messages = array(); $RecordNums = array(); if ($results && db_num_rows($results)) { $processing_start_time = time(); while ($row = db_fetch_assoc($results)) { $Messages[] = $row; $RecordNums[] = $row['record_num']; } $currentRecords = implode(",", $RecordNums); $query = "UPDATE email_queue " . "SET status = 'Processing', " . "processing_start_time = $processing_start_time " . "WHERE record_num IN ($currentRecords)"; writeLog($query); db_query($query); } db_query("COMMIT"); writeLog("Count Messages: ".count($Messages)); if (count($Messages) > 0) { $errorNums = array(); // Process each message for ($i = 0; $i < count($Messages); $i++) { $row = $Messages[$i]; extract($row); // Set status and processing start time // $processing_start_time = time(); // db_query("UPDATE email_queue SET status = 'Processing', processing_start_time = $processing_start_time WHERE record_num = $record_num"); // Convert attachments to an array if (strlen($attachments)) { $files = explode("\n",$attachments); $attachments = $files; } else { $attachments = array(); } $email_subject = htmlspecialchars_decode($email_subject,ENT_QUOTES); $email_subject = preg_replace("#&#","&",$email_subject); $email_message = htmlspecialchars_decode($email_message,ENT_QUOTES); $email_message = preg_replace("#&#","&",$email_message); writeLog("email_subject: $email_subject"); // Send email try { $sendOk = SendEmail($email_to, $email_from, $email_subject, $email_message, $email_from_name, $email_to_name, $attachments, $template_file); } catch (Exception $e) { $sendOk = false; error_log("cronEmailSend.php ($CurrentDomain): SendEmail exception for record $record_num: " . $e->getMessage()); } if ($sendOk) { $status = 'Sent'; $numSent++; } else { $status = 'Error'; $errorNums[] = $record_num; } writeLog("status: $status"); // Update status $priority = $delay; // Print status message $logText .= sprintf("%s %5s to %s from %s (%s) - %s\n",$processing_end_date_time, $status, $email_to, $email_from, $template_file, $email_subject." ($priority)"); $timeNow = time(); if ($timeNow > $endTime) break; } $processing_end_time = time(); $processing_end_date_time = date("Y-m-d H:i:s",$processing_end_time); $delay = $processing_end_time - $posted_time; // Only mark the records that actually sent successfully as 'Sent' $sentNums = array_diff($RecordNums, $errorNums); writeLog("Count sentNums: ".count($sentNums)); if (count($sentNums)) { $sentRecords = implode(",", $sentNums); $query = "UPDATE email_queue SET status = 'Sent', " . "processing_end_time = $processing_end_time, " . "processing_end_date_time = '$processing_end_date_time', " . "delay = $delay " . "WHERE record_num IN ($sentRecords)"; writeLog($query); db_query($query); } if (count($errorNums)) { $errorRecords = implode(",", $errorNums); $query = "UPDATE email_queue SET status = 'Error', " . "processing_end_time = $processing_end_time, " . "processing_end_date_time = '$processing_end_date_time' " . "WHERE record_num IN ($errorRecords)"; writeLog($query); db_query($query); } } sleep($sleepTime); $timeNow = time(); fprintf($fp, $logText); $logText = ''; // fprintf($fp,"-\n"); } @unlink($lockFile); if ($numSent > 0) { // Check for more queued messages $query = "SELECT count(*) FROM email_queue " . "WHERE status IN ('Queued','Processing')"; $count = db_getVal($query); fprintf($fp,"\n"); fprintf($fp,"Emails Sent: $numSent\n"); fprintf($fp,"Queued Messsages: $count\n"); } fprintf($fp,"End: %s\n\n-------------------------------------------\n",date("Y-m-d H:i:s",time())); ?>