5

Admin -> Stores -> Configuration -> Sales -> Sales Email -> Order -> Disabled

Where should I look and which module or modal to send the same email programmatically?

Update

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$order = $objectManager->create('\Magento\Sales\Model\Order')->load($orderId);

$emailSender = $objectManager->create('\Magento\Sales\Model\Order\Email\Sender\OrderSender');
$emailSender->send($order);

If I Admin -> Stores -> Configuration -> Sales -> Sales Email -> Order -> Disabled the above code doesn't trigger the email. Or if I enable, it send 2 email. I don't want the email that magento trigger for order confirmation. I want to do it.

1
  • Hello @iamkdev, it will send admin too? May 30, 2018 at 14:00

4 Answers 4

7

Look at Magento\Sales\Model\Order\Email\Sender\OrderSender. This is where you'll find the method to send the order confirmation for a given order.

1

Another solution without influencing Magento Core functionality (which happens when using a plugin) would be to inject a custom OrderIdentity that will always return true for isEnabled.

I tried out the solution on Magento OSS ver. 2.4.2-p1.

First, you extend \Magento\Sales\Model\Order\Email\Container\OrderIdentity and just return true for isEnabled. Alhtough, extending should be kept to a minimum, I think it is ok in this case, as we won't override the original class with a preference. We will just use it as a argument in di.xml.

app/code/Vendor/YourModule/Model/Order/Email/Container/EnabledOrderIdentity.php:

<?php

declare(strict_types=1);

namespace Vendor\YourModule\Model\Order\Email\Container;

/**
 * An order identity that will ignore the configuration for sales_email/order/enabled.
 */
class EnabledOrderIdentity extends \Magento\Sales\Model\Order\Email\Container\OrderIdentity
{
    /**
     * Always return true and do not consider config options
     *
     * @return bool
     */
    public function isEnabled(): bool
    {
        return true;
    }
}

Now, as we have our custom identity that won't care when sales_email/order/enabled is disabled, we can create a virtual type that replaces the identityContainer argument for OrderSender with our custom one. This virtual type can be used as argument for places where the injected OrderSender should be able to send emails without paying attention to the sales_email/order/enabled` setting.

app/code/Vendor/YourModule/etc/di.xml:

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <!-- Virtual OrderSender type that ignores order email disable setting -->
    <virtualType name="Vendor\YourModule\Model\Order\Email\Sender\OrderSender"
                 type="Magento\Sales\Model\Order\Email\Sender\OrderSender">
        <arguments>
            <argument name="identityContainer" xsi:type="object">Vendor\YourModule\Model\Order\Email\Container\EnabledOrderIdentity</argument>
        </arguments>
    </virtualType>

    <!-- Example usage -->
    <type name="Class\Where\You\Want\Custom\OrderSender\Test">
        <arguments>
            <argument name="orderSender" xsi:type="object">Vendor\YourModule\Model\Order\Email\Sender\OrderSender</argument>
        </arguments>
    </type>
</config>

In the class where you want to programmatically send the email while sales_email/order/enabled is set to disabled, must use constructor injection (instead of ObjectManager) to inject your custom OrderSender.

This can look like the following example:

<?php

declare(strict_types=1);

namespace Class\Where\You\Want\Custom\OrderSender;

use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Model\Order\Email\Sender\OrderSender;

class Test {
    /**
     * @var OrderRepositoryInterface
     */
    private OrderRepositoryInterface $orderRepository;
    
    /**
     * @var OrderSender
     */
    private OrderSender $orderSender;

    /**
     * Index constructor.
     *
     * @param OrderRepositoryInterface $orderRepository
     * @param OrderSender $orderSender
     */
    public function __construct(
        OrderRepositoryInterface $orderRepository,
        OrderSender $orderSender
    ) {
        $this->orderRepository = $orderRepository;
        $this->orderSender = $orderSender;
    }

    public function someFunction() {
        $order = $this->orderRepository->get(8); // Your logic to get the order
        $this->orderSender->send($order); // Order sender has custom identity that ignores settings
    }
}
0

Simply you can use below code to send order email

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();        
$order = $objectManager->create('\Magento\Sales\Model\Order')->load($orderId);
$order->setCanSendNewEmailFlag(true);
$order->save();
$session = $objectManager->create('\Magento\Checkout\Model\Session');
$session->setForceOrderMailSentOnSuccess(true);
$emailSender = $objectManager->create('\Magento\Sales\Model\Order\Email\Sender\OrderSender');
$emailSender->send($order);

You should not use the ObjectManager directly!

0

A hacky script to force send order confirmation emails, used to recover when some SMTP connection errors occurred.

Don't use object manager or bootstrap magento like this in production code.

<?php
use Magento\Framework\App\Bootstrap;
require __DIR__ . '/app/bootstrap.php';
$bootstrap = Bootstrap::create(BP, $_SERVER);
$obj = $bootstrap->getObjectManager();
$state = $obj->get(Magento\Framework\App\State::class);
$state->setAreaCode('frontend');
$obj->get(\Magento\Store\Model\App\Emulation::class)->startEnvironmentEmulation(1, 'frontend'); # replace with store id

$incrementIds = [
    '123456789',
];

$counter = 1;
foreach ($incrementIds as $incrementId) {
    echo str_pad((string)$counter, 3, " ", STR_PAD_LEFT) . " - $incrementId - " ;
    $order = $obj->create(\Magento\Sales\Model\Order::class);
    $order->loadByIncrementId($incrementId);
    if (!$order->getId()) {
        echo "DOES NOT EXIST" . PHP_EOL;
        continue;
    }

    $orderSender = $obj->create(\Magento\Sales\Model\Order\Email\Sender\OrderSender::class);
    $orderSender->send($order);
    $counter++;
    echo "SENT" . PHP_EOL;
}

echo "DONE" . PHP_EOL;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.