From 9aeca804a78c2025830e29f941eccd638c3c6038 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Wed, 24 Jul 2019 18:32:32 +0300 Subject: [PATCH 01/37] MC-15295: Added new Mail Interfaces, switched implementation in the Transport builder --- .../Magento/Email/Model/MailTransport.php | 113 +++++++++ app/code/Magento/Email/etc/di.xml | 5 +- .../Framework/Mail/MailEnvelopeBuilder.php | 69 ++++++ .../Framework/Mail/MessageEnvelope.php | 224 ++++++++++++++++++ .../Mail/MessageEnvelopeInterface.php | 97 ++++++++ .../Mail/MessageEnvelopeInterfaceFactory.php | 55 +++++ .../Magento/Framework/Mail/MimeInterface.php | 31 +++ .../Magento/Framework/Mail/MimeMessage.php | 81 +++++++ .../Framework/Mail/MimeMessageInterface.php | 65 +++++ .../Mail/MimeMessageInterfaceFactory.php | 55 +++++ .../Magento/Framework/Mail/MimePart.php | 209 ++++++++++++++++ .../Framework/Mail/MimePartInterface.php | 133 +++++++++++ .../Mail/MimePartInterfaceFactory.php | 49 ++++ .../Mail/Template/TransportBuilder.php | 84 +++++-- 14 files changed, 1253 insertions(+), 17 deletions(-) create mode 100644 app/code/Magento/Email/Model/MailTransport.php create mode 100644 lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php create mode 100644 lib/internal/Magento/Framework/Mail/MessageEnvelope.php create mode 100644 lib/internal/Magento/Framework/Mail/MessageEnvelopeInterface.php create mode 100644 lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php create mode 100644 lib/internal/Magento/Framework/Mail/MimeInterface.php create mode 100644 lib/internal/Magento/Framework/Mail/MimeMessage.php create mode 100644 lib/internal/Magento/Framework/Mail/MimeMessageInterface.php create mode 100644 lib/internal/Magento/Framework/Mail/MimeMessageInterfaceFactory.php create mode 100644 lib/internal/Magento/Framework/Mail/MimePart.php create mode 100644 lib/internal/Magento/Framework/Mail/MimePartInterface.php create mode 100644 lib/internal/Magento/Framework/Mail/MimePartInterfaceFactory.php diff --git a/app/code/Magento/Email/Model/MailTransport.php b/app/code/Magento/Email/Model/MailTransport.php new file mode 100644 index 000000000000..12bda86e9426 --- /dev/null +++ b/app/code/Magento/Email/Model/MailTransport.php @@ -0,0 +1,113 @@ +isSetReturnPath = (int) $scopeConfig->getValue( + self::XML_PATH_SENDING_SET_RETURN_PATH, + ScopeInterface::SCOPE_STORE + ); + $this->returnPathValue = $scopeConfig->getValue( + self::XML_PATH_SENDING_RETURN_PATH_EMAIL, + ScopeInterface::SCOPE_STORE + ); + + $this->zendTransport = new Sendmail($parameters); + $this->message = $message; + } + + /** + * @inheritdoc + */ + public function sendMessage() + { + try { + $zendMessage = Message::fromString($this->message->getRawMessage())->setEncoding('utf-8'); + if (2 === $this->isSetReturnPath && $this->returnPathValue) { + $zendMessage->setSender($this->returnPathValue); + } elseif (1 === $this->isSetReturnPath && $zendMessage->getFrom()->count()) { + $fromAddressList = $zendMessage->getFrom(); + $fromAddressList->rewind(); + $zendMessage->setSender($fromAddressList->current()->getEmail()); + } + + $this->zendTransport->send($zendMessage); + } catch (\Exception $e) { + throw new MailException(new Phrase($e->getMessage()), $e); + } + } + + /** + * @inheritdoc + */ + public function getMessage() + { + return $this->message; + } +} diff --git a/app/code/Magento/Email/etc/di.xml b/app/code/Magento/Email/etc/di.xml index 9ec3e04728a2..cf8afc9bf2af 100644 --- a/app/code/Magento/Email/etc/di.xml +++ b/app/code/Magento/Email/etc/di.xml @@ -8,8 +8,11 @@ - + + + + diff --git a/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php b/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php new file mode 100644 index 000000000000..595a7487178a --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php @@ -0,0 +1,69 @@ +messageEnvelopeFactory = $messageEnvelopeFactory; + $this->mimeMessageFactory = $mimeMessageFactory; + $this->mimePartFactory = $mimePartFactory; + } + + /** + * Builds message Envelope from Message Data array + * + * @param array $messageData + * @return MessageEnvelopeInterface + */ + public function buildByArray(array $messageData): MessageEnvelopeInterface + { + $parts = []; + foreach ($messageData['body'] as $item) { + if ($item instanceof MimePartInterface) { + $parts[] = $item; + } else { + $parts[] = $this->mimePartFactory->create($item); + } + } + $messageData['body'] = $this->mimeMessageFactory->create(['parts'=>$parts]); + + return $this->messageEnvelopeFactory->create($messageData); + } +} diff --git a/lib/internal/Magento/Framework/Mail/MessageEnvelope.php b/lib/internal/Magento/Framework/Mail/MessageEnvelope.php new file mode 100644 index 000000000000..18eaf035a33a --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MessageEnvelope.php @@ -0,0 +1,224 @@ +message = new ZendMessage(); + $mimeMessage = new \Zend\Mime\Message(); + $mimeMessage->setParts($body->getParts()); + $this->message->setBody($mimeMessage); + if ($encoding) { + $this->message->setEncoding($encoding); + } + if ($subject) { + $this->message->setSubject($subject); + } + if ($sender) { + $this->message->setSender($sender, $senderName); + } + $this->message->setReplyTo($replyTo); + $this->message->setTo($to); + $this->message->setFrom($from); + $this->message->setCc($cc); + $this->message->setBcc($bcc); + $this->mimeMessageFactory = $mimeMessageFactory; + } + + /** + * Get the message encoding + * + * @return string + */ + public function getEncoding(): string + { + return $this->message->getEncoding(); + } + + /** + * Access headers collection + * + * @return array + */ + public function getHeaders(): array + { + return $this->message->getHeaders()->toArray(); + } + + /** + * Retrieve list of From senders + * + * @return array + */ + public function getFrom(): array + { + return $this->convertAddressListToArray($this->message->getFrom()); + } + + /** + * Access the address list of the To header + * + * @return array + */ + public function getTo(): array + { + return $this->convertAddressListToArray($this->message->getTo()); + } + + /** + * Retrieve list of CC recipients + * + * @return array + */ + public function getCc(): array + { + return $this->convertAddressListToArray($this->message->getCc()); + } + + /** + * Retrieve list of BCC recipients + * + * @return array + */ + public function getBcc(): array + { + return $this->convertAddressListToArray($this->message->getBcc()); + } + + /** + * Access the address list of the Reply-To header + * + * @return array + */ + public function getReplyTo(): array + { + return $this->convertAddressListToArray($this->message->getReplyTo()); + } + + /** + * Retrieve the sender address, if any + * + * @return null|string + */ + public function getSender(): ?string + { + return $this->message->getSender(); + } + + /** + * Get the message subject header value + * + * @return null|string + */ + public function getSubject(): ?string + { + return $this->message->getSubject(); + } + + /** + * Return the currently set message body + * + * @return object|string|MimeMessageInterface + */ + public function getBody(): MimeMessageInterface + { + return $this->mimeMessageFactory->create([ + 'parts' => $this->message->getBody()->getParts() + ]); + } + + /** + * @inheritDoc + */ + public function getBodyText(): string + { + return $this->message->getBodyText(); + } + + /** + * @inheritdoc + */ + public function getRawMessage(): string + { + return $this->toString(); + } + + /** + * Serialize to string + * + * @return string + */ + public function toString(): string + { + return $this->message->toString(); + } + + /** + * Converts AddressList to array + * + * @param AddressList $addressList + * @return array + */ + private function convertAddressListToArray(AddressList $addressList): array + { + $arrayList = []; + foreach ($addressList as $email => $address) { + if ($address->getName()) { + $arrayList[$email] = $address->getName(); + } else { + $arrayList[] = $address->getEmail(); + } + } + + return $arrayList; + } +} diff --git a/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterface.php b/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterface.php new file mode 100644 index 000000000000..9c82d090135d --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterface.php @@ -0,0 +1,97 @@ +_objectManager = $objectManager; + $this->_instanceName = $instanceName; + } + + /** + * Create MessageEnvelopeInterface instance with specified parameters + * + * @param array $data + * @return MessageEnvelopeInterface + */ + public function create(array $data = []): MessageEnvelopeInterface + { + return $this->_objectManager->create($this->_instanceName, $data); + } +} diff --git a/lib/internal/Magento/Framework/Mail/MimeInterface.php b/lib/internal/Magento/Framework/Mail/MimeInterface.php new file mode 100644 index 000000000000..d491f83437a8 --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MimeInterface.php @@ -0,0 +1,31 @@ +[\x21\x23-\x26\x2a\x2b\x2d\x5e\5f\60\x7b-\x7ea-zA-Z0-9]+)\?(?P[\x21\x23-\x26\x2a\x2b\x2d\x5e\5f\60\x7b-\x7ea-zA-Z0-9]+)\?(?P[\x21-\x3e\x40-\x7e]+)#'; + // @codingStandardsIgnoreEnd +} diff --git a/lib/internal/Magento/Framework/Mail/MimeMessage.php b/lib/internal/Magento/Framework/Mail/MimeMessage.php new file mode 100644 index 000000000000..18c56212ba3c --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MimeMessage.php @@ -0,0 +1,81 @@ +mimeMessage = new ZendMimeMessage(); + $this->mimeMessage->setParts($parts); + } + + /** + * @inheritDoc + */ + public function getParts(): array + { + return $this->mimeMessage->getParts(); + } + + /** + * @inheritDoc + */ + public function isMultiPart(): bool + { + return $this->mimeMessage->isMultiPart(); + } + + /** + * @inheritDoc + */ + public function generateMessage(string $endOfLine = MimeInterface::LINEEND): string + { + return $this->mimeMessage->generateMessage($endOfLine); + } + + /** + * @inheritDoc + */ + public function getPartHeadersArray(int $partNum): array + { + return $this->mimeMessage->getPartHeadersArray($partNum); + } + + /** + * @inheritDoc + */ + public function getPartHeaders(int $partNum, string $endOfLine = MimeInterface::LINEEND): string + { + return $this->mimeMessage->getPartHeaders($partNum, $endOfLine); + } + + /** + * @inheritDoc + */ + public function getPartContent(int $partNum, string $endOfLine = MimeInterface::LINEEND): string + { + return $this->mimeMessage->getPartContent($partNum, $endOfLine); + } +} diff --git a/lib/internal/Magento/Framework/Mail/MimeMessageInterface.php b/lib/internal/Magento/Framework/Mail/MimeMessageInterface.php new file mode 100644 index 000000000000..043b9a908c9a --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MimeMessageInterface.php @@ -0,0 +1,65 @@ +_objectManager = $objectManager; + $this->_instanceName = $instanceName; + } + + /** + * Creates MimeMessageInterface instance with specified parameters + * + * @param array $data + * @return MimeMessageInterface + */ + public function create(array $data = []): MimeMessageInterface + { + return $this->_objectManager->create($this->_instanceName, $data); + } +} diff --git a/lib/internal/Magento/Framework/Mail/MimePart.php b/lib/internal/Magento/Framework/Mail/MimePart.php new file mode 100644 index 000000000000..fbbc14ee2337 --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MimePart.php @@ -0,0 +1,209 @@ +mimePart = new ZendMimePart($content); + $this->mimePart->setType($type); + $this->mimePart->setEncoding($encoding); + $this->mimePart->setFilters($filters); + if ($charset) { + $this->mimePart->setBoundary($boundary); + } + if ($charset) { + $this->mimePart->setCharset($charset); + } + if ($disposition) { + $this->mimePart->setDisposition($disposition); + } + if ($description) { + $this->mimePart->setDescription($description); + } + if ($fileName) { + $this->mimePart->setFileName($fileName); + } + if ($location) { + $this->mimePart->setLocation($location); + } + if ($language) { + $this->mimePart->setLanguage($language); + } + if ($isStream) { + $this->mimePart->setIsStream($isStream); + } + } + + /** + * @inheritDoc + */ + public function getType(): string + { + return $this->mimePart->getType(); + } + + /** + * @inheritDoc + */ + public function getEncoding(): string + { + return $this->mimePart->getEncoding(); + } + + /** + * @inheritDoc + */ + public function getDisposition(): string + { + return $this->mimePart->getDisposition(); + } + + /** + * @inheritDoc + */ + public function getDescription(): string + { + return $this->mimePart->getDescription(); + } + + /** + * @inheritDoc + */ + public function getFileName(): string + { + return $this->mimePart->getFileName(); + } + + /** + * @inheritDoc + */ + public function getCharset(): string + { + return $this->mimePart->getCharset(); + } + + /** + * @inheritDoc + */ + public function getBoundary(): string + { + return $this->mimePart->getBoundary(); + } + + /** + * @inheritDoc + */ + public function getLocation(): string + { + return $this->mimePart->getLocation(); + } + + /** + * @inheritDoc + */ + public function getLanguage(): string + { + return $this->mimePart->getLanguage(); + } + + /** + * @inheritDoc + */ + public function getFilters(): array + { + return $this->mimePart->getFilters(); + } + + /** + * @inheritDoc + */ + public function isStream(): bool + { + return $this->mimePart->isStream(); + } + + /** + * @inheritDoc + */ + public function getEncodedStream($endOfLine = MimeInterface::LINEEND) + { + return $this->mimePart->getEncodedStream($endOfLine); + } + + /** + * @inheritDoc + */ + public function getContent($endOfLine = MimeInterface::LINEEND) + { + return $this->mimePart->getContent($endOfLine); + } + + /** + * @inheritDoc + */ + public function getRawContent(): string + { + return $this->mimePart->getRawContent(); + } + + /** + * @inheritDoc + */ + public function getHeadersArray($endOfLine = MimeInterface::LINEEND): array + { + return $this->mimePart->getHeadersArray($endOfLine); + } + + /** + * @inheritDoc + */ + public function getHeaders($endOfLine = MimeInterface::LINEEND): string + { + return $this->mimePart->getHeaders($endOfLine); + } +} diff --git a/lib/internal/Magento/Framework/Mail/MimePartInterface.php b/lib/internal/Magento/Framework/Mail/MimePartInterface.php new file mode 100644 index 000000000000..6786549a618b --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MimePartInterface.php @@ -0,0 +1,133 @@ +_objectManager = $objectManager; + $this->_instanceName = $instanceName; + } + + /** + * Create MimePartInterface instance with specified parameters + * + * @param array $data + * @return MimePartInterface + */ + public function create(array $data = []): MimePartInterface + { + return $this->_objectManager->create($this->_instanceName, $data); + } +} diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 7bef92af57da..98c39fe379c2 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -5,13 +5,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Framework\Mail\Template; use Magento\Framework\App\TemplateTypesInterface; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Mail\MailEnvelopeBuilder; use Magento\Framework\Mail\MessageInterface; use Magento\Framework\Mail\MessageInterfaceFactory; +use Magento\Framework\Mail\MimeInterface; use Magento\Framework\Mail\TransportInterfaceFactory; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Phrase; @@ -97,6 +100,18 @@ class TransportBuilder */ private $messageFactory; + /** + * Param that used for storing all message data until it will be used + * + * @var array + */ + private $messageData = []; + + /** + * @var MailEnvelopeBuilder|null + */ + private $mailEnvelopeBuilder; + /** * @param FactoryInterface $templateFactory * @param MessageInterface $message @@ -105,6 +120,7 @@ class TransportBuilder * @param TransportInterfaceFactory $mailTransportFactory * @param MessageInterfaceFactory $messageFactory * + * @param MailEnvelopeBuilder|null $mailEnvelopeBuilder * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( @@ -113,14 +129,18 @@ public function __construct( SenderResolverInterface $senderResolver, ObjectManagerInterface $objectManager, TransportInterfaceFactory $mailTransportFactory, - MessageInterfaceFactory $messageFactory = null + MessageInterfaceFactory $messageFactory = null, + MailEnvelopeBuilder $mailEnvelopeBuilder =null ) { $this->templateFactory = $templateFactory; $this->objectManager = $objectManager; $this->_senderResolver = $senderResolver; $this->mailTransportFactory = $mailTransportFactory; - $this->messageFactory = $messageFactory ?: $this->objectManager->get(MessageInterfaceFactory::class); + $this->messageFactory = $messageFactory ?: $this->objectManager + ->get(MessageInterfaceFactory::class); $this->message = $this->messageFactory->create(); + $this->mailEnvelopeBuilder = $mailEnvelopeBuilder ?: $this->objectManager + ->get(MailEnvelopeBuilder::class); } /** @@ -132,7 +152,8 @@ public function __construct( */ public function addCc($address, $name = '') { - $this->message->addCc($address, $name); + $this->messageData['cc'][$address] = $name; + return $this; } @@ -145,7 +166,8 @@ public function addCc($address, $name = '') */ public function addTo($address, $name = '') { - $this->message->addTo($address, $name); + $this->messageData['to'][$address] = $name; + return $this; } @@ -157,7 +179,8 @@ public function addTo($address, $name = '') */ public function addBcc($address) { - $this->message->addBcc($address); + $this->messageData['bcc'] = [$address]; + return $this; } @@ -170,20 +193,21 @@ public function addBcc($address) */ public function setReplyTo($email, $name = null) { - $this->message->setReplyTo($email, $name); + $this->messageData['replyTo'][$email] = $name; + return $this; } /** * Set mail from address * - * @deprecated This function sets the from address but does not provide - * a way of setting the correct from addresses based on the scope. - * @see setFromByScope() - * * @param string|array $from * @return $this * @throws \Magento\Framework\Exception\MailException + * @see setFromByScope() + * + * @deprecated This function sets the from address but does not provide + * a way of setting the correct from addresses based on the scope. */ public function setFrom($from) { @@ -201,7 +225,32 @@ public function setFrom($from) public function setFromByScope($from, $scopeId = null) { $result = $this->_senderResolver->resolve($from, $scopeId); - $this->message->setFromAddress($result['email'], $result['name']); + $this->messageData['from'][$result['email']] = $result['name']; + return $this; + } + + /** + * + * + * @param $content + * @param string $type + * @param string $fileName + * @param string $disposition + * @return $this + */ + public function addAttachment( + $content, + string $type, + string $fileName, + string $disposition = MimeInterface::DISPOSITION_ATTACHMENT + ): self { + $this->messageData['body'][] = [ + 'content' => $content, + 'type' => $type, + 'fileName' => $fileName, + 'disposition' => $disposition + ]; + return $this; } @@ -278,7 +327,7 @@ public function getTransport() */ protected function reset() { - $this->message = $this->messageFactory->create(); + $this->messageData = []; $this->templateIdentifier = null; $this->templateVars = null; $this->templateOptions = null; @@ -306,14 +355,14 @@ protected function getTemplate() protected function prepareMessage() { $template = $this->getTemplate(); - $body = $template->processTemplate(); + $part['content'] = $template->processTemplate(); switch ($template->getType()) { case TemplateTypesInterface::TYPE_TEXT: - $this->message->setBodyText($body); + $part['type'] = MimeInterface::TYPE_TEXT; break; case TemplateTypesInterface::TYPE_HTML: - $this->message->setBodyHtml($body); + $part['type'] = MimeInterface::TYPE_HTML; break; default: @@ -321,7 +370,10 @@ protected function prepareMessage() new Phrase('Unknown template type') ); } - $this->message->setSubject(html_entity_decode($template->getSubject(), ENT_QUOTES)); + $this->messageData['body'][] = $part; + $this->messageData['subject'] = html_entity_decode($template->getSubject(), ENT_QUOTES); + $this->message = $this->mailEnvelopeBuilder->buildByArray($this->messageData); + return $this; } } From cb371d5cc9fab4fbffa6bed73658ec79d355fe83 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 25 Jul 2019 12:21:49 +0300 Subject: [PATCH 02/37] MC-15295: Review comments fixes --- .../Magento/Email/Model/MailTransport.php | 8 ++++-- .../Framework/Mail/MailEnvelopeBuilder.php | 12 +++++---- .../Mail/MessageEnvelopeInterfaceFactory.php | 10 ++++---- .../Magento/Framework/Mail/MimeMessage.php | 5 ++-- .../Mail/MimeMessageInterfaceFactory.php | 10 ++++---- .../Magento/Framework/Mail/MimePart.php | 7 +++--- .../Mail/MimePartInterfaceFactory.php | 10 ++++---- .../Mail/TransportInterfaceFactory.php | 25 +++++++++++-------- 8 files changed, 48 insertions(+), 39 deletions(-) diff --git a/app/code/Magento/Email/Model/MailTransport.php b/app/code/Magento/Email/Model/MailTransport.php index 12bda86e9426..8f489e4dfdc0 100644 --- a/app/code/Magento/Email/Model/MailTransport.php +++ b/app/code/Magento/Email/Model/MailTransport.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Email\Model; use Magento\Framework\App\Config\ScopeConfigInterface; @@ -21,6 +23,8 @@ */ class MailTransport implements TransportInterface { + private const IS_SET_RETURN_PATH_YES = 1; + private const IS_SET_RETURN_PATH_CUSTOM = 2; /** * Configuration path to source of Return-Path and whether it should be set at all * @see \Magento\Config\Model\Config\Source\Yesnocustom to possible values @@ -89,9 +93,9 @@ public function sendMessage() { try { $zendMessage = Message::fromString($this->message->getRawMessage())->setEncoding('utf-8'); - if (2 === $this->isSetReturnPath && $this->returnPathValue) { + if (self::IS_SET_RETURN_PATH_CUSTOM === $this->isSetReturnPath && $this->returnPathValue) { $zendMessage->setSender($this->returnPathValue); - } elseif (1 === $this->isSetReturnPath && $zendMessage->getFrom()->count()) { + } elseif (self::IS_SET_RETURN_PATH_YES === $this->isSetReturnPath && $zendMessage->getFrom()->count()) { $fromAddressList = $zendMessage->getFrom(); $fromAddressList->rewind(); $zendMessage->setSender($fromAddressList->current()->getEmail()); diff --git a/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php b/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php index 595a7487178a..0e29f84baec0 100644 --- a/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php +++ b/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php @@ -55,11 +55,13 @@ public function __construct( public function buildByArray(array $messageData): MessageEnvelopeInterface { $parts = []; - foreach ($messageData['body'] as $item) { - if ($item instanceof MimePartInterface) { - $parts[] = $item; - } else { - $parts[] = $this->mimePartFactory->create($item); + if (isset($messageData['body'])) { + foreach ($messageData['body'] as $item) { + if ($item instanceof MimePartInterface) { + $parts[] = $item; + } else { + $parts[] = $this->mimePartFactory->create($item); + } } } $messageData['body'] = $this->mimeMessageFactory->create(['parts'=>$parts]); diff --git a/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php b/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php index 004199bea681..a4e35aeebf62 100644 --- a/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php +++ b/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php @@ -23,12 +23,12 @@ class MessageEnvelopeInterfaceFactory /** * @var ObjectManagerInterface */ - protected $_objectManager; + private $objectManager; /** * @var string */ - protected $_instanceName; + private $instanceName; /** * @param ObjectManagerInterface $objectManager @@ -38,8 +38,8 @@ public function __construct( ObjectManagerInterface $objectManager, $instanceName = MessageEnvelopeInterface::class ) { - $this->_objectManager = $objectManager; - $this->_instanceName = $instanceName; + $this->objectManager = $objectManager; + $this->instanceName = $instanceName; } /** @@ -50,6 +50,6 @@ public function __construct( */ public function create(array $data = []): MessageEnvelopeInterface { - return $this->_objectManager->create($this->_instanceName, $data); + return $this->objectManager->create($this->instanceName, $data); } } diff --git a/lib/internal/Magento/Framework/Mail/MimeMessage.php b/lib/internal/Magento/Framework/Mail/MimeMessage.php index 18c56212ba3c..2d212deb2dca 100644 --- a/lib/internal/Magento/Framework/Mail/MimeMessage.php +++ b/lib/internal/Magento/Framework/Mail/MimeMessage.php @@ -24,9 +24,8 @@ class MimeMessage implements MimeMessageInterface * * @param array $parts */ - public function __construct( - array $parts - ) { + public function __construct(array $parts) + { $this->mimeMessage = new ZendMimeMessage(); $this->mimeMessage->setParts($parts); } diff --git a/lib/internal/Magento/Framework/Mail/MimeMessageInterfaceFactory.php b/lib/internal/Magento/Framework/Mail/MimeMessageInterfaceFactory.php index 81c1fdf99938..207febd7061e 100644 --- a/lib/internal/Magento/Framework/Mail/MimeMessageInterfaceFactory.php +++ b/lib/internal/Magento/Framework/Mail/MimeMessageInterfaceFactory.php @@ -23,12 +23,12 @@ class MimeMessageInterfaceFactory /** * @var ObjectManagerInterface */ - private $_objectManager; + private $objectManager; /** * @var string */ - private $_instanceName; + private $instanceName; /** * @param ObjectManagerInterface $objectManager @@ -38,8 +38,8 @@ public function __construct( ObjectManagerInterface $objectManager, $instanceName = MimeMessageInterface::class ) { - $this->_objectManager = $objectManager; - $this->_instanceName = $instanceName; + $this->objectManager = $objectManager; + $this->instanceName = $instanceName; } /** @@ -50,6 +50,6 @@ public function __construct( */ public function create(array $data = []): MimeMessageInterface { - return $this->_objectManager->create($this->_instanceName, $data); + return $this->objectManager->create($this->instanceName, $data); } } diff --git a/lib/internal/Magento/Framework/Mail/MimePart.php b/lib/internal/Magento/Framework/Mail/MimePart.php index fbbc14ee2337..747d95271c96 100644 --- a/lib/internal/Magento/Framework/Mail/MimePart.php +++ b/lib/internal/Magento/Framework/Mail/MimePart.php @@ -34,15 +34,16 @@ class MimePart implements MimePartInterface * @param array $filters * @param string $type * @param string $encoding + * @SuppressWarnings(PHPMD.NPathComplexity, PHPMD.ExcessiveParameterList) */ public function __construct( $content, ?string $type = MimeInterface::TYPE_OCTETSTREAM, - ?string $encoding = MimeInterface::ENCODING_8BIT, - ?array $filters = [], + ?string $fileName = null, ?string $disposition = null, + ?string $encoding = MimeInterface::ENCODING_8BIT, ?string $description = null, - ?string $fileName = null, + ?array $filters = [], ?string $charset = null, ?string $boundary = null, ?string $location = null, diff --git a/lib/internal/Magento/Framework/Mail/MimePartInterfaceFactory.php b/lib/internal/Magento/Framework/Mail/MimePartInterfaceFactory.php index 4470093898fd..e29fc8f6a51c 100644 --- a/lib/internal/Magento/Framework/Mail/MimePartInterfaceFactory.php +++ b/lib/internal/Magento/Framework/Mail/MimePartInterfaceFactory.php @@ -17,12 +17,12 @@ class MimePartInterfaceFactory /** * @var ObjectManagerInterface */ - protected $_objectManager; + private $objectManager; /** * @var string */ - protected $_instanceName; + private $instanceName; /** * @param ObjectManagerInterface $objectManager @@ -32,8 +32,8 @@ public function __construct( ObjectManagerInterface $objectManager, $instanceName = MimePartInterface::class ) { - $this->_objectManager = $objectManager; - $this->_instanceName = $instanceName; + $this->objectManager = $objectManager; + $this->instanceName = $instanceName; } /** @@ -44,6 +44,6 @@ public function __construct( */ public function create(array $data = []): MimePartInterface { - return $this->_objectManager->create($this->_instanceName, $data); + return $this->objectManager->create($this->instanceName, $data); } } diff --git a/lib/internal/Magento/Framework/Mail/TransportInterfaceFactory.php b/lib/internal/Magento/Framework/Mail/TransportInterfaceFactory.php index db86275954cb..5448df4e16ca 100644 --- a/lib/internal/Magento/Framework/Mail/TransportInterfaceFactory.php +++ b/lib/internal/Magento/Framework/Mail/TransportInterfaceFactory.php @@ -3,9 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Framework\Mail; +use Magento\Framework\ObjectManagerInterface; + /** * Factory class for \Magento\Framework\Mail\TransportInterface */ @@ -14,39 +17,39 @@ class TransportInterfaceFactory /** * Object Manager instance * - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ - protected $_objectManager = null; + private $objectManager; /** * Instance name to create * * @var string */ - protected $_instanceName = null; + private $instanceName; /** * Factory constructor * - * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager * @param string $instanceName */ public function __construct( - \Magento\Framework\ObjectManagerInterface $objectManager, - $instanceName = \Magento\Framework\Mail\TransportInterface::class + ObjectManagerInterface $objectManager, + $instanceName = TransportInterface::class ) { - $this->_objectManager = $objectManager; - $this->_instanceName = $instanceName; + $this->objectManager = $objectManager; + $this->instanceName = $instanceName; } /** * Create class instance with specified parameters * * @param array $data - * @return \Magento\Framework\Mail\TransportInterface + * @return TransportInterface */ - public function create(array $data = []) + public function create(array $data = []): TransportInterface { - return $this->_objectManager->create($this->_instanceName, $data); + return $this->objectManager->create($this->instanceName, $data); } } From 3e2498de7b01e4109c7fed27fe5ed93c3d0b0aa9 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 25 Jul 2019 13:06:55 +0300 Subject: [PATCH 03/37] MC-15295: Static test fixes --- .../Magento/Framework/Mail/MessageEnvelope.php | 1 + .../Framework/Mail/MessageEnvelopeInterfaceFactory.php | 10 +++------- .../Framework/Mail/MimeMessageInterfaceFactory.php | 10 +++------- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/MessageEnvelope.php b/lib/internal/Magento/Framework/Mail/MessageEnvelope.php index 18eaf035a33a..93d1fcee88bf 100644 --- a/lib/internal/Magento/Framework/Mail/MessageEnvelope.php +++ b/lib/internal/Magento/Framework/Mail/MessageEnvelope.php @@ -39,6 +39,7 @@ class MessageEnvelope implements MessageEnvelopeInterface * @param string|null $senderName * @param string|null $subject * @param string|null $encoding + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( MimeMessageInterface $body, diff --git a/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php b/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php index a4e35aeebf62..350cf9a27e38 100644 --- a/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php +++ b/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php @@ -1,13 +1,9 @@ Date: Thu, 25 Jul 2019 13:14:31 +0300 Subject: [PATCH 04/37] MC-15295: Copyright fixes --- lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php | 2 -- .../Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php | 2 -- .../Magento/Framework/Mail/MimeMessageInterfaceFactory.php | 2 -- 3 files changed, 6 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php b/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php index 0e29f84baec0..77c652bd64f9 100644 --- a/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php +++ b/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php @@ -1,7 +1,5 @@ Date: Thu, 25 Jul 2019 14:21:20 +0300 Subject: [PATCH 05/37] MC-15295: Static test fixes --- .../Framework/Mail/MessageEnvelope.php | 6 ++--- .../Magento/Framework/Mail/MimePart.php | 27 ++++++++++--------- .../Mail/Template/TransportBuilder.php | 7 ++--- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/MessageEnvelope.php b/lib/internal/Magento/Framework/Mail/MessageEnvelope.php index 93d1fcee88bf..649c5576f163 100644 --- a/lib/internal/Magento/Framework/Mail/MessageEnvelope.php +++ b/lib/internal/Magento/Framework/Mail/MessageEnvelope.php @@ -172,9 +172,9 @@ public function getSubject(): ?string */ public function getBody(): MimeMessageInterface { - return $this->mimeMessageFactory->create([ - 'parts' => $this->message->getBody()->getParts() - ]); + return $this->mimeMessageFactory->create( + ['parts' => $this->message->getBody()->getParts()] + ); } /** diff --git a/lib/internal/Magento/Framework/Mail/MimePart.php b/lib/internal/Magento/Framework/Mail/MimePart.php index 747d95271c96..036b7b9db8de 100644 --- a/lib/internal/Magento/Framework/Mail/MimePart.php +++ b/lib/internal/Magento/Framework/Mail/MimePart.php @@ -22,19 +22,20 @@ class MimePart implements MimePartInterface /** * MimePart constructor * - * @param string $disposition - * @param string $description - * @param string $fileName - * @param string $charset - * @param string $boundary - * @param string $location - * @param string $language - * @param bool $isStream - * @param $content - * @param array $filters - * @param string $type - * @param string $encoding - * @SuppressWarnings(PHPMD.NPathComplexity, PHPMD.ExcessiveParameterList) + * @param resource|string $content + * @param string|null $type + * @param string|null $fileName + * @param string|null $disposition + * @param string|null $encoding + * @param string|null $description + * @param array|null $filters + * @param string|null $charset + * @param string|null $boundary + * @param string|null $location + * @param string|null $language + * @param bool|null $isStream + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( $content, diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 98c39fe379c2..bcc5561393db 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -130,7 +130,7 @@ public function __construct( ObjectManagerInterface $objectManager, TransportInterfaceFactory $mailTransportFactory, MessageInterfaceFactory $messageFactory = null, - MailEnvelopeBuilder $mailEnvelopeBuilder =null + MailEnvelopeBuilder $mailEnvelopeBuilder = null ) { $this->templateFactory = $templateFactory; $this->objectManager = $objectManager; @@ -230,12 +230,13 @@ public function setFromByScope($from, $scopeId = null) } /** + * Add mail attachment * - * - * @param $content + * @param resource|string $content * @param string $type * @param string $fileName * @param string $disposition + * * @return $this */ public function addAttachment( From 525e1cf7252133d084768b49e44ace22714c6651 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Fri, 26 Jul 2019 13:20:23 +0300 Subject: [PATCH 06/37] MC-15295: Integration tests fix, check sem ver for refactoring Transport class --- app/code/Magento/Email/Model/Transport.php | 5 +++-- app/code/Magento/Email/etc/di.xml | 2 +- .../testsuite/Magento/Customer/Controller/AccountTest.php | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Email/Model/Transport.php b/app/code/Magento/Email/Model/Transport.php index 90a4e6571c9b..604ede37f753 100644 --- a/app/code/Magento/Email/Model/Transport.php +++ b/app/code/Magento/Email/Model/Transport.php @@ -7,6 +7,7 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Exception\MailException; +use Magento\Framework\Mail\MessageEnvelopeInterface; use Magento\Framework\Mail\MessageInterface; use Magento\Framework\Mail\TransportInterface; use Magento\Framework\Phrase; @@ -59,12 +60,12 @@ class Transport implements TransportInterface private $message; /** - * @param MessageInterface $message Email message object + * @param MessageEnvelopeInterface $message Email message object * @param ScopeConfigInterface $scopeConfig Core store config * @param null|string|array|\Traversable $parameters Config options for sendmail parameters */ public function __construct( - MessageInterface $message, + MessageEnvelopeInterface $message, ScopeConfigInterface $scopeConfig, $parameters = null ) { diff --git a/app/code/Magento/Email/etc/di.xml b/app/code/Magento/Email/etc/di.xml index cf8afc9bf2af..1c46d2f7ae8c 100644 --- a/app/code/Magento/Email/etc/di.xml +++ b/app/code/Magento/Email/etc/di.xml @@ -8,7 +8,7 @@ - + diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index b80f00b16f0b..78e238887306 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -754,7 +754,7 @@ public function testLoginPostRedirect($redirectDashboard, string $redirectUrl) */ public function testConfirmationEmailWithSpecialCharacters(): void { - $email = 'customer+confirmation@example.com'; + $email = 'John Smith '; $this->dispatch('customer/account/confirmation/email/customer%2Bconfirmation%40email.com'); $this->getRequest()->setPostValue('email', $email); $this->dispatch('customer/account/confirmation/email/customer%2Bconfirmation%40email.com'); From 6dbb0cd7606c722b05eb6df444503f38ba0d25a7 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Fri, 26 Jul 2019 14:53:55 +0300 Subject: [PATCH 07/37] MC-15295: Remove MailTransport --- .../Magento/Email/Model/MailTransport.php | 117 ------------------ app/code/Magento/Email/Model/Transport.php | 2 + 2 files changed, 2 insertions(+), 117 deletions(-) delete mode 100644 app/code/Magento/Email/Model/MailTransport.php diff --git a/app/code/Magento/Email/Model/MailTransport.php b/app/code/Magento/Email/Model/MailTransport.php deleted file mode 100644 index 8f489e4dfdc0..000000000000 --- a/app/code/Magento/Email/Model/MailTransport.php +++ /dev/null @@ -1,117 +0,0 @@ -isSetReturnPath = (int) $scopeConfig->getValue( - self::XML_PATH_SENDING_SET_RETURN_PATH, - ScopeInterface::SCOPE_STORE - ); - $this->returnPathValue = $scopeConfig->getValue( - self::XML_PATH_SENDING_RETURN_PATH_EMAIL, - ScopeInterface::SCOPE_STORE - ); - - $this->zendTransport = new Sendmail($parameters); - $this->message = $message; - } - - /** - * @inheritdoc - */ - public function sendMessage() - { - try { - $zendMessage = Message::fromString($this->message->getRawMessage())->setEncoding('utf-8'); - if (self::IS_SET_RETURN_PATH_CUSTOM === $this->isSetReturnPath && $this->returnPathValue) { - $zendMessage->setSender($this->returnPathValue); - } elseif (self::IS_SET_RETURN_PATH_YES === $this->isSetReturnPath && $zendMessage->getFrom()->count()) { - $fromAddressList = $zendMessage->getFrom(); - $fromAddressList->rewind(); - $zendMessage->setSender($fromAddressList->current()->getEmail()); - } - - $this->zendTransport->send($zendMessage); - } catch (\Exception $e) { - throw new MailException(new Phrase($e->getMessage()), $e); - } - } - - /** - * @inheritdoc - */ - public function getMessage() - { - return $this->message; - } -} diff --git a/app/code/Magento/Email/Model/Transport.php b/app/code/Magento/Email/Model/Transport.php index 604ede37f753..4e7a83db5ef7 100644 --- a/app/code/Magento/Email/Model/Transport.php +++ b/app/code/Magento/Email/Model/Transport.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Email\Model; use Magento\Framework\App\Config\ScopeConfigInterface; From a56e68324e4fc5901d833713edaa814803879cec Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Fri, 26 Jul 2019 17:05:04 +0300 Subject: [PATCH 08/37] MC-15295: Fix Magento\Customer\Controller\AccountTest --- .../testsuite/Magento/Customer/Controller/AccountTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index 78e238887306..566dfbadedd2 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -754,7 +754,7 @@ public function testLoginPostRedirect($redirectDashboard, string $redirectUrl) */ public function testConfirmationEmailWithSpecialCharacters(): void { - $email = 'John Smith '; + $email = 'customer+confirmation@example.com'; $this->dispatch('customer/account/confirmation/email/customer%2Bconfirmation%40email.com'); $this->getRequest()->setPostValue('email', $email); $this->dispatch('customer/account/confirmation/email/customer%2Bconfirmation%40email.com'); @@ -769,7 +769,7 @@ public function testConfirmationEmailWithSpecialCharacters(): void $message = $this->transportBuilderMock->getSentMessage(); $rawMessage = $message->getRawMessage(); - $this->assertContains('To: ' . $email, $rawMessage); + $this->assertContains('To: John Smith <' . $email . '>', $rawMessage); $content = $message->getBody()->getParts()[0]->getRawContent(); $confirmationUrl = $this->getConfirmationUrlFromMessageContent($content); From 4d77014e83cc2f691a90cef87d750791918f4bf6 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Mon, 29 Jul 2019 12:34:42 +0300 Subject: [PATCH 09/37] MC-18269: fix integration --- .graphqlconfig | 15 +++++++++++++++ .../Framework/Mail/Template/TransportBuilder.php | 8 ++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 .graphqlconfig diff --git a/.graphqlconfig b/.graphqlconfig new file mode 100644 index 000000000000..8c2cf7fcb632 --- /dev/null +++ b/.graphqlconfig @@ -0,0 +1,15 @@ +{ + "name": "Untitled GraphQL Schema", + "schemaPath": "schema.graphql", + "extensions": { + "endpoints": { + "Default GraphQL Endpoint": { + "url": "http://localhost:8080/graphql", + "headers": { + "user-agent": "JS GraphQL" + }, + "introspect": false + } + } + } +} \ No newline at end of file diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index bcc5561393db..df099750c170 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -166,7 +166,11 @@ public function addCc($address, $name = '') */ public function addTo($address, $name = '') { - $this->messageData['to'][$address] = $name; + if (!$name) { + $this->messageData['to'][] = $address; + } else { + $this->messageData['to'][$address] = $name; + } return $this; } @@ -179,7 +183,7 @@ public function addTo($address, $name = '') */ public function addBcc($address) { - $this->messageData['bcc'] = [$address]; + $this->messageData['bcc'] = $address; return $this; } From d84f463cdea305b3b037eff226b4c133781caf50 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Tue, 30 Jul 2019 11:15:14 +0300 Subject: [PATCH 10/37] MC-18269: fix html_entity_decode issue --- .../Magento/Framework/Mail/Template/TransportBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index df099750c170..33c10cd1bdcb 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -376,7 +376,7 @@ protected function prepareMessage() ); } $this->messageData['body'][] = $part; - $this->messageData['subject'] = html_entity_decode($template->getSubject(), ENT_QUOTES); + $this->messageData['subject'] = html_entity_decode((string)$template->getSubject(), ENT_QUOTES); $this->message = $this->mailEnvelopeBuilder->buildByArray($this->messageData); return $this; From d91ec6add2d5d8f448ef8188d9e7fef16195af14 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Tue, 30 Jul 2019 14:25:48 +0300 Subject: [PATCH 11/37] MC-18269: fix unit tests --- .../Mail/Template/TransportBuilder.php | 5 +- .../Unit/Template/TransportBuilderTest.php | 68 +++---------------- 2 files changed, 11 insertions(+), 62 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 33c10cd1bdcb..8bc27a90ce71 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -79,7 +79,7 @@ class TransportBuilder /** * Message * - * @var \Magento\Framework\Mail\Message + * @var \Magento\Framework\Mail\MessageEnvelopeInterface */ protected $message; @@ -138,7 +138,6 @@ public function __construct( $this->mailTransportFactory = $mailTransportFactory; $this->messageFactory = $messageFactory ?: $this->objectManager ->get(MessageInterfaceFactory::class); - $this->message = $this->messageFactory->create(); $this->mailEnvelopeBuilder = $mailEnvelopeBuilder ?: $this->objectManager ->get(MailEnvelopeBuilder::class); } @@ -169,7 +168,7 @@ public function addTo($address, $name = '') if (!$name) { $this->messageData['to'][] = $address; } else { - $this->messageData['to'][$address] = $name; + $this->messageData['to'][$address] = $name; } return $this; diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index c9781281d353..447a3466bafa 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -9,6 +9,7 @@ use Magento\Framework\App\TemplateTypesInterface; use Magento\Framework\Mail\MessageInterface; use Magento\Framework\Mail\MessageInterfaceFactory; +use Magento\Framework\Mail\MimeInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -55,6 +56,11 @@ class TransportBuilderTest extends \PHPUnit\Framework\TestCase */ protected $mailTransportFactoryMock; + /** + * @var \Magento\Framework\Mail\MailEnvelopeBuilder|\PHPUnit_Framework_MockObject_MockObject + */ + protected $mailEnvelopeBuilder; + /** * @return void */ @@ -65,6 +71,7 @@ protected function setUp() $this->messageMock = $this->createMock(\Magento\Framework\Mail\Message::class); $this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); $this->senderResolverMock = $this->createMock(\Magento\Framework\Mail\Template\SenderResolverInterface::class); + $this->mailEnvelopeBuilder = $this->createMock(\Magento\Framework\Mail\MailEnvelopeBuilder::class); $this->mailTransportFactoryMock = $this->getMockBuilder( \Magento\Framework\Mail\TransportInterfaceFactory::class )->disableOriginalConstructor() @@ -74,7 +81,6 @@ protected function setUp() ->disableOriginalConstructor() ->setMethods(['create']) ->getMockForAbstractClass(); - $this->messageFactoryMock->expects($this->atLeastOnce())->method('create')->willReturn($this->messageMock); $this->builder = $objectManagerHelper->getObject( $this->builderClassName, [ @@ -120,12 +126,12 @@ public function testGetTransport($templateType, $messageType, $bodyText, $templa ->with($this->equalTo('Email Subject')) ->willReturnSelf(); - $this->messageMock->expects($this->exactly((int)($messageType == MessageInterface::TYPE_TEXT))) + $this->messageMock->expects($this->exactly((int)($messageType === MimeInterface::TYPE_TEXT))) ->method('setBodyText') ->with($this->equalTo($bodyText)) ->willReturnSelf(); - $this->messageMock->expects($this->exactly((int)($messageType == MessageInterface::TYPE_HTML))) + $this->messageMock->expects($this->exactly((int)($messageType === MimeInterface::TYPE_HTML))) ->method('setBodyHtml') ->with($this->equalTo($bodyText)) ->willReturnSelf(); @@ -137,8 +143,6 @@ public function testGetTransport($templateType, $messageType, $bodyText, $templa ->with($this->equalTo(['message' => $this->messageMock])) ->willReturn($transport); - $this->messageFactoryMock->expects($this->once())->method('create')->willReturn($transport); - $this->builder->setTemplateIdentifier('identifier')->setTemplateVars($vars)->setTemplateOptions($options); $this->assertInstanceOf(\Magento\Framework\Mail\TransportInterface::class, $this->builder->getTransport()); } @@ -160,7 +164,6 @@ public function testGetTransportWithException() $template->expects($this->once())->method('setVars')->with($this->equalTo($vars))->willReturnSelf(); $template->expects($this->once())->method('setOptions')->with($this->equalTo($options))->willReturnSelf(); $template->expects($this->once())->method('getType')->willReturn('Unknown'); - $this->messageFactoryMock->expects($this->once())->method('create'); $this->templateFactoryMock->expects($this->once()) ->method('get') ->with($this->equalTo('identifier'), $this->equalTo('Test\Namespace\Template')) @@ -203,60 +206,7 @@ public function testSetFromByScope() ->method('resolve') ->with($sender, $scopeId) ->willReturn($sender); - $this->messageMock->expects($this->once()) - ->method('setFromAddress') - ->with($sender['email'], $sender['name']) - ->willReturnSelf(); $this->builder->setFromByScope($sender, $scopeId); } - - /** - * @return void - */ - public function testSetCc() - { - $this->messageMock->expects($this->once())->method('addCc')->with('cc@example.com')->willReturnSelf(); - - $this->builder->addCc('cc@example.com'); - } - - /** - * @return void - */ - public function testAddTo() - { - $this->messageMock->expects($this->once()) - ->method('addTo') - ->with('to@example.com', 'recipient') - ->willReturnSelf(); - - $this->builder->addTo('to@example.com', 'recipient'); - } - - /** - * @return void - */ - public function testAddBcc() - { - $this->messageMock->expects($this->once()) - ->method('addBcc') - ->with('bcc@example.com') - ->willReturnSelf(); - - $this->builder->addBcc('bcc@example.com'); - } - - /** - * @return void - */ - public function testSetReplyTo() - { - $this->messageMock->expects($this->once()) - ->method('setReplyTo') - ->with('replyTo@example.com', 'replyName') - ->willReturnSelf(); - - $this->builder->setReplyTo('replyTo@example.com', 'replyName'); - } } From e3f1b8246eb2e824067fd5945ea4fde2e906c1a7 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Tue, 30 Jul 2019 15:24:41 +0300 Subject: [PATCH 12/37] MC-18269: fix unit tests --- .../Unit/Template/TransportBuilderTest.php | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index 447a3466bafa..c226d88a1100 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -60,6 +60,10 @@ class TransportBuilderTest extends \PHPUnit\Framework\TestCase * @var \Magento\Framework\Mail\MailEnvelopeBuilder|\PHPUnit_Framework_MockObject_MockObject */ protected $mailEnvelopeBuilder; + /** + * @var \Magento\Framework\Mail\MessageEnvelopeInterface|\PHPUnit\Framework\MockObject\MockObject + */ + private $messageEnvelopeMock; /** * @return void @@ -69,6 +73,7 @@ protected function setUp() $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->templateFactoryMock = $this->createMock(\Magento\Framework\Mail\Template\FactoryInterface::class); $this->messageMock = $this->createMock(\Magento\Framework\Mail\Message::class); + $this->messageEnvelopeMock = $this->createMock(\Magento\Framework\Mail\MessageEnvelopeInterface::class); $this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); $this->senderResolverMock = $this->createMock(\Magento\Framework\Mail\Template\SenderResolverInterface::class); $this->mailEnvelopeBuilder = $this->createMock(\Magento\Framework\Mail\MailEnvelopeBuilder::class); @@ -121,26 +126,10 @@ public function testGetTransport($templateType, $messageType, $bodyText, $templa ->with($this->equalTo('identifier'), $this->equalTo($templateNamespace)) ->willReturn($template); - $this->messageMock->expects($this->once()) - ->method('setSubject') - ->with($this->equalTo('Email Subject')) - ->willReturnSelf(); - - $this->messageMock->expects($this->exactly((int)($messageType === MimeInterface::TYPE_TEXT))) - ->method('setBodyText') - ->with($this->equalTo($bodyText)) - ->willReturnSelf(); - - $this->messageMock->expects($this->exactly((int)($messageType === MimeInterface::TYPE_HTML))) - ->method('setBodyHtml') - ->with($this->equalTo($bodyText)) - ->willReturnSelf(); - $transport = $this->createMock(\Magento\Framework\Mail\TransportInterface::class); $this->mailTransportFactoryMock->expects($this->at(0)) ->method('create') - ->with($this->equalTo(['message' => $this->messageMock])) ->willReturn($transport); $this->builder->setTemplateIdentifier('identifier')->setTemplateVars($vars)->setTemplateOptions($options); From 622b109a2efb289ec2e8bbf5ef07f5d72c01558f Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Tue, 30 Jul 2019 15:29:56 +0300 Subject: [PATCH 13/37] MC-18269: fix unit tests --- .../Framework/Mail/Test/Unit/Template/TransportBuilderTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index c226d88a1100..3a102639de72 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -8,8 +8,6 @@ use Magento\Framework\App\TemplateTypesInterface; use Magento\Framework\Mail\MessageInterface; -use Magento\Framework\Mail\MessageInterfaceFactory; -use Magento\Framework\Mail\MimeInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -76,7 +74,6 @@ protected function setUp() $this->messageEnvelopeMock = $this->createMock(\Magento\Framework\Mail\MessageEnvelopeInterface::class); $this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); $this->senderResolverMock = $this->createMock(\Magento\Framework\Mail\Template\SenderResolverInterface::class); - $this->mailEnvelopeBuilder = $this->createMock(\Magento\Framework\Mail\MailEnvelopeBuilder::class); $this->mailTransportFactoryMock = $this->getMockBuilder( \Magento\Framework\Mail\TransportInterfaceFactory::class )->disableOriginalConstructor() From cc6f97f0200e1686fd7ceb2f8964858b61f0da62 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Tue, 30 Jul 2019 15:43:31 +0300 Subject: [PATCH 14/37] MC-18269: fix unit tests --- .../Newsletter/Model/Queue/TransportBuilder.php | 10 ++++------ .../Test/Unit/Model/Queue/TransportBuilderTest.php | 9 +-------- .../Framework/Mail/Template/TransportBuilder.php | 4 ++-- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php index 502a19d298c4..e6cfdab10262 100644 --- a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php +++ b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php @@ -47,12 +47,10 @@ protected function prepareMessage() /** @var AbstractTemplate $template */ $template = $this->getTemplate()->setData($this->templateData); $this->setTemplateFilter($template); - - $this->message->setBodyHtml( - $template->getProcessedTemplate($this->templateVars) - )->setSubject( - $template->getSubject() - ); + $part['content'] = $template->getProcessedTemplate($this->templateVars); + $this->messageData['body'][] = $part; + $this->messageData['subject'] = $template->getSubject(); + $this->message = $this->mailEnvelopeBuilder->buildByArray($this->messageData); return $this; } diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php index e8b141a24c9e..7b435c91a668 100644 --- a/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php +++ b/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php @@ -68,11 +68,7 @@ public function setUp() )->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); - $this->messageFactoryMock = $this->getMockBuilder(\Magento\Framework\Mail\MessageInterfaceFactory::class) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMockForAbstractClass(); - $this->messageFactoryMock->expects($this->atLeastOnce())->method('create')->willReturn($this->messageMock); + $this->builder = $objectManagerHelper->getObject( $this->builderClassName, [ @@ -137,9 +133,6 @@ public function testGetTransport( $this->returnValue($template) ); - $this->messageMock->expects($this->once())->method('setBodyHtml')->willReturnSelf(); - $this->messageMock->expects($this->once())->method('setSubject')->willReturnSelf(); - $this->builder->setTemplateIdentifier( 'identifier' )->setTemplateVars( diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 8bc27a90ce71..fd79a02c5a74 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -105,12 +105,12 @@ class TransportBuilder * * @var array */ - private $messageData = []; + protected $messageData = []; /** * @var MailEnvelopeBuilder|null */ - private $mailEnvelopeBuilder; + protected $mailEnvelopeBuilder; /** * @param FactoryInterface $templateFactory From 8b3f4278df0e1ed083c38f0a31c5d95f0ccc160c Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Tue, 30 Jul 2019 17:16:36 +0300 Subject: [PATCH 15/37] MC-18269: fix static tests --- .../Mail/Test/Unit/Template/TransportBuilderTest.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index 3a102639de72..fe604573ad4f 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -99,12 +99,11 @@ protected function setUp() /** * @dataProvider getTransportDataProvider * @param int $templateType - * @param string $messageType * @param string $bodyText * @param string $templateNamespace * @return void */ - public function testGetTransport($templateType, $messageType, $bodyText, $templateNamespace) + public function testGetTransport($templateType, $bodyText, $templateNamespace) { $this->builder->setTemplateModel($templateNamespace); @@ -168,13 +167,11 @@ public function getTransportDataProvider() return [ [ TemplateTypesInterface::TYPE_TEXT, - MessageInterface::TYPE_TEXT, 'Plain text', null ], [ TemplateTypesInterface::TYPE_HTML, - MessageInterface::TYPE_HTML, '

