<?php
 class vB_Mail_Queue { use vB_Trait_NoSerialize; static ?vB_Mail_Queue $instance; private array $mailsql = []; private bool $bulk = false; private int $mailsize = 0; public static function instance() { if (!isset(self::$instance)) { self::$instance = new vB_Mail_Queue(); } return self::$instance; } private function __construct() { $useCron = vB::getDatastore()->getOption('mailqueue'); if (!$useCron) { vB_Shutdown::instance()->add(self::execQueue(...)); } } public function enqueue(array|string $to, string $subject, string $message, bool $isHtml, array $headers, array|string $replyto) : void { $data = [ 'to' => $to, 'subject' => $subject, 'message' => $message, 'replyto' => $replyto, 'headers' => $headers, 'ishtml' => $isHtml, ]; $this->mailsql[] = $data; if ($this->bulk) { $this->mailsize += $this->arraySize($data); if ($this->mailsize > 524288) { $this->saveItems(); } } else { $this->saveItems(); } } private function arraySize(array $a) : int { $size = 0; foreach ($a as $v) { $size += is_array($v) ? $this->arraySize($v) : strlen($v); } return $size; } public function setBulk($bulk) { if (!$bulk AND $this->mailsql) { $this->saveItems(); } $this->bulk = $bulk; } private function saveItems() : void { $insertdata = []; foreach ($this->mailsql AS $data) { $insertdata[] = [ vB::getRequest()->getTimeNow(), serialize($data), ]; } vB::getDbAssertor()->insertMultiple('mailqueue', ['dateline', 'data'], $insertdata); $this->mailsql = []; $this->mailsize = 0; } public function execQueue() : array { $db = vB::getDbAssertor(); $vboptions = vB::getDatastore()->getValue('options'); if ($vboptions['usemailqueue'] == 2) { $db->assertQuery('mailqueue_locktable'); } $emailarray = $db->getRows('mailqueue', [vB_dB_Query::PARAM_LIMIT => intval($vboptions['emailsendnum'])], false, 'mailqueueid'); if (count($emailarray)) { $db->delete('mailqueue', ['mailqueueid' => array_keys($emailarray)]); } if ($vboptions['usemailqueue'] == 2) { $db->assertQuery('unlock_tables'); } $errors = []; if (count($emailarray)) { $transport = vB_Mail_Transport::createDefault(); $transport->startBatch(); foreach ($emailarray AS $row) { try { $data = vb_unserialize($row['data']); $transport->setDataUtf8Encoded($data['isutf8'] ?? false); $status = $transport->send($data['to'], $data['subject'], $data['message'], $data['ishtml'], $data['headers'], $data['replyto']); if (!$status) { $errors[] = 'FAILED: ' . (is_array($data['to']) ? $data['to'][0] : $data['to']) . ' ' . $data['subject']; } } catch (Exception $e) { $errors[] = 'FAILED: ' . (is_array($data['to']) ? $data['to'][0] : $data['to']) . ' ' . $data['subject'] . ': ' . $e->getMessage(); } } $transport->endBatch(); } return $errors; } } 