订单已经生成,后台也能看到邮箱地址,但客户收不到通知。先不要用同一订单反复测试,因为发信逻辑可能已经把它标记为 queued。应从“是否排队、谁消费、是否交给邮件服务器”三段拆开检查。

确定当前是不是异步发送

bin/magento config:show sales_email/general/async_sending
bin/magento cron:run --group default
php -r 'echo date("c"), PHP_EOL;'
date -u

异步发送开启时,结账成功只负责记录需要发送,真正发送依赖 Cron。应用时区、数据库 UTC 时间和服务器时间差异过大,会让任务看起来“还没到执行时间”。

不要只看 cron:run 的退出码

SELECT job_code, status, scheduled_at, executed_at, finished_at,
       LEFT(messages, 300) AS message
FROM cron_schedule
WHERE job_code LIKE '%email%' OR job_code LIKE '%send%'
ORDER BY schedule_id DESC LIMIT 30;

SELECT status, COUNT(*)
FROM cron_schedule
WHERE scheduled_at > UTC_TIMESTAMP() - INTERVAL 2 HOUR
GROUP BY status;

大量 pending 且 executed_at 为空,优先查系统 crontab 和进程锁;大量 error,读取 messages 和 var/log/cron.log;success 但仍无邮件,则说明 Magento 任务跑完了,问题可能在 transport、SMTP 中继或收件方。

用单独的传输测试隔离 SMTP

openssl s_client -starttls smtp -connect smtp.example.com:587 -crlf
nc -vz smtp.example.com 587
grep -RniE 'smtp|transport|mail|authentication failed|timed out' var/log | tail -n 80

生产环境不要把真实密码写进命令历史。若使用 SMTP 扩展,打开它自己的 debug 日志并完成一次受控测试,然后立即关闭详细日志,避免记录收件人和服务器响应。

订单状态与发送标志也要核对

SELECT entity_id, increment_id, customer_email,
       send_email, email_sent, created_at
FROM sales_order
WHERE increment_id='000000123';

send_email=0 表示该订单根本没被安排发送;email_sent=1 只代表应用认为发送完成,不等于对方收件箱一定收到。后者要继续查邮件服务商的投递、退信和抑制列表。

修复后新建一笔测试订单,记录订单号、Cron 执行时间和邮件服务商 message ID。只有这三处能串起来,才算链路恢复;“后台点发送邮件没有报错”不是可靠结论。