no message

This commit is contained in:
hellcat 2026-05-08 16:08:40 +08:00
parent f648674399
commit 01f5202b20
9 changed files with 516 additions and 73 deletions

View File

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

View File

@ -13,7 +13,7 @@ use App\Services\Auth;
use App\Services\Cache; use App\Services\Cache;
use App\Services\Captcha; use App\Services\Captcha;
use App\Services\Filter; use App\Services\Filter;
use App\Services\MailMust; use App\Services\MailHub;
use App\Services\MFA; use App\Services\MFA;
use App\Services\RateLimit; use App\Services\RateLimit;
use App\Services\Reward; 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); $redis->setex('email_verify:' . $email_code, Config::obtain('email_verify_code_ttl'), $email);
try { try {
MailMust::sendVcode( MailHub::vcode($_ENV['appName'].' - 验证邮件', [
$email, 'code' => $email_code,
$_ENV['appName'] . ' - 验证邮件', 'expire' => date('Y-m-d H:i:s', time() + Config::obtain('email_verify_code_ttl')),
'verify_code.tpl', ])->to($email);
[
'code' => $email_code,
'expire' => date('Y-m-d H:i:s', time() + Config::obtain('email_verify_code_ttl')),
]
);
} catch (Exception|ClientExceptionInterface $e) { } catch (Exception|ClientExceptionInterface $e) {
return ResponseHelper::error($response, '邮件发送失败,请联系网站管理员。'); return ResponseHelper::error($response, '邮件发送失败,请联系网站管理员。');
} }

View File

@ -23,23 +23,25 @@ final class EmailQueue extends Model
protected $connection = 'default'; protected $connection = 'default';
protected $table = 'email_queue'; 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->to_email = $to;
$this->subject = $subject; $this->subject = $subject;
$this->template = $template; $this->template = $template;
$this->time = time(); $this->time = time();
$this->array = json_encode($array); $this->array = json_encode($array);
$this->scene = $scene;
$this->save(); $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->to_email = $to;
$this->subject = $subject; $this->subject = $subject;
$this->template = $template; $this->template = $template;
$this->time = time(); $this->time = time();
$this->array = json_encode($array); $this->array = json_encode($array);
$this->scene = $scene;
$this->type = "bulk"; $this->type = "bulk";
$this->save(); $this->save();
} }

View File

@ -63,10 +63,14 @@ final class Cron
// maillog报表监控title // maillog报表监控title
public static function mailLogReport() public static function mailLogReport()
{ {
//// *start 标题数量统计
$sYesterday = date("Y-m-d", strtotime("-1 day"));
$cMailLogCount = ModelMailLog::select('title', DB::raw('count(*) as total')) $cMailLogCount = ModelMailLog::select('title', DB::raw('count(*) as total'))
->groupBy('title') ->whereDate('date', $sYesterday)
->orderBy('total', 'desc') ->groupBy('title')
->get(); ->orderBy('total', 'desc')
->get();
$sMsg = "\n====== ".$_ENV["site_code"]."发送邮件标题统计 ======"; $sMsg = "\n====== ".$_ENV["site_code"]."发送邮件标题统计 ======";
foreach ($cMailLogCount as $oMailLogCount) { foreach ($cMailLogCount as $oMailLogCount) {
@ -75,8 +79,36 @@ final class Cron
TeleSlave::notify()->enableDetail(false)->send($sMsg); 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";
} }
// 必达邮件报表 - 必须在重置之前调用 // 必达邮件报表 - 必须在重置之前调用

View File

@ -6,9 +6,6 @@ namespace App\Services\Mail;
use App\Models\Config; use App\Models\Config;
use Exception; use Exception;
//use PHPMailer\PHPMailer\PHPMailer;
//use App\Models\MailLog as ModelMailLog;
//use App\Services\Mail\Resend;
use App\Models\MailMust as ModelMailMust; use App\Models\MailMust as ModelMailMust;
use Resend as ResendSdk; use Resend as ResendSdk;
@ -39,41 +36,6 @@ final class Resend extends Base
throw new Exception("Resend 服务器未返回有效 ID"); 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);
//
// }
//
// }
} }

194
src/Services/MailHub.php Executable file
View File