Html message

', 'Test\Namespace\Template' ] From 3a90a0f61e953c8b943b8242525e77477cee8455 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Wed, 31 Jul 2019 15:58:28 +0300 Subject: [PATCH 16/37] MC-15295: refactoring interfaces and implementation acoarding to code review from Igor Menik --- .graphqlconfig | 15 -- app/code/Magento/Email/Model/Transport.php | 6 +- app/code/Magento/Email/etc/di.xml | 3 - .../Model/Queue/TransportBuilder.php | 174 +++++++++++++++++- .../Unit/Model/Queue/TransportBuilderTest.php | 5 + app/etc/di.xml | 6 + .../{MessageEnvelope.php => EmailMessage.php} | 54 ++---- ...nterface.php => EmailMessageInterface.php} | 8 +- .../Framework/Mail/MailEnvelopeBuilder.php | 69 ------- .../Mail/MessageEnvelopeInterfaceFactory.php | 49 ----- .../Magento/Framework/Mail/MimeInterface.php | 12 +- .../Magento/Framework/Mail/MimeMessage.php | 8 +- .../Framework/Mail/MimeMessageInterface.php | 8 +- .../Mail/MimeMessageInterfaceFactory.php | 49 ----- .../Magento/Framework/Mail/MimePart.php | 18 +- .../Framework/Mail/MimePartInterface.php | 8 +- .../Mail/MimePartInterfaceFactory.php | 49 ----- .../Mail/Template/TransportBuilder.php | 106 ++++++----- .../Unit/Template/TransportBuilderTest.php | 16 +- lib/internal/Magento/Framework/composer.json | 1 + 20 files changed, 300 insertions(+), 364 deletions(-) delete mode 100644 .graphqlconfig rename lib/internal/Magento/Framework/Mail/{MessageEnvelope.php => EmailMessage.php} (80%) rename lib/internal/Magento/Framework/Mail/{MessageEnvelopeInterface.php => EmailMessageInterface.php} (90%) delete mode 100644 lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php delete mode 100644 lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php delete mode 100644 lib/internal/Magento/Framework/Mail/MimeMessageInterfaceFactory.php delete mode 100644 lib/internal/Magento/Framework/Mail/MimePartInterfaceFactory.php diff --git a/.graphqlconfig b/.graphqlconfig deleted file mode 100644 index 8c2cf7fcb632..000000000000 --- a/.graphqlconfig +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "Untitled GraphQL Schema", - "schemaPath": "schema.graphql", - "extensions": { - "endpoints": { - "Default GraphQL Endpoint": { - "url": "http://localhost:8080/graphql", - "headers": { - "user-agent": "JS GraphQL" - }, - "introspect": false - } - } - } -} \ No newline at end of file diff --git a/app/code/Magento/Email/Model/Transport.php b/app/code/Magento/Email/Model/Transport.php index 4e7a83db5ef7..cbce1682cb5f 100644 --- a/app/code/Magento/Email/Model/Transport.php +++ b/app/code/Magento/Email/Model/Transport.php @@ -9,7 +9,7 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Exception\MailException; -use Magento\Framework\Mail\MessageEnvelopeInterface; +use Magento\Framework\Mail\EmailMessageInterface; use Magento\Framework\Mail\MessageInterface; use Magento\Framework\Mail\TransportInterface; use Magento\Framework\Phrase; @@ -62,12 +62,12 @@ class Transport implements TransportInterface private $message; /** - * @param MessageEnvelopeInterface $message Email message object + * @param EmailMessageInterface $message Email message object * @param ScopeConfigInterface $scopeConfig Core store config * @param null|string|array|\Traversable $parameters Config options for sendmail parameters */ public function __construct( - MessageEnvelopeInterface $message, + EmailMessageInterface $message, ScopeConfigInterface $scopeConfig, $parameters = null ) { diff --git a/app/code/Magento/Email/etc/di.xml b/app/code/Magento/Email/etc/di.xml index 1c46d2f7ae8c..9ec3e04728a2 100644 --- a/app/code/Magento/Email/etc/di.xml +++ b/app/code/Magento/Email/etc/di.xml @@ -10,9 +10,6 @@ - - - diff --git a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php index e6cfdab10262..7143c1388893 100644 --- a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php +++ b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php @@ -3,10 +3,24 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Newsletter\Model\Queue; use Magento\Email\Model\AbstractTemplate; +use Magento\Framework\Mail\EmailMessageInterfaceFactory; +use Magento\Framework\Mail\MessageInterface; +use Magento\Framework\Mail\MessageInterfaceFactory; +use Magento\Framework\Mail\MimeMessageInterfaceFactory; +use Magento\Framework\Mail\MimePartInterfaceFactory; +use Magento\Framework\Mail\Template\FactoryInterface; +use Magento\Framework\Mail\Template\SenderResolverInterface; +use Magento\Framework\Mail\TransportInterfaceFactory; +use Magento\Framework\ObjectManagerInterface; +/** + * Class TransportBuilder + */ class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder { /** @@ -16,6 +30,151 @@ class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder */ protected $templateData = []; + /** + * Param that used for storing all message data until it will be used + * + * @var array + */ + private $messageData = []; + + /** + * @var EmailMessageInterfaceFactory + */ + private $emailMessageInterfaceFactory; + + /** + * @var MimeMessageInterfaceFactory + */ + private $mimeMessageInterfaceFactory; + + /** + * @var MimePartInterfaceFactory + */ + private $mimePartInterfaceFactory; + + /** + * TransportBuilder constructor + * + * @param FactoryInterface $templateFactory + * @param MessageInterface $message + * @param SenderResolverInterface $senderResolver + * @param ObjectManagerInterface $objectManager + * @param TransportInterfaceFactory $mailTransportFactory + * @param MessageInterfaceFactory|null $messageFactory + * @param EmailMessageInterfaceFactory|null $emailMessageInterfaceFactory + * @param MimeMessageInterfaceFactory|null $mimeMessageInterfaceFactory + * @param MimePartInterfaceFactory|null $mimePartInterfaceFactory + */ + public function __construct( + FactoryInterface $templateFactory, + MessageInterface $message, + SenderResolverInterface $senderResolver, + ObjectManagerInterface $objectManager, + TransportInterfaceFactory $mailTransportFactory, + MessageInterfaceFactory $messageFactory = null, + EmailMessageInterfaceFactory $emailMessageInterfaceFactory = null, + MimeMessageInterfaceFactory $mimeMessageInterfaceFactory = null, + MimePartInterfaceFactory $mimePartInterfaceFactory = null + ) { + parent::__construct( + $templateFactory, + $message, + $senderResolver, + $objectManager, + $mailTransportFactory, + $messageFactory, + $emailMessageInterfaceFactory, + $mimeMessageInterfaceFactory, + $mimePartInterfaceFactory + ); + $this->emailMessageInterfaceFactory = $emailMessageInterfaceFactory ?: $this->objectManager + ->get(EmailMessageInterfaceFactory::class); + $this->mimeMessageInterfaceFactory = $mimeMessageInterfaceFactory ?: $this->objectManager + ->get(MimeMessageInterfaceFactory::class); + $this->mimePartInterfaceFactory = $mimePartInterfaceFactory ?: $this->objectManager + ->get(MimePartInterfaceFactory::class); + } + + /** + * @inheritDoc + */ + public function addCc($address, $name = '') + { + $this->messageData['cc'][$address] = $name; + + return $this; + } + + /** + * Add to address + * + * @param array|string $address + * @param string $name + * @return $this + */ + public function addTo($address, $name = '') + { + if (!$name) { + $this->messageData['to'][] = $address; + } else { + $this->messageData['to'][$address] = $name; + } + + return $this; + } + + /** + * @inheritDoc + */ + public function addBcc($address) + { + $this->messageData['bcc'] = $address; + + return $this; + } + + /** + * @inheritDoc + */ + public function setReplyTo($email, $name = null) + { + $this->messageData['replyTo'][$email] = $name; + + return $this; + } + + /** + * @inheritDoc + */ + public function setFrom($from) + { + return $this->setFromByScope($from, null); + } + + /** + * @inheritDoc + */ + public function setFromByScope($from, $scopeId = null) + { + $result = $this->_senderResolver->resolve($from, $scopeId); + $this->messageData['from'][$result['email']] = $result['name']; + + return $this; + } + + /** + * @inheritDoc + */ + protected function reset() + { + $this->messageData = []; + $this->templateIdentifier = null; + $this->templateVars = null; + $this->templateOptions = null; + + return $this; + } + /** * Set template data * @@ -25,11 +184,15 @@ class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder public function setTemplateData($data) { $this->templateData = $data; + return $this; } /** + * Sets up template filter + * * @param AbstractTemplate $template + * * @return void */ protected function setTemplateFilter(AbstractTemplate $template) @@ -48,9 +211,16 @@ protected function prepareMessage() $template = $this->getTemplate()->setData($this->templateData); $this->setTemplateFilter($template); $part['content'] = $template->getProcessedTemplate($this->templateVars); - $this->messageData['body'][] = $part; $this->messageData['subject'] = $template->getSubject(); - $this->message = $this->mailEnvelopeBuilder->buildByArray($this->messageData); + + $this->messageData['body'] = $this->mimeMessageInterfaceFactory + ->create(['parts' => [$this->mimePartInterfaceFactory->create([$part])]]); + + $this->messageData['subject'] = html_entity_decode( + (string)$template->getSubject(), + ENT_QUOTES + ); + $this->message = $this->emailMessageInterfaceFactory->create($this->messageData); return $this; } diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php index 7b435c91a668..f0f4eb2af99a 100644 --- a/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php +++ b/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php @@ -3,11 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Newsletter\Test\Unit\Model\Queue; use Magento\Framework\App\TemplateTypesInterface; use Magento\Framework\Mail\MessageInterface; +/** + * Class TransportBuilderTest + */ class TransportBuilderTest extends \PHPUnit\Framework\TestCase { /** diff --git a/app/etc/di.xml b/app/etc/di.xml index afe8f36b7de8..1a74fd9d7f84 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -1771,4 +1771,10 @@ + + +
diff --git a/lib/internal/Magento/Framework/Mail/MessageEnvelope.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php similarity index 80% rename from lib/internal/Magento/Framework/Mail/MessageEnvelope.php rename to lib/internal/Magento/Framework/Mail/EmailMessage.php index 649c5576f163..d2cdb3771322 100644 --- a/lib/internal/Magento/Framework/Mail/MessageEnvelope.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -9,11 +9,12 @@ use Zend\Mail\AddressList; use Zend\Mail\Message as ZendMessage; +use Zend\Mime\Message as ZendMimeMessage; /** - * Class MessageEnvelope + * Class EmailMessage */ -class MessageEnvelope implements MessageEnvelopeInterface +class EmailMessage implements EmailMessageInterface { /** * @var ZendMessage @@ -21,15 +22,15 @@ class MessageEnvelope implements MessageEnvelopeInterface private $message; /** - * @var MimeMessageFactory + * @var MimeMessageInterfaceFactory */ private $mimeMessageFactory; /** - * MessageEnvelope constructor + * EmailMessage constructor * * @param MimeMessageInterface $body - * @param MimeMessageFactory $mimeMessageFactory + * @param MimeMessageInterfaceFactory $mimeMessageFactory * @param array|null $to * @param array|null $from * @param array|null $cc @@ -39,11 +40,12 @@ class MessageEnvelope implements MessageEnvelopeInterface * @param string|null $senderName * @param string|null $subject * @param string|null $encoding + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( MimeMessageInterface $body, - MimeMessageFactory $mimeMessageFactory, + MimeMessageInterfaceFactory $mimeMessageFactory, ?array $to = [], ?array $from = [], ?array $cc = [], @@ -55,7 +57,7 @@ public function __construct( ?string $encoding = '' ) { $this->message = new ZendMessage(); - $mimeMessage = new \Zend\Mime\Message(); + $mimeMessage = new ZendMimeMessage(); $mimeMessage->setParts($body->getParts()); $this->message->setBody($mimeMessage); if ($encoding) { @@ -76,9 +78,7 @@ public function __construct( } /** - * Get the message encoding - * - * @return string + * @inheritDoc */ public function getEncoding(): string { @@ -86,9 +86,7 @@ public function getEncoding(): string } /** - * Access headers collection - * - * @return array + * @inheritDoc */ public function getHeaders(): array { @@ -96,9 +94,7 @@ public function getHeaders(): array } /** - * Retrieve list of From senders - * - * @return array + * @inheritDoc */ public function getFrom(): array { @@ -106,9 +102,7 @@ public function getFrom(): array } /** - * Access the address list of the To header - * - * @return array + * @inheritDoc */ public function getTo(): array { @@ -116,9 +110,7 @@ public function getTo(): array } /** - * Retrieve list of CC recipients - * - * @return array + * @inheritDoc */ public function getCc(): array { @@ -136,9 +128,7 @@ public function getBcc(): array } /** - * Access the address list of the Reply-To header - * - * @return array + * @inheritDoc */ public function getReplyTo(): array { @@ -146,9 +136,7 @@ public function getReplyTo(): array } /** - * Retrieve the sender address, if any - * - * @return null|string + * @inheritDoc */ public function getSender(): ?string { @@ -156,9 +144,7 @@ public function getSender(): ?string } /** - * Get the message subject header value - * - * @return null|string + * @inheritDoc */ public function getSubject(): ?string { @@ -166,11 +152,9 @@ public function getSubject(): ?string } /** - * Return the currently set message body - * - * @return object|string|MimeMessageInterface + * @inheritDoc */ - public function getBody(): MimeMessageInterface + public function getBody(): ?MimeMessageInterface { return $this->mimeMessageFactory->create( ['parts' => $this->message->getBody()->getParts()] diff --git a/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterface.php b/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php similarity index 90% rename from lib/internal/Magento/Framework/Mail/MessageEnvelopeInterface.php rename to lib/internal/Magento/Framework/Mail/EmailMessageInterface.php index 9c82d090135d..523d97cd0a42 100644 --- a/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterface.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php @@ -7,9 +7,9 @@ namespace Magento\Framework\Mail; /** - * Interface MessageEnvelopeInterface + * Interface EmailMessageInterface */ -interface MessageEnvelopeInterface +interface EmailMessageInterface { /** * Get the message encoding @@ -77,9 +77,9 @@ public function getSubject(): ?string; /** * Return the currently set message body * - * @return object|string|MimeMessageInterface + * @return MimeMessageInterface|null */ - public function getBody(): MimeMessageInterface; + public function getBody(): ?MimeMessageInterface; /** * Get the string-serialized message body text diff --git a/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php b/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php deleted file mode 100644 index 77c652bd64f9..000000000000 --- a/lib/internal/Magento/Framework/Mail/MailEnvelopeBuilder.php +++ /dev/null @@ -1,69 +0,0 @@ -messageEnvelopeFactory = $messageEnvelopeFactory; - $this->mimeMessageFactory = $mimeMessageFactory; - $this->mimePartFactory = $mimePartFactory; - } - - /** - * Builds message Envelope from Message Data array - * - * @param array $messageData - * @return MessageEnvelopeInterface - */ - public function buildByArray(array $messageData): MessageEnvelopeInterface - { - $parts = []; - if (isset($messageData['body'])) { - foreach ($messageData['body'] as $item) { - if ($item instanceof MimePartInterface) { - $parts[] = $item; - } else { - $parts[] = $this->mimePartFactory->create($item); - } - } - } - $messageData['body'] = $this->mimeMessageFactory->create(['parts'=>$parts]); - - return $this->messageEnvelopeFactory->create($messageData); - } -} diff --git a/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php b/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php deleted file mode 100644 index 92cfa5355a95..000000000000 --- a/lib/internal/Magento/Framework/Mail/MessageEnvelopeInterfaceFactory.php +++ /dev/null @@ -1,49 +0,0 @@ -objectManager = $objectManager; - $this->instanceName = $instanceName; - } - - /** - * Create MessageEnvelopeInterface instance with specified parameters - * - * @param array $data - * @return MessageEnvelopeInterface - */ - public function create(array $data = []): MessageEnvelopeInterface - { - return $this->objectManager->create($this->instanceName, $data); - } -} diff --git a/lib/internal/Magento/Framework/Mail/MimeInterface.php b/lib/internal/Magento/Framework/Mail/MimeInterface.php index d491f83437a8..026dd188d168 100644 --- a/lib/internal/Magento/Framework/Mail/MimeInterface.php +++ b/lib/internal/Magento/Framework/Mail/MimeInterface.php @@ -7,22 +7,24 @@ namespace Magento\Framework\Mail; /** - * Interface MimeInterface + * Interface MimeInterface used providing constants + * + * @see \Zend\Mime\Mime */ interface MimeInterface { // @codingStandardsIgnoreStart - public const TYPE_OCTETSTREAM = 'application/octet-stream'; + public const TYPE_OCTET_STREAM = 'application/octet-stream'; public const TYPE_TEXT = 'text/plain'; public const TYPE_HTML = 'text/html'; public const ENCODING_7BIT = '7bit'; public const ENCODING_8BIT = '8bit'; - public const ENCODING_QUOTEDPRINTABLE = 'quoted-printable'; + public const ENCODING_QUOTED_PRINTABLE = 'quoted-printable'; public const ENCODING_BASE64 = 'base64'; public const DISPOSITION_ATTACHMENT = 'attachment'; public const DISPOSITION_INLINE = 'inline'; - public const LINELENGTH = 72; - public const LINEEND = "\n"; + public const LINE_LENGTH = 72; + public const LINE_END = "\n"; public const MULTIPART_ALTERNATIVE = 'multipart/alternative'; public const MULTIPART_MIXED = 'multipart/mixed'; public const MULTIPART_RELATED = 'multipart/related'; diff --git a/lib/internal/Magento/Framework/Mail/MimeMessage.php b/lib/internal/Magento/Framework/Mail/MimeMessage.php index 2d212deb2dca..4d783dafd1d7 100644 --- a/lib/internal/Magento/Framework/Mail/MimeMessage.php +++ b/lib/internal/Magento/Framework/Mail/MimeMessage.php @@ -49,7 +49,7 @@ public function isMultiPart(): bool /** * @inheritDoc */ - public function generateMessage(string $endOfLine = MimeInterface::LINEEND): string + public function getMessage(string $endOfLine = MimeInterface::LINE_END): string { return $this->mimeMessage->generateMessage($endOfLine); } @@ -57,7 +57,7 @@ public function generateMessage(string $endOfLine = MimeInterface::LINEEND): str /** * @inheritDoc */ - public function getPartHeadersArray(int $partNum): array + public function getPartHeadersAsArray(int $partNum): array { return $this->mimeMessage->getPartHeadersArray($partNum); } @@ -65,7 +65,7 @@ public function getPartHeadersArray(int $partNum): array /** * @inheritDoc */ - public function getPartHeaders(int $partNum, string $endOfLine = MimeInterface::LINEEND): string + public function getPartHeaders(int $partNum, string $endOfLine = MimeInterface::LINE_END): string { return $this->mimeMessage->getPartHeaders($partNum, $endOfLine); } @@ -73,7 +73,7 @@ public function getPartHeaders(int $partNum, string $endOfLine = MimeInterface:: /** * @inheritDoc */ - public function getPartContent(int $partNum, string $endOfLine = MimeInterface::LINEEND): string + public function getPartContent(int $partNum, string $endOfLine = MimeInterface::LINE_END): string { return $this->mimeMessage->getPartContent($partNum, $endOfLine); } diff --git a/lib/internal/Magento/Framework/Mail/MimeMessageInterface.php b/lib/internal/Magento/Framework/Mail/MimeMessageInterface.php index 043b9a908c9a..a272bcfd8980 100644 --- a/lib/internal/Magento/Framework/Mail/MimeMessageInterface.php +++ b/lib/internal/Magento/Framework/Mail/MimeMessageInterface.php @@ -32,7 +32,7 @@ public function isMultiPart(): bool; * * @return string */ - public function generateMessage(string $endOfLine = MimeInterface::LINEEND): string; + public function getMessage(string $endOfLine = MimeInterface::LINE_END): string; /** * Get the headers of a given part as an array @@ -41,7 +41,7 @@ public function generateMessage(string $endOfLine = MimeInterface::LINEEND): str * * @return array */ - public function getPartHeadersArray(int $partNum): array; + public function getPartHeadersAsArray(int $partNum): array; /** * Get the headers of a given part as a string @@ -51,7 +51,7 @@ public function getPartHeadersArray(int $partNum): array; * * @return string */ - public function getPartHeaders(int $partNum, string $endOfLine = MimeInterface::LINEEND): string; + public function getPartHeaders(int $partNum, string $endOfLine = MimeInterface::LINE_END): string; /** * Get the (encoded) content of a given part as a string @@ -61,5 +61,5 @@ public function getPartHeaders(int $partNum, string $endOfLine = MimeInterface:: * * @return string */ - public function getPartContent(int $partNum, string $endOfLine = MimeInterface::LINEEND): string; + public function getPartContent(int $partNum, string $endOfLine = MimeInterface::LINE_END): string; } diff --git a/lib/internal/Magento/Framework/Mail/MimeMessageInterfaceFactory.php b/lib/internal/Magento/Framework/Mail/MimeMessageInterfaceFactory.php deleted file mode 100644 index da1be8753bb0..000000000000 --- a/lib/internal/Magento/Framework/Mail/MimeMessageInterfaceFactory.php +++ /dev/null @@ -1,49 +0,0 @@ -objectManager = $objectManager; - $this->instanceName = $instanceName; - } - - /** - * Creates MimeMessageInterface instance with specified parameters - * - * @param array $data - * @return MimeMessageInterface - */ - public function create(array $data = []): MimeMessageInterface - { - return $this->objectManager->create($this->instanceName, $data); - } -} diff --git a/lib/internal/Magento/Framework/Mail/MimePart.php b/lib/internal/Magento/Framework/Mail/MimePart.php index 036b7b9db8de..e33090559a63 100644 --- a/lib/internal/Magento/Framework/Mail/MimePart.php +++ b/lib/internal/Magento/Framework/Mail/MimePart.php @@ -7,6 +7,7 @@ namespace Magento\Framework\Mail; +use Magento\Framework\Exception\MailException; use Zend\Mime\Part as ZendMimePart; /** @@ -34,12 +35,13 @@ class MimePart implements MimePartInterface * @param string|null $location * @param string|null $language * @param bool|null $isStream + * * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( $content, - ?string $type = MimeInterface::TYPE_OCTETSTREAM, + ?string $type = MimeInterface::TYPE_OCTET_STREAM, ?string $fileName = null, ?string $disposition = null, ?string $encoding = MimeInterface::ENCODING_8BIT, @@ -51,7 +53,11 @@ public function __construct( ?string $language = null, ?bool $isStream = null ) { - $this->mimePart = new ZendMimePart($content); + try { + $this->mimePart = new ZendMimePart($content); + } catch (\Zend\Mime\Exception\InvalidArgumentException $e) { + throw new MailException(__($e->getMessage())); + } $this->mimePart->setType($type); $this->mimePart->setEncoding($encoding); $this->mimePart->setFilters($filters); @@ -172,7 +178,7 @@ public function isStream(): bool /** * @inheritDoc */ - public function getEncodedStream($endOfLine = MimeInterface::LINEEND) + public function getEncodedStream($endOfLine = MimeInterface::LINE_END) { return $this->mimePart->getEncodedStream($endOfLine); } @@ -180,7 +186,7 @@ public function getEncodedStream($endOfLine = MimeInterface::LINEEND) /** * @inheritDoc */ - public function getContent($endOfLine = MimeInterface::LINEEND) + public function getContent($endOfLine = MimeInterface::LINE_END) { return $this->mimePart->getContent($endOfLine); } @@ -196,7 +202,7 @@ public function getRawContent(): string /** * @inheritDoc */ - public function getHeadersArray($endOfLine = MimeInterface::LINEEND): array + public function getHeadersAsArray($endOfLine = MimeInterface::LINE_END): array { return $this->mimePart->getHeadersArray($endOfLine); } @@ -204,7 +210,7 @@ public function getHeadersArray($endOfLine = MimeInterface::LINEEND): array /** * @inheritDoc */ - public function getHeaders($endOfLine = MimeInterface::LINEEND): string + public function getHeaders($endOfLine = MimeInterface::LINE_END): string { return $this->mimePart->getHeaders($endOfLine); } diff --git a/lib/internal/Magento/Framework/Mail/MimePartInterface.php b/lib/internal/Magento/Framework/Mail/MimePartInterface.php index 6786549a618b..2de4c134da50 100644 --- a/lib/internal/Magento/Framework/Mail/MimePartInterface.php +++ b/lib/internal/Magento/Framework/Mail/MimePartInterface.php @@ -95,7 +95,7 @@ public function isStream(): bool; * * @return resource */ - public function getEncodedStream($endOfLine = MimeInterface::LINEEND); + public function getEncodedStream($endOfLine = MimeInterface::LINE_END); /** * Get the Content of the current Mime Part in the given encoding. @@ -104,7 +104,7 @@ public function getEncodedStream($endOfLine = MimeInterface::LINEEND); * * @return string|resource */ - public function getContent($endOfLine = MimeInterface::LINEEND); + public function getContent($endOfLine = MimeInterface::LINE_END); /** * Get the RAW unencoded content from this part @@ -120,7 +120,7 @@ public function getRawContent(): string; * * @return array */ - public function getHeadersArray($endOfLine = MimeInterface::LINEEND): array; + public function getHeadersAsArray($endOfLine = MimeInterface::LINE_END): array; /** * Create and return the array of headers for this MIME part @@ -129,5 +129,5 @@ public function getHeadersArray($endOfLine = MimeInterface::LINEEND): array; * * @return string */ - public function getHeaders($endOfLine = MimeInterface::LINEEND): string; + public function getHeaders($endOfLine = MimeInterface::LINE_END): string; } diff --git a/lib/internal/Magento/Framework/Mail/MimePartInterfaceFactory.php b/lib/internal/Magento/Framework/Mail/MimePartInterfaceFactory.php deleted file mode 100644 index e29fc8f6a51c..000000000000 --- a/lib/internal/Magento/Framework/Mail/MimePartInterfaceFactory.php +++ /dev/null @@ -1,49 +0,0 @@ -objectManager = $objectManager; - $this->instanceName = $instanceName; - } - - /** - * Create MimePartInterface instance with specified parameters - * - * @param array $data - * @return MimePartInterface - */ - public function create(array $data = []): MimePartInterface - { - return $this->objectManager->create($this->instanceName, $data); - } -} diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index fd79a02c5a74..a5d06ffb9e58 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -11,10 +11,16 @@ use Magento\Framework\App\TemplateTypesInterface; use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Mail\MailEnvelopeBuilder; +use Magento\Framework\Exception\MailException; +use Magento\Framework\Mail\EmailMessageInterface; +use Magento\Framework\Mail\EmailMessageInterfaceFactory; use Magento\Framework\Mail\MessageInterface; use Magento\Framework\Mail\MessageInterfaceFactory; use Magento\Framework\Mail\MimeInterface; +use Magento\Framework\Mail\MimeMessageInterfaceFactory; +use Magento\Framework\Mail\MimePartInterfaceFactory; +use Magento\Framework\Mail\TemplateInterface; +use Magento\Framework\Mail\TransportInterface; use Magento\Framework\Mail\TransportInterfaceFactory; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Phrase; @@ -58,7 +64,7 @@ class TransportBuilder /** * Mail Transport * - * @var \Magento\Framework\Mail\TransportInterface + * @var TransportInterface */ protected $transport; @@ -72,55 +78,64 @@ class TransportBuilder /** * Object Manager * - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ protected $objectManager; /** * Message * - * @var \Magento\Framework\Mail\MessageEnvelopeInterface + * @var EmailMessageInterface */ protected $message; /** * Sender resolver * - * @var \Magento\Framework\Mail\Template\SenderResolverInterface + * @var SenderResolverInterface */ protected $_senderResolver; /** - * @var \Magento\Framework\Mail\TransportInterfaceFactory + * @var TransportInterfaceFactory */ protected $mailTransportFactory; - /** - * @var \Magento\Framework\Mail\MessageInterfaceFactory - */ - private $messageFactory; - /** * Param that used for storing all message data until it will be used * * @var array */ - protected $messageData = []; + private $messageData = []; + + /** + * @var EmailMessageInterfaceFactory + */ + private $emailMessageInterfaceFactory; /** - * @var MailEnvelopeBuilder|null + * @var MimeMessageInterfaceFactory */ - protected $mailEnvelopeBuilder; + private $mimeMessageInterfaceFactory; /** + * @var MimePartInterfaceFactory + */ + private $mimePartInterfaceFactory; + + /** + * TransportBuilder constructor + * * @param FactoryInterface $templateFactory * @param MessageInterface $message * @param SenderResolverInterface $senderResolver * @param ObjectManagerInterface $objectManager * @param TransportInterfaceFactory $mailTransportFactory - * @param MessageInterfaceFactory $messageFactory + * @param MessageInterfaceFactory|null $messageFactory + * @param EmailMessageInterfaceFactory|null $emailMessageInterfaceFactory + * @param MimeMessageInterfaceFactory|null $mimeMessageInterfaceFactory + * @param MimePartInterfaceFactory|null $mimePartInterfaceFactory * - * @param MailEnvelopeBuilder|null $mailEnvelopeBuilder * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( @@ -130,16 +145,20 @@ public function __construct( ObjectManagerInterface $objectManager, TransportInterfaceFactory $mailTransportFactory, MessageInterfaceFactory $messageFactory = null, - MailEnvelopeBuilder $mailEnvelopeBuilder = null + EmailMessageInterfaceFactory $emailMessageInterfaceFactory = null, + MimeMessageInterfaceFactory $mimeMessageInterfaceFactory = null, + MimePartInterfaceFactory $mimePartInterfaceFactory = null ) { $this->templateFactory = $templateFactory; $this->objectManager = $objectManager; $this->_senderResolver = $senderResolver; $this->mailTransportFactory = $mailTransportFactory; - $this->messageFactory = $messageFactory ?: $this->objectManager - ->get(MessageInterfaceFactory::class); - $this->mailEnvelopeBuilder = $mailEnvelopeBuilder ?: $this->objectManager - ->get(MailEnvelopeBuilder::class); + $this->emailMessageInterfaceFactory = $emailMessageInterfaceFactory ?: $this->objectManager + ->get(EmailMessageInterfaceFactory::class); + $this->mimeMessageInterfaceFactory = $mimeMessageInterfaceFactory ?: $this->objectManager + ->get(MimeMessageInterfaceFactory::class); + $this->mimePartInterfaceFactory = $mimePartInterfaceFactory ?: $this->objectManager + ->get(MimePartInterfaceFactory::class); } /** @@ -206,7 +225,7 @@ public function setReplyTo($email, $name = null) * * @param string|array $from * @return $this - * @throws \Magento\Framework\Exception\MailException + * @throws MailException * @see setFromByScope() * * @deprecated This function sets the from address but does not provide @@ -223,7 +242,7 @@ public function setFrom($from) * @param string|array $from * @param string|int $scopeId * @return $this - * @throws \Magento\Framework\Exception\MailException + * @throws MailException */ public function setFromByScope($from, $scopeId = null) { @@ -232,32 +251,6 @@ public function setFromByScope($from, $scopeId = null) return $this; } - /** - * Add mail attachment - * - * @param resource|string $content - * @param string $type - * @param string $fileName - * @param string $disposition - * - * @return $this - */ - public function addAttachment( - $content, - string $type, - string $fileName, - string $disposition = MimeInterface::DISPOSITION_ATTACHMENT - ): self { - $this->messageData['body'][] = [ - 'content' => $content, - 'type' => $type, - 'fileName' => $fileName, - 'disposition' => $disposition - ]; - - return $this; - } - /** * Set template identifier * @@ -309,7 +302,7 @@ public function setTemplateOptions($templateOptions) /** * Get mail transport * - * @return \Magento\Framework\Mail\TransportInterface + * @return TransportInterface * @throws LocalizedException */ public function getTransport() @@ -341,7 +334,7 @@ protected function reset() /** * Get template * - * @return \Magento\Framework\Mail\TemplateInterface + * @return TemplateInterface */ protected function getTemplate() { @@ -374,9 +367,14 @@ protected function prepareMessage() new Phrase('Unknown template type') ); } - $this->messageData['body'][] = $part; - $this->messageData['subject'] = html_entity_decode((string)$template->getSubject(), ENT_QUOTES); - $this->message = $this->mailEnvelopeBuilder->buildByArray($this->messageData); + $this->messageData['body'] = $this->mimeMessageInterfaceFactory + ->create(['parts' => [$this->mimePartInterfaceFactory->create([$part])]]); + + $this->messageData['subject'] = html_entity_decode( + (string)$template->getSubject(), + ENT_QUOTES + ); + $this->message = $this->emailMessageInterfaceFactory->create($this->messageData); return $this; } diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index fe604573ad4f..f62ed8b2e7de 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -3,14 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Framework\Mail\Test\Unit\Template; use Magento\Framework\App\TemplateTypesInterface; -use Magento\Framework\Mail\MessageInterface; /** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * Class TransportBuilderTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class TransportBuilderTest extends \PHPUnit\Framework\TestCase { @@ -55,13 +57,9 @@ class TransportBuilderTest extends \PHPUnit\Framework\TestCase protected $mailTransportFactoryMock; /** - * @var \Magento\Framework\Mail\MailEnvelopeBuilder|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Mail\EmailMessageInterface|\PHPUnit\Framework\MockObject\MockObject */ - protected $mailEnvelopeBuilder; - /** - * @var \Magento\Framework\Mail\MessageEnvelopeInterface|\PHPUnit\Framework\MockObject\MockObject - */ - private $messageEnvelopeMock; + private $emailMessageMock; /** * @return void @@ -71,7 +69,7 @@ protected function setUp() $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->templateFactoryMock = $this->createMock(\Magento\Framework\Mail\Template\FactoryInterface::class); $this->messageMock = $this->createMock(\Magento\Framework\Mail\Message::class); - $this->messageEnvelopeMock = $this->createMock(\Magento\Framework\Mail\MessageEnvelopeInterface::class); + $this->emailMessageMock = $this->createMock(\Magento\Framework\Mail\EmailMessageInterface::class); $this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); $this->senderResolverMock = $this->createMock(\Magento\Framework\Mail\Template\SenderResolverInterface::class); $this->mailTransportFactoryMock = $this->getMockBuilder( diff --git a/lib/internal/Magento/Framework/composer.json b/lib/internal/Magento/Framework/composer.json index b153cb513af2..9e3d44103b04 100644 --- a/lib/internal/Magento/Framework/composer.json +++ b/lib/internal/Magento/Framework/composer.json @@ -37,6 +37,7 @@ "zendframework/zend-stdlib": "^2.7.7", "zendframework/zend-uri": "^2.5.1", "zendframework/zend-validator": "^2.6.0", + "zendframework/zend-mail": "^2.9.0", "guzzlehttp/guzzle": "^6.3.3" }, "archive": { From 7fd2dc8581ac1722ed5f51671d12a8bc50a63aa2 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Wed, 31 Jul 2019 19:20:57 +0300 Subject: [PATCH 17/37] MC-15295: Implementation of MailAddress and MailAddressList DTO, refactoring EmailMessage and Transport builder --- .../Magento/Framework/Mail/EmailMessage.php | 120 +++++---- .../Framework/Mail/EmailMessageInterface.php | 28 +- .../Magento/Framework/Mail/MailAddress.php | 35 +++ .../Framework/Mail/MailAddressList.php | 242 ++++++++++++++++++ .../Mail/Template/TransportBuilder.php | 86 ++++++- 5 files changed, 444 insertions(+), 67 deletions(-) create mode 100644 lib/internal/Magento/Framework/Mail/MailAddress.php create mode 100644 lib/internal/Magento/Framework/Mail/MailAddressList.php diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index d2cdb3771322..1cf9df0c0300 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -7,6 +7,8 @@ namespace Magento\Framework\Mail; +use Magento\Framework\Exception\MailException; +use Zend\Mail\Address as ZendAddress; use Zend\Mail\AddressList; use Zend\Mail\Message as ZendMessage; use Zend\Mime\Message as ZendMimeMessage; @@ -26,33 +28,46 @@ class EmailMessage implements EmailMessageInterface */ private $mimeMessageFactory; + /** + * @var MailAddressListFactory + */ + private $mailAddressListFactory; + + /** + * @var MailAddressFactory + */ + private $mailAddressFactory; + /** * EmailMessage constructor * * @param MimeMessageInterface $body + * @param MailAddressList $to * @param MimeMessageInterfaceFactory $mimeMessageFactory - * @param array|null $to - * @param array|null $from - * @param array|null $cc - * @param array|null $bcc - * @param array|null $replyTo - * @param string|null $sender - * @param string|null $senderName + * @param MailAddressListFactory $mailAddressListFactory + * @param MailAddressFactory $mailAddressFactory + * @param MailAddressList|null $from + * @param MailAddressList|null $cc + * @param MailAddressList|null $bcc + * @param MailAddressList|null $replyTo + * @param MailAddress|null $sender * @param string|null $subject * @param string|null $encoding * + * @throws MailException * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( MimeMessageInterface $body, + MailAddressList $to, MimeMessageInterfaceFactory $mimeMessageFactory, - ?array $to = [], - ?array $from = [], - ?array $cc = [], - ?array $bcc = [], - ?array $replyTo = [], - ?string $sender = '', - ?string $senderName = '', + MailAddressListFactory $mailAddressListFactory, + MailAddressFactory $mailAddressFactory, + ?MailAddressList $from = null, + ?MailAddressList $cc = null, + ?MailAddressList $bcc = null, + ?MailAddressList $replyTo = null, + ?MailAddress $sender = null, ?string $subject = '', ?string $encoding = '' ) { @@ -67,14 +82,20 @@ public function __construct( $this->message->setSubject($subject); } if ($sender) { - $this->message->setSender($sender, $senderName); + $this->message->setSender($sender); } $this->message->setReplyTo($replyTo); + if ($to->count() < 1) { + throw new MailException(__('Email message must have at list one addressee')); + } + $this->message->setTo($to); $this->message->setFrom($from); $this->message->setCc($cc); $this->message->setBcc($bcc); $this->mimeMessageFactory = $mimeMessageFactory; + $this->mailAddressListFactory = $mailAddressListFactory; + $this->mailAddressFactory = $mailAddressFactory; } /** @@ -96,51 +117,60 @@ public function getHeaders(): array /** * @inheritDoc */ - public function getFrom(): array + public function getFrom(): ?MailAddressList { - return $this->convertAddressListToArray($this->message->getFrom()); + return $this->convertAddressListToMailAddressList($this->message->getFrom()); } /** * @inheritDoc */ - public function getTo(): array + public function getTo(): MailAddressList { - return $this->convertAddressListToArray($this->message->getTo()); + return $this->convertAddressListToMailAddressList($this->message->getTo()); } /** * @inheritDoc */ - public function getCc(): array + public function getCc(): ?MailAddressList { - return $this->convertAddressListToArray($this->message->getCc()); + return $this->convertAddressListToMailAddressList($this->message->getCc()); } /** - * Retrieve list of BCC recipients - * - * @return array + * @inheritDoc */ - public function getBcc(): array + public function getBcc(): ?MailAddressList { - return $this->convertAddressListToArray($this->message->getBcc()); + return $this->convertAddressListToMailAddressList($this->message->getBcc()); } /** * @inheritDoc */ - public function getReplyTo(): array + public function getReplyTo(): ?MailAddressList { - return $this->convertAddressListToArray($this->message->getReplyTo()); + return $this->convertAddressListToMailAddressList($this->message->getReplyTo()); } /** * @inheritDoc */ - public function getSender(): ?string + public function getSender(): ?MailAddress { - return $this->message->getSender(); + /** @var ZendAddress $zendSender */ + if (!$zendSender = $this->message->getSender()) { + return null; + } + + return $this->mailAddressFactory->create( + [ + 'email' => $zendSender->getEmail(), + 'name' => $zendSender->getName(), + 'comment' => $zendSender->getComment() + ] + ); } /** @@ -154,7 +184,7 @@ public function getSubject(): ?string /** * @inheritDoc */ - public function getBody(): ?MimeMessageInterface + public function getBody(): MimeMessageInterface { return $this->mimeMessageFactory->create( ['parts' => $this->message->getBody()->getParts()] @@ -178,9 +208,7 @@ public function getRawMessage(): string } /** - * Serialize to string - * - * @return string + * @inheritDoc */ public function toString(): string { @@ -191,17 +219,23 @@ public function toString(): string * Converts AddressList to array * * @param AddressList $addressList - * @return array + * @return MailAddressList + * @throws MailException */ - private function convertAddressListToArray(AddressList $addressList): array + private function convertAddressListToMailAddressList(AddressList $addressList): MailAddressList { - $arrayList = []; - foreach ($addressList as $email => $address) { - if ($address->getName()) { - $arrayList[$email] = $address->getName(); - } else { - $arrayList[] = $address->getEmail(); - } + /** @var MailAddressList $arrayList */ + $arrayList = $this->mailAddressListFactory->create(); + foreach ($addressList as $address) { + $arrayList->add( + $this->mailAddressFactory->create( + [ + 'email' => $address->getEmail(), + 'name' => $address->getName(), + 'comment' => $address->getComment() + ] + ) + ); } return $arrayList; diff --git a/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php b/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php index 523d97cd0a42..25f9659b3c8a 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php @@ -28,44 +28,44 @@ public function getHeaders(): array; /** * Retrieve list of From senders * - * @return array + * @return MailAddressList|null */ - public function getFrom(): array; + public function getFrom(): ?MailAddressList; /** * Access the address list of the To header * - * @return array + * @return MailAddressList */ - public function getTo(): array; + public function getTo(): MailAddressList; /** * Retrieve list of CC recipients * - * @return array + * @return MailAddressList|null */ - public function getCc(): array; + public function getCc(): ?MailAddressList; /** * Retrieve list of BCC recipients * - * @return array + * @return MailAddressList|null */ - public function getBcc(): array; + public function getBcc(): ?MailAddressList; /** * Access the address list of the Reply-To header * - * @return array + * @return MailAddressList|null */ - public function getReplyTo(): array; + public function getReplyTo(): ?MailAddressList; /** * Retrieve the sender address, if any * - * @return null|array + * @return MailAddress|null */ - public function getSender(): ?string; + public function getSender(): ?MailAddress; /** * Get the message subject header value @@ -77,9 +77,9 @@ public function getSubject(): ?string; /** * Return the currently set message body * - * @return MimeMessageInterface|null + * @return MimeMessageInterface */ - public function getBody(): ?MimeMessageInterface; + public function getBody(): MimeMessageInterface; /** * Get the string-serialized message body text diff --git a/lib/internal/Magento/Framework/Mail/MailAddress.php b/lib/internal/Magento/Framework/Mail/MailAddress.php new file mode 100644 index 000000000000..8919d0dec64b --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MailAddress.php @@ -0,0 +1,35 @@ +getMessage())); + } + } + + +} diff --git a/lib/internal/Magento/Framework/Mail/MailAddressList.php b/lib/internal/Magento/Framework/Mail/MailAddressList.php new file mode 100644 index 000000000000..2737aeeb64d7 --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MailAddressList.php @@ -0,0 +1,242 @@ +mailAddressFactory = $mailAddressFactory; + } + + /** + * Add an address to the list + * + * @param string|MailAddress $emailOrAddress + * @param null|string $name + * + * @return MailAddressList + * @throws MailException + */ + public function add($emailOrAddress, ?string $name = null): MailAddressList + { + if (is_string($emailOrAddress)) { + $emailOrAddress = $this->createAddress($emailOrAddress, $name); + } + + if (! $emailOrAddress instanceof MailAddress) { + throw new MailException(__( + '%s expects an email address or %s\MailAddress object as its first argument; received "%s"', + __METHOD__, + __NAMESPACE__, + (is_object($emailOrAddress) ? get_class($emailOrAddress) : gettype($emailOrAddress)) + )); + } + + $email = strtolower($emailOrAddress->getEmail()); + if ($this->has($email)) { + return $this; + } + + $this->addresses[$email] = $emailOrAddress; + return $this; + } + + /** + * Add many addresses at once + * + * @param array $addresses + * + * @return MailAddressList + * @throws MailException + */ + public function addMany(array $addresses): MailAddressList + { + foreach ($addresses as $key => $value) { + if (is_int($key) || is_numeric($key)) { + $this->add($value); + continue; + } + + if (! is_string($key)) { + throw new MailException(__( + 'Invalid key type in provided addresses array ("%s")', + (is_object($key) ? get_class($key) : var_export($key, 1)) + )); + } + + $this->add($key, $value); + } + + return $this; + } + + /** + * Merge another address list into this one + * + * @param MailAddressList $addressList + * + * @return MailAddressList + * @throws MailException + */ + public function merge(MailAddressList $addressList): MailAddressList + { + foreach ($addressList as $address) { + $this->add($address); + } + return $this; + } + + /** + * Does the email exist in this list? + * + * @param string $email + * + * @return bool + */ + public function has($email): bool + { + $email = strtolower($email); + + return isset($this->addresses[$email]); + } + + /** + * Delete an address from the list + * + * @param string $email + * + * @return bool + */ + public function delete($email): bool + { + $email = strtolower($email); + if (!isset($this->addresses[$email])) { + return false; + } + + unset($this->addresses[$email]); + + return true; + } + + /** + * Return count of addresses + * + * @return int + */ + public function count(): int + { + return count($this->addresses); + } + + /** + * Rewind iterator + * + * @return mixed + */ + public function rewind() + { + return reset($this->addresses); + } + + /** + * Return current item in iteration + * + * @return MailAddress + */ + public function current(): MailAddress + { + return current($this->addresses); + } + + /** + * Return key of current item of iteration + * + * @return string + */ + public function key(): string + { + return key($this->addresses); + } + + /** + * Move to next item + * + * @return mixed + */ + public function next() + { + return next($this->addresses); + } + + /** + * Is the current item of iteration valid? + * + * @return bool + */ + public function valid(): bool + { + $key = key($this->addresses); + + return ($key !== null && $key !== false); + } + + /** + * Create an address object + * + * @param string $email + * @param string|null $name + * + * @return MailAddress + */ + private function createAddress(string $email, ?string $name=null): MailAddress + { + return $this->mailAddressFactory->create(['email' => $email, 'name' => $name]); + } + + /** + * Add an address to the list from any valid string format, such as + * - "ZF Dev" + * - dev@zf.com + * + * @param string $address + * @param null|string $comment Comment associated with the address, if any. + * @return MailAddressList + * @throws MailException + */ + public function addFromString($address, $comment = null): MailAddressList + { + $this->add(MailAddress::fromString($address, $comment)); + + return $this; + } +} diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index a5d06ffb9e58..1326985a2163 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -4,6 +4,7 @@ * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. + * @noinspection PhpUnusedParameterInspection */ declare(strict_types=1); @@ -14,6 +15,8 @@ use Magento\Framework\Exception\MailException; use Magento\Framework\Mail\EmailMessageInterface; use Magento\Framework\Mail\EmailMessageInterfaceFactory; +use Magento\Framework\Mail\MailAddressList; +use Magento\Framework\Mail\MailAddressListFactory; use Magento\Framework\Mail\MessageInterface; use Magento\Framework\Mail\MessageInterfaceFactory; use Magento\Framework\Mail\MimeInterface; @@ -123,6 +126,11 @@ class TransportBuilder */ private $mimePartInterfaceFactory; + /** + * @var MailAddressListFactory|null + */ + private $mailAddressListFactory; + /** * TransportBuilder constructor * @@ -135,7 +143,7 @@ class TransportBuilder * @param EmailMessageInterfaceFactory|null $emailMessageInterfaceFactory * @param MimeMessageInterfaceFactory|null $mimeMessageInterfaceFactory * @param MimePartInterfaceFactory|null $mimePartInterfaceFactory - * + * @param MailAddressListFactory|null $mailAddressListFactory * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( @@ -147,7 +155,8 @@ public function __construct( MessageInterfaceFactory $messageFactory = null, EmailMessageInterfaceFactory $emailMessageInterfaceFactory = null, MimeMessageInterfaceFactory $mimeMessageInterfaceFactory = null, - MimePartInterfaceFactory $mimePartInterfaceFactory = null + MimePartInterfaceFactory $mimePartInterfaceFactory = null, + MailAddressListFactory $mailAddressListFactory = null ) { $this->templateFactory = $templateFactory; $this->objectManager = $objectManager; @@ -159,6 +168,7 @@ public function __construct( ->get(MimeMessageInterfaceFactory::class); $this->mimePartInterfaceFactory = $mimePartInterfaceFactory ?: $this->objectManager ->get(MimePartInterfaceFactory::class); + $this->mailAddressListFactory = $mailAddressListFactory; } /** @@ -166,11 +176,16 @@ public function __construct( * * @param array|string $address * @param string $name + * * @return $this + * @throws MailException */ public function addCc($address, $name = '') { - $this->messageData['cc'][$address] = $name; + if (!isset($this->messageData['cc'])) { + $this->messageData['cc'] = $this->mailAddressListFactory->create(); + } + $this->getMailAddresses($this->messageData['cc'], $address, $name); return $this; } @@ -180,15 +195,16 @@ public function addCc($address, $name = '') * * @param array|string $address * @param string $name + * * @return $this + * @throws MailException */ public function addTo($address, $name = '') { - if (!$name) { - $this->messageData['to'][] = $address; - } else { - $this->messageData['to'][$address] = $name; + if (!isset($this->messageData['to'])) { + $this->messageData['to'] = $this->mailAddressListFactory->create(); } + $this->getMailAddresses($this->messageData['to'], $address, $name); return $this; } @@ -197,11 +213,17 @@ public function addTo($address, $name = '') * Add bcc address * * @param array|string $address + * * @return $this + * @throws MailException */ public function addBcc($address) { $this->messageData['bcc'] = $address; + if (!isset($this->messageData['bcc'])) { + $this->messageData['bcc'] = $this->mailAddressListFactory->create(); + } + $this->getMailAddresses($this->messageData['bcc'], $address); return $this; } @@ -211,11 +233,16 @@ public function addBcc($address) * * @param string $email * @param string|null $name + * * @return $this + * @throws MailException */ public function setReplyTo($email, $name = null) { - $this->messageData['replyTo'][$email] = $name; + if (!isset($this->messageData['replyTo'])) { + $this->messageData['replyTo'] = $this->mailAddressListFactory->create(); + } + $this->getMailAddresses($this->messageData['replyTo'], $email, $name); return $this; } @@ -224,6 +251,7 @@ public function setReplyTo($email, $name = null) * Set mail from address * * @param string|array $from + * * @return $this * @throws MailException * @see setFromByScope() @@ -233,7 +261,7 @@ public function setReplyTo($email, $name = null) */ public function setFrom($from) { - return $this->setFromByScope($from, null); + return $this->setFromByScope($from); } /** @@ -241,13 +269,18 @@ public function setFrom($from) * * @param string|array $from * @param string|int $scopeId + * * @return $this * @throws MailException */ public function setFromByScope($from, $scopeId = null) { $result = $this->_senderResolver->resolve($from, $scopeId); - $this->messageData['from'][$result['email']] = $result['name']; + if (!isset($this->messageData['from'])) { + $this->messageData['from'] = $this->mailAddressListFactory->create(); + } + $this->getMailAddresses($this->messageData['from'], $result['email'], $result['name']); + return $this; } @@ -255,11 +288,13 @@ public function setFromByScope($from, $scopeId = null) * Set template identifier * * @param string $templateIdentifier + * * @return $this */ public function setTemplateIdentifier($templateIdentifier) { $this->templateIdentifier = $templateIdentifier; + return $this; } @@ -267,6 +302,7 @@ public function setTemplateIdentifier($templateIdentifier) * Set template model * * @param string $templateModel + * * @return $this */ public function setTemplateModel($templateModel) @@ -279,11 +315,13 @@ public function setTemplateModel($templateModel) * Set template vars * * @param array $templateVars + * * @return $this */ public function setTemplateVars($templateVars) { $this->templateVars = $templateVars; + return $this; } @@ -296,6 +334,7 @@ public function setTemplateVars($templateVars) public function setTemplateOptions($templateOptions) { $this->templateOptions = $templateOptions; + return $this; } @@ -378,4 +417,31 @@ protected function prepareMessage() return $this; } + + /** + * Handles possible incoming types of email (string or array) + * + * @param MailAddressList $mailAddressList + * @param string|array $emailOrList + * @param string|null $name + * + * @return void + * @throws MailException + */ + private function getMailAddresses(MailAddressList $mailAddressList, $emailOrList, ?string $name = null): void + { + if (is_array($emailOrList)) { + $mailAddressList->addMany($emailOrList); + + return; + } + + if (is_string($emailOrList) && $name === null) { + $mailAddressList->addFromString($emailOrList); + + return; + } + + $mailAddressList->add($emailOrList, $name); + } } From 3aabe1926b5b2555200118b73a432ac0c68f9b93 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Wed, 31 Jul 2019 21:39:40 +0300 Subject: [PATCH 18/37] MC-15295: Fix MailAddress disign, Add MailAddressConverter --- .../Model/Queue/TransportBuilder.php | 121 +++++++-- .../Magento/Framework/Mail/EmailMessage.php | 93 ++++--- .../Framework/Mail/EmailMessageInterface.php | 22 +- .../Magento/Framework/Mail/MailAddress.php | 53 ++-- .../Framework/Mail/MailAddressConverter.php | 86 +++++++ .../Framework/Mail/MailAddressList.php | 242 ------------------ .../Magento/Framework/Mail/MimePart.php | 2 + .../Mail/Template/TransportBuilder.php | 63 ++--- .../Unit/Template/TransportBuilderTest.php | 2 +- 9 files changed, 312 insertions(+), 372 deletions(-) create mode 100644 lib/internal/Magento/Framework/Mail/MailAddressConverter.php delete mode 100644 lib/internal/Magento/Framework/Mail/MailAddressList.php diff --git a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php index 7143c1388893..17e344c94453 100644 --- a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php +++ b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php @@ -1,4 +1,7 @@ emailMessageInterfaceFactory = $emailMessageInterfaceFactory ?: $this->objectManager ->get(EmailMessageInterfaceFactory::class); @@ -93,14 +108,22 @@ public function __construct( ->get(MimeMessageInterfaceFactory::class); $this->mimePartInterfaceFactory = $mimePartInterfaceFactory ?: $this->objectManager ->get(MimePartInterfaceFactory::class); + $this->mailAddressConverter = $mailAddressConverter ?: $this->objectManager + ->get(MailAddressConverter::class); } /** - * @inheritDoc + * Add cc address + * + * @param array|string $address + * @param string $name + * + * @return \Magento\Framework\Mail\Template\TransportBuilder + * @throws MailException */ public function addCc($address, $name = '') { - $this->messageData['cc'][$address] = $name; + $this->getMailAddresses('cc', $address, $name); return $this; } @@ -110,54 +133,79 @@ public function addCc($address, $name = '') * * @param array|string $address * @param string $name + * * @return $this + * @throws MailException */ public function addTo($address, $name = '') { - if (!$name) { - $this->messageData['to'][] = $address; - } else { - $this->messageData['to'][$address] = $name; - } + $this->getMailAddresses('to', $address, $name); return $this; } /** - * @inheritDoc + * Add bcc address + * + * @param array|string $address + * + * @return $this + * @throws MailException */ public function addBcc($address) { - $this->messageData['bcc'] = $address; + $this->getMailAddresses('bcc', $address); return $this; } /** - * @inheritDoc + * Set Reply-To Header + * + * @param string $email + * @param string|null $name + * + * @return $this + * @throws MailException */ public function setReplyTo($email, $name = null) { - $this->messageData['replyTo'][$email] = $name; + + $this->getMailAddresses('replyTo', $email, $name); return $this; } /** - * @inheritDoc + * Set mail from address + * + * @param string|array $from + * + * @return $this + * @throws MailException + * @see setFromByScope() + * + * @deprecated This function sets the from address but does not provide + * a way of setting the correct from addresses based on the scope. */ public function setFrom($from) { - return $this->setFromByScope($from, null); + return $this->setFromByScope($from); } /** - * @inheritDoc + * Set mail from address by scopeId + * + * @param string|array $from + * @param string|int $scopeId + * + * @return $this + * @throws MailException */ public function setFromByScope($from, $scopeId = null) { $result = $this->_senderResolver->resolve($from, $scopeId); - $this->messageData['from'][$result['email']] = $result['name']; + $this->getMailAddresses('from', $result['email'], $result['name']); return $this; } @@ -207,21 +255,44 @@ protected function setTemplateFilter(AbstractTemplate $template) */ protected function prepareMessage() { - /** @var AbstractTemplate $template */ + /** @var AbstractTemplate|TemplateInterface $template */ $template = $this->getTemplate()->setData($this->templateData); $this->setTemplateFilter($template); - $part['content'] = $template->getProcessedTemplate($this->templateVars); + $content = $template->getProcessedTemplate($this->templateVars); $this->messageData['subject'] = $template->getSubject(); - $this->messageData['body'] = $this->mimeMessageInterfaceFactory - ->create(['parts' => [$this->mimePartInterfaceFactory->create([$part])]]); - - $this->messageData['subject'] = html_entity_decode( - (string)$template->getSubject(), - ENT_QUOTES + $mimePart = $this->mimePartInterfaceFactory->create( + ['content' => $content] ); + $this->messageData['body'] = $this->mimeMessageInterfaceFactory->create( + ['parts' => [$mimePart]] + ); + $this->message = $this->emailMessageInterfaceFactory->create($this->messageData); return $this; } + + /** + * Handles possible incoming types of email (string or array) + * + * @param string $addressType + * @param string|array $emailOrList + * @param string|null $name + * + * @return void + * @throws MailException + */ + private function getMailAddresses(string $addressType, $emailOrList, ?string $name = null): void + { + if (is_array($emailOrList)) { + $this->messageData[$addressType] = array_merge( + $this->messageData[$addressType], + $this->mailAddressConverter->convertMany($emailOrList) + ); + + return; + } + $this->messageData[$addressType][] = $this->mailAddressConverter->convert($emailOrList, $name); + } } diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 1cf9df0c0300..41827bc9830d 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -42,14 +42,13 @@ class EmailMessage implements EmailMessageInterface * EmailMessage constructor * * @param MimeMessageInterface $body - * @param MailAddressList $to + * @param array $to * @param MimeMessageInterfaceFactory $mimeMessageFactory - * @param MailAddressListFactory $mailAddressListFactory * @param MailAddressFactory $mailAddressFactory - * @param MailAddressList|null $from - * @param MailAddressList|null $cc - * @param MailAddressList|null $bcc - * @param MailAddressList|null $replyTo + * @param MailAddress[]|null $from + * @param MailAddress[]|null $cc + * @param MailAddress[]|null $bcc + * @param MailAddress[]|null $replyTo * @param MailAddress|null $sender * @param string|null $subject * @param string|null $encoding @@ -59,14 +58,13 @@ class EmailMessage implements EmailMessageInterface */ public function __construct( MimeMessageInterface $body, - MailAddressList $to, + array $to, MimeMessageInterfaceFactory $mimeMessageFactory, - MailAddressListFactory $mailAddressListFactory, MailAddressFactory $mailAddressFactory, - ?MailAddressList $from = null, - ?MailAddressList $cc = null, - ?MailAddressList $bcc = null, - ?MailAddressList $replyTo = null, + ?array $from = null, + ?array $cc = null, + ?array $bcc = null, + ?array $replyTo = null, ?MailAddress $sender = null, ?string $subject = '', ?string $encoding = '' @@ -82,19 +80,27 @@ public function __construct( $this->message->setSubject($subject); } if ($sender) { - $this->message->setSender($sender); + $this->message->setSender($sender->getEmail(), $sender->getName()); } - $this->message->setReplyTo($replyTo); - if ($to->count() < 1) { + if (count($to) < 1) { throw new MailException(__('Email message must have at list one addressee')); } - - $this->message->setTo($to); - $this->message->setFrom($from); - $this->message->setCc($cc); - $this->message->setBcc($bcc); + $this->message->setTo( + $this->convertMailAddressArrayToZendAddressList($to) + ); + $this->message->setReplyTo( + $this->convertMailAddressArrayToZendAddressList($replyTo) + ); + $this->message->setFrom( + $this->convertMailAddressArrayToZendAddressList($from) + ); + $this->message->setCc( + $this->convertMailAddressArrayToZendAddressList($cc) + ); + $this->message->setBcc( + $this->convertMailAddressArrayToZendAddressList($bcc) + ); $this->mimeMessageFactory = $mimeMessageFactory; - $this->mailAddressListFactory = $mailAddressListFactory; $this->mailAddressFactory = $mailAddressFactory; } @@ -117,7 +123,7 @@ public function getHeaders(): array /** * @inheritDoc */ - public function getFrom(): ?MailAddressList + public function getFrom(): ?array { return $this->convertAddressListToMailAddressList($this->message->getFrom()); } @@ -125,7 +131,7 @@ public function getFrom(): ?MailAddressList /** * @inheritDoc */ - public function getTo(): MailAddressList + public function getTo(): array { return $this->convertAddressListToMailAddressList($this->message->getTo()); } @@ -133,7 +139,7 @@ public function getTo(): MailAddressList /** * @inheritDoc */ - public function getCc(): ?MailAddressList + public function getCc(): ?array { return $this->convertAddressListToMailAddressList($this->message->getCc()); } @@ -141,7 +147,7 @@ public function getCc(): ?MailAddressList /** * @inheritDoc */ - public function getBcc(): ?MailAddressList + public function getBcc(): ?array { return $this->convertAddressListToMailAddressList($this->message->getBcc()); } @@ -149,7 +155,7 @@ public function getBcc(): ?MailAddressList /** * @inheritDoc */ - public function getReplyTo(): ?MailAddressList + public function getReplyTo(): ?array { return $this->convertAddressListToMailAddressList($this->message->getReplyTo()); } @@ -167,8 +173,7 @@ public function getSender(): ?MailAddress return $this->mailAddressFactory->create( [ 'email' => $zendSender->getEmail(), - 'name' => $zendSender->getName(), - 'comment' => $zendSender->getComment() + 'name' => $zendSender->getName() ] ); } @@ -219,25 +224,37 @@ public function toString(): string * Converts AddressList to array * * @param AddressList $addressList - * @return MailAddressList - * @throws MailException + * @return MailAddress[] */ - private function convertAddressListToMailAddressList(AddressList $addressList): MailAddressList + private function convertAddressListToMailAddressList(AddressList $addressList): array { - /** @var MailAddressList $arrayList */ - $arrayList = $this->mailAddressListFactory->create(); + $arrayList = []; foreach ($addressList as $address) { - $arrayList->add( + $arrayList[] = $this->mailAddressFactory->create( [ 'email' => $address->getEmail(), - 'name' => $address->getName(), - 'comment' => $address->getComment() + 'name' => $address->getName() ] - ) - ); + ); } return $arrayList; } + + /** + * Converts MailAddress array to AddressList + * + * @param MailAddress[] $arrayList + * @return AddressList + */ + private function convertMailAddressArrayToZendAddressList(array $arrayList): AddressList + { + $zendAddressList = new AddressList(); + foreach ($arrayList as $address) { + $zendAddressList->add($address->getEmail(), $address->getName()); + } + + return $zendAddressList; + } } diff --git a/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php b/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php index 25f9659b3c8a..87534bfebca0 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php @@ -28,37 +28,37 @@ public function getHeaders(): array; /** * Retrieve list of From senders * - * @return MailAddressList|null + * @return MailAddress[]|null */ - public function getFrom(): ?MailAddressList; + public function getFrom(): ?array; /** * Access the address list of the To header * - * @return MailAddressList + * @return MailAddress[] */ - public function getTo(): MailAddressList; + public function getTo(): array; /** * Retrieve list of CC recipients * - * @return MailAddressList|null + * @return MailAddress[]|null */ - public function getCc(): ?MailAddressList; + public function getCc(): ?array; /** - * Retrieve list of BCC recipients + * Retrieve list of Bcc recipients * - * @return MailAddressList|null + * @return MailAddress[]|null */ - public function getBcc(): ?MailAddressList; + public function getBcc(): ?array; /** * Access the address list of the Reply-To header * - * @return MailAddressList|null + * @return MailAddress[]|null */ - public function getReplyTo(): ?MailAddressList; + public function getReplyTo(): ?array; /** * Retrieve the sender address, if any diff --git a/lib/internal/Magento/Framework/Mail/MailAddress.php b/lib/internal/Magento/Framework/Mail/MailAddress.php index 8919d0dec64b..adf0eac54698 100644 --- a/lib/internal/Magento/Framework/Mail/MailAddress.php +++ b/lib/internal/Magento/Framework/Mail/MailAddress.php @@ -7,29 +7,52 @@ namespace Magento\Framework\Mail; -use Magento\Framework\Exception\MailException; -use Zend\Mail\Address; -use Zend\Mail\Exception\InvalidArgumentException; - /** * Class MailAddress */ -class MailAddress extends Address +class MailAddress { /** - * @inheritDoc + * @var string|null + */ + private $name; + + /** + * @var string + */ + private $email; + + /** + * MailAddress constructor * - * @return MailAddress - * @throws MailException + * @param string|null $email + * @param string|null $name */ - public static function fromString($address, $comment = null) - { - try { - return parent::fromString($address, $comment); - } catch (InvalidArgumentException $e) { - throw new MailException(__($e->getMessage())); - } + public function __construct( + ?string $email, + ?string $name + ) { + $this->email = $email; + $this->name = $name; } + /** + * Name getter + * + * @return string|null + */ + public function getName(): ?string + { + return $this->name; + } + /** + * Email getter + * + * @return string + */ + public function getEmail(): string + { + return $this->email; + } } diff --git a/lib/internal/Magento/Framework/Mail/MailAddressConverter.php b/lib/internal/Magento/Framework/Mail/MailAddressConverter.php new file mode 100644 index 000000000000..b0b4e44cbfba --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/MailAddressConverter.php @@ -0,0 +1,86 @@ +mailAddressFactory = $mailAddressFactory; + } + + /** + * Creates MailAddress from string values + * + * @param string $email + * @param string|null $name + * + * @return MailAddress + */ + public function convert(string $email, ?string $name = null): MailAddress + { + return $this->mailAddressFactory->create( + [ + 'name' => $name, + 'email' => $email + ] + ); + } + + /** + * Converts array to list of MailAddresses + * + * @param array $addresses + * + * @return MailAddress[] + * @throws MailException + */ + public function convertMany(array $addresses): array + { + $addressList = []; + foreach ($addresses as $key=>$value) { + + if (is_int($key) || is_numeric($key)) { + $addressList[] = $this->convert($value); + continue; + } + + if (! is_string($key)) { + throw new MailException(__( + 'Invalid key type in provided addresses array ("%s")', + (is_object($key) ? get_class($key) : var_export($key, 1)) + )); + } + $addressList[] = $this->convert($key, $value); + } + + return $addressList; + } +} diff --git a/lib/internal/Magento/Framework/Mail/MailAddressList.php b/lib/internal/Magento/Framework/Mail/MailAddressList.php deleted file mode 100644 index 2737aeeb64d7..000000000000 --- a/lib/internal/Magento/Framework/Mail/MailAddressList.php +++ /dev/null @@ -1,242 +0,0 @@ -mailAddressFactory = $mailAddressFactory; - } - - /** - * Add an address to the list - * - * @param string|MailAddress $emailOrAddress - * @param null|string $name - * - * @return MailAddressList - * @throws MailException - */ - public function add($emailOrAddress, ?string $name = null): MailAddressList - { - if (is_string($emailOrAddress)) { - $emailOrAddress = $this->createAddress($emailOrAddress, $name); - } - - if (! $emailOrAddress instanceof MailAddress) { - throw new MailException(__( - '%s expects an email address or %s\MailAddress object as its first argument; received "%s"', - __METHOD__, - __NAMESPACE__, - (is_object($emailOrAddress) ? get_class($emailOrAddress) : gettype($emailOrAddress)) - )); - } - - $email = strtolower($emailOrAddress->getEmail()); - if ($this->has($email)) { - return $this; - } - - $this->addresses[$email] = $emailOrAddress; - return $this; - } - - /** - * Add many addresses at once - * - * @param array $addresses - * - * @return MailAddressList - * @throws MailException - */ - public function addMany(array $addresses): MailAddressList - { - foreach ($addresses as $key => $value) { - if (is_int($key) || is_numeric($key)) { - $this->add($value); - continue; - } - - if (! is_string($key)) { - throw new MailException(__( - 'Invalid key type in provided addresses array ("%s")', - (is_object($key) ? get_class($key) : var_export($key, 1)) - )); - } - - $this->add($key, $value); - } - - return $this; - } - - /** - * Merge another address list into this one - * - * @param MailAddressList $addressList - * - * @return MailAddressList - * @throws MailException - */ - public function merge(MailAddressList $addressList): MailAddressList - { - foreach ($addressList as $address) { - $this->add($address); - } - return $this; - } - - /** - * Does the email exist in this list? - * - * @param string $email - * - * @return bool - */ - public function has($email): bool - { - $email = strtolower($email); - - return isset($this->addresses[$email]); - } - - /** - * Delete an address from the list - * - * @param string $email - * - * @return bool - */ - public function delete($email): bool - { - $email = strtolower($email); - if (!isset($this->addresses[$email])) { - return false; - } - - unset($this->addresses[$email]); - - return true; - } - - /** - * Return count of addresses - * - * @return int - */ - public function count(): int - { - return count($this->addresses); - } - - /** - * Rewind iterator - * - * @return mixed - */ - public function rewind() - { - return reset($this->addresses); - } - - /** - * Return current item in iteration - * - * @return MailAddress - */ - public function current(): MailAddress - { - return current($this->addresses); - } - - /** - * Return key of current item of iteration - * - * @return string - */ - public function key(): string - { - return key($this->addresses); - } - - /** - * Move to next item - * - * @return mixed - */ - public function next() - { - return next($this->addresses); - } - - /** - * Is the current item of iteration valid? - * - * @return bool - */ - public function valid(): bool - { - $key = key($this->addresses); - - return ($key !== null && $key !== false); - } - - /** - * Create an address object - * - * @param string $email - * @param string|null $name - * - * @return MailAddress - */ - private function createAddress(string $email, ?string $name=null): MailAddress - { - return $this->mailAddressFactory->create(['email' => $email, 'name' => $name]); - } - - /** - * Add an address to the list from any valid string format, such as - * - "ZF Dev" - * - dev@zf.com - * - * @param string $address - * @param null|string $comment Comment associated with the address, if any. - * @return MailAddressList - * @throws MailException - */ - public function addFromString($address, $comment = null): MailAddressList - { - $this->add(MailAddress::fromString($address, $comment)); - - return $this; - } -} diff --git a/lib/internal/Magento/Framework/Mail/MimePart.php b/lib/internal/Magento/Framework/Mail/MimePart.php index e33090559a63..42a4cfc933dd 100644 --- a/lib/internal/Magento/Framework/Mail/MimePart.php +++ b/lib/internal/Magento/Framework/Mail/MimePart.php @@ -38,6 +38,8 @@ class MimePart implements MimePartInterface * * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @throws MailException */ public function __construct( $content, diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 1326985a2163..c751e6a5f97f 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -15,6 +15,8 @@ use Magento\Framework\Exception\MailException; use Magento\Framework\Mail\EmailMessageInterface; use Magento\Framework\Mail\EmailMessageInterfaceFactory; +use Magento\Framework\Mail\MailAddress; +use Magento\Framework\Mail\MailAddressConverter; use Magento\Framework\Mail\MailAddressList; use Magento\Framework\Mail\MailAddressListFactory; use Magento\Framework\Mail\MessageInterface; @@ -125,11 +127,10 @@ class TransportBuilder * @var MimePartInterfaceFactory */ private $mimePartInterfaceFactory; - /** - * @var MailAddressListFactory|null + * @var MailAddressConverter|null */ - private $mailAddressListFactory; + private $mailAddressConverter; /** * TransportBuilder constructor @@ -143,7 +144,7 @@ class TransportBuilder * @param EmailMessageInterfaceFactory|null $emailMessageInterfaceFactory * @param MimeMessageInterfaceFactory|null $mimeMessageInterfaceFactory * @param MimePartInterfaceFactory|null $mimePartInterfaceFactory - * @param MailAddressListFactory|null $mailAddressListFactory + * @param MailAddressConverter|null $mailAddressConverter * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( @@ -156,7 +157,7 @@ public function __construct( EmailMessageInterfaceFactory $emailMessageInterfaceFactory = null, MimeMessageInterfaceFactory $mimeMessageInterfaceFactory = null, MimePartInterfaceFactory $mimePartInterfaceFactory = null, - MailAddressListFactory $mailAddressListFactory = null + MailAddressConverter $mailAddressConverter=null ) { $this->templateFactory = $templateFactory; $this->objectManager = $objectManager; @@ -168,7 +169,8 @@ public function __construct( ->get(MimeMessageInterfaceFactory::class); $this->mimePartInterfaceFactory = $mimePartInterfaceFactory ?: $this->objectManager ->get(MimePartInterfaceFactory::class); - $this->mailAddressListFactory = $mailAddressListFactory; + $this->mailAddressConverter = $mailAddressConverter ?: $this->objectManager + ->get(MailAddressConverter::class); } /** @@ -182,10 +184,7 @@ public function __construct( */ public function addCc($address, $name = '') { - if (!isset($this->messageData['cc'])) { - $this->messageData['cc'] = $this->mailAddressListFactory->create(); - } - $this->getMailAddresses($this->messageData['cc'], $address, $name); + $this->getMailAddresses('cc', $address, $name); return $this; } @@ -201,10 +200,7 @@ public function addCc($address, $name = '') */ public function addTo($address, $name = '') { - if (!isset($this->messageData['to'])) { - $this->messageData['to'] = $this->mailAddressListFactory->create(); - } - $this->getMailAddresses($this->messageData['to'], $address, $name); + $this->getMailAddresses('to', $address, $name); return $this; } @@ -219,11 +215,7 @@ public function addTo($address, $name = '') */ public function addBcc($address) { - $this->messageData['bcc'] = $address; - if (!isset($this->messageData['bcc'])) { - $this->messageData['bcc'] = $this->mailAddressListFactory->create(); - } - $this->getMailAddresses($this->messageData['bcc'], $address); + $this->getMailAddresses('bcc', $address); return $this; } @@ -239,10 +231,8 @@ public function addBcc($address) */ public function setReplyTo($email, $name = null) { - if (!isset($this->messageData['replyTo'])) { - $this->messageData['replyTo'] = $this->mailAddressListFactory->create(); - } - $this->getMailAddresses($this->messageData['replyTo'], $email, $name); + + $this->getMailAddresses('replyTo', $email, $name); return $this; } @@ -276,10 +266,7 @@ public function setFrom($from) public function setFromByScope($from, $scopeId = null) { $result = $this->_senderResolver->resolve($from, $scopeId); - if (!isset($this->messageData['from'])) { - $this->messageData['from'] = $this->mailAddressListFactory->create(); - } - $this->getMailAddresses($this->messageData['from'], $result['email'], $result['name']); + $this->getMailAddresses('from', $result['email'], $result['name']); return $this; } @@ -391,7 +378,7 @@ protected function getTemplate() protected function prepareMessage() { $template = $this->getTemplate(); - $part['content'] = $template->processTemplate(); + $content = $template->processTemplate(); switch ($template->getType()) { case TemplateTypesInterface::TYPE_TEXT: $part['type'] = MimeInterface::TYPE_TEXT; @@ -407,7 +394,7 @@ protected function prepareMessage() ); } $this->messageData['body'] = $this->mimeMessageInterfaceFactory - ->create(['parts' => [$this->mimePartInterfaceFactory->create([$part])]]); + ->create(['parts' => [$this->mimePartInterfaceFactory->create(['content'=>$content])]]); $this->messageData['subject'] = html_entity_decode( (string)$template->getSubject(), @@ -421,27 +408,23 @@ protected function prepareMessage() /** * Handles possible incoming types of email (string or array) * - * @param MailAddressList $mailAddressList + * @param string $addressType * @param string|array $emailOrList * @param string|null $name * * @return void * @throws MailException */ - private function getMailAddresses(MailAddressList $mailAddressList, $emailOrList, ?string $name = null): void + private function getMailAddresses(string $addressType, $emailOrList, ?string $name = null): void { if (is_array($emailOrList)) { - $mailAddressList->addMany($emailOrList); - - return; - } - - if (is_string($emailOrList) && $name === null) { - $mailAddressList->addFromString($emailOrList); + $this->messageData[$addressType] = array_merge( + $this->messageData[$addressType], + $this->mailAddressConverter->convertMany($emailOrList) + ); return; } - - $mailAddressList->add($emailOrList, $name); + $this->messageData[$addressType][] = $this->mailAddressConverter->convert($emailOrList, $name); } } diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index f62ed8b2e7de..fa4182ab078f 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -12,7 +12,7 @@ /** * Class TransportBuilderTest * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class TransportBuilderTest extends \PHPUnit\Framework\TestCase { From 279c7138e8d782fe4ecae79191971b7c42d1defc Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Wed, 31 Jul 2019 22:25:18 +0300 Subject: [PATCH 19/37] MC-15295: get rid of noinspection annotations --- .../Magento/Newsletter/Model/Queue/TransportBuilder.php | 3 --- .../Magento/Framework/Mail/Template/TransportBuilder.php | 6 +----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php index 17e344c94453..8a551f69bcd9 100644 --- a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php +++ b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php @@ -1,7 +1,4 @@ getMailAddresses('replyTo', $email, $name); return $this; From f45ecc6b59d20e3a3d1da6ddc1cae8ae61dd23ba Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Wed, 31 Jul 2019 22:35:17 +0300 Subject: [PATCH 20/37] MC-15295: rename Address and AddressConverter --- .../Model/Queue/TransportBuilder.php | 21 +++++------ .../Mail/{MailAddress.php => Address.php} | 2 +- ...ressConverter.php => AddressConverter.php} | 24 ++++++------ .../Magento/Framework/Mail/EmailMessage.php | 37 ++++++++----------- .../Framework/Mail/EmailMessageInterface.php | 14 +++---- .../Mail/Template/TransportBuilder.php | 18 ++++----- 6 files changed, 55 insertions(+), 61 deletions(-) rename lib/internal/Magento/Framework/Mail/{MailAddress.php => Address.php} (98%) rename lib/internal/Magento/Framework/Mail/{MailAddressConverter.php => AddressConverter.php} (79%) diff --git a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php index 8a551f69bcd9..5a22c740a1f4 100644 --- a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php +++ b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php @@ -10,8 +10,7 @@ use Magento\Email\Model\AbstractTemplate; use Magento\Framework\Exception\MailException; use Magento\Framework\Mail\EmailMessageInterfaceFactory; -use Magento\Framework\Mail\MailAddressConverter; -use Magento\Framework\Mail\MailAddressList; +use Magento\Framework\Mail\AddressConverter; use Magento\Framework\Mail\MessageInterface; use Magento\Framework\Mail\MessageInterfaceFactory; use Magento\Framework\Mail\MimeMessageInterfaceFactory; @@ -57,9 +56,9 @@ class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder private $mimePartInterfaceFactory; /** - * @var MailAddressConverter|null + * @var AddressConverter|null */ - private $mailAddressConverter; + private $addressConverter; /** * TransportBuilder constructor @@ -73,7 +72,7 @@ class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder * @param EmailMessageInterfaceFactory|null $emailMessageInterfaceFactory * @param MimeMessageInterfaceFactory|null $mimeMessageInterfaceFactory * @param MimePartInterfaceFactory|null $mimePartInterfaceFactory - * @param MailAddressConverter|null $mailAddressConverter + * @param AddressConverter|null $addressConverter */ public function __construct( FactoryInterface $templateFactory, @@ -85,7 +84,7 @@ public function __construct( EmailMessageInterfaceFactory $emailMessageInterfaceFactory = null, MimeMessageInterfaceFactory $mimeMessageInterfaceFactory = null, MimePartInterfaceFactory $mimePartInterfaceFactory = null, - MailAddressConverter $mailAddressConverter = null + AddressConverter $addressConverter = null ) { parent::__construct( $templateFactory, @@ -97,7 +96,7 @@ public function __construct( $emailMessageInterfaceFactory, $mimeMessageInterfaceFactory, $mimePartInterfaceFactory, - $mailAddressConverter + $addressConverter ); $this->emailMessageInterfaceFactory = $emailMessageInterfaceFactory ?: $this->objectManager ->get(EmailMessageInterfaceFactory::class); @@ -105,8 +104,8 @@ public function __construct( ->get(MimeMessageInterfaceFactory::class); $this->mimePartInterfaceFactory = $mimePartInterfaceFactory ?: $this->objectManager ->get(MimePartInterfaceFactory::class); - $this->mailAddressConverter = $mailAddressConverter ?: $this->objectManager - ->get(MailAddressConverter::class); + $this->addressConverter = $addressConverter ?: $this->objectManager + ->get(AddressConverter::class); } /** @@ -285,11 +284,11 @@ private function getMailAddresses(string $addressType, $emailOrList, ?string $na if (is_array($emailOrList)) { $this->messageData[$addressType] = array_merge( $this->messageData[$addressType], - $this->mailAddressConverter->convertMany($emailOrList) + $this->addressConverter->convertMany($emailOrList) ); return; } - $this->messageData[$addressType][] = $this->mailAddressConverter->convert($emailOrList, $name); + $this->messageData[$addressType][] = $this->addressConverter->convert($emailOrList, $name); } } diff --git a/lib/internal/Magento/Framework/Mail/MailAddress.php b/lib/internal/Magento/Framework/Mail/Address.php similarity index 98% rename from lib/internal/Magento/Framework/Mail/MailAddress.php rename to lib/internal/Magento/Framework/Mail/Address.php index adf0eac54698..18e1a8c72f21 100644 --- a/lib/internal/Magento/Framework/Mail/MailAddress.php +++ b/lib/internal/Magento/Framework/Mail/Address.php @@ -10,7 +10,7 @@ /** * Class MailAddress */ -class MailAddress +class Address { /** * @var string|null diff --git a/lib/internal/Magento/Framework/Mail/MailAddressConverter.php b/lib/internal/Magento/Framework/Mail/AddressConverter.php similarity index 79% rename from lib/internal/Magento/Framework/Mail/MailAddressConverter.php rename to lib/internal/Magento/Framework/Mail/AddressConverter.php index b0b4e44cbfba..19437672197d 100644 --- a/lib/internal/Magento/Framework/Mail/MailAddressConverter.php +++ b/lib/internal/Magento/Framework/Mail/AddressConverter.php @@ -16,24 +16,24 @@ use Magento\Framework\Exception\MailException; /** - * Class MailAddressConverter + * Class AddressConverter */ -class MailAddressConverter +class AddressConverter { /** - * @var MailAddressFactory + * @var AddressFactory */ - private $mailAddressFactory; + private $addressFactory; /** - * MailAddressConverter constructor + * AddressConverter constructor * - * @param MailAddressFactory $mailAddressFactory + * @param AddressFactory $addressFactory */ public function __construct( - MailAddressFactory $mailAddressFactory + AddressFactory $addressFactory ) { - $this->mailAddressFactory = $mailAddressFactory; + $this->addressFactory = $addressFactory; } /** @@ -42,11 +42,11 @@ public function __construct( * @param string $email * @param string|null $name * - * @return MailAddress + * @return Address */ - public function convert(string $email, ?string $name = null): MailAddress + public function convert(string $email, ?string $name = null): Address { - return $this->mailAddressFactory->create( + return $this->addressFactory->create( [ 'name' => $name, 'email' => $email @@ -59,7 +59,7 @@ public function convert(string $email, ?string $name = null): MailAddress * * @param array $addresses * - * @return MailAddress[] + * @return Address[] * @throws MailException */ public function convertMany(array $addresses): array diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 41827bc9830d..21c70f732a06 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -29,14 +29,9 @@ class EmailMessage implements EmailMessageInterface private $mimeMessageFactory; /** - * @var MailAddressListFactory + * @var AddressFactory */ - private $mailAddressListFactory; - - /** - * @var MailAddressFactory - */ - private $mailAddressFactory; + private $addressFactory; /** * EmailMessage constructor @@ -44,12 +39,12 @@ class EmailMessage implements EmailMessageInterface * @param MimeMessageInterface $body * @param array $to * @param MimeMessageInterfaceFactory $mimeMessageFactory - * @param MailAddressFactory $mailAddressFactory - * @param MailAddress[]|null $from - * @param MailAddress[]|null $cc - * @param MailAddress[]|null $bcc - * @param MailAddress[]|null $replyTo - * @param MailAddress|null $sender + * @param AddressFactory $addressFactory + * @param Address[]|null $from + * @param Address[]|null $cc + * @param Address[]|null $bcc + * @param Address[]|null $replyTo + * @param Address|null $sender * @param string|null $subject * @param string|null $encoding * @@ -60,12 +55,12 @@ public function __construct( MimeMessageInterface $body, array $to, MimeMessageInterfaceFactory $mimeMessageFactory, - MailAddressFactory $mailAddressFactory, + AddressFactory $addressFactory, ?array $from = null, ?array $cc = null, ?array $bcc = null, ?array $replyTo = null, - ?MailAddress $sender = null, + ?Address $sender = null, ?string $subject = '', ?string $encoding = '' ) { @@ -101,7 +96,7 @@ public function __construct( $this->convertMailAddressArrayToZendAddressList($bcc) ); $this->mimeMessageFactory = $mimeMessageFactory; - $this->mailAddressFactory = $mailAddressFactory; + $this->addressFactory = $addressFactory; } /** @@ -163,14 +158,14 @@ public function getReplyTo(): ?array /** * @inheritDoc */ - public function getSender(): ?MailAddress + public function getSender(): ?Address { /** @var ZendAddress $zendSender */ if (!$zendSender = $this->message->getSender()) { return null; } - return $this->mailAddressFactory->create( + return $this->addressFactory->create( [ 'email' => $zendSender->getEmail(), 'name' => $zendSender->getName() @@ -224,14 +219,14 @@ public function toString(): string * Converts AddressList to array * * @param AddressList $addressList - * @return MailAddress[] + * @return Address[] */ private function convertAddressListToMailAddressList(AddressList $addressList): array { $arrayList = []; foreach ($addressList as $address) { $arrayList[] = - $this->mailAddressFactory->create( + $this->addressFactory->create( [ 'email' => $address->getEmail(), 'name' => $address->getName() @@ -245,7 +240,7 @@ private function convertAddressListToMailAddressList(AddressList $addressList): /** * Converts MailAddress array to AddressList * - * @param MailAddress[] $arrayList + * @param Address[] $arrayList * @return AddressList */ private function convertMailAddressArrayToZendAddressList(array $arrayList): AddressList diff --git a/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php b/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php index 87534bfebca0..95f83ff679cd 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessageInterface.php @@ -28,44 +28,44 @@ public function getHeaders(): array; /** * Retrieve list of From senders * - * @return MailAddress[]|null + * @return Address[]|null */ public function getFrom(): ?array; /** * Access the address list of the To header * - * @return MailAddress[] + * @return Address[] */ public function getTo(): array; /** * Retrieve list of CC recipients * - * @return MailAddress[]|null + * @return Address[]|null */ public function getCc(): ?array; /** * Retrieve list of Bcc recipients * - * @return MailAddress[]|null + * @return Address[]|null */ public function getBcc(): ?array; /** * Access the address list of the Reply-To header * - * @return MailAddress[]|null + * @return Address[]|null */ public function getReplyTo(): ?array; /** * Retrieve the sender address, if any * - * @return MailAddress|null + * @return Address|null */ - public function getSender(): ?MailAddress; + public function getSender(): ?Address; /** * Get the message subject header value diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 0d92f17bce98..2333021f5036 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -14,7 +14,7 @@ use Magento\Framework\Exception\MailException; use Magento\Framework\Mail\EmailMessageInterface; use Magento\Framework\Mail\EmailMessageInterfaceFactory; -use Magento\Framework\Mail\MailAddressConverter; +use Magento\Framework\Mail\AddressConverter; use Magento\Framework\Mail\MessageInterface; use Magento\Framework\Mail\MessageInterfaceFactory; use Magento\Framework\Mail\MimeInterface; @@ -125,9 +125,9 @@ class TransportBuilder private $mimePartInterfaceFactory; /** - * @var MailAddressConverter|null + * @var AddressConverter|null */ - private $mailAddressConverter; + private $addressConverter; /** * TransportBuilder constructor @@ -141,7 +141,7 @@ class TransportBuilder * @param EmailMessageInterfaceFactory|null $emailMessageInterfaceFactory * @param MimeMessageInterfaceFactory|null $mimeMessageInterfaceFactory * @param MimePartInterfaceFactory|null $mimePartInterfaceFactory - * @param MailAddressConverter|null $mailAddressConverter + * @param addressConverter|null $addressConverter * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( @@ -154,7 +154,7 @@ public function __construct( EmailMessageInterfaceFactory $emailMessageInterfaceFactory = null, MimeMessageInterfaceFactory $mimeMessageInterfaceFactory = null, MimePartInterfaceFactory $mimePartInterfaceFactory = null, - MailAddressConverter $mailAddressConverter=null + AddressConverter $addressConverter=null ) { $this->templateFactory = $templateFactory; $this->objectManager = $objectManager; @@ -166,8 +166,8 @@ public function __construct( ->get(MimeMessageInterfaceFactory::class); $this->mimePartInterfaceFactory = $mimePartInterfaceFactory ?: $this->objectManager ->get(MimePartInterfaceFactory::class); - $this->mailAddressConverter = $mailAddressConverter ?: $this->objectManager - ->get(MailAddressConverter::class); + $this->addressConverter = $addressConverter ?: $this->objectManager + ->get(AddressConverter::class); } /** @@ -416,11 +416,11 @@ private function getMailAddresses(string $addressType, $emailOrList, ?string $na if (is_array($emailOrList)) { $this->messageData[$addressType] = array_merge( $this->messageData[$addressType], - $this->mailAddressConverter->convertMany($emailOrList) + $this->addressConverter->convertMany($emailOrList) ); return; } - $this->messageData[$addressType][] = $this->mailAddressConverter->convert($emailOrList, $name); + $this->messageData[$addressType][] = $this->addressConverter->convert($emailOrList, $name); } } From 6f8b8b861b6671c2a22245b106ccc922c116e41f Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Wed, 31 Jul 2019 22:39:34 +0300 Subject: [PATCH 21/37] MC-15295: add copy pasted class to black list --- .../Magento/Test/Php/_files/phpcpd/blacklist/common.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt index e59cd0983da1..c25df7e6becb 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt +++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt @@ -216,3 +216,4 @@ Magento/Elasticsearch6/Model/Client Magento/Config/App/Config/Type Magento/InventoryReservationCli/Test/Integration Magento/InventoryAdminUi/Controller/Adminhtml +Magento/Newsletter/Model/Queue/TransportBuilder From cd11bda25422bd5fab2339900ad1dbb0823a8ca3 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 1 Aug 2019 10:43:58 +0300 Subject: [PATCH 22/37] MC-15295: Changes from review --- .../Model/Queue/TransportBuilder.php | 20 +++++++------- .../Framework/Mail/AddressConverter.php | 10 ++----- .../Magento/Framework/Mail/EmailMessage.php | 24 ++++++++--------- .../Magento/Framework/Mail/MimePart.php | 2 +- .../Mail/Template/TransportBuilder.php | 26 ++++++++++--------- .../Unit/Template/TransportBuilderTest.php | 4 +++ 6 files changed, 43 insertions(+), 43 deletions(-) diff --git a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php index 5a22c740a1f4..a35326fe06c7 100644 --- a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php +++ b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php @@ -119,7 +119,7 @@ public function __construct( */ public function addCc($address, $name = '') { - $this->getMailAddresses('cc', $address, $name); + $this->addAddressByType('cc', $address, $name); return $this; } @@ -135,7 +135,7 @@ public function addCc($address, $name = '') */ public function addTo($address, $name = '') { - $this->getMailAddresses('to', $address, $name); + $this->addAddressByType('to', $address, $name); return $this; } @@ -150,7 +150,7 @@ public function addTo($address, $name = '') */ public function addBcc($address) { - $this->getMailAddresses('bcc', $address); + $this->addAddressByType('bcc', $address); return $this; } @@ -167,7 +167,7 @@ public function addBcc($address) public function setReplyTo($email, $name = null) { - $this->getMailAddresses('replyTo', $email, $name); + $this->addAddressByType('replyTo', $email, $name); return $this; } @@ -201,7 +201,7 @@ public function setFrom($from) public function setFromByScope($from, $scopeId = null) { $result = $this->_senderResolver->resolve($from, $scopeId); - $this->getMailAddresses('from', $result['email'], $result['name']); + $this->addAddressByType('from', $result['email'], $result['name']); return $this; } @@ -273,22 +273,22 @@ protected function prepareMessage() * Handles possible incoming types of email (string or array) * * @param string $addressType - * @param string|array $emailOrList + * @param string|array $email * @param string|null $name * * @return void * @throws MailException */ - private function getMailAddresses(string $addressType, $emailOrList, ?string $name = null): void + private function addAddressByType(string $addressType, $email, ?string $name = null): void { - if (is_array($emailOrList)) { + if (is_array($email)) { $this->messageData[$addressType] = array_merge( $this->messageData[$addressType], - $this->addressConverter->convertMany($emailOrList) + $this->addressConverter->convertMany($email) ); return; } - $this->messageData[$addressType][] = $this->addressConverter->convert($emailOrList, $name); + $this->messageData[$addressType][] = $this->addressConverter->convert($email, $name); } } diff --git a/lib/internal/Magento/Framework/Mail/AddressConverter.php b/lib/internal/Magento/Framework/Mail/AddressConverter.php index 19437672197d..3c7a0ff2f522 100644 --- a/lib/internal/Magento/Framework/Mail/AddressConverter.php +++ b/lib/internal/Magento/Framework/Mail/AddressConverter.php @@ -1,13 +1,7 @@ message->setTo( - $this->convertMailAddressArrayToZendAddressList($to) + $this->convertAddressArrayToAddressList($to) ); $this->message->setReplyTo( - $this->convertMailAddressArrayToZendAddressList($replyTo) + $this->convertAddressArrayToAddressList($replyTo) ); $this->message->setFrom( - $this->convertMailAddressArrayToZendAddressList($from) + $this->convertAddressArrayToAddressList($from) ); $this->message->setCc( - $this->convertMailAddressArrayToZendAddressList($cc) + $this->convertAddressArrayToAddressList($cc) ); $this->message->setBcc( - $this->convertMailAddressArrayToZendAddressList($bcc) + $this->convertAddressArrayToAddressList($bcc) ); $this->mimeMessageFactory = $mimeMessageFactory; $this->addressFactory = $addressFactory; @@ -120,7 +120,7 @@ public function getHeaders(): array */ public function getFrom(): ?array { - return $this->convertAddressListToMailAddressList($this->message->getFrom()); + return $this->convertAddressListToAddressArray($this->message->getFrom()); } /** @@ -128,7 +128,7 @@ public function getFrom(): ?array */ public function getTo(): array { - return $this->convertAddressListToMailAddressList($this->message->getTo()); + return $this->convertAddressListToAddressArray($this->message->getTo()); } /** @@ -136,7 +136,7 @@ public function getTo(): array */ public function getCc(): ?array { - return $this->convertAddressListToMailAddressList($this->message->getCc()); + return $this->convertAddressListToAddressArray($this->message->getCc()); } /** @@ -144,7 +144,7 @@ public function getCc(): ?array */ public function getBcc(): ?array { - return $this->convertAddressListToMailAddressList($this->message->getBcc()); + return $this->convertAddressListToAddressArray($this->message->getBcc()); } /** @@ -152,7 +152,7 @@ public function getBcc(): ?array */ public function getReplyTo(): ?array { - return $this->convertAddressListToMailAddressList($this->message->getReplyTo()); + return $this->convertAddressListToAddressArray($this->message->getReplyTo()); } /** @@ -221,7 +221,7 @@ public function toString(): string * @param AddressList $addressList * @return Address[] */ - private function convertAddressListToMailAddressList(AddressList $addressList): array + private function convertAddressListToAddressArray(AddressList $addressList): array { $arrayList = []; foreach ($addressList as $address) { @@ -243,7 +243,7 @@ private function convertAddressListToMailAddressList(AddressList $addressList): * @param Address[] $arrayList * @return AddressList */ - private function convertMailAddressArrayToZendAddressList(array $arrayList): AddressList + private function convertAddressArrayToAddressList(array $arrayList): AddressList { $zendAddressList = new AddressList(); foreach ($arrayList as $address) { diff --git a/lib/internal/Magento/Framework/Mail/MimePart.php b/lib/internal/Magento/Framework/Mail/MimePart.php index 42a4cfc933dd..69103d519482 100644 --- a/lib/internal/Magento/Framework/Mail/MimePart.php +++ b/lib/internal/Magento/Framework/Mail/MimePart.php @@ -57,7 +57,7 @@ public function __construct( ) { try { $this->mimePart = new ZendMimePart($content); - } catch (\Zend\Mime\Exception\InvalidArgumentException $e) { + } catch (\Exception $e) { throw new MailException(__($e->getMessage())); } $this->mimePart->setType($type); diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 2333021f5036..b53a030c2f66 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -181,7 +181,7 @@ public function __construct( */ public function addCc($address, $name = '') { - $this->getMailAddresses('cc', $address, $name); + $this->addAddressByType('cc', $address, $name); return $this; } @@ -197,7 +197,7 @@ public function addCc($address, $name = '') */ public function addTo($address, $name = '') { - $this->getMailAddresses('to', $address, $name); + $this->addAddressByType('to', $address, $name); return $this; } @@ -212,7 +212,7 @@ public function addTo($address, $name = '') */ public function addBcc($address) { - $this->getMailAddresses('bcc', $address); + $this->addAddressByType('bcc', $address); return $this; } @@ -228,7 +228,7 @@ public function addBcc($address) */ public function setReplyTo($email, $name = null) { - $this->getMailAddresses('replyTo', $email, $name); + $this->addAddressByType('replyTo', $email, $name); return $this; } @@ -262,7 +262,7 @@ public function setFrom($from) public function setFromByScope($from, $scopeId = null) { $result = $this->_senderResolver->resolve($from, $scopeId); - $this->getMailAddresses('from', $result['email'], $result['name']); + $this->addAddressByType('from', $result['email'], $result['name']); return $this; } @@ -389,8 +389,10 @@ protected function prepareMessage() new Phrase('Unknown template type') ); } - $this->messageData['body'] = $this->mimeMessageInterfaceFactory - ->create(['parts' => [$this->mimePartInterfaceFactory->create(['content'=>$content])]]); + $mimePart = $this->mimePartInterfaceFactory->create(['content' => $content]); + $this->messageData['body'] = $this->mimeMessageInterfaceFactory->create( + ['parts' => [$mimePart]] + ); $this->messageData['subject'] = html_entity_decode( (string)$template->getSubject(), @@ -405,22 +407,22 @@ protected function prepareMessage() * Handles possible incoming types of email (string or array) * * @param string $addressType - * @param string|array $emailOrList + * @param string|array $email * @param string|null $name * * @return void * @throws MailException */ - private function getMailAddresses(string $addressType, $emailOrList, ?string $name = null): void + private function addAddressByType(string $addressType, $email, ?string $name = null): void { - if (is_array($emailOrList)) { + if (is_array($email)) { $this->messageData[$addressType] = array_merge( $this->messageData[$addressType], - $this->addressConverter->convertMany($emailOrList) + $this->addressConverter->convertMany($email) ); return; } - $this->messageData[$addressType][] = $this->addressConverter->convert($emailOrList, $name); + $this->messageData[$addressType][] = $this->addressConverter->convert($email, $name); } } diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index fa4182ab078f..5ceeb81d897c 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -60,6 +60,10 @@ class TransportBuilderTest extends \PHPUnit\Framework\TestCase * @var \Magento\Framework\Mail\EmailMessageInterface|\PHPUnit\Framework\MockObject\MockObject */ private $emailMessageMock; + /** + * @var \PHPUnit\Framework\MockObject\MockObject + */ + private $mimePartFactoryMock; /** * @return void From 138dc925aa1b58a5278dc07b9a2381354305aeb4 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 1 Aug 2019 14:36:09 +0300 Subject: [PATCH 23/37] MC-15295: Added integration test --- .../Framework/Mail/EmailMessageTest.php | 256 ++++++++++++++++++ .../Magento/Framework/Mail/EmailMessage.php | 30 +- .../Magento/Framework/Mail/MimePart.php | 2 +- .../Framework/Mail/MimePartInterface.php | 2 +- 4 files changed, 273 insertions(+), 17 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php diff --git a/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php b/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php new file mode 100644 index 000000000000..3467b1ecb54f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php @@ -0,0 +1,256 @@ + [ + ['email' => 'to@adobe.com', 'name' => 'Addressee'] + ], + 'replyTo' => ['email' => 'replyTo@adobe.com', 'name' => 'Reply To Address'], + 'from' => 'from@adobe.com', + 'sender' => ['email' => 'sender@adobe.com', 'name' => 'Sender'], + 'cc' => [ + 'cc1@adobe.com' => 'CC 1 Address', + 'cc2@adobe.com' => 'CC 2 Address', + 'cc3@adobe.com' => 'CC 3 Address', + ], + 'bcc' => ['bcc1@adobe.com', 'bcc2@adobe.com'], + ]; + + /** + * @var string + */ + private $subject = 'Test subject'; + + /** + * @var string + */ + private $description = 'Test description'; + + /** + * + * @return void + */ + protected function setUp() + { + $this->di = Bootstrap::getObjectManager(); + $this->mimePartFactory = $this->di->get(MimePartInterfaceFactory::class); + $this->mimeMessageFactory = $this->di->get(MimeMessageInterfaceFactory::class); + $this->messageConverter = $this->di->get(AddressConverter::class); + $this->messageFactory = $this->di->get(EmailMessageInterfaceFactory::class); + } + + /** + * @return array + */ + public function getEmailMessageDataProvider(): array + { + return [ + [ + 'Content Test', + MimeInterface::TYPE_TEXT + ], [ + + '

Html message

', + MimeInterface::TYPE_HTML + ] + ]; + } + + /** + * Tests Email Message with Addresses + * + * @dataProvider getEmailMessageDataProvider + * @param $content + * @param $type + * @return void + * @throws MailException + */ + public function testEmailMessage($content, $type): void + { + $mimePart = $this->mimePartFactory->create([ + 'content' => $content, + 'description' => $this->description, + 'type' => $type + ]); + + $mimeMessage = $this->mimeMessageFactory->create([ + 'parts' => [$mimePart] + ]); + + $this->addressFactory = $this->di->get(AddressFactory::class); + /** @var Address $addressTo */ + $to = [ + $this->addressFactory->create( + [ + 'email' => $this->addressList['to'][0]['email'], + 'name' => $this->addressList['to'][0]['name'] + ] + ) + ]; + + $from = [$this->messageConverter->convert($this->addressList['from'])]; + $cc = $this->messageConverter->convertMany($this->addressList['cc']); + $replyTo = [ + $this->messageConverter->convert( + $this->addressList['replyTo']['email'], + $this->addressList['replyTo']['name'] + ) + ]; + $bcc = $this->messageConverter->convertMany($this->addressList['bcc']); + $sender = $this->messageConverter->convert( + $this->addressList['sender']['email'], + $this->addressList['sender']['name'] + ); + $data = [ + 'body' => $mimeMessage, + 'subject' => $this->subject, + 'from' => $from, + 'to' => $to, + 'cc' => $cc, + 'replyTo' => $replyTo, + 'bcc' => $bcc, + 'sender' => $sender + ]; + $message = $this->messageFactory->create($data); + + $this->assertContains($content, $message->toString()); + $this->assertContains('Content-Type: ' . $type, $message->toString()); + $senderString = 'Sender: ' . $sender->getName() . ' <' . $sender->getEmail() . '>'; + $this->assertContains($senderString, $message->toString()); + $this->assertContains('From: ' . $from[0]->getEmail(), $message->toString()); + $replyToString = 'Reply-To: ' . $replyTo[0]->getName() . ' <' . $replyTo[0]->getEmail() . '>'; + $this->assertContains($replyToString, $message->toString()); + $toString = 'To: ' . $to[0]->getName() . ' <' . $to[0]->getEmail() . '>'; + $this->assertContains($toString, $message->toString()); + $ccString = 'Cc: ' . $cc[0]->getName() . ' <' . $cc[0]->getEmail() . '>'; + $this->assertContains($ccString, $message->toString()); + $this->assertContains('Bcc: ' . $bcc[0]->getEmail(), $message->toString()); + $this->assertContains('Content-Description: ' . $this->description, $message->toString()); + $this->assertContains('Subject: ' . $this->subject, $message->toString()); + $this->assertContains($content, $message->toString()); + //tests address factory + $this->assertInstanceOf(Address::class, $message->getTo()[0]); + //tests address converter convert method + $this->assertInstanceOf(Address::class, $message->getFrom()[0]); + //tests address converter convertMany method + $this->assertInstanceOf(Address::class, $message->getCc()[0]); + } + + /** + * Test Email Message with Xml Attachment + * + * @return void + */ + public function testEmailMessageWithAttachment(): void + { + $mimePartMain = $this->mimePartFactory->create([ + 'content' => 'Test', + 'description' => $this->description, + 'type' => MimeInterface::TYPE_TEXT + ]); + $mimePartAttachment = $this->mimePartFactory->create([ + 'content' => $this->getXmlContent(), + 'disposition' => MimeInterface::DISPOSITION_ATTACHMENT, + 'fileName' => self::ATTACHMENT_FILE_NAME, + 'type' => self::XML_TYPE + ]); + + $mimeMessage = $this->mimeMessageFactory->create([ + 'parts' => [$mimePartMain, $mimePartAttachment] + ]); + + $this->addressFactory = $this->di->get(AddressFactory::class); + /** @var Address $addressTo */ + $addressTo = $this->addressFactory + ->create( + [ + 'email' => $this->addressList['to'][0]['email'], + 'name' => $this->addressList['to'][0]['name'] + ] + ); + + $data = [ + 'body' => $mimeMessage, + 'subject' => $this->subject, + 'to' => [$addressTo], + ]; + $message = $this->messageFactory->create($data); + + $this->assertContains($this->getXmlContent(), $message->toString()); + $this->assertContains('Content-Type: ' . self::XML_TYPE, $message->toString()); + $contentDisposition = 'Content-Disposition: ' . MimeInterface::DISPOSITION_ATTACHMENT + . '; filename="' . self::ATTACHMENT_FILE_NAME . '"'; + $this->assertContains($contentDisposition, $message->toString()); + } + + /** + * Provides xml content + * + * @return string + */ + private function getXmlContent(): string + { + return ' + + + + + Furman\Test\Command\Testbed + + + + +'; + } +} diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 48923ab419e9..ab7c759574f9 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -80,21 +80,21 @@ public function __construct( if (count($to) < 1) { throw new MailException(__('Email message must have at list one addressee')); } - $this->message->setTo( - $this->convertAddressArrayToAddressList($to) - ); - $this->message->setReplyTo( - $this->convertAddressArrayToAddressList($replyTo) - ); - $this->message->setFrom( - $this->convertAddressArrayToAddressList($from) - ); - $this->message->setCc( - $this->convertAddressArrayToAddressList($cc) - ); - $this->message->setBcc( - $this->convertAddressArrayToAddressList($bcc) - ); + if ($sender) { + $this->message->setTo($this->convertAddressArrayToAddressList($to)); + } + if ($sender) { + $this->message->setReplyTo($this->convertAddressArrayToAddressList($replyTo)); + } + if ($sender) { + $this->message->setFrom($this->convertAddressArrayToAddressList($from)); + } + if ($sender) { + $this->message->setCc($this->convertAddressArrayToAddressList($cc)); + } + if ($sender) { + $this->message->setBcc($this->convertAddressArrayToAddressList($bcc)); + } $this->mimeMessageFactory = $mimeMessageFactory; $this->addressFactory = $addressFactory; } diff --git a/lib/internal/Magento/Framework/Mail/MimePart.php b/lib/internal/Magento/Framework/Mail/MimePart.php index 69103d519482..51f51ae5a276 100644 --- a/lib/internal/Magento/Framework/Mail/MimePart.php +++ b/lib/internal/Magento/Framework/Mail/MimePart.php @@ -204,7 +204,7 @@ public function getRawContent(): string /** * @inheritDoc */ - public function getHeadersAsArray($endOfLine = MimeInterface::LINE_END): array + public function getHeadersArray($endOfLine = MimeInterface::LINE_END): array { return $this->mimePart->getHeadersArray($endOfLine); } diff --git a/lib/internal/Magento/Framework/Mail/MimePartInterface.php b/lib/internal/Magento/Framework/Mail/MimePartInterface.php index 2de4c134da50..e56b460caa06 100644 --- a/lib/internal/Magento/Framework/Mail/MimePartInterface.php +++ b/lib/internal/Magento/Framework/Mail/MimePartInterface.php @@ -120,7 +120,7 @@ public function getRawContent(): string; * * @return array */ - public function getHeadersAsArray($endOfLine = MimeInterface::LINE_END): array; + public function getHeadersArray($endOfLine = MimeInterface::LINE_END): array; /** * Create and return the array of headers for this MIME part From d5237c33dc5f9124e22b2075fcb41c17765ed27a Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 1 Aug 2019 14:48:40 +0300 Subject: [PATCH 24/37] MC-15295: Fix static tests --- .../Newsletter/Model/Queue/TransportBuilder.php | 4 ++++ .../Magento/Framework/Mail/AddressConverter.php | 14 ++++++++------ .../Framework/Mail/Template/TransportBuilder.php | 3 ++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php index a35326fe06c7..aa3a2bcfe0f5 100644 --- a/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php +++ b/app/code/Magento/Newsletter/Model/Queue/TransportBuilder.php @@ -23,6 +23,8 @@ /** * Class TransportBuilder + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder { @@ -73,6 +75,8 @@ class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder * @param MimeMessageInterfaceFactory|null $mimeMessageInterfaceFactory * @param MimePartInterfaceFactory|null $mimePartInterfaceFactory * @param AddressConverter|null $addressConverter + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( FactoryInterface $templateFactory, diff --git a/lib/internal/Magento/Framework/Mail/AddressConverter.php b/lib/internal/Magento/Framework/Mail/AddressConverter.php index 3c7a0ff2f522..23cc504c6fc1 100644 --- a/lib/internal/Magento/Framework/Mail/AddressConverter.php +++ b/lib/internal/Magento/Framework/Mail/AddressConverter.php @@ -59,18 +59,20 @@ public function convert(string $email, ?string $name = null): Address public function convertMany(array $addresses): array { $addressList = []; - foreach ($addresses as $key=>$value) { + foreach ($addresses as $key => $value) { if (is_int($key) || is_numeric($key)) { $addressList[] = $this->convert($value); continue; } - if (! is_string($key)) { - throw new MailException(__( - 'Invalid key type in provided addresses array ("%s")', - (is_object($key) ? get_class($key) : var_export($key, 1)) - )); + if (!is_string($key)) { + throw new MailException( + __( + 'Invalid key type in provided addresses array ("%1")', + (is_object($key) ? get_class($key) : var_export($key, 1)) + ) + ); } $addressList[] = $this->convert($key, $value); } diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index b53a030c2f66..03d8fa095102 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -143,6 +143,7 @@ class TransportBuilder * @param MimePartInterfaceFactory|null $mimePartInterfaceFactory * @param addressConverter|null $addressConverter * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( FactoryInterface $templateFactory, @@ -154,7 +155,7 @@ public function __construct( EmailMessageInterfaceFactory $emailMessageInterfaceFactory = null, MimeMessageInterfaceFactory $mimeMessageInterfaceFactory = null, MimePartInterfaceFactory $mimePartInterfaceFactory = null, - AddressConverter $addressConverter=null + AddressConverter $addressConverter = null ) { $this->templateFactory = $templateFactory; $this->objectManager = $objectManager; From eeadf6f0c2e08d91e2ce6ff0020a837e440eb5ff Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 1 Aug 2019 15:26:30 +0300 Subject: [PATCH 25/37] MC-15295: Fix static tests --- .../Magento/Test/Php/_files/phpcpd/blacklist/common.txt | 1 + lib/internal/Magento/Framework/Mail/EmailMessage.php | 2 ++ .../Mail/Test/Unit/Template/TransportBuilderTest.php | 4 ---- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt index c25df7e6becb..4653203f4d57 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt +++ b/dev/tests/static/testsuite/Magento/Test/Php/_files/phpcpd/blacklist/common.txt @@ -217,3 +217,4 @@ Magento/Config/App/Config/Type Magento/InventoryReservationCli/Test/Integration Magento/InventoryAdminUi/Controller/Adminhtml Magento/Newsletter/Model/Queue/TransportBuilder +Magento/Framework/Mail/Template/TransportBuilder \ No newline at end of file diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index ab7c759574f9..158eb52ed0c1 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -50,6 +50,8 @@ class EmailMessage implements EmailMessageInterface * * @throws MailException * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function __construct( MimeMessageInterface $body, diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index 5ceeb81d897c..fa4182ab078f 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -60,10 +60,6 @@ class TransportBuilderTest extends \PHPUnit\Framework\TestCase * @var \Magento\Framework\Mail\EmailMessageInterface|\PHPUnit\Framework\MockObject\MockObject */ private $emailMessageMock; - /** - * @var \PHPUnit\Framework\MockObject\MockObject - */ - private $mimePartFactoryMock; /** * @return void From 837d0db59aed1c7eacd11ebdd195ad72baf9408a Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 1 Aug 2019 16:11:44 +0300 Subject: [PATCH 26/37] MC-15295: Fix integration tests --- lib/internal/Magento/Framework/Mail/EmailMessage.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 158eb52ed0c1..e84db78eccbb 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -82,19 +82,19 @@ public function __construct( if (count($to) < 1) { throw new MailException(__('Email message must have at list one addressee')); } - if ($sender) { + if ($to) { $this->message->setTo($this->convertAddressArrayToAddressList($to)); } - if ($sender) { + if ($replyTo) { $this->message->setReplyTo($this->convertAddressArrayToAddressList($replyTo)); } - if ($sender) { - $this->message->setFrom($this->convertAddressArrayToAddressList($from)); + if ($replyTo) { + $this->message->setFrom($this->convertAddressArrayToAddressList($replyTo)); } - if ($sender) { + if ($cc) { $this->message->setCc($this->convertAddressArrayToAddressList($cc)); } - if ($sender) { + if ($bcc) { $this->message->setBcc($this->convertAddressArrayToAddressList($bcc)); } $this->mimeMessageFactory = $mimeMessageFactory; From 2b77950a48fd301c84343b585b9d923fcf1e6444 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 1 Aug 2019 17:24:53 +0300 Subject: [PATCH 27/37] MC-15295: Fix integration tests --- .../Framework/Mail/Template/TransportBuilder.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index 03d8fa095102..f9d513561b23 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -416,14 +416,16 @@ protected function prepareMessage() */ private function addAddressByType(string $addressType, $email, ?string $name = null): void { - if (is_array($email)) { + if (is_string($email)) { + $this->messageData[$addressType][] = $this->addressConverter->convert($email, $name); + return; + } + $convertedAddressArray = $this->addressConverter->convertMany($email); + if (isset($this->messageData[$addressType])) { $this->messageData[$addressType] = array_merge( $this->messageData[$addressType], - $this->addressConverter->convertMany($email) + $convertedAddressArray ); - - return; } - $this->messageData[$addressType][] = $this->addressConverter->convert($email, $name); } } From 2a9a85b0dc2447f518e049b54ed9b4fe239017c0 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 1 Aug 2019 17:37:51 +0300 Subject: [PATCH 28/37] MC-15295: Fix integration tests --- .../Framework/Mail/EmailMessageTest.php | 57 +++++++++++-------- .../Magento/Framework/Mail/EmailMessage.php | 2 +- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php b/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php index 3467b1ecb54f..0d6a7824ef67 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php @@ -118,15 +118,19 @@ public function getEmailMessageDataProvider(): array */ public function testEmailMessage($content, $type): void { - $mimePart = $this->mimePartFactory->create([ - 'content' => $content, - 'description' => $this->description, - 'type' => $type - ]); + $mimePart = $this->mimePartFactory->create( + [ + 'content' => $content, + 'description' => $this->description, + 'type' => $type + ] + ); - $mimeMessage = $this->mimeMessageFactory->create([ - 'parts' => [$mimePart] - ]); + $mimeMessage = $this->mimeMessageFactory->create( + [ + 'parts' => [$mimePart] + ] + ); $this->addressFactory = $this->di->get(AddressFactory::class); /** @var Address $addressTo */ @@ -194,21 +198,27 @@ public function testEmailMessage($content, $type): void */ public function testEmailMessageWithAttachment(): void { - $mimePartMain = $this->mimePartFactory->create([ - 'content' => 'Test', - 'description' => $this->description, - 'type' => MimeInterface::TYPE_TEXT - ]); - $mimePartAttachment = $this->mimePartFactory->create([ - 'content' => $this->getXmlContent(), - 'disposition' => MimeInterface::DISPOSITION_ATTACHMENT, - 'fileName' => self::ATTACHMENT_FILE_NAME, - 'type' => self::XML_TYPE - ]); + $mimePartMain = $this->mimePartFactory->create( + [ + 'content' => 'Test', + 'description' => $this->description, + 'type' => MimeInterface::TYPE_TEXT + ] + ); + $mimePartAttachment = $this->mimePartFactory->create( + [ + 'content' => $this->getXmlContent(), + 'disposition' => MimeInterface::DISPOSITION_ATTACHMENT, + 'fileName' => self::ATTACHMENT_FILE_NAME, + 'type' => self::XML_TYPE + ] + ); - $mimeMessage = $this->mimeMessageFactory->create([ - 'parts' => [$mimePartMain, $mimePartAttachment] - ]); + $mimeMessage = $this->mimeMessageFactory->create( + [ + 'parts' => [$mimePartMain, $mimePartAttachment] + ] + ); $this->addressFactory = $this->di->get(AddressFactory::class); /** @var Address $addressTo */ @@ -242,7 +252,8 @@ public function testEmailMessageWithAttachment(): void private function getXmlContent(): string { return ' - + diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index e84db78eccbb..3986887d27e9 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -89,7 +89,7 @@ public function __construct( $this->message->setReplyTo($this->convertAddressArrayToAddressList($replyTo)); } if ($replyTo) { - $this->message->setFrom($this->convertAddressArrayToAddressList($replyTo)); + $this->message->setFrom($this->convertAddressArrayToAddressList($from)); } if ($cc) { $this->message->setCc($this->convertAddressArrayToAddressList($cc)); From 89061b20d6c0396d031bdb2336b26d439acc7f97 Mon Sep 17 00:00:00 2001 From: Falk Ulbricht Date: Thu, 1 Aug 2019 17:24:12 +0200 Subject: [PATCH 29/37] MC-15295: Fix unit tests --- .../Unit/Template/TransportBuilderTest.php | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index fa4182ab078f..49d9d47a2883 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -8,6 +8,11 @@ namespace Magento\Framework\Mail\Test\Unit\Template; use Magento\Framework\App\TemplateTypesInterface; +use Magento\Framework\Mail\EmailMessageInterface; +use Magento\Framework\Mail\EmailMessageInterfaceFactory; +use Magento\Framework\Mail\MimePartInterface; +use Magento\Framework\Mail\MimePartInterfaceFactory; +use PHPUnit\Framework\MockObject\MockObject; /** * Class TransportBuilderTest @@ -61,6 +66,16 @@ class TransportBuilderTest extends \PHPUnit\Framework\TestCase */ private $emailMessageMock; + /** + * @var MimePartInterfaceFactory|MockObject + */ + private $mimePartFactoryMock; + + /** + * @var EmailMessageInterfaceFactory|MockObject + */ + private $emailMessageInterfaceFactoryMock; + /** * @return void */ @@ -81,6 +96,10 @@ protected function setUp() ->disableOriginalConstructor() ->setMethods(['create']) ->getMockForAbstractClass(); + + $this->emailMessageInterfaceFactoryMock = $this->createMock(EmailMessageInterfaceFactory::class); + $this->mimePartFactoryMock = $this->createMock(MimePartInterfaceFactory::class); + $this->builder = $objectManagerHelper->getObject( $this->builderClassName, [ @@ -89,7 +108,9 @@ protected function setUp() 'objectManager' => $this->objectManagerMock, 'senderResolver' => $this->senderResolverMock, 'mailTransportFactory' => $this->mailTransportFactoryMock, - 'messageFactory' => $this->messageFactoryMock + 'messageFactory' => $this->messageFactoryMock, + 'emailMessageInterfaceFactory' => $this->emailMessageInterfaceFactoryMock, + 'mimePartInterfaceFactory' => $this->mimePartFactoryMock, ] ); } @@ -108,6 +129,20 @@ public function testGetTransport($templateType, $bodyText, $templateNamespace) $vars = ['reason' => 'Reason', 'customer' => 'Customer']; $options = ['area' => 'frontend', 'store' => 1]; + /** @var MimePartInterface|MockObject $mimePartMock */ + $mimePartMock = $this->createMock(MimePartInterface::class); + + $this->mimePartFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($mimePartMock); + + /** @var EmailMessageInterface|MockObject $emailMessage */ + $emailMessage = $this->createMock(EmailMessageInterface::class); + + $this->emailMessageInterfaceFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($emailMessage); + $template = $this->createMock(\Magento\Framework\Mail\TemplateInterface::class); $template->expects($this->once())->method('setVars')->with($this->equalTo($vars))->willReturnSelf(); $template->expects($this->once())->method('setOptions')->with($this->equalTo($options))->willReturnSelf(); @@ -127,7 +162,9 @@ public function testGetTransport($templateType, $bodyText, $templateNamespace) ->willReturn($transport); $this->builder->setTemplateIdentifier('identifier')->setTemplateVars($vars)->setTemplateOptions($options); - $this->assertInstanceOf(\Magento\Framework\Mail\TransportInterface::class, $this->builder->getTransport()); + + $result = $this->builder->getTransport(); + $this->assertInstanceOf(\Magento\Framework\Mail\TransportInterface::class, $result); } /** From eb9baad698901a8178c9699a4e0c26e1d76219e9 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 1 Aug 2019 23:10:04 +0300 Subject: [PATCH 30/37] MC-15295: Refactoring Exceptions --- .../Framework/Mail/AddressConverter.php | 6 +++--- .../Magento/Framework/Mail/EmailMessage.php | 6 +++--- .../Exception/InvalidArgumentException.php | 21 +++++++++++++++++++ .../Magento/Framework/Mail/MimePart.php | 8 +++---- .../Framework/Mail/MimePartInterface.php | 2 +- .../Mail/Template/TransportBuilder.php | 13 ++++++------ lib/internal/Magento/Framework/composer.json | 1 + 7 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 lib/internal/Magento/Framework/Mail/Exception/InvalidArgumentException.php diff --git a/lib/internal/Magento/Framework/Mail/AddressConverter.php b/lib/internal/Magento/Framework/Mail/AddressConverter.php index 23cc504c6fc1..1de1644e03b3 100644 --- a/lib/internal/Magento/Framework/Mail/AddressConverter.php +++ b/lib/internal/Magento/Framework/Mail/AddressConverter.php @@ -7,7 +7,7 @@ namespace Magento\Framework\Mail; -use Magento\Framework\Exception\MailException; +use Magento\Framework\Mail\Exception\InvalidArgumentException; /** * Class AddressConverter @@ -54,7 +54,7 @@ public function convert(string $email, ?string $name = null): Address * @param array $addresses * * @return Address[] - * @throws MailException + * @throws InvalidArgumentException */ public function convertMany(array $addresses): array { @@ -67,7 +67,7 @@ public function convertMany(array $addresses): array } if (!is_string($key)) { - throw new MailException( + throw new InvalidArgumentException( __( 'Invalid key type in provided addresses array ("%1")', (is_object($key) ? get_class($key) : var_export($key, 1)) diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 3986887d27e9..b62f48ffd7ff 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -7,7 +7,7 @@ namespace Magento\Framework\Mail; -use Magento\Framework\Exception\MailException; +use Magento\Framework\Mail\Exception\InvalidArgumentException; use Zend\Mail\Address as ZendAddress; use Zend\Mail\AddressList; use Zend\Mail\Message as ZendMessage; @@ -47,8 +47,8 @@ class EmailMessage implements EmailMessageInterface * @param Address|null $sender * @param string|null $subject * @param string|null $encoding + * @throws InvalidArgumentException * - * @throws MailException * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.CyclomaticComplexity) @@ -80,7 +80,7 @@ public function __construct( $this->message->setSender($sender->getEmail(), $sender->getName()); } if (count($to) < 1) { - throw new MailException(__('Email message must have at list one addressee')); + throw new InvalidArgumentException(__('Email message must have at list one addressee')); } if ($to) { $this->message->setTo($this->convertAddressArrayToAddressList($to)); diff --git a/lib/internal/Magento/Framework/Mail/Exception/InvalidArgumentException.php b/lib/internal/Magento/Framework/Mail/Exception/InvalidArgumentException.php new file mode 100644 index 000000000000..f0abcb293b4b --- /dev/null +++ b/lib/internal/Magento/Framework/Mail/Exception/InvalidArgumentException.php @@ -0,0 +1,21 @@ +mimePart = new ZendMimePart($content); } catch (\Exception $e) { - throw new MailException(__($e->getMessage())); + throw new InvalidArgumentException(__($e->getMessage())); } $this->mimePart->setType($type); $this->mimePart->setEncoding($encoding); diff --git a/lib/internal/Magento/Framework/Mail/MimePartInterface.php b/lib/internal/Magento/Framework/Mail/MimePartInterface.php index e56b460caa06..8a658cdf975c 100644 --- a/lib/internal/Magento/Framework/Mail/MimePartInterface.php +++ b/lib/internal/Magento/Framework/Mail/MimePartInterface.php @@ -7,7 +7,7 @@ namespace Magento\Framework\Mail; /** - * Interface MimePartInterface + * Interface representing a MIME part. */ interface MimePartInterface { diff --git a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php index f9d513561b23..4a8d6572faaf 100644 --- a/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php +++ b/lib/internal/Magento/Framework/Mail/Template/TransportBuilder.php @@ -15,6 +15,7 @@ use Magento\Framework\Mail\EmailMessageInterface; use Magento\Framework\Mail\EmailMessageInterfaceFactory; use Magento\Framework\Mail\AddressConverter; +use Magento\Framework\Mail\Exception\InvalidArgumentException; use Magento\Framework\Mail\MessageInterface; use Magento\Framework\Mail\MessageInterfaceFactory; use Magento\Framework\Mail\MimeInterface; @@ -178,7 +179,6 @@ public function __construct( * @param string $name * * @return $this - * @throws MailException */ public function addCc($address, $name = '') { @@ -194,7 +194,7 @@ public function addCc($address, $name = '') * @param string $name * * @return $this - * @throws MailException + * @throws InvalidArgumentException */ public function addTo($address, $name = '') { @@ -209,7 +209,7 @@ public function addTo($address, $name = '') * @param array|string $address * * @return $this - * @throws MailException + * @throws InvalidArgumentException */ public function addBcc($address) { @@ -225,7 +225,7 @@ public function addBcc($address) * @param string|null $name * * @return $this - * @throws MailException + * @throws InvalidArgumentException */ public function setReplyTo($email, $name = null) { @@ -240,7 +240,7 @@ public function setReplyTo($email, $name = null) * @param string|array $from * * @return $this - * @throws MailException + * @throws InvalidArgumentException * @see setFromByScope() * * @deprecated This function sets the from address but does not provide @@ -258,6 +258,7 @@ public function setFrom($from) * @param string|int $scopeId * * @return $this + * @throws InvalidArgumentException * @throws MailException */ public function setFromByScope($from, $scopeId = null) @@ -412,7 +413,7 @@ protected function prepareMessage() * @param string|null $name * * @return void - * @throws MailException + * @throws InvalidArgumentException */ private function addAddressByType(string $addressType, $email, ?string $name = null): void { diff --git a/lib/internal/Magento/Framework/composer.json b/lib/internal/Magento/Framework/composer.json index 1aca0aab7196..c42323a2ecc0 100644 --- a/lib/internal/Magento/Framework/composer.json +++ b/lib/internal/Magento/Framework/composer.json @@ -38,6 +38,7 @@ "zendframework/zend-uri": "^2.5.1", "zendframework/zend-validator": "^2.6.0", "zendframework/zend-mail": "^2.9.0", + "zendframework/zend-mime": "^2.5.0", "guzzlehttp/guzzle": "^6.3.3" }, "archive": { From 3a39ce2d02aa6d15bb1ff54365d387db709501d6 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Thu, 1 Aug 2019 23:39:42 +0300 Subject: [PATCH 31/37] MC-15295: Refactoring Exceptions --- lib/internal/Magento/Framework/Mail/AddressConverter.php | 4 ++-- lib/internal/Magento/Framework/Mail/EmailMessage.php | 2 +- lib/internal/Magento/Framework/Mail/MimePart.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/AddressConverter.php b/lib/internal/Magento/Framework/Mail/AddressConverter.php index 1de1644e03b3..d787482f1757 100644 --- a/lib/internal/Magento/Framework/Mail/AddressConverter.php +++ b/lib/internal/Magento/Framework/Mail/AddressConverter.php @@ -68,8 +68,8 @@ public function convertMany(array $addresses): array if (!is_string($key)) { throw new InvalidArgumentException( - __( - 'Invalid key type in provided addresses array ("%1")', + sprintf( + 'Invalid key type in provided addresses array ("%s")', (is_object($key) ? get_class($key) : var_export($key, 1)) ) ); diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index b62f48ffd7ff..4457bcf84eed 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -80,7 +80,7 @@ public function __construct( $this->message->setSender($sender->getEmail(), $sender->getName()); } if (count($to) < 1) { - throw new InvalidArgumentException(__('Email message must have at list one addressee')); + throw new InvalidArgumentException('Email message must have at list one addressee'); } if ($to) { $this->message->setTo($this->convertAddressArrayToAddressList($to)); diff --git a/lib/internal/Magento/Framework/Mail/MimePart.php b/lib/internal/Magento/Framework/Mail/MimePart.php index 22288712111e..9c1047cc84c4 100644 --- a/lib/internal/Magento/Framework/Mail/MimePart.php +++ b/lib/internal/Magento/Framework/Mail/MimePart.php @@ -58,7 +58,7 @@ public function __construct( try { $this->mimePart = new ZendMimePart($content); } catch (\Exception $e) { - throw new InvalidArgumentException(__($e->getMessage())); + throw new InvalidArgumentException($e->getMessage()); } $this->mimePart->setType($type); $this->mimePart->setEncoding($encoding); From 008262324c9875c78f8643728752100a07dc1d9d Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Fri, 2 Aug 2019 12:52:08 +0300 Subject: [PATCH 32/37] MC-15295: fix unit tests --- .../Unit/Model/Queue/TransportBuilderTest.php | 131 +++++++++++------- .../Unit/Template/TransportBuilderTest.php | 57 ++++---- 2 files changed, 112 insertions(+), 76 deletions(-) diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php index f0f4eb2af99a..a217138b1329 100644 --- a/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php +++ b/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php @@ -1,4 +1,5 @@ -templateFactoryMock = $this->createMock(\Magento\Framework\Mail\Template\FactoryInterface::class); - $this->messageMock = $this->getMockBuilder(\Magento\Framework\Mail\MessageInterface::class) + $objectManagerHelper = new ObjectManager($this); + $this->templateFactoryMock = $this->createMock(FactoryInterface::class); + $this->messageMock = $this->getMockBuilder(MessageInterface::class) ->disableOriginalConstructor() ->setMethods(['setBodyHtml', 'setSubject']) ->getMockForAbstractClass(); - $this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); - $this->senderResolverMock = $this->createMock(\Magento\Framework\Mail\Template\SenderResolverInterface::class); - $this->mailTransportFactoryMock = $this->getMockBuilder( - \Magento\Framework\Mail\TransportInterfaceFactory::class - )->disableOriginalConstructor() + + $this->emailMessageInterfaceFactoryMock = $this->createMock(EmailMessageInterfaceFactory::class); + $this->mimePartFactoryMock = $this->createMock(MimePartInterfaceFactory::class); + + $this->objectManagerMock = $this->createMock(ObjectManagerInterface::class); + $this->senderResolverMock = $this->createMock(SenderResolverInterface::class); + $this->mailTransportFactoryMock = $this->getMockBuilder(TransportInterfaceFactory::class) + ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); @@ -82,7 +113,9 @@ public function setUp() 'objectManager' => $this->objectManagerMock, 'senderResolver' => $this->senderResolverMock, 'mailTransportFactory' => $this->mailTransportFactoryMock, - 'messageFactory' => $this->messageFactoryMock + 'messageFactory' => $this->messageFactoryMock, + 'emailMessageInterfaceFactory' => $this->emailMessageInterfaceFactoryMock, + 'mimePartInterfaceFactory' => $this->mimePartFactoryMock, ] ); } @@ -92,12 +125,13 @@ public function setUp() * @param string $bodyText * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @throws \Magento\Framework\Exception\LocalizedException */ public function testGetTransport( $templateType = TemplateTypesInterface::TYPE_HTML, $bodyText = '

Html message

' - ) { - $filter = $this->createMock(\Magento\Email\Model\Template\Filter::class); + ): void { + $filter = $this->createMock(Filter::class); $data = [ 'template_subject' => 'Email Subject', 'template_text' => $bodyText, @@ -107,36 +141,33 @@ public function testGetTransport( ]; $vars = ['reason' => 'Reason', 'customer' => 'Customer']; $options = ['area' => 'frontend', 'store' => 1]; - $template = $this->createMock(\Magento\Email\Model\Template::class); + + /** @var MimePartInterface|MockObject $mimePartMock */ + $mimePartMock = $this->createMock(MimePartInterface::class); + + $this->mimePartFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($mimePartMock); + + /** @var EmailMessageInterface|MockObject $emailMessage */ + $emailMessage = $this->createMock(EmailMessageInterface::class); + + $this->emailMessageInterfaceFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($emailMessage); + + $template = $this->createMock(Template::class); $template->expects($this->once())->method('setVars')->with($this->equalTo($vars))->will($this->returnSelf()); - $template->expects( - $this->once() - )->method( - 'setOptions' - )->with( - $this->equalTo($options) - )->will( - $this->returnSelf() - ); - $template->expects($this->once())->method('getSubject')->will($this->returnValue('Email Subject')); + $template->expects($this->once())->method('setOptions')->with($this->equalTo($options))->will($this->returnSelf()); + $template->expects($this->once())->method('getSubject')->willReturn('Email Subject'); $template->expects($this->once())->method('setData')->with($this->equalTo($data))->will($this->returnSelf()); - $template->expects($this->once()) - ->method('getProcessedTemplate') - ->with($vars) - ->willReturn($bodyText); - $template->expects($this->once()) - ->method('setTemplateFilter') - ->with($filter); - - $this->templateFactoryMock->expects( - $this->once() - )->method( - 'get' - )->with( - $this->equalTo('identifier') - )->will( - $this->returnValue($template) - ); + $template->expects($this->once())->method('getProcessedTemplate')->with($vars)->willReturn($bodyText); + $template->expects($this->once())->method('setTemplateFilter')->with($filter); + + $this->templateFactoryMock->expects($this->once()) + ->method('get') + ->with($this->equalTo('identifier')) + ->willReturn($template); $this->builder->setTemplateIdentifier( 'identifier' diff --git a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php index 49d9d47a2883..74f40e76353f 100644 --- a/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php +++ b/lib/internal/Magento/Framework/Mail/Test/Unit/Template/TransportBuilderTest.php @@ -10,49 +10,60 @@ use Magento\Framework\App\TemplateTypesInterface; use Magento\Framework\Mail\EmailMessageInterface; use Magento\Framework\Mail\EmailMessageInterfaceFactory; +use Magento\Framework\Mail\Message; +use Magento\Framework\Mail\MessageInterfaceFactory; use Magento\Framework\Mail\MimePartInterface; use Magento\Framework\Mail\MimePartInterfaceFactory; +use Magento\Framework\Mail\Template\FactoryInterface; +use Magento\Framework\Mail\Template\SenderResolverInterface; +use Magento\Framework\Mail\Template\TransportBuilder; +use Magento\Framework\Mail\TemplateInterface; +use Magento\Framework\Mail\TransportInterface; +use Magento\Framework\Mail\TransportInterfaceFactory; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; /** * Class TransportBuilderTest * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class TransportBuilderTest extends \PHPUnit\Framework\TestCase +class TransportBuilderTest extends TestCase { /** * @var string */ - protected $builderClassName = \Magento\Framework\Mail\Template\TransportBuilder::class; + protected $builderClassName = TransportBuilder::class; /** - * @var \Magento\Framework\Mail\Template\TransportBuilder + * @var TransportBuilder */ protected $builder; /** - * @var \Magento\Framework\Mail\Template\FactoryInterface | \PHPUnit_Framework_MockObject_MockObject + * @var FactoryInterface | \PHPUnit_Framework_MockObject_MockObject */ protected $templateFactoryMock; /** - * @var \Magento\Framework\Mail\Message | \PHPUnit_Framework_MockObject_MockObject + * @var Message | \PHPUnit_Framework_MockObject_MockObject */ protected $messageMock; /** - * @var \Magento\Framework\ObjectManagerInterface | \PHPUnit_Framework_MockObject_MockObject + * @var ObjectManagerInterface | \PHPUnit_Framework_MockObject_MockObject */ protected $objectManagerMock; /** - * @var \Magento\Framework\Mail\Template\SenderResolverInterface | \PHPUnit_Framework_MockObject_MockObject + * @var SenderResolverInterface | \PHPUnit_Framework_MockObject_MockObject */ protected $senderResolverMock; /** - * @var \Magento\Framework\Mail\MessageInterfaceFactory| \PHPUnit_Framework_MockObject_MockObject + * @var MessageInterfaceFactory| \PHPUnit_Framework_MockObject_MockObject */ private $messageFactoryMock; @@ -61,11 +72,6 @@ class TransportBuilderTest extends \PHPUnit\Framework\TestCase */ protected $mailTransportFactoryMock; - /** - * @var \Magento\Framework\Mail\EmailMessageInterface|\PHPUnit\Framework\MockObject\MockObject - */ - private $emailMessageMock; - /** * @var MimePartInterfaceFactory|MockObject */ @@ -81,18 +87,17 @@ class TransportBuilderTest extends \PHPUnit\Framework\TestCase */ protected function setUp() { - $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->templateFactoryMock = $this->createMock(\Magento\Framework\Mail\Template\FactoryInterface::class); - $this->messageMock = $this->createMock(\Magento\Framework\Mail\Message::class); - $this->emailMessageMock = $this->createMock(\Magento\Framework\Mail\EmailMessageInterface::class); - $this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); - $this->senderResolverMock = $this->createMock(\Magento\Framework\Mail\Template\SenderResolverInterface::class); + $objectManagerHelper = new ObjectManager($this); + $this->templateFactoryMock = $this->createMock(FactoryInterface::class); + $this->messageMock = $this->createMock(Message::class); + $this->objectManagerMock = $this->createMock(ObjectManagerInterface::class); + $this->senderResolverMock = $this->createMock(SenderResolverInterface::class); $this->mailTransportFactoryMock = $this->getMockBuilder( - \Magento\Framework\Mail\TransportInterfaceFactory::class + TransportInterfaceFactory::class )->disableOriginalConstructor() ->setMethods(['create']) ->getMockForAbstractClass(); - $this->messageFactoryMock = $this->getMockBuilder(\Magento\Framework\Mail\MessageInterfaceFactory::class) + $this->messageFactoryMock = $this->getMockBuilder(MessageInterfaceFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMockForAbstractClass(); @@ -143,7 +148,7 @@ public function testGetTransport($templateType, $bodyText, $templateNamespace) ->method('create') ->willReturn($emailMessage); - $template = $this->createMock(\Magento\Framework\Mail\TemplateInterface::class); + $template = $this->createMock(TemplateInterface::class); $template->expects($this->once())->method('setVars')->with($this->equalTo($vars))->willReturnSelf(); $template->expects($this->once())->method('setOptions')->with($this->equalTo($options))->willReturnSelf(); $template->expects($this->once())->method('getSubject')->willReturn('Email Subject'); @@ -155,7 +160,7 @@ public function testGetTransport($templateType, $bodyText, $templateNamespace) ->with($this->equalTo('identifier'), $this->equalTo($templateNamespace)) ->willReturn($template); - $transport = $this->createMock(\Magento\Framework\Mail\TransportInterface::class); + $transport = $this->createMock(TransportInterface::class); $this->mailTransportFactoryMock->expects($this->at(0)) ->method('create') @@ -164,7 +169,7 @@ public function testGetTransport($templateType, $bodyText, $templateNamespace) $this->builder->setTemplateIdentifier('identifier')->setTemplateVars($vars)->setTemplateOptions($options); $result = $this->builder->getTransport(); - $this->assertInstanceOf(\Magento\Framework\Mail\TransportInterface::class, $result); + $this->assertInstanceOf(TransportInterface::class, $result); } /** @@ -180,7 +185,7 @@ public function testGetTransportWithException() $vars = ['reason' => 'Reason', 'customer' => 'Customer']; $options = ['area' => 'frontend', 'store' => 1]; - $template = $this->createMock(\Magento\Framework\Mail\TemplateInterface::class); + $template = $this->createMock(TemplateInterface::class); $template->expects($this->once())->method('setVars')->with($this->equalTo($vars))->willReturnSelf(); $template->expects($this->once())->method('setOptions')->with($this->equalTo($options))->willReturnSelf(); $template->expects($this->once())->method('getType')->willReturn('Unknown'); @@ -191,7 +196,7 @@ public function testGetTransportWithException() $this->builder->setTemplateIdentifier('identifier')->setTemplateVars($vars)->setTemplateOptions($options); - $this->assertInstanceOf(\Magento\Framework\Mail\TransportInterface::class, $this->builder->getTransport()); + $this->assertInstanceOf(TransportInterface::class, $this->builder->getTransport()); } /** From 07b72273f5422a0801094b352aca5ef6f3f7032c Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Fri, 2 Aug 2019 15:26:54 +0300 Subject: [PATCH 33/37] MC-15295: fix static tests --- .../Unit/Model/Queue/TransportBuilderTest.php | 20 +++++++++++++------ composer.json | 1 + .../Exception/InvalidArgumentException.php | 10 ++-------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php index a217138b1329..8f5626b42ff3 100644 --- a/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php +++ b/app/code/Magento/Newsletter/Test/Unit/Model/Queue/TransportBuilderTest.php @@ -30,6 +30,8 @@ /** * Class TransportBuilderTest + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class TransportBuilderTest extends TestCase { @@ -157,12 +159,18 @@ public function testGetTransport( ->willReturn($emailMessage); $template = $this->createMock(Template::class); - $template->expects($this->once())->method('setVars')->with($this->equalTo($vars))->will($this->returnSelf()); - $template->expects($this->once())->method('setOptions')->with($this->equalTo($options))->will($this->returnSelf()); - $template->expects($this->once())->method('getSubject')->willReturn('Email Subject'); - $template->expects($this->once())->method('setData')->with($this->equalTo($data))->will($this->returnSelf()); - $template->expects($this->once())->method('getProcessedTemplate')->with($vars)->willReturn($bodyText); - $template->expects($this->once())->method('setTemplateFilter')->with($filter); + $template->expects($this->once())->method('setVars') + ->with($this->equalTo($vars))->will($this->returnSelf()); + $template->expects($this->once())->method('setOptions') + ->with($this->equalTo($options))->will($this->returnSelf()); + $template->expects($this->once())->method('getSubject') + ->willReturn('Email Subject'); + $template->expects($this->once())->method('setData') + ->with($this->equalTo($data))->will($this->returnSelf()); + $template->expects($this->once())->method('getProcessedTemplate') + ->with($vars)->willReturn($bodyText); + $template->expects($this->once())->method('setTemplateFilter') + ->with($filter); $this->templateFactoryMock->expects($this->once()) ->method('get') diff --git a/composer.json b/composer.json index 9998cb0b9bf7..b649a36d3ae5 100644 --- a/composer.json +++ b/composer.json @@ -68,6 +68,7 @@ "zendframework/zend-json": "^2.6.1", "zendframework/zend-log": "^2.9.1", "zendframework/zend-mail": "^2.9.0", + "zendframework/zend-mime": "^2.5.0", "zendframework/zend-modulemanager": "^2.7", "zendframework/zend-mvc": "~2.7.0", "zendframework/zend-serializer": "^2.7.2", diff --git a/lib/internal/Magento/Framework/Mail/Exception/InvalidArgumentException.php b/lib/internal/Magento/Framework/Mail/Exception/InvalidArgumentException.php index f0abcb293b4b..b9442a77658d 100644 --- a/lib/internal/Magento/Framework/Mail/Exception/InvalidArgumentException.php +++ b/lib/internal/Magento/Framework/Mail/Exception/InvalidArgumentException.php @@ -1,13 +1,7 @@ Date: Fri, 2 Aug 2019 17:13:44 +0300 Subject: [PATCH 34/37] MC-15295: Added updates to composer.lock --- composer.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.lock b/composer.lock index a2ff8dcdcdd6..4f3bb4dd5f53 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f08218963fdc3dc7eebdd7ede7fd7236", + "content-hash": "366fc5a3ebd182ddb8f48b36b928147c", "packages": [ { "name": "braintree/braintree_php", @@ -6821,7 +6821,7 @@ "time": "2019-06-10T17:57:40+00:00" }, { - "name": "mikey179/vfsstream", + "name": "mikey179/vfsStream", "version": "v1.6.6", "source": { "type": "git", From 98d4606a0924237f489ea225f6abd7db76e14524 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Fri, 2 Aug 2019 20:13:43 +0300 Subject: [PATCH 35/37] MC-15295: Fix default values for Mime Part --- lib/internal/Magento/Framework/Mail/EmailMessage.php | 2 +- lib/internal/Magento/Framework/Mail/MimePart.php | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/Mail/EmailMessage.php b/lib/internal/Magento/Framework/Mail/EmailMessage.php index 4457bcf84eed..aaef97507518 100644 --- a/lib/internal/Magento/Framework/Mail/EmailMessage.php +++ b/lib/internal/Magento/Framework/Mail/EmailMessage.php @@ -88,7 +88,7 @@ public function __construct( if ($replyTo) { $this->message->setReplyTo($this->convertAddressArrayToAddressList($replyTo)); } - if ($replyTo) { + if ($from) { $this->message->setFrom($this->convertAddressArrayToAddressList($from)); } if ($cc) { diff --git a/lib/internal/Magento/Framework/Mail/MimePart.php b/lib/internal/Magento/Framework/Mail/MimePart.php index 9c1047cc84c4..1ada4f5e3ad6 100644 --- a/lib/internal/Magento/Framework/Mail/MimePart.php +++ b/lib/internal/Magento/Framework/Mail/MimePart.php @@ -15,6 +15,8 @@ */ class MimePart implements MimePartInterface { + public const CHARSET_UTF8 = 'utf-8'; + /** * @var ZendMimePart */ @@ -43,13 +45,13 @@ class MimePart implements MimePartInterface */ public function __construct( $content, - ?string $type = MimeInterface::TYPE_OCTET_STREAM, + ?string $type = MimeInterface::TYPE_HTML, ?string $fileName = null, - ?string $disposition = null, - ?string $encoding = MimeInterface::ENCODING_8BIT, + ?string $disposition = MimeInterface::DISPOSITION_INLINE, + ?string $encoding = MimeInterface::ENCODING_UTF8, ?string $description = null, ?array $filters = [], - ?string $charset = null, + ?string $charset = self::CHARSET_UTF8, ?string $boundary = null, ?string $location = null, ?string $language = null, From 09cb75ec30c45aac2ba8bc6c303ffddf1bed5603 Mon Sep 17 00:00:00 2001 From: Stepan Furman <15912461+Stepa4man@users.noreply.github.com> Date: Fri, 2 Aug 2019 21:07:59 +0300 Subject: [PATCH 36/37] Update MimePart.php --- lib/internal/Magento/Framework/Mail/MimePart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/Magento/Framework/Mail/MimePart.php b/lib/internal/Magento/Framework/Mail/MimePart.php index 1ada4f5e3ad6..9b9bb6eadbec 100644 --- a/lib/internal/Magento/Framework/Mail/MimePart.php +++ b/lib/internal/Magento/Framework/Mail/MimePart.php @@ -48,7 +48,7 @@ public function __construct( ?string $type = MimeInterface::TYPE_HTML, ?string $fileName = null, ?string $disposition = MimeInterface::DISPOSITION_INLINE, - ?string $encoding = MimeInterface::ENCODING_UTF8, + ?string $encoding = MimeInterface::ENCODING_QUOTED_PRINTABLE, ?string $description = null, ?array $filters = [], ?string $charset = self::CHARSET_UTF8, From 968cbf6ce4f69bbf0e79def62173f709793e3761 Mon Sep 17 00:00:00 2001 From: Stepan Furman Date: Fri, 2 Aug 2019 22:41:42 +0300 Subject: [PATCH 37/37] MC-15295: Fix integration, attachment --- .../testsuite/Magento/Framework/Mail/EmailMessageTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php b/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php index 0d6a7824ef67..10a54b4e1b87 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Mail/EmailMessageTest.php @@ -210,6 +210,7 @@ public function testEmailMessageWithAttachment(): void 'content' => $this->getXmlContent(), 'disposition' => MimeInterface::DISPOSITION_ATTACHMENT, 'fileName' => self::ATTACHMENT_FILE_NAME, + 'encoding' => MimeInterface::ENCODING_8BIT, 'type' => self::XML_TYPE ] );