diff --git a/src/Controllers/Admin/TicketController.php b/src/Controllers/Admin/TicketController.php index 940a33cda..e03c5672d 100755 --- a/src/Controllers/Admin/TicketController.php +++ b/src/Controllers/Admin/TicketController.php @@ -97,7 +97,9 @@ final class TicketController extends BaseController Notification::notifyUser( $user, $_ENV['appName'] . ' - 工单被回复', - '你好,有人回复了工单

回复内容:'.$comment + '你好,有人回复了工单

回复内容:'.$comment, + 'one', + 'tk_ry' ); $ticket->content = json_encode(array_merge($content_old, $content_new)); @@ -145,7 +147,9 @@ final class TicketController extends BaseController Notification::notifyUser( $user, $_ENV['appName'] . ' - 工单被回复', - '你好,AI 回复了工单,请你查看。' + '你好,有人回复了工单

回复内容:'.$comment, + 'one', + 'tk_ry' ); $ticket->content = json_encode(array_merge($content_old, $content_new)); diff --git a/src/Controllers/AuthController.php b/src/Controllers/AuthController.php index a6f0c4742..c895fe4a3 100755 --- a/src/Controllers/AuthController.php +++ b/src/Controllers/AuthController.php @@ -13,7 +13,7 @@ use App\Services\Auth; use App\Services\Cache; use App\Services\Captcha; use App\Services\Filter; -use App\Services\MailMust; +use App\Services\MailHub; use App\Services\MFA; use App\Services\RateLimit; use App\Services\Reward; @@ -206,15 +206,10 @@ final class AuthController extends BaseController $redis->setex('email_verify:' . $email_code, Config::obtain('email_verify_code_ttl'), $email); try { - MailMust::sendVcode( - $email, - $_ENV['appName'] . ' - 验证邮件', - 'verify_code.tpl', - [ - 'code' => $email_code, - 'expire' => date('Y-m-d H:i:s', time() + Config::obtain('email_verify_code_ttl')), - ] - ); + MailHub::vcode($_ENV['appName'].' - 验证邮件', [ + 'code' => $email_code, + 'expire' => date('Y-m-d H:i:s', time() + Config::obtain('email_verify_code_ttl')), + ])->to($email); } catch (Exception|ClientExceptionInterface $e) { return ResponseHelper::error($response, '邮件发送失败,请联系网站管理员。'); } diff --git a/src/Models/EmailQueue.php b/src/Models/EmailQueue.php index 53b7b4e4a..737d2ecc6 100755 --- a/src/Models/EmailQueue.php +++ b/src/Models/EmailQueue.php @@ -23,23 +23,25 @@ final class EmailQueue extends Model protected $connection = 'default'; protected $table = 'email_queue'; - public function add($to, $subject, $template, $array): void + public function add($to, $subject, $template, $array, $scene): void { $this->to_email = $to; $this->subject = $subject; $this->template = $template; $this->time = time(); $this->array = json_encode($array); + $this->scene = $scene; $this->save(); } - public function add_bulk($to, $subject, $template, $array): void + public function add_bulk($to, $subject, $template, $array, $scene): void { $this->to_email = $to; $this->subject = $subject; $this->template = $template; $this->time = time(); $this->array = json_encode($array); + $this->scene = $scene; $this->type = "bulk"; $this->save(); } diff --git a/src/Services/Cron.php b/src/Services/Cron.php index c1f4e7bf6..7136a302d 100755 --- a/src/Services/Cron.php +++ b/src/Services/Cron.php @@ -63,10 +63,14 @@ final class Cron // maillog报表(监控title) public static function mailLogReport() { + //// *start 标题数量统计 + $sYesterday = date("Y-m-d", strtotime("-1 day")); + $cMailLogCount = ModelMailLog::select('title', DB::raw('count(*) as total')) - ->groupBy('title') - ->orderBy('total', 'desc') - ->get(); + ->whereDate('date', $sYesterday) + ->groupBy('title') + ->orderBy('total', 'desc') + ->get(); $sMsg = "\n====== ".$_ENV["site_code"]."发送邮件标题统计 ======"; foreach ($cMailLogCount as $oMailLogCount) { @@ -75,8 +79,36 @@ final class Cron TeleSlave::notify()->enableDetail(false)->send($sMsg); - echo "\nmailLogReport - ok"; + //// *end 标题数量统计 + //// *start 报错统计 + $iMailErrorCount = ModelMailLog::whereDate('date', $sYesterday) + ->where('error', '!=', '') + ->count(); + + $sMsg = "\n====== ".$_ENV["site_code"]."发送邮件error统计 ======"; + + if (!$iMailErrorCount) { + $sMsg .= "\n今日无报错log!"; + } else { + $sMsg .= "\n今日报错log有{$iMailErrorCount}个"; + + $cMailError = ModelMailLog::whereDate('date', $sYesterday) + ->where('error', '!=', '') + ->orderBy('date', 'desc') + ->limit(5) + ->get(); + + foreach ($cMailError as $oMailError) { + $sMsg .= "\n------ to:{$oMailError->to}、title:{$oMailError->title} ------"; + $sMsg .= "\n".$oMailError; + } + } + + TeleSlave::warn()->enableDetail(false)->send($sMsg); + //// *end 报错统计 + + echo "\nmailLogReport - ok"; } // 必达邮件报表 - 必须在重置之前调用 diff --git a/src/Services/Mail/Resend.php b/src/Services/Mail/Resend.php index 9e2d6fdd0..0abc1b891 100755 --- a/src/Services/Mail/Resend.php +++ b/src/Services/Mail/Resend.php @@ -6,9 +6,6 @@ namespace App\Services\Mail; use App\Models\Config; use Exception; -//use PHPMailer\PHPMailer\PHPMailer; -//use App\Models\MailLog as ModelMailLog; -//use App\Services\Mail\Resend; use App\Models\MailMust as ModelMailMust; use Resend as ResendSdk; @@ -39,41 +36,6 @@ final class Resend extends Base throw new Exception("Resend 服务器未返回有效 ID"); } - $this->oModelMailMust->_incr(); - } - public function getClientCode() - { - return 'resend'; - } - -// public function send($to, $subject, $body): void -// { -// try { -// -// $oResult = $this->oMailSdk->emails->send([ -// 'from' => $this->oModelMailMust->auther, -// 'to' => [$to], -// 'subject' => $subject, -// 'html' => $body, -// ]); -// -// $sResultId = is_array($oResult) ? ($oResult['id'] ?? null) : ($oResult->id ?? null); -// -// if (!$sResultId) { -// throw new Exception("Resend 服务器未返回有效 ID"); -// } -// -// $this->oModelMailMust->_incr(); -// -// } catch (\Exception $e) { -// -// $s = "有邮件发送失败(logid:{$oMailLog->id}): " . $e->getMessage(); -// -// TeleSlave::warn()->send($s); -// -// } -// -// } } diff --git a/src/Services/MailHub.php b/src/Services/MailHub.php new file mode 100755 index 000000000..0fe76114d --- /dev/null +++ b/src/Services/MailHub.php @@ -0,0 +1,194 @@ +to("xxx@gmail.com"); + MailHub::start()->setScene("vcode")->setTitle($sTitle)->setView("verify_code", $aArr)->setTo("xxx@gmail.com")->send(); + */ +final class MailHub +{ + private $sTemplate = "one"; + private $aTemplateArr = []; + private $sScene = ''; + private $sTo = ''; + private $oClient; + private $sView = ''; + private $sClientCode = ''; + private $sDriver = ''; + private $sTitle = ''; + + public static function start() + { + $oInstance = new self(); + + return $oInstance; + } + + public static function vcode($sTitle, $aArr) + { + $oInstance = self::start(); + $oInstance->setScene("vcode"); + $oInstance->setTitle($sTitle); + $oInstance->setView("verify_code", $aArr); + return $oInstance; + } + + public static function admin($sTitle, $aArr) + { + $oInstance = self::start(); + $oInstance->setScene("admin"); + $oInstance->setTitle($sTitle); + $oInstance->setView("one", $aArr); + return $oInstance; + } + + public function setTitle($sTitle) + { + $this->sTitle = $sTitle; + + return $this; + } + + public function setView($sTemplate, $aArr) + { + if (!str_ends_with($sTemplate, '.tpl')) { + $sTemplate .= '.tpl'; + } + + $this->sTemplate = $sTemplate; + $this->aTemplateArr = $aArr; + + return $this; + } + + public function setScene($sScene) + { + $this->sScene = $sScene; + + return $this; + } + + public function setTo($sTo) + { + $this->sTo = $sTo; + + return $this; + } + + private function buildClient() + { + $this->sDriver = Config::_hit('email_driver:'.$this->sScene); + + if ($this->sDriver == "must") { + $this->sClientCode = ModelMailMust::where("status", 1)->orderBy("sort")->first()?->client; + } + + if (!$this->sClientCode) { + $this->sClientCode = Config::_hit('email_driver'); + } + + return match ($this->sClientCode) { + 'alibabacloud' => new AlibabaCloud(), + 'mailchimp' => new Mailchimp(), + 'mailgun' => new Mailgun(), + 'postal' => new Postal(), + 'sendgrid' => new SendGrid(), + 'ses' => new Ses(), + 'smtp' => new Smtp(), + 'resend' => new Resend(), + default => new NullMail(), + }; + } + + public function buildView() + { + $smarty = new Smarty(); + $smarty->setTemplateDir(BASE_PATH . '/resources/email/'); + $smarty->setCompileDir(BASE_PATH . '/storage/framework/smarty/compile/'); + $smarty->setCacheDir(BASE_PATH . '/storage/framework/smarty/cache/'); + $smarty->assign('config', View::getConfig()); + + foreach ($this->aTemplateArr as $key => $value) { + $smarty->assign($key, $value); + } + + return $smarty->fetch($this->sTemplate); + } + + private function build() + { + $this->oClient = $this->buildClient(); + $this->sView = $this->buildView(); + } + + public function send() + { + $this->build(); + + $sError = ""; + + try { + $this->oClient->send($this->sTo, $this->sTitle, $this->sView); + $this->save(); + } catch (\Throwable $e) { + $sError = $e->getMessage(); + throw $e; + } finally { + $this->log($sError); + } + + } + + private function save() + { + if ($this->sDriver == "must") { + $oModelMailMust = ModelMailMust::where('client', $this->sClientCode)->first(); + + if (!$oModelMailMust) { + return; + } + + $oModelMailMust->_incr(); + } + } + + private function log($sError) + { + $oMailLog = new ModelMailLog(); + $oMailLog->to = $this->sTo; + $oMailLog->title = $this->sTitle; + $oMailLog->scene = $this->sScene; + $oMailLog->client = $this->sClientCode; + $oMailLog->error = $sError; + $oMailLog->date = date("Y-m-d H:i:s"); + $oMailLog->save(); + } + + public function to($sTo) + { + $this->sTo = $sTo; + $this->send(); + } + +} diff --git a/src/Services/MailMust.php b/src/Services/MailMust_reng.php similarity index 98% rename from src/Services/MailMust.php rename to src/Services/MailMust_reng.php index daea9140f..863709e4f 100755 --- a/src/Services/MailMust.php +++ b/src/Services/MailMust_reng.php @@ -27,6 +27,7 @@ final class MailMust return match ($oMailMust->client) { 'resend' => new Resend(), + 'smtp' => new Smtp(), default => new NullMail(), }; diff --git a/src/Services/Notification.php b/src/Services/Notification.php index 911905fa5..e3ba370f1 100755 --- a/src/Services/Notification.php +++ b/src/Services/Notification.php @@ -9,6 +9,7 @@ use App\Models\User; use GuzzleHttp\Exception\GuzzleException; use Psr\Http\Client\ClientExceptionInterface; use Telegram\Bot\Exceptions\TelegramSDKException; +use App\Services\MailHub; final class Notification { @@ -17,43 +18,79 @@ final class Notification * @throws TelegramSDKException * @throws ClientExceptionInterface */ - public static function notifyAdmin($title = '', $msg = '', $template = 'warn.tpl'): void +// public static function notifyAdmin($title = '', $msg = '', $template = 'warn.tpl'): void +// { +// $admins = (new User())->where('is_admin', 1)->get(); +// +// foreach ($admins as $admin) { +// if ($admin->contact_method === 1 || $admin->im_type === 0) { +// Mail::send( +// $admin->email, +// $title, +// $template, +// [ +// 'user' => $admin, +// 'title' => $title, +// 'text' => $msg, +// ] +// ); +// } else { +// IM::send($admin->im_value, $msg, $admin->im_type); +// } +// } +// } + + public static function notifyAdmin($title = '', $msg = '', $template = 'warn.tpl', $scene = ''): void { $admins = (new User())->where('is_admin', 1)->get(); foreach ($admins as $admin) { if ($admin->contact_method === 1 || $admin->im_type === 0) { - Mail::send( - $admin->email, - $title, - $template, - [ - 'user' => $admin, - 'title' => $title, - 'text' => $msg, - ] - ); + + MailHub::admin($title, [ + 'user' => $admin, + 'title' => $title, + 'text' => $msg, + ])->to($admin->email); + } else { IM::send($admin->im_value, $msg, $admin->im_type); } } } - + /** - * @throws GuzzleException + * @throws GuzzleException$scene * @throws TelegramSDKException * @throws ClientExceptionInterface */ - public static function notifyUser($user, $title = '', $msg = '', $template = 'warn.tpl'): void +// public static function notifyUser($user, $title = '', $msg = '', $template = 'warn.tpl'): void +// { +// if ($user->contact_method === 1 || $user->im_type === 0) { +// $array = [ +// 'user' => $user, +// 'title' => $title, +// 'text' => $msg, +// ]; +// +// (new EmailQueue())->add($user->email, $title, $template, $array); +// } else { +// IM::send($user->im_value, $msg, $user->im_type); +// } +// } + + public static function notifyUser($user, $title = '', $msg = '', $template = 'warn.tpl', $scene = ''): void { if ($user->contact_method === 1 || $user->im_type === 0) { + $array = [ 'user' => $user, 'title' => $title, 'text' => $msg, ]; + + (new EmailQueue())->add($user->email, $title, $template, $array, $scene); - (new EmailQueue())->add($user->email, $title, $template, $array); } else { IM::send($user->im_value, $msg, $user->im_type); } @@ -63,19 +100,40 @@ final class Notification * @throws GuzzleException * @throws TelegramSDKException */ - public static function notifyAllUser($title = '', $msg = '', $template = 'warn.tpl'): void +// public static function notifyAllUser($title = '', $msg = '', $template = 'warn.tpl', $scene = ''): void +// { +// $users = User::all(); +// +// foreach ($users as $user) { +// if ($user->contact_method === 1 || $user->im_type === 0) { +// $array = [ +// 'user' => $user, +// 'title' => $title, +// 'text' => $msg, +// ]; +// +// (new EmailQueue())->add($user->email, $title, $template, $array); +// } else { +// IM::send($user->im_value, $msg, $user->im_type); +// } +// } +// } + + public static function notifyAllUser($title = '', $msg = '', $template = 'warn.tpl', $scene = ''): void { $users = User::all(); foreach ($users as $user) { if ($user->contact_method === 1 || $user->im_type === 0) { + $array = [ 'user' => $user, 'title' => $title, 'text' => $msg, ]; + + (new EmailQueue())->add($user->email, $title, $template, $array, $scene); - (new EmailQueue())->add($user->email, $title, $template, $array); } else { IM::send($user->im_value, $msg, $user->im_type); } diff --git a/src/Services/NotificationV2.php b/src/Services/NotificationV2.php new file mode 100755 index 000000000..80f35e555 --- /dev/null +++ b/src/Services/NotificationV2.php @@ -0,0 +1,195 @@ +where('is_admin', 1)->get(); + + foreach ($admins as $admin) { + if ($admin->contact_method === 1 || $admin->im_type === 0) { + Mail::send( + $admin->email, + $title, + $template, + [ + 'user' => $admin, + 'title' => $title, + 'text' => $msg, + ] + ); + } else { + IM::send($admin->im_value, $msg, $admin->im_type); + } + } + } + + public static function user() + { + if ($user->contact_method === 1 || $user->im_type === 0) { + $array = [ + 'user' => $user, + 'title' => $title, + 'text' => $msg, + ]; + + (new EmailQueue())->add($user->email, $title, $template, $array); + } else { + IM::send($user->im_value, $msg, $user->im_type); + } + } + + + + + + + + + + /** + * @throws GuzzleException + * @throws TelegramSDKException + * @throws ClientExceptionInterface + */ +// public static function notifyAdmin($title = '', $msg = '', $template = 'warn.tpl'): void +// { +// $admins = (new User())->where('is_admin', 1)->get(); +// +// foreach ($admins as $admin) { +// if ($admin->contact_method === 1 || $admin->im_type === 0) { +// Mail::send( +// $admin->email, +// $title, +// $template, +// [ +// 'user' => $admin, +// 'title' => $title, +// 'text' => $msg, +// ] +// ); +// } else { +// IM::send($admin->im_value, $msg, $admin->im_type); +// } +// } +// } + + public static function notifyAdmin($title = '', $msg = '', $template = 'warn.tpl', $scene = ''): void + { + $admins = (new User())->where('is_admin', 1)->get(); + + foreach ($admins as $admin) { + if ($admin->contact_method === 1 || $admin->im_type === 0) { + + MailHub::admin($title, [ + 'user' => $admin, + 'title' => $title, + 'text' => $msg, + ])->to($admin->email); + + } else { + IM::send($admin->im_value, $msg, $admin->im_type); + } + } + } + + /** + * @throws GuzzleException$scene + * @throws TelegramSDKException + * @throws ClientExceptionInterface + */ +// public static function notifyUser($user, $title = '', $msg = '', $template = 'warn.tpl'): void +// { +// if ($user->contact_method === 1 || $user->im_type === 0) { +// $array = [ +// 'user' => $user, +// 'title' => $title, +// 'text' => $msg, +// ]; +// +// (new EmailQueue())->add($user->email, $title, $template, $array); +// } else { +// IM::send($user->im_value, $msg, $user->im_type); +// } +// } + + public static function notifyUser($user, $title = '', $msg = '', $template = 'warn.tpl', $scene = ''): void + { + if ($user->contact_method === 1 || $user->im_type === 0) { + + $array = [ + 'user' => $user, + 'title' => $title, + 'text' => $msg, + ]; + + (new EmailQueue())->add($user->email, $title, $template, $array, $scene); + + } else { + IM::send($user->im_value, $msg, $user->im_type); + } + } + + /** + * @throws GuzzleException + * @throws TelegramSDKException + */ +// public static function notifyAllUser($title = '', $msg = '', $template = 'warn.tpl', $scene = ''): void +// { +// $users = User::all(); +// +// foreach ($users as $user) { +// if ($user->contact_method === 1 || $user->im_type === 0) { +// $array = [ +// 'user' => $user, +// 'title' => $title, +// 'text' => $msg, +// ]; +// +// (new EmailQueue())->add($user->email, $title, $template, $array); +// } else { +// IM::send($user->im_value, $msg, $user->im_type); +// } +// } +// } + + public static function notifyAllUser($title = '', $msg = '', $template = 'warn.tpl', $scene = ''): void + { + $users = User::all(); + + foreach ($users as $user) { + if ($user->contact_method === 1 || $user->im_type === 0) { + + $array = [ + 'user' => $user, + 'title' => $title, + 'text' => $msg, + ]; + + (new EmailQueue())->add($user->email, $title, $template, $array, $scene); + + } else { + IM::send($user->im_value, $msg, $user->im_type); + } + } + } +}