skip to Main Content

Hallo everyone,

since the release of Magento 2.2 the old override Zend_Mail_Transport_Sendmail does not work anymore.

before, an rewrite in etc/di.xml and model/Transport.php worked.

<preference for="MagentoFrameworkMailTransport" type="MyModulMyPluginModelTransport"/>

and

namespace MyModulMyPluginModel;

class Transport extends Zend_Mail_Transport_Sendmail implements MagentoFrameworkMailTransportInterface
{

    protected $_message;

    /**
     * @param MagentoFrameworkMailMessageInterface $message
     * @throws Zend_Mail_Exception
     */
    public function __construct(
        MagentoFrameworkMailMessageInterface $message
    )
    {
        if (!$message instanceof Zend_Mail) {
            throw new InvalidArgumentException('The message should be an instance of Zend_Mail');
        }

        parent::__construct('-f ' . '[email protected]');
        $this->_message = $message;
    }



   /**
     * Send a mail using this transport
     *
     * @return void
     * @throws MagentoFrameworkExceptionMailException
     */
    public function sendMessage()
    {
        try {
            parent::send($this->_message);
        } catch (Exception $e) {
            throw new MagentoFrameworkExceptionMailException(new MagentoFrameworkPhrase($e->getMessage()), $e);
        }
    }

    /**
     * @inheritdoc
     */
    public function getMessage()
    {
        return $this->_message;
    }

    /**
     * Send mail using PHP native mail()
     *
     * @access public
     * @return void
     * @throws Zend_Mail_Transport_Exception if parameters is set
     *         but not a string
     * @throws Zend_Mail_Transport_Exception on mail() failure
     */
    public function _sendMail()
    {

        /**
         *  revert changes from update to 2.1.7
         *
         *  mailing was not working with Envelope >= 2.1.7
         */
        if ($this->parameters === null) {
            set_error_handler(array($this, '_handleMailErrors'));
            $result = mail(
                $this->recipients,
                $this->_mail->getSubject(),
                $this->body,
                $this->header);
            restore_error_handler();
        } else {
            if(!is_string($this->parameters)) {
                /**
                 * @see Zend_Mail_Transport_Exception
                 *
                 * Exception is thrown here because
                 * $parameters is a public property
                 */
                #require_once 'Zend/Mail/Transport/Exception.php';
                throw new Zend_Mail_Transport_Exception(
                    'Parameters were set but are not a string'
                );
            }

            set_error_handler(array($this, '_handleMailErrors'));
            $result = mail(
                $this->recipients,
                $this->_mail->getSubject(),
                $this->body,
                $this->header,
                $this->parameters);
            restore_error_handler();
        }

        if ($this->_errstr !== null || !$result) {
            /**
             * @see Zend_Mail_Transport_Exception
             */
            #require_once 'Zend/Mail/Transport/Exception.php';
            throw new Zend_Mail_Transport_Exception('Unable to send mail. ' . $this->_errstr);
        }
    }
}

But now i am kind of lost

I tryed creating a plugin, which seem to be the ways it is supposed to be done now.

<type name="MagentoFrameworkMailTransport">
    <plugin sortOrder="50" name="SendMailPlugin" type="MyModulMyPluginPluginSendMailPlugin"/>
</type>

I also read about overriding “TransportInterface”, but i am not getting it to work. I only need it to call the constructor on my plugin.

best regards and thanks in advance

UPDATE:

It is working again now. The Problem was really just the TransportInterface. I thought i tryed that already or maybe it had something to do with “generation” cache …

<preference for="MagentoFrameworkMailTransportInterface" type="MyModulMyPluginModelTransport" />

So when override a class the preference needs to point to the interface.

I did not get the plugin version to work yet. In my first attempts i was not even sure how to call the methode in the plugin “after__construct” or “afterConstruct”. Also it is calling the parent::contruct.

If i get it to work in the end i will post it.

Thanks you all for your help.

UPDATE 2:

A Plugin solution ist not possible in this case, since contruct methodes can not be set for a plugin.

https://www.mageplaza.com/magento-2-module-development/magento-2-plugin-interceptor.html

3

Answers


  1. Ok, first of all you misunderstand the role of plugins in Magento 2. You try to use it as a class which overrides another class but this is a wrong approach. With plugins you are able to wrap public methods in a class either by changing input, output or both. You can read more about plugins in documentation

    What you are looking for is an override in M2 fashion so you need to get familiar with dependency injection and preferences

    Your initial approach is correct. Do you have properly configured sequence in your module to make sure that your module is loaded after Magento_Email? Verify the sequence in etc/config.php

    Another thing you can try is to set preference for TransportInterface rather than on transport model especially if your override is global.

    Login or Signup to reply.
  2. You need to use plugin for model
    app/code/Magento/Email/Model/Transport.php

    Create yours di.xml in the folder of your module

    <config>
    <type name="MagentoEmailModelTransport">
      <plugin name="yourpluginforemail" type="MyModuleModelMyPlugin" sortOrder="1" />
    </type>
    

    And your plugin file should be looke like

        <?php
    
    namespace MyModuleModel;
    
    class MyPlugin
    {
        public function afterSendEmail($subject, $result)
        {
            return 'some thing else'
        }
    }
    ?>
    

    Or if you want, you can override this file by creation own and set sequence

    die.xml in your module

    and

    module.xml

    <module name="My_Module" setup_version="2.0.1">
                <sequence>
                    <module name="Magento_Email"/>
    
                </sequence>
            </module>
    

    Then it will override it.

    So two ways – override class or one method via “after”, “before” “around” plugin

    Login or Signup to reply.
  3. Bartosz Herba

    solution worked in single shot. Thank you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search