不推荐用 php-mailgun 库发大规模营销邮件,因其仅为轻量级 API 封装,无队列、重试、节流及批量能力,易触发 Mailgun 速率限制或封禁 API key;正确做法是直接调用 Mailgun 批量接口(如 /messages)并配合异步队列系统。

直接说结论:不推荐用 php-mailgun 库发大规模营销邮件,它本质是轻量级封装,没内置队列、重试、节流或批量发送能力,强行用会触发 Mailgun 的速率限制甚至封禁 API key。
为什么 php-mailgun 不适合营销邮件场景
这个库只是对 Mailgun HTTP API 的简单 cURL 封装,send() 方法每次调用都发起一次同步请求,没有:
- 自动分批(Mailgun 单次
/messages接口最多收 1000 个收件人) - 失败后指数退避重试(比如临时 429 或 503)
- 连接池或并发控制(并发开太高会被限流)
- 收件人去重、硬/软退信处理逻辑
你用它循环发 10 万封,大概率在第 3000 封左右收到 429 Too Many Requests,然后整个流程卡死。
正确做法:用 Mailgun 官方推荐的批量接口 + 队列驱动
营销邮件必须走 Mailgun 的 /messages.mime(发原始 MIME)或更稳妥的 /messages 批量模式,并配合异步任务系统。实操建议如下:
立即学习“PHP免费学习笔记(深入)”;
- 用
guzzlehttp/guzzle直接调用 Mailgun API,别套一层php-mailgun - 收件人列表按每 900 人一组切片(留 100 余量防字段膨胀)
- 每组构造一个含
to数组的 JSON 请求体,POST到https://api.mailgun.net/v3/YOUR_DOMAIN/messages - PHP 侧用
symfony/messenger或laravel/framework的队列推任务,Worker 进程里执行发送 - 务必在请求头加
Authorization: Basic {base64(api:key-xxx)},别依赖库自动拼
示例关键片段:
$client = new \GuzzleHttp\Client();
$response = $client->post('https://api.mailgun.net/v3/yourdomain.com/messages', [
'auth' => ['api', 'key-xxxxxxxxxx'],
'form_params' => [
'from' => 'news@yourdomain.com',
'to' => ['a@example.com', 'b@example.com'],
'subject' => 'Weekly Digest',
'html' => '<h1>Hello</h1>'
]
]);
Composer 安装和基础配置陷阱
即使你坚持要用 php-mailgun,也得避开几个坑:
- 别装
php-mailgun/php-mailgun—— 这个包已三年未更新,不兼容 PHP 8.1+,且依赖过时的guzzlehttp/guzzle ~5.0 - 改用社区维护的
mailgun/mailgun-php:composer require mailgun/mailgun-php - 初始化时必须显式传入
HttpClient实例,否则默认用 Guzzle 6,但新版 Mailgun API 要求User-Agent头含版本号,否则返回400 Bad Request -
setApiEndpoint()必须设为https://api.mailgun.net,不能漏掉/v3—— 它不是路径而是 API 版本前缀
错误写法:$mgClient = Mailgun::create('key-xxx');
正确写法:$mgClient = Mailgun::create('key-xxx', ['endpoint' => 'https://api.mailgun.net'] );
真正的大规模发送,核心不在“怎么装库”,而在怎么把「发信」这个动作从 Web 请求生命周期里摘出来,压进队列,再配好监控和退信回调。Mailgun 的 routes 和 webhooks 比客户端库重要十倍。



















