diff --git a/app/code/Magento/Newsletter/Model/Template.php b/app/code/Magento/Newsletter/Model/Template.php index 5e4b273b9c62b..d6fad4b8f0f77 100644 --- a/app/code/Magento/Newsletter/Model/Template.php +++ b/app/code/Magento/Newsletter/Model/Template.php @@ -38,12 +38,6 @@ */ class Template extends \Magento\Email\Model\AbstractTemplate { - /** - * Mail object - * - * @var \Zend_Mail - */ - protected $_mail; /** * Store manager to emulate design diff --git a/composer.json b/composer.json index e7c306315a5c5..b40c6b6fca1ce 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "zendframework/zend-validator": "^2.6.0", "zendframework/zend-crypt": "^2.6.0", "zendframework/zend-console": "^2.6.0", + "zendframework/zend-mail": "^2.8.0", "zendframework/zend-modulemanager": "^2.7", "zendframework/zend-mvc": "~2.6.3", "zendframework/zend-text": "^2.6.0", diff --git a/composer.lock b/composer.lock index 88e39d69744ca..ca47fe4bbb2c3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "36aef861e85e9529c55d9b2d2910bd44", + "content-hash": "ef3db62dd163eb8ffe9085e10041e6e5", "packages": [ { "name": "braintree/braintree_php", @@ -1479,16 +1479,16 @@ }, { "name": "symfony/console", - "version": "v2.8.22", + "version": "v2.8.24", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "3ef6ef64abecd566d551d9e7f6393ac6e93b2462" + "reference": "46e65f8d98c9ab629bbfcc16a4ff023f61c37fb2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3ef6ef64abecd566d551d9e7f6393ac6e93b2462", - "reference": "3ef6ef64abecd566d551d9e7f6393ac6e93b2462", + "url": "https://api.github.com/repos/symfony/console/zipball/46e65f8d98c9ab629bbfcc16a4ff023f61c37fb2", + "reference": "46e65f8d98c9ab629bbfcc16a4ff023f61c37fb2", "shasum": "" }, "require": { @@ -1536,7 +1536,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-06-02T14:36:56+00:00" + "time": "2017-07-03T08:04:30+00:00" }, { "name": "symfony/debug", @@ -1597,7 +1597,7 @@ }, { "name": "symfony/event-dispatcher", - "version": "v2.8.22", + "version": "v2.8.24", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -1657,16 +1657,16 @@ }, { "name": "symfony/filesystem", - "version": "v3.3.2", + "version": "v3.3.4", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "c709670bf64721202ddbe4162846f250735842c0" + "reference": "311fa718389efbd8b627c272b9324a62437018cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/c709670bf64721202ddbe4162846f250735842c0", - "reference": "c709670bf64721202ddbe4162846f250735842c0", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/311fa718389efbd8b627c272b9324a62437018cc", + "reference": "311fa718389efbd8b627c272b9324a62437018cc", "shasum": "" }, "require": { @@ -1702,11 +1702,11 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2017-05-28T14:08:56+00:00" + "time": "2017-06-24T09:29:48+00:00" }, { "name": "symfony/finder", - "version": "v3.3.2", + "version": "v3.3.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -1814,16 +1814,16 @@ }, { "name": "symfony/process", - "version": "v2.8.22", + "version": "v2.8.24", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d54232f5682fda2f8bbebff7c81b864646867ab9" + "reference": "57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d54232f5682fda2f8bbebff7c81b864646867ab9", - "reference": "d54232f5682fda2f8bbebff7c81b864646867ab9", + "url": "https://api.github.com/repos/symfony/process/zipball/57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8", + "reference": "57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8", "shasum": "" }, "require": { @@ -1859,7 +1859,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-05-08T01:19:21+00:00" + "time": "2017-07-03T08:04:30+00:00" }, { "name": "tedivm/jshrink", @@ -2960,6 +2960,68 @@ ], "time": "2017-05-17T16:03:26+00:00" }, + { + "name": "zendframework/zend-mail", + "version": "2.8.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-mail.git", + "reference": "248230940ab1453b2a532a8fde76c5a6470d7aad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-mail/zipball/248230940ab1453b2a532a8fde76c5a6470d7aad", + "reference": "248230940ab1453b2a532a8fde76c5a6470d7aad", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": "^7.0 || ^5.6", + "zendframework/zend-loader": "^2.5", + "zendframework/zend-mime": "^2.5", + "zendframework/zend-stdlib": "^2.7 || ^3.0", + "zendframework/zend-validator": "^2.6" + }, + "require-dev": { + "phpunit/phpunit": "^6.0.8 || ^5.7.15", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-config": "^2.6", + "zendframework/zend-crypt": "^2.6", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3" + }, + "suggest": { + "ext-intl": "Handle IDN in AddressList hostnames", + "zendframework/zend-crypt": "Crammd5 support in SMTP Auth", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3 when using SMTP to deliver messages" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev", + "dev-develop": "2.9-dev" + }, + "zf": { + "component": "Zend\\Mail", + "config-provider": "Zend\\Mail\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\Mail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages", + "homepage": "https://github.com/zendframework/zend-mail", + "keywords": [ + "mail", + "zf2" + ], + "time": "2017-06-08T20:03:58+00:00" + }, { "name": "zendframework/zend-math", "version": "2.7.0", @@ -3010,6 +3072,55 @@ ], "time": "2016-04-07T16:29:53+00:00" }, + { + "name": "zendframework/zend-mime", + "version": "2.6.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-mime.git", + "reference": "9e53a97a3c190d45cc5d584daaaf487d509a9285" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-mime/zipball/9e53a97a3c190d45cc5d584daaaf487d509a9285", + "reference": "9e53a97a3c190d45cc5d584daaaf487d509a9285", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.7 || ^5.7", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-mail": "^2.6" + }, + "suggest": { + "zendframework/zend-mail": "Zend\\Mail component" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev", + "dev-develop": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Mime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-mime", + "keywords": [ + "mime", + "zf2" + ], + "time": "2017-01-16T16:43:38+00:00" + }, { "name": "zendframework/zend-modulemanager", "version": "2.7.2", @@ -4945,7 +5056,7 @@ }, { "name": "symfony/config", - "version": "v3.2.9", + "version": "v3.2.11", "source": { "type": "git", "url": "https://github.com/symfony/config.git", @@ -5337,7 +5448,7 @@ }, { "name": "symfony/stopwatch", - "version": "v3.3.2", + "version": "v3.3.4", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -5386,7 +5497,7 @@ }, { "name": "symfony/yaml", - "version": "v2.8.22", + "version": "v2.8.24", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", @@ -5435,16 +5546,16 @@ }, { "name": "theseer/fdomdocument", - "version": "1.6.5", + "version": "1.6.6", "source": { "type": "git", "url": "https://github.com/theseer/fDOMDocument.git", - "reference": "8dcfd392135a5bd938c3c83ea71419501ad9855d" + "reference": "6e8203e40a32a9c770bcb62fe37e68b948da6dca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/8dcfd392135a5bd938c3c83ea71419501ad9855d", - "reference": "8dcfd392135a5bd938c3c83ea71419501ad9855d", + "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/6e8203e40a32a9c770bcb62fe37e68b948da6dca", + "reference": "6e8203e40a32a9c770bcb62fe37e68b948da6dca", "shasum": "" }, "require": { @@ -5471,7 +5582,7 @@ ], "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.", "homepage": "https://github.com/theseer/fDOMDocument", - "time": "2017-04-21T14:50:31+00:00" + "time": "2017-06-30T11:53:12+00:00" } ], "aliases": [], diff --git a/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php b/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php index cd23913a34a3d..e26a33d73e537 100644 --- a/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php +++ b/dev/tests/integration/testsuite/Magento/Newsletter/Model/SubscriberTest.php @@ -6,6 +6,8 @@ namespace Magento\Newsletter\Model; +use Magento\TestFramework\Mail\Template\TransportBuilderMock; + class SubscriberTest extends \PHPUnit_Framework_TestCase { /** @@ -27,13 +29,14 @@ protected function setUp() public function testEmailConfirmation() { $this->_model->subscribe('customer_confirm@example.com'); + /** @var TransportBuilderMock $transportBuilder */ $transportBuilder = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->get(\Magento\TestFramework\Mail\Template\TransportBuilderMock::class); // confirmationCode 'ysayquyajua23iq29gxwu2eax2qb6gvy' is taken from fixture $this->assertContains( '/newsletter/subscriber/confirm/id/' . $this->_model->getSubscriberId() . '/code/ysayquyajua23iq29gxwu2eax2qb6gvy', - $transportBuilder->getSentMessage()->getBodyHtml()->getRawContent() + $transportBuilder->getSentMessage()->getRawMessage() ); $this->assertEquals(Subscriber::STATUS_NOT_ACTIVE, $this->_model->getSubscriberStatus()); } diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/Model/EmailTest.php b/dev/tests/integration/testsuite/Magento/ProductAlert/Model/EmailTest.php index 681b0afd10ae8..5262cc7b4b571 100644 --- a/dev/tests/integration/testsuite/Magento/ProductAlert/Model/EmailTest.php +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/Model/EmailTest.php @@ -82,7 +82,7 @@ public function testSend($isCustomerIdUsed) ); $this->assertContains( 'John Smith,', - $transportBuilder->getSentMessage()->getBodyHtml()->getRawContent() + $transportBuilder->getSentMessage()->getRawMessage() ); } diff --git a/dev/tests/integration/testsuite/Magento/ProductAlert/Model/ObserverTest.php b/dev/tests/integration/testsuite/Magento/ProductAlert/Model/ObserverTest.php index 64bc4dff5674a..cf59839d83f93 100644 --- a/dev/tests/integration/testsuite/Magento/ProductAlert/Model/ObserverTest.php +++ b/dev/tests/integration/testsuite/Magento/ProductAlert/Model/ObserverTest.php @@ -56,7 +56,7 @@ public function testProcess() ); $this->assertContains( 'John Smith,', - $transportBuilder->getSentMessage()->getBodyHtml()->getRawContent() + $transportBuilder->getSentMessage()->getRawMessage() ); } } diff --git a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php index 8d9e2d697d8c8..395753ed28cff 100644 --- a/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php +++ b/dev/tests/integration/testsuite/Magento/Wishlist/Controller/IndexTest.php @@ -158,7 +158,7 @@ public function testSendAction() ); $actualResult = \Zend_Mime_Decode::decodeQuotedPrintable( - $transportBuilder->getSentMessage()->getBodyHtml()->getContent() + $transportBuilder->getSentMessage()->getRawMessage() ); $this->assertStringMatchesFormat( diff --git a/lib/internal/Magento/Framework/Mail/Message.php b/lib/internal/Magento/Framework/Mail/Message.php index 9a99f7d8f11ef..89581b36c62fc 100644 --- a/lib/internal/Magento/Framework/Mail/Message.php +++ b/lib/internal/Magento/Framework/Mail/Message.php @@ -7,14 +7,29 @@ */ namespace Magento\Framework\Mail; -class Message extends \Zend_Mail implements MessageInterface +use Zend\Mime\Mime; +use Zend\Mime\Part; + +/** + * @todo get rid of temporal coupling (setMessageType() + setBody()) + * - deprecate setMessageType(), setBody() and getBody() + * - implement setBodyHtml(), setBodyText(), getBodyHtml() and getBodyText() + * - change usage in \Magento\Framework\Mail\Template\TransportBuilder::prepareMessage() + */ +class Message implements MessageInterface { /** - * @param string $charset + * @var \Zend\Mail\Message + */ + private $zendMessage; + + /** + * @param string $encoding */ - public function __construct($charset = 'utf-8') + public function __construct($encoding = 'utf-8') { - parent::__construct($charset); + $this->zendMessage = new \Zend\Mail\Message; + $this->zendMessage->setEncoding($encoding); } /** @@ -25,35 +40,125 @@ public function __construct($charset = 'utf-8') protected $messageType = self::TYPE_TEXT; /** - * Set message body + * Set message type * - * @param string $body + * @param string $type + * @return $this + */ + public function setMessageType($type) + { + $this->messageType = $type; + return $this; + } + + /** + * @param null|object|string|\Zend\Mime\Message $body * @return $this */ public function setBody($body) { - return $this->messageType == self::TYPE_TEXT ? $this->setBodyText($body) : $this->setBodyHtml($body); + if (is_string($body) && $this->messageType === MessageInterface::TYPE_HTML) { + $body = self::createHtmlMimeFromString($body); + } + $this->zendMessage->setBody($body); + return $this; } /** - * Set message body - * - * @return string + * @param string $subject + * @return $this + */ + public function setSubject($subject) + { + $this->zendMessage->setSubject($subject); + return $this; + } + + /** + * @return null|string + */ + public function getSubject() + { + return $this->zendMessage->getSubject(); + } + + /** + * @return object */ public function getBody() { - return $this->messageType == self::TYPE_TEXT ? $this->getBodyText() : $this->getBodyHtml(); + return $this->zendMessage->getBody(); } /** - * Set message type - * - * @param string $type + * @param array|string $fromAddress * @return $this */ - public function setMessageType($type) + public function setFrom($fromAddress) { - $this->messageType = $type; + $this->zendMessage->setFrom($fromAddress); + return $this; + } + + /** + * @param array|string $toAddress + * @return $this + */ + public function addTo($toAddress) + { + $this->zendMessage->addTo($toAddress); + return $this; + } + + /** + * @param array|string $ccAddress + * @return $this + */ + public function addCc($ccAddress) + { + $this->zendMessage->addCc($ccAddress); + return $this; + } + + /** + * @param array|string $bccAddress + * @return $this + */ + public function addBcc($bccAddress) + { + $this->zendMessage->addBcc($bccAddress); + return $this; + } + + /** + * @param array|string $replyToAddress + * @return $this + */ + public function setReplyTo($replyToAddress) + { + $this->zendMessage->setReplyTo($replyToAddress); return $this; } + + /** + * @return string + */ + public function getRawMessage() + { + return $this->zendMessage->toString(); + } + + /** + * @param string $htmlBody + * @return \Zend\Mime\Message + */ + private function createHtmlMimeFromString($htmlBody) + { + $htmlPart = new Part($htmlBody); + $htmlPart->setCharset($this->zendMessage->getEncoding()); + $htmlPart->setType(Mime::TYPE_HTML); + $mimeMessage = new \Zend\Mime\Message(); + $mimeMessage->addPart($htmlPart); + return $mimeMessage; + } } diff --git a/lib/internal/Magento/Framework/Mail/MessageInterface.php b/lib/internal/Magento/Framework/Mail/MessageInterface.php index 868f2a4c9cfa9..939b5b73d31fe 100644 --- a/lib/internal/Magento/Framework/Mail/MessageInterface.php +++ b/lib/internal/Magento/Framework/Mail/MessageInterface.php @@ -96,4 +96,11 @@ public function setReplyTo($replyToAddress); * @return $this */ public function setMessageType($type); + + /** + * Get message source code + * + * @return string + */ + public function getRawMessage(); } diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php index a21207511f0fa..3f272fae43842 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/MessageTest.php @@ -14,6 +14,7 @@ class MessageTest extends \PHPUnit_Framework_TestCase protected function setUp() { + $this->markTestSkipped('obsolete ZF 1 test'); $this->_messageMock = $this->getMock( \Magento\Framework\Mail\Message::class, ['getBodyText', 'getBodyHtml', 'setBodyText', 'setBodyHtml'] diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/TransportTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/TransportTest.php index 21975168fbfcf..5badc8efee95f 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/TransportTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/TransportTest.php @@ -7,43 +7,17 @@ class TransportTest extends \PHPUnit_Framework_TestCase { - /** - * @var \PHPUnit_Framework_MockObject - */ - protected $_messageMock; - - /** - * @var \Magento\Framework\Mail\Transport - */ - protected $_transport; - - protected function setUp() - { - $this->_messageMock = $this->getMock(\Magento\Framework\Mail\Message::class, [], [], '', false); - $this->_transport = new \Magento\Framework\Mail\Transport($this->_messageMock); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The message should be an instance of \Zend_Mail - */ - public function testTransportWithIncorrectMessageObject() - { - $this->_messageMock = $this->getMock(\Magento\Framework\Mail\MessageInterface::class); - $this->_transport = new \Magento\Framework\Mail\Transport($this->_messageMock); - } - /** * @covers \Magento\Framework\Mail\Transport::sendMessage * @expectedException \Magento\Framework\Exception\MailException - * @expectedExceptionMessage No body specified + * @expectedExceptionMessage Invalid email; contains no "To" header */ public function testSendMessageBrokenMessage() { - $this->_messageMock->expects($this->any()) - ->method('getParts') - ->will($this->returnValue(['a', 'b'])); + $transport = new \Magento\Framework\Mail\Transport( + new \Magento\Framework\Mail\Message() + ); - $this->_transport->sendMessage(); + $transport->sendMessage(); } } diff --git a/lib/internal/Magento/Framework/Mail/Transport.php b/lib/internal/Magento/Framework/Mail/Transport.php index 257dc33b11676..0e969e372f454 100644 --- a/lib/internal/Magento/Framework/Mail/Transport.php +++ b/lib/internal/Magento/Framework/Mail/Transport.php @@ -6,12 +6,17 @@ */ namespace Magento\Framework\Mail; -class Transport extends \Zend_Mail_Transport_Sendmail implements \Magento\Framework\Mail\TransportInterface +class Transport implements \Magento\Framework\Mail\TransportInterface { + /** + * @var \Zend\Mail\Transport\Sendmail + */ + private $zendTransport; + /** * @var \Magento\Framework\Mail\MessageInterface */ - protected $_message; + private $message; /** * @param MessageInterface $message @@ -20,11 +25,8 @@ class Transport extends \Zend_Mail_Transport_Sendmail implements \Magento\Framew */ public function __construct(\Magento\Framework\Mail\MessageInterface $message, $parameters = null) { - if (!$message instanceof \Zend_Mail) { - throw new \InvalidArgumentException('The message should be an instance of \Zend_Mail'); - } - parent::__construct($parameters); - $this->_message = $message; + $this->zendTransport = new \Zend\Mail\Transport\Sendmail($parameters); + $this->message = $message; } /** @@ -36,7 +38,9 @@ public function __construct(\Magento\Framework\Mail\MessageInterface $message, $ public function sendMessage() { try { - parent::send($this->_message); + $this->zendTransport->send( + \Zend\Mail\Message::fromString($this->message->getRawMessage()) + ); } catch (\Exception $e) { throw new \Magento\Framework\Exception\MailException(new \Magento\Framework\Phrase($e->getMessage()), $e); }