Как работает асинхронная отправка электронной почты в Magento 2
В Magento 1.x если вы установите для этой конфигурации значение включено Store > Configration > Sales > Sales Emails > General Settings > Asynchronous sending
, Magento вместо отправки электронной почты при размещении заказа добавляет запись в таблицу очередей (core_email_queue
), а затем приходит задание cron, считывает все записи из очереди и отправляет электронные письма.
Я не нахожу core_email_queue
таблицу в Magento 2. Как эта функция работает в Magento 2?
1 answers
Я понятия не имел, как отправляются электронные письма в Magento 2, но ваш вопрос заинтересовал меня, поэтому я немного изучил.
Я начал свое расследование с поиска по электронной почте ключевого слова в cronjobs и получил следующий результат.
$ n98-magerun2 sys:cron:list | grep mail
| sales_send_order_creditmemo_emails | default | */1 | * | * | * | * |
| sales_send_order_emails | default | */1 | * | * | * | * |
| sales_send_order_invoice_emails | default | */1 | * | * | * | * |
| sales_send_order_shipment_emails | default | */1 | * | * | * | * |
Итак, есть несколько закадычных друзей, которые отвечают за отправку электронных писем. Это показывает нам, что они асинхронны.
Я выбрал sales_send_order_emails
cronjob для исследования, потому что я могу легко создать новый заказ для его тестирования. Тогда у меня есть искал sales_send_order_emails
во всем проекте и нашел следующий файл vendor/magento/module-sales/etc/crontab.xml
. В нем есть следующая запись cron-задания.
<job name="sales_send_order_emails" instance="SalesOrderSendEmailsCron" method="execute">
<schedule>*/1 * * * *</schedule>
</job>
SalesOrderSendEmailsCron
очевидно, что это виртуальный тип, в противном случае он должен иметь пространства имен. Этот виртуальный тип определен в vendor/magento/module-sales/etc/di.xml
.
<virtualType name="SalesOrderSendEmailsCron" type="Magento\Sales\Cron\SendEmails">
<arguments>
<argument name="emailSenderHandler" xsi:type="object">SalesOrderSendEmails</argument>
</arguments>
</virtualType>
Таким образом, виртуальный тип SalesOrderSendEmailsCron
на самом деле является классом Magento\Sales\Cron\SendEmails
. Как вы можете видеть, у этого класса есть конструктор только с одним аргументом, и он задан как виртуальный тип SalesOrderSendEmails
. Этот виртуальный тип также определен в vendor/magento/module-sales/etc/di.xml
. Вот такой тип определение:
<virtualType name="SalesOrderSendEmails" type="Magento\Sales\Model\EmailSenderHandler">
<arguments>
<argument name="emailSender" xsi:type="object">Magento\Sales\Model\Order\Email\Sender\OrderSender</argument>
<argument name="entityResource" xsi:type="object">Magento\Sales\Model\ResourceModel\Order</argument>
<argument name="entityCollection" xsi:type="object" shared="false">Magento\Sales\Model\ResourceModel\Order\Collection</argument>
</arguments>
</virtualType>
Таким образом, настоящим отправителем почты является Magento\Sales\Model\EmailSenderHandler
. Если вы откроете этот файл, вы увидите следующий метод:
public function sendEmails()
{
if ($this->globalConfig->getValue('sales_email/general/async_sending')) {
$this->entityCollection->addFieldToFilter('send_email', ['eq' => 1]);
$this->entityCollection->addFieldToFilter('email_sent', ['null' => true]);
/** @var \Magento\Sales\Model\AbstractModel $item */
foreach ($this->entityCollection->getItems() as $item) {
if ($this->emailSender->send($item, true)) {
$this->entityResource->save(
$item->setEmailSent(true)
);
}
}
}
}
Если вы зададите sales_email/general/async_sending
конфигурацию как true
, то это задание будет отправлять почту. Он также имеет следующие фильтры для выборки заказов.
$this->entityCollection->addFieldToFilter('send_email', ['eq' => 1]);
$this->entityCollection->addFieldToFilter('email_sent', ['null' => true]);
В результате у вас есть атрибуты send_email
и email_sent
в вашей таблице sales_order
. Если для send_email
задано значение 1
для заказа, это задание должно отправить электронное письмо для заказа. Если email_sent
не NULL
, то он имеет уже сделано.