302 lines
11 KiB
PHP
302 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\SystemConfig;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
class MailService
|
|
{
|
|
/**
|
|
* 发送配对码邮件
|
|
*/
|
|
public function sendPairCode(string $email, string $code, int $expireMinutes = 10): bool
|
|
{
|
|
try {
|
|
$config = $this->getMailConfig();
|
|
|
|
if (!$config['enabled']) {
|
|
\Log::warning('邮件服务未启用');
|
|
return false;
|
|
}
|
|
|
|
$siteName = SystemConfig::getValue('system', 'site_name', 'ERP系统');
|
|
|
|
Mail::send([], [], function ($message) use ($email, $code, $expireMinutes, $config, $siteName) {
|
|
$message->to($email)
|
|
->from($config['from_email'], $config['from_name'])
|
|
->subject("【{$siteName}】异地登录验证 - 配对码")
|
|
->html($this->buildPairCodeEmail($code, $expireMinutes, $siteName));
|
|
});
|
|
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
\Log::error('发送配对码邮件失败: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发送邮箱修改验证码
|
|
*/
|
|
public function sendEmailChangeCode(string $newEmail, string $code, string $userName = ''): bool
|
|
{
|
|
try {
|
|
$config = $this->getMailConfig();
|
|
|
|
if (!$config['enabled']) {
|
|
\Log::warning('邮件服务未启用');
|
|
return false;
|
|
}
|
|
|
|
$siteName = SystemConfig::getValue('system', 'site_name', 'ERP系统');
|
|
|
|
Mail::send([], [], function ($message) use ($newEmail, $code, $config, $siteName, $userName) {
|
|
$message->to($newEmail)
|
|
->from($config['from_email'], $config['from_name'])
|
|
->subject("【{$siteName}】邮箱修改验证码")
|
|
->html($this->buildEmailChangeEmail($code, $siteName, $userName));
|
|
});
|
|
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
\Log::error('发送邮箱修改验证码邮件失败: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发送重置密码邮件
|
|
*/
|
|
public function sendResetPasswordCode(string $email, string $code, int $expireMinutes = 30): bool
|
|
{
|
|
try {
|
|
$config = $this->getMailConfig();
|
|
|
|
if (!$config['enabled']) {
|
|
\Log::warning('邮件服务未启用');
|
|
return false;
|
|
}
|
|
|
|
$siteName = SystemConfig::getValue('system', 'site_name', 'ERP系统');
|
|
|
|
Mail::send([], [], function ($message) use ($email, $code, $expireMinutes, $config, $siteName) {
|
|
$message->to($email)
|
|
->from($config['from_email'], $config['from_name'])
|
|
->subject("【{$siteName}】密码重置验证码")
|
|
->html($this->buildResetPasswordEmail($code, $expireMinutes, $siteName));
|
|
});
|
|
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
\Log::error('发送重置密码邮件失败: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取邮件配置
|
|
*/
|
|
public function getMailConfig(): array
|
|
{
|
|
$cacheKey = 'mail_service_config';
|
|
|
|
return Cache::remember($cacheKey, 3600, function () {
|
|
return [
|
|
'enabled' => SystemConfig::getValue('mail', 'enabled', false),
|
|
'driver' => SystemConfig::getValue('mail', 'driver', 'smtp'),
|
|
'host' => SystemConfig::getValue('mail', 'host', ''),
|
|
'port' => (int) SystemConfig::getValue('mail', 'port', 465),
|
|
'encryption' => SystemConfig::getValue('mail', 'encryption', 'ssl'),
|
|
'username' => SystemConfig::getValue('mail', 'username', ''),
|
|
'password' => SystemConfig::getValue('mail', 'password', ''),
|
|
'from_email' => SystemConfig::getValue('mail', 'from_email', 'noreply@erp.local'),
|
|
'from_name' => SystemConfig::getValue('mail', 'from_name', 'ERP系统'),
|
|
];
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 应用邮件配置到 Laravel
|
|
*/
|
|
public function applyConfig(): void
|
|
{
|
|
$config = $this->getMailConfig();
|
|
|
|
if (!$config['enabled']) {
|
|
return;
|
|
}
|
|
|
|
config([
|
|
'mail.default' => $config['driver'],
|
|
'mail.mailers.smtp.host' => $config['host'],
|
|
'mail.mailers.smtp.port' => $config['port'],
|
|
'mail.mailers.smtp.encryption' => $config['encryption'],
|
|
'mail.mailers.smtp.username' => $config['username'],
|
|
'mail.mailers.smtp.password' => $config['password'],
|
|
'mail.from.address' => $config['from_email'],
|
|
'mail.from.name' => $config['from_name'],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 测试邮件连接
|
|
*/
|
|
public function testConnection(): array
|
|
{
|
|
try {
|
|
$config = $this->getMailConfig();
|
|
|
|
if (!$config['enabled']) {
|
|
return ['success' => false, 'message' => '邮件服务未启用'];
|
|
}
|
|
|
|
Mail::send([], [], function ($message) use ($config) {
|
|
$message->to($config['from_email'])
|
|
->from($config['from_email'], $config['from_name'])
|
|
->subject('ERP邮件服务测试')
|
|
->text('这是一封测试邮件,证明邮件服务配置正确。');
|
|
});
|
|
|
|
return ['success' => true, 'message' => '邮件发送成功'];
|
|
} catch (\Exception $e) {
|
|
return ['success' => false, 'message' => '邮件发送失败: ' . $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 构建配对码邮件内容
|
|
*/
|
|
private function buildPairCodeEmail(string $code, int $expireMinutes, string $siteName): string
|
|
{
|
|
return <<<HTML
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<style>
|
|
body { font-family: Arial, sans-serif; background: #f5f5f5; margin: 0; padding: 20px; }
|
|
.container { max-width: 500px; margin: 0 auto; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
|
.header { background: #409eff; color: #fff; padding: 24px; text-align: center; }
|
|
.header h1 { margin: 0; font-size: 20px; }
|
|
.content { padding: 32px 24px; }
|
|
.code-box { background: #f8f9fa; border: 2px dashed #409eff; border-radius: 8px; padding: 20px; text-align: center; margin: 20px 0; }
|
|
.code { font-size: 32px; font-weight: bold; letter-spacing: 8px; color: #409eff; }
|
|
.warning { color: #e6a23c; font-size: 14px; margin-top: 16px; }
|
|
.footer { background: #f5f7fa; padding: 16px; text-align: center; font-size: 12px; color: #909399; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>【{$siteName}】异地登录验证</h1>
|
|
</div>
|
|
<div class="content">
|
|
<p>您好,您在另一台设备尝试登录您的账号。</p>
|
|
<p>以下是您的登录配对码:</p>
|
|
<div class="code-box">
|
|
<div class="code">{$code}</div>
|
|
</div>
|
|
<p class="warning">⚠️ 配对码有效期为 {$expireMinutes} 分钟,请勿告诉他人!</p>
|
|
<p>如果不是您本人操作,请忽略此邮件,并建议您尽快修改密码。</p>
|
|
</div>
|
|
<div class="footer">
|
|
<p>此邮件由系统自动发送,请勿回复。</p>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
HTML;
|
|
}
|
|
|
|
/**
|
|
* 构建重置密码邮件内容
|
|
*/
|
|
private function buildResetPasswordEmail(string $code, int $expireMinutes, string $siteName): string
|
|
{
|
|
return <<<HTML
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<style>
|
|
body { font-family: Arial, sans-serif; background: #f5f5f5; margin: 0; padding: 20px; }
|
|
.container { max-width: 500px; margin: 0 auto; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
|
.header { background: #67c23a; color: #fff; padding: 24px; text-align: center; }
|
|
.header h1 { margin: 0; font-size: 20px; }
|
|
.content { padding: 32px 24px; }
|
|
.code-box { background: #f8f9fa; border: 2px dashed #67c23a; border-radius: 8px; padding: 20px; text-align: center; margin: 20px 0; }
|
|
.code { font-size: 32px; font-weight: bold; letter-spacing: 8px; color: #67c23a; }
|
|
.warning { color: #e6a23c; font-size: 14px; margin-top: 16px; }
|
|
.footer { background: #f5f7fa; padding: 16px; text-align: center; font-size: 12px; color: #909399; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>【{$siteName}】密码重置验证码</h1>
|
|
</div>
|
|
<div class="content">
|
|
<p>您正在重置账号密码,请使用以下验证码:</p>
|
|
<div class="code-box">
|
|
<div class="code">{$code}</div>
|
|
</div>
|
|
<p class="warning">⚠️ 验证码有效期为 {$expireMinutes} 分钟,请勿告诉他人!</p>
|
|
<p>如果不是您本人操作,请忽略此邮件。</p>
|
|
</div>
|
|
<div class="footer">
|
|
<p>此邮件由系统自动发送,请勿回复。</p>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
HTML;
|
|
}
|
|
|
|
/**
|
|
* 构建邮箱修改验证码邮件
|
|
*/
|
|
private function buildEmailChangeEmail(string $code, string $siteName, string $userName = ''): string
|
|
{
|
|
$greeting = $userName ? "亲爱的 {$userName}" : "您好";
|
|
return <<<HTML
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<style>
|
|
body { font-family: Arial, sans-serif; background: #f5f5f5; margin: 0; padding: 20px; }
|
|
.container { max-width: 500px; margin: 0 auto; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
|
.header { background: #409eff; color: #fff; padding: 24px; text-align: center; }
|
|
.header h1 { margin: 0; font-size: 20px; }
|
|
.content { padding: 32px 24px; }
|
|
.code-box { background: #f8f9fa; border: 2px dashed #409eff; border-radius: 8px; padding: 20px; text-align: center; margin: 20px 0; }
|
|
.code { font-size: 32px; font-weight: bold; letter-spacing: 8px; color: #409eff; }
|
|
.warning { color: #e6a23c; font-size: 14px; margin-top: 16px; }
|
|
.footer { background: #f5f7fa; padding: 16px; text-align: center; font-size: 12px; color: #909399; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>【{$siteName}】邮箱修改验证码</h1>
|
|
</div>
|
|
<div class="content">
|
|
<p>{$greeting},您正在修改绑定邮箱,请使用以下验证码:</p>
|
|
<div class="code-box">
|
|
<div class="code">{$code}</div>
|
|
</div>
|
|
<p class="warning">⚠️ 验证码有效期为 30 分钟,请勿告诉他人!</p>
|
|
<p>如果不是您本人操作,请忽略此邮件。</p>
|
|
</div>
|
|
<div class="footer">
|
|
<p>此邮件由系统自动发送,请勿回复。</p>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
HTML;
|
|
}
|
|
}
|