Laravel结合Mailgun发送邮件出现413请求实体过大错误
解决Laravel+Mailgun发送75M大附件的413错误问题
嘿,这个问题我之前帮朋友踩过类似的坑,咱们一步步拆解原因和解决方案:
首先,你碰到的413 Request Entity Too Large看似是服务器端的大小限制,但核心可能是Mailgun本身的套餐限制——免费版单邮件总大小(含附件)上限是25MB,付费版也只有100MB,而且这里的大小是base64编码后的总大小(编码后体积会上涨约33%),75MB的原始文件编码后刚好接近100MB,再加上邮件正文,很容易超阈值,这就是你改了PHP和Nginx配置还没用的关键原因。
第一步:先确认Mailgun的限制
先去你的Mailgun后台查看当前套餐的邮件总大小上限:
- 免费套餐:单邮件(含附件)最大25MB
- 付费基础/进阶套餐:最大100MB
注意:这里计算的是整个邮件的编码后体积,不是原始附件大小,这点很容易被忽略。
第二步:针对75M附件的可行解决方案
如果必须发送这个大文件,不建议硬怼Mailgun的限制,推荐这两种更稳妥的方式:
1. 上传到云存储,发临时下载链接(首推)
这是行业通用做法,既避开所有邮箱服务商的附件限制,又更安全:
- 把文件传到AWS S3、阿里云OSS或者你自己的服务器磁盘,生成一个带有效期的临时链接(比如24小时后失效)
- 在邮件正文里插入这个链接,告诉收件人点击下载
- Laravel里用
Storage门面就能快速实现,举个S3的例子:
// 生成24小时有效的临时下载链接 $downloadUrl = Storage::disk('s3')->temporaryUrl( 'path/to/your/large-file.zip', now()->addHours(24) ); // 然后在邮件视图里输出链接 // <a href="{{ $downloadUrl }}">点击下载大文件(24小时内有效)</a>
2. 若坚持用Mailgun发送(仅限付费版)
如果你是Mailgun付费用户,且确认编码后的总大小在100MB以内,可以做这些调整确保请求能成功:
- PHP端配置检查:除了
upload_max_filesize和post_max_size,一定要把memory_limit调到至少256MB(处理大文件需要足够内存),修改php.ini后记得重启PHP-FPM - Web服务器配置:
- Nginx:在
server块里添加client_max_body_size 100M;,同时确认LimitRequestBody设为104857600(100MB),然后重启Nginx - Apache:除了
LimitRequestBody,还要启用mod_reqtimeout模块,设置足够长的超时时间
- Nginx:在
- Laravel发送优化:用最新版的
laravel/mailgun包,避免旧版本的bug,发送时设置更长的超时时间:
use Illuminate\Support\Facades\Http; $response = Http::withToken(config('services.mailgun.secret')) ->timeout(300) // 设为5分钟超时,避免大文件上传超时 ->attach('large-file.zip', file_get_contents(storage_path('app/large-file.zip'))) ->post('https://api.mailgun.net/v3/mg.domain.com/messages', [ 'from' => '你的应用 <noreply@domain.com>', 'to' => '收件人@example.com', 'subject' => '大文件附件', 'text' => '请查收附件' ]);
处理大文件与邮件的通用建议
- 尽量用链接替代直接发附件:不仅Mailgun,Gmail、Outlook等主流邮箱也有25MB左右的附件限制,就算你发出去,收件人也可能收不到
- 先压缩文件:用ZIP或7-Zip压缩,文档、图片类文件压缩率很高,能大幅减小体积
- 异步发送:带大附件的邮件发送很耗时,别在用户请求里同步处理,用Laravel队列(Queue)异步发送,避免请求超时
- 监控发送状态:配置Laravel的邮件失败日志,或者用Mailgun的Webhook监控发送结果,及时处理失败情况
- 分块处理超大文件:如果文件远超100MB,拆成多个小文件分开发送,或者用云存储的分块上传功能后生成链接
内容的提问来源于stack exchange,提问作者Fenn-CS
相关产品推荐
相关产品推荐