@ -0,0 +1,194 @@
<?php
declare(strict_types=1);
namespace App\Services;
use App\Models\Config;
use App\Services\Mail\AlibabaCloud;
use App\Services\Mail\Mailchimp;
use App\Services\Mail\Mailgun;
use App\Services\Mail\NullMail;
use App\Services\Mail\Postal;
use App\Services\Mail\SendGrid;
use App\Services\Mail\Ses;
use App\Services\Mail\Smtp;
use App\Services\Mail\Resend;
use App\Services\Mail\Smtp_bulk;
use App\Models\MailLog;
use Exception;
use Psr\Http\Client\ClientExceptionInterface;
use Smarty\Smarty;
use App\Models\MailMust as ModelMailMust;
use App\Models\MailLog as ModelMailLog;
/*
MailHub::vcode($sTitle, $sArr)->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();
}
}

View File

@ -27,6 +27,7 @@ final class MailMust
return match ($oMailMust->client) { return match ($oMailMust->client) {
'resend' => new Resend(), 'resend' => new Resend(),
'smtp' => new Smtp(),
default => new NullMail(), default => new NullMail(),
}; };

View File

@ -9,6 +9,7 @@ use App\Models\User;
use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Client\ClientExceptionInterface; use Psr\Http\Client\ClientExceptionInterface;
use Telegram\Bot\Exceptions\TelegramSDKException; use Telegram\Bot\Exceptions\TelegramSDKException;
use App\Services\MailHub;
final class Notification final class Notification
{ {
@ -17,43 +18,79 @@ final class Notification
* @throws TelegramSDKException * @throws TelegramSDKException
* @throws ClientExceptionInterface * @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(); $admins = (new User())->where('is_admin', 1)->get();
foreach ($admins as $admin) { foreach ($admins as $admin) {
if ($admin->contact_method === 1 || $admin->im_type === 0) { if ($admin->contact_method === 1 || $admin->im_type === 0) {
Mail::send(
$admin->email, MailHub::admin($title, [
$title, 'user' => $admin,
$template, 'title' => $title,
[ 'text' => $msg,
'user' => $admin, ])->to($admin->email);
'title' => $title,
'text' => $msg,
]
);
} else { } else {
IM::send($admin->im_value, $msg, $admin->im_type); IM::send($admin->im_value, $msg, $admin->im_type);
} }
} }
} }
/** /**
* @throws GuzzleException * @throws GuzzleException$scene
* @throws TelegramSDKException * @throws TelegramSDKException
* @throws ClientExceptionInterface * @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) { if ($user->contact_method === 1 || $user->im_type === 0) {
$array = [ $array = [
'user' => $user, 'user' => $user,
'title' => $title, 'title' => $title,
'text' => $msg, 'text' => $msg,
]; ];
(new EmailQueue())->add($user->email, $title, $template, $array, $scene);
(new EmailQueue())->add($user->email, $title, $template, $array);
} else { } else {
IM::send($user->im_value, $msg, $user->im_type); IM::send($user->im_value, $msg, $user->im_type);
} }
@ -63,19 +100,40 @@ final class Notification
* @throws GuzzleException * @throws GuzzleException
* @throws TelegramSDKException * @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(); $users = User::all();
foreach ($users as $user) { foreach ($users as $user) {
if ($user->contact_method === 1 || $user->im_type === 0) { if ($user->contact_method === 1 || $user->im_type === 0) {
$array = [ $array = [
'user' => $user, 'user' => $user,
'title' => $title, 'title' => $title,
'text' => $msg, 'text' => $msg,
]; ];
(new EmailQueue())->add($user->email, $title, $template, $array, $scene);
(new EmailQueue())->add($user->email, $title, $template, $array);
} else { } else {
IM::send($user->im_value, $msg, $user->im_type); IM::send($user->im_value, $msg, $user->im_type);
} }

195
src/Services/NotificationV2.php Executable file
View File

@ -0,0 +1,195 @@
<?php
declare(strict_types=1);
namespace App\Services;
use App\Models\EmailQueue;
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
{
public static function start()
{
$oInstance = new self();
return $oInstance;
}
public static function admin()
{
$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 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);
}
}
}
}