mirror of
https://github.com/kuaifan/dootask.git
synced 2026-06-23 15:52:22 +00:00
refactor(mail): 邮件发送弃用 guanguans/notify 改用 symfony/mailer
guanguans/notify 在本项目仅用于 SMTP 发信,但其 1.x 线已停更、email 渠道 自 3.x 起被上游移除(无升级路径)。改用项目已自带的 symfony/mailer(Laravel 13 传递依赖),零新增依赖,并一并移除孤儿依赖 overtrue/http、symfony/options-resolver。 - EmailNoticeTask / UserEmailVerification / SystemController 三处发信改为 new Mailer(Transport::fromDsn(...)) + new Email();API 1:1 等价 (from/to/subject/html 同名,verify_peer=0 仍受 symfony 8.x 支持, notify 本就裸调 symfony 故异常透传不变、getCode()===550 仍成立) - 移除 UserTransfer 未使用的 notify import - 顺带修复既有 bug:超时判断字面量 "Timed Out" 与 symfony 实际消息 "timed out" 大小写不匹配,改 stripos 大小写不敏感 验证:phpstan 0 错误、composer audit 无公告;邮箱验证码、系统邮件测试两条 链路实测发信成功。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
468abe9902
commit
2f8dee44c2
@ -17,12 +17,13 @@ use App\Module\Timer;
|
||||
use App\Models\Setting;
|
||||
use LdapRecord\Container;
|
||||
use App\Module\BillExport;
|
||||
use Guanguans\Notify\Factory;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
use Symfony\Component\Mailer\Transport;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use App\Models\UserCheckinRecord;
|
||||
use App\Module\Apps;
|
||||
use App\Module\BillMultipleExport;
|
||||
use LdapRecord\LdapRecordException;
|
||||
use Guanguans\Notify\Messages\EmailMessage;
|
||||
use Swoole\Coroutine;
|
||||
|
||||
/**
|
||||
@ -1232,21 +1233,19 @@ class SystemController extends AbstractController
|
||||
}
|
||||
try {
|
||||
Setting::validateAddr($all['to'], function($to) use ($all) {
|
||||
Factory::mailer()
|
||||
->setDsn("smtp://{$all['account']}:{$all['password']}@{$all['smtp_server']}:{$all['port']}?verify_peer=0")
|
||||
->setMessage(EmailMessage::create()
|
||||
->from(Base::settingFind('system', 'system_alias', 'Task') . " <{$all['account']}>")
|
||||
->to($to)
|
||||
->subject('Mail sending test')
|
||||
->html('<p>' . Doo::translate('收到此电子邮件意味着您的邮箱配置正确。') . '</p>'))
|
||||
->send();
|
||||
$mailer = new Mailer(Transport::fromDsn("smtp://{$all['account']}:{$all['password']}@{$all['smtp_server']}:{$all['port']}?verify_peer=0"));
|
||||
$mailer->send((new Email())
|
||||
->from(Base::settingFind('system', 'system_alias', 'Task') . " <{$all['account']}>")
|
||||
->to($to)
|
||||
->subject('Mail sending test')
|
||||
->html('<p>' . Doo::translate('收到此电子邮件意味着您的邮箱配置正确。') . '</p>'));
|
||||
}, function () {
|
||||
throw new \Exception("收件人地址错误或已被忽略");
|
||||
});
|
||||
return Base::retSuccess('成功发送');
|
||||
} catch (\Throwable $e) {
|
||||
// 一般是请求超时
|
||||
if (str_contains($e->getMessage(), "Timed Out")) {
|
||||
if (stripos($e->getMessage(), "timed out") !== false) {
|
||||
return Base::retError("邮件发送超时,请检查邮箱配置是否正确");
|
||||
} elseif ($e->getCode() === 550) {
|
||||
return Base::retError('邮件内容被拒绝,请检查邮箱是否开启接收功能');
|
||||
|
||||
@ -7,8 +7,9 @@ use App\Module\Base;
|
||||
use App\Module\Doo;
|
||||
use App\Module\Timer;
|
||||
use Carbon\Carbon;
|
||||
use Guanguans\Notify\Factory;
|
||||
use Guanguans\Notify\Messages\EmailMessage;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
use Symfony\Component\Mailer\Transport;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
/**
|
||||
* App\Models\UserEmailVerification
|
||||
@ -97,16 +98,14 @@ class UserEmailVerification extends AbstractModel
|
||||
);
|
||||
break;
|
||||
}
|
||||
Factory::mailer()
|
||||
->setDsn("smtp://{$setting['account']}:{$setting['password']}@{$setting['smtp_server']}:{$setting['port']}?verify_peer=0")
|
||||
->setMessage(EmailMessage::create()
|
||||
->from($alias . " <{$setting['account']}>")
|
||||
->to($email)
|
||||
->subject($subject)
|
||||
->html($content))
|
||||
->send();
|
||||
$mailer = new Mailer(Transport::fromDsn("smtp://{$setting['account']}:{$setting['password']}@{$setting['smtp_server']}:{$setting['port']}?verify_peer=0"));
|
||||
$mailer->send((new Email())
|
||||
->from($alias . " <{$setting['account']}>")
|
||||
->to($email)
|
||||
->subject($subject)
|
||||
->html($content));
|
||||
} catch (\Throwable $e) {
|
||||
if (str_contains($e->getMessage(), "Timed Out")) {
|
||||
if (stripos($e->getMessage(), "timed out") !== false) {
|
||||
throw new ApiException("邮件发送超时,请检查邮箱配置是否正确");
|
||||
} elseif ($e->getCode() === 550) {
|
||||
throw new ApiException('邮件内容被拒绝,请检查邮箱是否开启接收功能');
|
||||
|
||||
@ -5,8 +5,6 @@ namespace App\Models;
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Module\Base;
|
||||
use Carbon\Carbon;
|
||||
use Guanguans\Notify\Factory;
|
||||
use Guanguans\Notify\Messages\EmailMessage;
|
||||
|
||||
/**
|
||||
* App\Models\UserTransfer
|
||||
|
||||
@ -9,8 +9,9 @@ use App\Module\Base;
|
||||
use App\Module\Doo;
|
||||
use App\Module\Timer;
|
||||
use Carbon\Carbon;
|
||||
use Guanguans\Notify\Factory;
|
||||
use Guanguans\Notify\Messages\EmailMessage;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
use Symfony\Component\Mailer\Transport;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
/**
|
||||
* 未读消息邮件通知任务
|
||||
@ -258,20 +259,18 @@ class EmailNoticeTask extends AbstractTask
|
||||
private function sendEmail($user, $emailData): void
|
||||
{
|
||||
Setting::validateAddr($user->email, function($to) use ($emailData) {
|
||||
Factory::mailer()
|
||||
->setDsn(sprintf(
|
||||
'smtp://%s:%s@%s:%s?verify_peer=0',
|
||||
$this->emailSetting['account'],
|
||||
$this->emailSetting['password'],
|
||||
$this->emailSetting['smtp_server'],
|
||||
$this->emailSetting['port']
|
||||
))
|
||||
->setMessage(EmailMessage::create()
|
||||
->from(sprintf('%s <%s>', Base::settingFind('system', 'system_alias', 'Task'), $this->emailSetting['account']))
|
||||
->to($to)
|
||||
->subject($emailData['subject'])
|
||||
->html($emailData['content']))
|
||||
->send();
|
||||
$mailer = new Mailer(Transport::fromDsn(sprintf(
|
||||
'smtp://%s:%s@%s:%s?verify_peer=0',
|
||||
$this->emailSetting['account'],
|
||||
$this->emailSetting['password'],
|
||||
$this->emailSetting['smtp_server'],
|
||||
$this->emailSetting['port']
|
||||
)));
|
||||
$mailer->send((new Email())
|
||||
->from(sprintf('%s <%s>', Base::settingFind('system', 'system_alias', 'Task'), $this->emailSetting['account']))
|
||||
->to($to)
|
||||
->subject($emailData['subject'])
|
||||
->html($emailData['content']));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,6 @@
|
||||
"ext-zip": "*",
|
||||
"directorytree/ldaprecord-laravel": "^4.0",
|
||||
"firebase/php-jwt": "^7.1",
|
||||
"guanguans/notify": "~1.28.0",
|
||||
"guzzlehttp/guzzle": "^7.3.0",
|
||||
"hedeqiang/umeng": "^2.1",
|
||||
"laravel/framework": "^13.0",
|
||||
|
||||
279
composer.lock
generated
279
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "6e15c4192dce5dc139bbff83fc0f8db8",
|
||||
"content-hash": "394ccedcb5eb9fcf3ebadc4c65689688",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
@ -1064,154 +1064,6 @@
|
||||
],
|
||||
"time": "2025-12-27T19:43:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guanguans/notify",
|
||||
"version": "1.28.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guanguans/notify.git",
|
||||
"reference": "e2dac64cf99ba3e41abe7aefaf59ef5cd3acf161"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guanguans/notify/zipball/e2dac64cf99ba3e41abe7aefaf59ef5cd3acf161",
|
||||
"reference": "e2dac64cf99ba3e41abe7aefaf59ef5cd3acf161",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"overtrue/http": "^1.2",
|
||||
"php": ">=7.2.5",
|
||||
"psr/log": "^1.1 || ^2.0 || ^3.0",
|
||||
"symfony/options-resolver": "^5.4 || ^6.0 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.8",
|
||||
"brainmaestro/composer-git-hooks": "^2.8 || ^3.0",
|
||||
"dms/phpunit-arraysubset-asserts": "^0.5",
|
||||
"ergebnis/composer-normalize": "^2.19",
|
||||
"friendsofphp/php-cs-fixer": "^3.4",
|
||||
"mockery/mockery": "^1.3",
|
||||
"php-mock/php-mock-phpunit": "^2.9",
|
||||
"phpstan/extension-installer": "^1.3",
|
||||
"phpstan/phpstan": "^1.10",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.1",
|
||||
"phpunit/phpunit": "^8.5 || ^9.0",
|
||||
"rector/rector": "^0.19",
|
||||
"symfony/mailer": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/var-dumper": "^5.4 || ^6.0 || ^7.0",
|
||||
"textalk/websocket": "^1.5",
|
||||
"vimeo/psalm": "^4.30 || ^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/mailer": "Required to use the email.",
|
||||
"textalk/websocket": "Required to use the QQ channel bot."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"hooks": {
|
||||
"post-merge": [
|
||||
"composer checks"
|
||||
],
|
||||
"pre-commit": [
|
||||
"composer checks"
|
||||
]
|
||||
},
|
||||
"bamarni-bin": {
|
||||
"bin-links": true,
|
||||
"forward-command": true,
|
||||
"target-directory": "vendor-bin"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/Support/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Guanguans\\Notify\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "guanguans",
|
||||
"email": "ityaozm@gmail.com",
|
||||
"homepage": "https://www.guanguans.cn",
|
||||
"role": "developer"
|
||||
}
|
||||
],
|
||||
"description": "Push notification sdk(Bark、Chanify、DingTalk、Discord、Email、FeiShu、Gitter、Google Chat、iGot、Logger、Mattermost、Microsoft Teams、Now Push、Ntfy、PushBack、Push、PushDeer、Pushover、PushPlus、QQ Channel Bot、Rocket Chat、ServerChan、Showdoc Push、Slack、Telegram、Webhook、WeWork、XiZhi、YiFengChuanHua、Zulip).com",
|
||||
"homepage": "https://github.com/guanguans/notify",
|
||||
"keywords": [
|
||||
"Bark",
|
||||
"Feishu",
|
||||
"Mattermost",
|
||||
"Ntfy",
|
||||
"PushDeer",
|
||||
"QQ Bot",
|
||||
"QQ 机器人",
|
||||
"QQ 频道",
|
||||
"QQ 频道机器人",
|
||||
"Server酱",
|
||||
"chanify",
|
||||
"dingtalk",
|
||||
"discord",
|
||||
"email",
|
||||
"gitter",
|
||||
"googleChat",
|
||||
"iGot",
|
||||
"logger",
|
||||
"microsoft teams",
|
||||
"notification",
|
||||
"notifier",
|
||||
"notify",
|
||||
"now push",
|
||||
"push",
|
||||
"pushBack",
|
||||
"pushPlus",
|
||||
"pushover",
|
||||
"qq",
|
||||
"rocketchat",
|
||||
"sdk",
|
||||
"serverChan",
|
||||
"showdoc push",
|
||||
"slack",
|
||||
"telegram",
|
||||
"webhook",
|
||||
"wework",
|
||||
"xiZhi",
|
||||
"zulip",
|
||||
"一封传话",
|
||||
"企业微信",
|
||||
"企业微信群机器人",
|
||||
"微信",
|
||||
"息知",
|
||||
"机器人",
|
||||
"邮件",
|
||||
"钉钉",
|
||||
"钉钉群",
|
||||
"钉钉群机器人",
|
||||
"飞书",
|
||||
"飞书群机器人"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guanguans/notify/issues",
|
||||
"source": "https://github.com/guanguans/notify"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.guanguans.cn/images/wechat.jpeg",
|
||||
"type": "wechat"
|
||||
}
|
||||
],
|
||||
"time": "2024-01-17T06:56:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "7.11.1",
|
||||
@ -4027,64 +3879,6 @@
|
||||
},
|
||||
"time": "2026-02-23T07:40:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "overtrue/http",
|
||||
"version": "1.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/overtrue/http.git",
|
||||
"reference": "e6e4c2ff274b1050d681288495878ee8fd3f1209"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/overtrue/http/zipball/e6e4c2ff274b1050d681288495878ee8fd3f1209",
|
||||
"reference": "e6e4c2ff274b1050d681288495878ee8fd3f1209",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-simplexml": "*",
|
||||
"guzzlehttp/guzzle": "^6.3 || ^7.0",
|
||||
"php": ">=7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"brainmaestro/composer-git-hooks": "^2.7",
|
||||
"friendsofphp/php-cs-fixer": "^2.15 || ^3.0",
|
||||
"mockery/mockery": "^1.0",
|
||||
"overtrue/phplint": "^1.1 || ^2.0 || ^3.0",
|
||||
"phpunit/phpunit": "^6.5 || ^8.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Overtrue\\Http\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "overtrue",
|
||||
"email": "anzhengchao@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A simple http client wrapper.",
|
||||
"support": {
|
||||
"issues": "https://github.com/overtrue/http/issues",
|
||||
"source": "https://github.com/overtrue/http/tree/1.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/overtrue",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-14T06:24:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "overtrue/pinyin",
|
||||
"version": "5.3.4",
|
||||
@ -6458,77 +6252,6 @@
|
||||
],
|
||||
"time": "2026-05-29T05:06:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"version": "v7.4.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/options-resolver.git",
|
||||
"reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/2888fcdc4dc2fd5f7c7397be78631e8af12e02b4",
|
||||
"reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"symfony/deprecation-contracts": "^2.5|^3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\OptionsResolver\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides an improved replacement for the array_replace PHP function",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"config",
|
||||
"configuration",
|
||||
"options"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/options-resolver/tree/v7.4.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-24T13:12:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.37.0",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user