feat(notice): PHPMailer 邮箱驱动与短信公众号骨架

This commit is contained in:
augushong
2026-10-12 12:09:00 +00:00
parent e95e5942ea
commit 02f77f4eca
6 changed files with 382 additions and 5 deletions

View File

@@ -0,0 +1,85 @@
<?php
namespace base\common\notice\channel;
use base\common\notice\NoticeChannelInterface;
use PHPMailer\PHPMailer\Exception as PHPMailerException;
use PHPMailer\PHPMailer\PHPMailer;
use RuntimeException;
/**
* 邮件渠道驱动(PHPMailer SMTP).
*
* 读取 sysconfig notify 组 SMTP 参数执行真实投递:
* 抛出异常视为投递失败,异常消息携带 PHPMailer ErrorInfo(含 SMTP 会话 lastError),
* timer 消费者据此退避重试直至终态。
*/
class EmailChannel implements NoticeChannelInterface
{
public static function name(): string
{
return 'email';
}
public function send(array $target, array $notice): bool
{
// 全局总闸:DB 值为字符串,(int) 强转判断;仅 '1' 视为启用(缺省/0 均为关,
// 与系统配置 notify 组 notify_email_enable 默认值 0 一致),关闭即抛异常。
if ((int) sysconfig('notify', 'notify_email_enable') !== 1) {
throw new RuntimeException('邮件发送失败: 渠道未启用(notify_email_enable != 1)');
}
$host = (string) sysconfig('notify', 'notify_smtp_host');
$port = (int) sysconfig('notify', 'notify_smtp_port');
$secure = strtolower((string) sysconfig('notify', 'notify_smtp_secure'));
$user = (string) sysconfig('notify', 'notify_smtp_user');
$pass = (string) sysconfig('notify', 'notify_smtp_pass');
$from = (string) sysconfig('notify', 'notify_smtp_from', 'notice@localhost');
$fromName = (string) sysconfig('notify', 'notify_smtp_from_name');
$title = (string) ($notice['title'] ?? '');
$content = (string) ($notice['content'] ?? '');
$mailer = new PHPMailer(true);
try {
$mailer->isSMTP();
$mailer->Host = $host;
$mailer->Port = $port;
// SMTPSecure 映射:ssl→隐式 SMTPS;tls→STARTTLS;none/未知→明文。
// 明文场景必须显式关闭 SMTPAutoTLS:PHPMailer 默认会对明文会话自动尝试
// STARTTLS 升级,Mailpit 等纯明文本地服务会被误判为失败。
if ($secure === 'ssl') {
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
} elseif ($secure === 'tls') {
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
} else {
$mailer->SMTPSecure = '';
$mailer->SMTPAutoTLS = false;
}
// SMTP 认证仅在配置了用户名时启用(Mailpit 等本地无认证服务不设置)
if ($user !== '') {
$mailer->SMTPAuth = true;
$mailer->Username = $user;
$mailer->Password = $pass;
}
$mailer->CharSet = 'UTF-8';
$mailer->isHTML(true);
$mailer->setFrom($from, $fromName);
$mailer->addAddress((string) ($target['target_addr'] ?? ''));
$mailer->Subject = $title;
$mailer->Body = '<div style="font-family:Arial,sans-serif;">'
. '<h3>' . $title . '</h3>'
. '<div>' . nl2br($content) . '</div>'
. '</div>';
$mailer->send();
} catch (PHPMailerException $e) {
// send() 抛出的 Exception 消息即 $mailer->ErrorInfo(setError 已拼接
// SMTP lastError/detail/smtp_code),异常链保留原始异常供上游追溯
throw new RuntimeException('邮件发送失败: ' . $e->getMessage(), 0, $e);
}
return true;
}
}