Как работает асинхронная отправка электронной почты в 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?

Author: Sejal Shah, 2017-10-26

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, то он имеет уже сделано.

 48
Author: Bunyamin Inan, 2017-10-26 12:19:51