Skip to content

Sending multiple emails using the TransportBuilder class causes an Zend_Mail exception #14236

@david-kominek

Description

@david-kominek

Preconditions

  1. Magento 2.2.3
  2. PHP 7.0.12
  3. MySQL 5.7.18

Steps to reproduce

  1. Fresh install of Magento
  2. Make a custom module with 2 observer classes on an event('sales_order_place_after'). Each of these observers should inject the TransportBuilder class and send an email:
$transport = $this->transportBuilder
    ->setTemplateIdentifier('email_template_identifier')
    ->setTemplateOptions([
        'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
        'store' => 1
    ])
    ->setTemplateVars($data)
    ->setFrom($sender)
    ->addTo($mailto);

// important that this is its own line for when we override the transport builder due to how PHP polymorphism works :(
$transport = $this->transportBuilder->getTransport();

$transport->sendMessage();
  1. Checkout and place an order.

Expected result

  1. Two emails will be sent...

Actual result

  1. The first email is sent, the second email is never sent...
  2. The second observer will throw an exception in the $transport->sendMessage() function: throw new Zend_Mail_Exception('From Header set twice');
  3. The system.log file will show the following line: "[2018-03-21 19:32:06] main.ERROR: From Header set twice [] []"

The issue seems to be that the transport builder is not adequately cleaning up the $message variable after getting the transport. The solution is to overwrite the TransportBuilder class, and in the function getTransport() to the following:

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
	<preference for="Magento\Framework\Mail\Template\TransportBuilder" type="Vendor\Module\Model\Mail\TransportBuilder" />
</config>
class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
    public function getTransport()
    {
        $mailTransport = parent::getTransport();
        $this->message->clearFrom()
            ->clearReplyTo()
            ->clearReturnPath()
            ->clearSubject()
            ->clearMessageId()
            ->clearRecipients()
            ->setParts([]);

        return $mailTransport;
    }
}

Edit: I don't feel that @dimonovp really reviewed this ticket. Can we have it reopened and reviewed?

Metadata

Metadata

Assignees

Labels

Fixed in 2.3.xThe issue has been fixed in 2.3 release lineIssue: Cannot ReproduceCannot reproduce the issue on the latest `2.4-develop` branchIssue: Clear DescriptionGate 2 Passed. Manual verification of the issue description passedIssue: Format is validGate 1 Passed. Automatic verification of issue format passed

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions