Magento 2.4在sales_order_place_after观察者中发送带CSV附件邮件
Magento 2.4 订单生成后自动发送带CSV附件邮件实现方案
现有代码问题前置修正
原有代码存在依赖缺失、属性未赋值的问题,先做基础修复:
- 类头部补充缺失的命名空间引用,禁止直接调用ObjectManager实例化类,严格遵循Magento2依赖注入规范
- 构造函数补充邮件发送、文件读取必需的依赖项,补全原有传入但未赋值的类属性
- 所有路径读取、邮件发送逻辑绑定订单所属门店,适配多门店场景
第一步:补全类引用与构造函数依赖
首先在类文件顶部补充以下use引用:
use Magento\Framework\Filesystem\DirectoryList; use Psr\Log\LoggerInterface; use Magento\Framework\Mail\Template\TransportBuilder; use Magento\Framework\Translate\Inline\StateInterface; use Magento\Framework\Filesystem\Driver\File as FileDriver; use Magento\Framework\Mail\MimePart; use Magento\Framework\Mail\MimeMessage;
修正后的构造函数如下,替换原有构造函数即可:
public function __construct( \Magento\Framework\App\RequestInterface $request, \Magento\Sales\Model\Order $order, \Magento\Framework\App\Response\Http\FileFactory $fileFactory, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Customer\Model\Customer $customer, \Magento\Store\Model\StoreManagerInterface $storemanager, \Magento\Checkout\Model\Session $checkoutSession, \Magento\Sales\Model\OrderFactory $orderFactory, LoggerInterface $logger, \Magento\Catalog\Model\ProductFactory $productFactory, \Magento\Catalog\Model\ProductRepository $productRepository, TransportBuilder $transportBuilder, StateInterface $inlineTranslation, FileDriver $fileDriver ) { $this->_scopeConfig = $scopeConfig; $this->_customer = $customer; $this->_storemanager = $storemanager; $this->_request = $request; $this->_order = $order; $this->_fileFactory = $fileFactory; $this->directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); $this->_productRepository = $productRepository; $this->logger = $logger; $this->_checkoutSession = $checkoutSession; $this->_orderFactory = $orderFactory; $this->transportBuilder = $transportBuilder; $this->inlineTranslation = $inlineTranslation; $this->fileDriver = $fileDriver; }
注意:原有构造函数里传入的ObjectManager依赖直接删除,Magento2禁止在业务代码中直接调用ObjectManager,会导致编译报错、模式不兼容问题。
第二步:在execute方法中补充邮件发送逻辑
在原有CSV生成代码的$stream->close();行之后,补充以下邮件发送代码。该代码适配Magento2.4版本的邮件接口,不会出现版本兼容问题:
// CSV文件绝对路径 $filePath = $this->directory->getAbsolutePath($file); try { // 暂停行内翻译,避免邮件内容异常 $this->inlineTranslation->suspend(); // 读取CSV文件内容生成附件 $fileContent = $this->fileDriver->fileGetContents($filePath); $attachment = new MimePart( $fileContent, 'text/csv', \Zend_Mime::DISPOSITION_ATTACHMENT, \Zend_Mime::ENCODING_BASE64, basename($filePath) ); // 从系统配置读取发件人信息(通用销售邮箱配置) $sender = [ 'name' => $this->_scopeConfig->getValue( 'trans_email/ident_sales/name', \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $order->getStoreId() ), 'email' => $this->_scopeConfig->getValue( 'trans_email/ident_sales/email', \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $order->getStoreId() ) ]; // 构建邮件 $transport = $this->transportBuilder->setTemplateIdentifier('sales_order_csv_email') // 此处替换为你自己创建的邮件模板ID ->setTemplateOptions([ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, 'store' => $order->getStoreId() ]) ->setTemplateVars([ 'order' => $order, 'customer_name' => $order->getCustomerName() ]) ->setFrom($sender) ->addTo($order->getCustomerEmail(), $order->getCustomerName()) ->addAttachment($attachment) // 2.4版本原生支持addAttachment方法,无需修改核心类 ->getTransport(); // 发送邮件 $transport->sendMessage(); $this->inlineTranslation->resume(); // 若不需要留存CSV文件,可取消下方注释,发送成功后自动删除文件 // $this->fileDriver->deleteFile($filePath); } catch (\Exception $e) { $this->inlineTranslation->resume(); // 邮件发送失败仅记录日志,不阻断正常下单流程 $this->logger->error('订单CSV邮件发送失败,订单ID:' . $order->getId() . ',错误信息:' . $e->getMessage()); }
上线前必做配置
- 进入后台 营销->通信->邮件模板,新建模板选择通用模板,填写邮件正文内容,模板标识设置为代码中对应的
sales_order_csv_email - 代码上传后执行以下命令生效:
bin/magento setup:di:compile bin/magento cache:clean
注意事项
- 不要使用网上流传的直接修改TransportBuilder核心类、实例化废弃Zend_Mail类的方案,上述代码使用2.4版本原生支持的接口,升级小版本不会出现兼容问题
- 多门店场景下所有配置读取都绑定订单所属门店ID,不会出现门店信息错配
- 异常捕获逻辑保证邮件发送失败时不会导致用户下单报错,影响转化
内容的提问来源于stack exchange,提问作者samina khan
相关产品推荐
相关产品推荐

