Laravel站点根目录Cron脚本使用Mail facade发邮件失败求助
首先咱们先搞定最开始的「a facade root has not been set」错误——这是因为Cron执行的脚本是独立进程,没有加载Laravel的框架环境,Facades根本没法工作。你需要在脚本开头正确初始化Laravel,下面是标准的初始化代码:
<?php // 替换成你的Laravel项目根目录绝对路径 $rootPath = '/path/to/your/laravel/project'; // 加载自动加载器 require $rootPath.'/vendor/autoload.php'; // 初始化Laravel应用 $app = require_once $rootPath.'/bootstrap/app.php'; // 启动应用内核,完成框架初始化 $kernel = $app->make(Illuminate\Contracts\Console\Kernel::class); $kernel->bootstrap();
这段代码会帮你把Laravel的整个环境搭起来,Facades就能正常调用了。
接下来解决「无报错但收不到邮件」的问题,咱们一步步排查:
检查Cron执行环境的配置加载
Cron的执行环境和Web服务器不一样,可能读不到你的.env文件里的邮件配置。你可以在脚本里临时打印配置确认:dd(config('mail'));如果配置不对,要么在Cron命令里指定工作目录(比如
cd /path/to/laravel && php script.php),要么在脚本里手动加载.env:$dotenv = Dotenv\Dotenv::createImmutable($rootPath); $dotenv->load();确认邮件驱动配置正确
检查.env里的MAIL_MAILER,如果是log或者array,邮件只会存在日志里或者内存里,不会实际发送。要改成smtp、sendmail或者你用的第三方邮件服务驱动(比如mailgun、ses),同时确保MAIL_HOST、MAIL_PORT、MAIL_USERNAME、MAIL_PASSWORD这些参数都准确无误。查看Laravel日志
就算脚本没抛出错误,邮件发送过程中的问题也会记录在storage/logs/laravel.log里。去看看日志里有没有和邮件相关的警告或者错误,比如SMTP连接失败、认证错误之类的细节。脱离Cron测试邮件发送
先直接在命令行里运行你的脚本:php /path/to/your/script.php,看看能不能收到邮件,同时观察命令行有没有输出错误。另外也可以用Artisan命令快速测试邮件配置:php artisan tinker Mail::raw('测试邮件内容', function($message) { $message->to('your-email@example.com')->subject('测试邮件'); });如果这个测试能收到邮件,那问题大概率出在Cron的执行环境上,比如权限、路径或者环境变量。
检查Cron执行权限
确保执行Cron的用户和Web服务器用户一致(比如都是www-data),不然可能会出现权限问题,比如无法写入日志、无法读取配置文件。你可以在脚本里加一句echo whoami();确认当前执行用户。确认邮件队列状态(如果用了队列)
如果你配置了邮件队列(比如MAIL_QUEUE=database),那邮件会被放进队列,需要启动队列worker才能实际发送:php artisan queue:work如果Cron脚本发送邮件用了队列,但worker没在运行,邮件就会一直留在队列里,不会发送出去。
内容的提问来源于stack exchange,提问作者Stephsen

