在 Laravel 中通过 MCP 协议发送邮件需要完成以下关键步骤,这里提供完整实现指南:
一、服务端配置
- 创建邮件工具类
// app/Tools/EmailTool.php
namespace App\Tools;
use PhpMcp\Laravel\Server\Attributes\McpTool;
use Illuminate\Support\Facades\Mail;
use App\Mail\TransactionalEmail;
use Illuminate\Support\Facades\Validator;
class EmailTool {
#[McpTool(
name: "send_email",
description: "发送事务邮件",
params: [
'recipient' => 'required|email',
'subject' => 'required|string|max:120',
'template' => 'required|string|in:invoice,welcome,reset',
'variables' => 'array'
]
)]
public function send(array $params): array {
// 二次校验确保安全
$validator = Validator::make($params, [
'recipient' => 'required|email',
'template' => 'required|exists:mail_templates,name'
]);
if ($validator->fails()) {
abort(422, $validator->errors()->first());
}
// 实际发送邮件
Mail::to($params['recipient'])
->queue(new TransactionalEmail(
$params['subject'],
$params['template'],
$params['variables'] ?? []
));
return [
'status' => 'queued',
'message' => '邮件已进入发送队列',
'timestamp' => now()->toDateTimeString()
];
}
}
- 创建邮件模板类
// app/Mail/TransactionalEmail.php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class TransactionalEmail extends Mailable {
use Queueable, SerializesModels;
public function __construct(
public string $subject,
public string $template,
public array $variables = []
) {}
public function build() {
return $this->subject($this->subject)
->view('emails.' . $this->template)
->with($this->variables);
}
}
二、客户端调用示例(JavaScript)
// 连接到 MCP 服务
const mcp = new McpClient('https://api.yourdomain.com/mcp/sse', {
token: AUTH_TOKEN // 服务端签发的 JWT
});
// 调用邮件发送工具
async function sendInvoiceEmail() {
const response = await mcp.execute('send_email', {
recipient: 'client@example.com',
subject: '您的订单发票 #INV-2023-0456',
template: 'invoice',
variables: {
invoice_number: 'INV-2023-0456',
amount: 2499.00,
due_date: '2023-12-31'
}
});
console.log('邮件发送状态:', response);
// 输出: {status: "queued", message: "邮件已进入发送队列", ...}
}
// 处理错误
mcp.on('error', (err) => {
console.error('邮件发送失败:', err);
});
三、关键配置项
- MCP 路由配置 (
config/mcp.php)
'transports' => [
'sse' => [
'route' => '/mcp/sse',
'middleware' => ['auth:api', 'throttle:100/minute']
]
],
'security' => [
'jwt_secret' => env('MCP_JWT_SECRET', env('APP_KEY')),
'allowed_origins' => ['https://your-frontend.com']
]
- 邮件队列配置 (
.env)
MAIL_MAILER=smtp
MAIL_HOST=mail.example.com
MAIL_PORT=587
MAIL_USERNAME=no-reply@example.com
MAIL_PASSWORD=yourpassword
MAIL_ENCRYPTION=tls
QUEUE_CONNECTION=redis # 使用队列发送
四、高级功能实现
- 邮件发送限流
// 在路由中添加限流中间件
Mcp::route()->middleware(['throttle:emails:60,1']);
// 在 AppServiceProvider 中定义限流器
RateLimiter::for('emails', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
- 邮件追踪
// 修改邮件工具类
#[McpTool(/* ... */)]
public function send(array $params): array {
$mail = new TransactionalEmail(/* ... */);
// 添加邮件追踪ID
$trackingId = Str::uuid();
$mail->withSwiftMessage(function ($message) use ($trackingId) {
$message->getHeaders()->addTextHeader('X-Mail-Tracking-ID', $trackingId);
});
Mail::queue($mail);
return [
'tracking_id' => $trackingId,
// ...
];
}
- 模板预检接口
#[McpTool(
name: "preview_template",
description: "预览邮件模板"
)]
public function preview(string $template, array $variables = []) {
return view('emails.' . $template, $variables)->render();
}
五、调试技巧
- 测试发送本地邮件
php artisan tinker
>>> Mcp::call('send_email', [
'recipient' => 'test@localhost',
'subject' => '测试邮件',
'template' => 'test'
]);
- 查看邮件日志
tail -f storage/logs/mcp-*.log
# 启用调试模式
MCP_LOG_LEVEL=debug
六、安全建议
- 敏感操作审计
// 在工具类中添加审计日志
public function send(array $params) {
activity('mcp_email')
->withProperties([
'recipient' => $params['recipient'],
'template' => $params['template']
])
->log('邮件发送请求');
// ...发送逻辑...
}
- IP 白名单限制
// config/mcp.php
'security' => [
'allowed_ips' => [
'192.168.1.0/24',
'172.16.0.0/12'
]
]
通过以上实现,您将获得一个安全可靠、支持队列发送、带有完整审计日志的 MCP 邮件服务。实际生产部署时建议:
- 使用 Redis 或 Horizon 管理邮件队列
- 配置邮件送达状态监控(如 Mailgun 或 Sendgrid 的回调)
- 定期审计邮件发送日志
- 为高风险操作添加二次确认机制

1201

被折叠的 条评论
为什么被折叠?



