Відповіді:
M2 не виходить з коробки, однак це функція, вбудована в zend фреймворк. Ось хороша довідка, як додати цю функціональність у magento: https://blog.bitexpert.de/blog/sending-mails-with-attachments-in-magento-2/
У випадку, якщо посилання перерветься, створіть таке
<?php
namespace Your\CustomModule\Magento\Mail\Template;
class TransportBuilder
extends \Magento\Framework\Mail\Template\TransportBuilder
{
public function addAttachment(
$body,
$mimeType = Zend_Mime::TYPE_OCTETSTREAM,
$disposition = Zend_Mime::DISPOSITION_ATTACHMENT,
$encoding = Zend_Mime::ENCODING_BASE64,
$filename = null
) {
$this->message->createAttachment($body, $mimeType, $disposition, $encoding, $filename);
return $this;
}
}
потім додайте в etc / di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="\Magento\Framework\Mail\Template\TransportBuilder"
type="\Your\CustomModule\Magento\Mail\Template\TransportBuilder" />
</config>
Тепер ви можете використовувати addAttachment()
на своєму сайті.
Станом на Magento 2.2.7, описані вище рішення більше не працюють, оскільки їх \Magento\Framework\Mail\Message
розширення поширюється \Zend_Mail
.
Щоб обійти відсутність простого способу додавання вкладених файлів через конструктор транспорту (який, здається, зараз є правильним місцем для такої функції), потрібно створити заміну на TransportBuilder і скористатися цим \Zend\Mime\Part
:
<?php
namespace Your\CustomModule\Magento\Mail\Template;
use Magento\Framework\Mail\MessageInterface;
use Magento\Framework\Mail\MessageInterfaceFactory;
use Magento\Framework\Mail\Template\FactoryInterface;
use Magento\Framework\Mail\Template\SenderResolverInterface;
use Magento\Framework\Mail\TransportInterfaceFactory;
use Magento\Framework\ObjectManagerInterface;
use Zend\Mime\Mime;
use Zend\Mime\Part as MimePart;
use Zend\Mime\PartFactory as MimePartFactory;
use Zend\Mime\Message as MimeMessage;
use Zend\Mime\MessageFactory as MimeMessageFactory;
class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
/** @var MimePart[] */
private $parts = [];
/** @var MimeMessageFactory */
private $mimeMessageFactory;
/** @var MimePartFactory */
private $mimePartFactory;
public function __construct(
FactoryInterface $templateFactory,
MessageInterface $message,
SenderResolverInterface $senderResolver,
ObjectManagerInterface $objectManager,
TransportInterfaceFactory $mailTransportFactory,
MimePartFactory $mimePartFactory,
MimeMessageFactory $mimeMessageFactory,
MessageInterfaceFactory $messageFactory = null
) {
parent::__construct(
$templateFactory,
$message,
$senderResolver,
$objectManager,
$mailTransportFactory,
$messageFactory
);
$this->mimePartFactory = $mimePartFactory;
$this->mimeMessageFactory = $mimeMessageFactory;
}
protected function prepareMessage()
{
parent::prepareMessage();
$mimeMessage = $this->getMimeMessage($this->message);
foreach ($this->parts as $part) {
$mimeMessage->addPart($part);
}
$this->message->setBody($mimeMessage);
return $this;
}
public function addAttachment(
$body,
$mimeType = Mime::TYPE_OCTETSTREAM,
$disposition = Mime::DISPOSITION_ATTACHMENT,
$encoding = Mime::ENCODING_BASE64,
$filename = null
) {
$this->parts[] = $this->createMimePart($body, $mimeType, $disposition, $encoding, $filename);
return $this;
}
private function createMimePart(
$content,
$type = Mime::TYPE_OCTETSTREAM,
$disposition = Mime::DISPOSITION_ATTACHMENT,
$encoding = Mime::ENCODING_BASE64,
$filename = null
) {
/** @var MimePart $mimePart */
$mimePart = $this->mimePartFactory->create(['content' => $content]);
$mimePart->setType($type);
$mimePart->setDisposition($disposition);
$mimePart->setEncoding($encoding);
if ($filename) {
$mimePart->setFileName($filename);
}
return $mimePart;
}
private function getMimeMessage(MessageInterface $message)
{
$body = $message->getBody();
if ($body instanceof MimeMessage) {
return $body;
}
/** @var MimeMessage $mimeMessage */
$mimeMessage = $this->mimeMessageFactory->create();
if ($body) {
$mimePart = $this->createMimePart((string)$body, Mime::TYPE_TEXT, Mime::DISPOSITION_INLINE);
$mimeMessage->setParts([$mimePart]);
}
return $mimeMessage;
}
}
Не забудьте замінити оригінал \Magento\Framework\Mail\Template\TransportBuilder
вашою реалізацією через di.xml
.
Зауважте, що ця реалізація, ймовірно, порушиться з майбутнім випуском Magento, оскільки \Magento\Framework\Mail\MessageInterface::setBody()
він застарілий і може бути скоро видалений.
HTH
Magento 2 Спеціальний електронний лист від модуля, не надає вкладення зображень.
Якщо ви хочете використовувати вкладення зображень із шаблонами електронної пошти в Magento 2, вам потрібно перекрити клас, Magento \ Framework \ Mail \ Template \ TransportBuilder
Magento Out-of-box не забезпечує функцію вкладення електронної пошти. Ви можете переглядати блоги для надсилання вкладених зображень у деталях,
Вам потрібно додати логіку, як нижче,
public function addAttachment(
$body,
$mimeType = \Zend_Mime::TYPE_OCTETSTREAM,
$disposition = \Zend_Mime::DISPOSITION_ATTACHMENT,
$encoding = \Zend_Mime::ENCODING_BASE64,
$filename = null
) {
$this->message->createAttachment($body, $mimeType, $disposition, $encoding, $filename);
return $this;
}
Ось ідеальна відповідь, щоб надіслати PDF в електронній пошті magetno 2.3
$transport = $_transportBuilder->setTemplateIdentifier(20)
->setTemplateOptions($templateOptions)
->setTemplateVars($templateVars)
->setFrom($from)
->addTo($vendor_email)
->getTransport();
$html = $transport->getMessage()>getBody()->generateMessage();
$bodyMessage = new \Zend\Mime\Part($html);
$bodyMessage->type = 'text/html';
$attachment = $_transportBuilder->addAttachment($pdfData,$fileName);
$bodyPart = new \Zend\Mime\Message();
$bodyPart->setParts(array($bodyMessage,$attachment));
$transport->getMessage()->setBody($bodyPart);
$transport->sendMessage();
$inlineTranslation->resume();
Це була моя відповідь на Magento 2.3, оскільки це було головне питання в Google, і, здається, в коментарях багато людей шукають.
Здається, в інших публікаціях є багато бажання щодо перезапису TransportBuilder
класу за замовчуванням через etc/di.xml
, проте модуль, над яким я працюю, настільки малий, що я не хочу, щоб він відповідав за замовчуванням, TransportBuilder
тому я створив клас Helper (повинен Можливо, це буде модель, заснована на тому, наскільки вона поєднана із заявленим шаблоном електронної пошти, але я відхиляюся).
У TransportBuilder
нього немає публічного доступу до TransportInterface
, але натомість генерує клон щоразу і потім скидає програму. Мені було легше побудувати свій TransportInterface
екземпляр, а потім прикріпити свої Part
об’єкти вкладення до повідомлення транспорту. Якщо ви вважаєте за потрібне перезаписати типові за TransportBuilder
допомогою налаштування ін'єкції залежності, будьте обережні щодо оновлення загальнодоступних методів. Не забудьте попрактикуватись O, зберігаючи свій код ТВЕРДО !
namespace Vendor\Module\Helper;
use Magento\Framework\App\Area;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Framework\DataObject;
use Magento\Framework\Filesystem\Io\File;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Mail\TransportInterface;
use Magento\Store\Model\StoreManagerInterface;
use Zend_Mime;
use Zend\Mime\Part;
/**
* This was initially built out to send a single email. Abstract this as you
* wish.
*
* @package Vendor\Module\Helper
*/
class Mail extends AbstractHelper
{
/**
* @var Context
*/
protected $context;
/**
* @var TransportBuilder
*/
protected $transportBuilder;
/**
* @var StoreManagerInterface
*/
protected $storeManager;
/**
* @var Config
*/
protected $config;
/**
* Mail constructor.
*
* @param Context $context
* @param TransportBuilder $transportBuilder
* @param StoreManagerInterface $storeManager
* @param Config $config
* @param File $file
*/
public function __construct(
Context $context,
TransportBuilder $transportBuilder,
StoreManagerInterface $storeManager,
Config $config,
File $file
) {
parent::__construct($context);
$this->transportBuilder = $transportBuilder;
$this->storeManager = $storeManager;
$this->config = $config;
$this->file = $file;
}
/**
* Send the email for a Help Center submission.
*
* @param DataObject $templateParams
* @param array $attachments
* @return void
*/
public function send(DataObject $templateParams, array $attachments = [])
{
$storeId = $this->storeManager->getStore()->getId();
// Build transport
/** @var \Magento\Framework\Mail\TransportInterface $transport */
$transport = $this->transportBuilder
->setTemplateOptions(['area' => Area::AREA_FRONTEND, 'store' => $storeId])
->setTemplateIdentifier($this->config->getEmailTemplate())
->setTemplateVars($templateParams->toArray())
->setFrom($this->config->getEmailSender())
->addTo($this->config->getEmailRecipient(), 'Help Center')
/**
* Something important to note is that when the getTransport()
* function is run, the message is compiled and then the builder
* class resets (as of 2.3.1).
*
* This is note worthy because if you want to send > 1 attachment,
* your $builder will be reset -- losing all of the ->set* functions
* you just used above as well as your attachment.
*
* Since we append attachments to the transport, it's easier to:
* build -> attach -> send. And this way multiple attachments
* can be included. :thumbsup:
*/
->getTransport();
// Attach Images to transport
foreach ($attachments as $a) {
$transport = $this->addAttachment($transport, $a);
}
// Send transport
$transport->sendMessage();
}
/**
* Add an attachment to the message inside the transport builder.
*
* @param TransportInterface $transportBuilder
* @param array $file Sanitized index from $_FILES
* @return TransportInterface
*/
protected function addAttachment(TransportInterface $transport, array $file): TransportInterface
{
$part = $this->createAttachment($file);
$transport->getMessage()->addPart($part);
return $transport;
}
/**
* Create an zend mime part that is an attachment to attach to the email.
*
* This was my usecase, you'll need to edit this to your own needs.
*
* @param array $file Sanitized index from $_FILES
* @return Part
*/
protected function createAttachment(array $file): Part
{
$ext = '.' . explode('/', $file['type'])[1];
$fileName = md5(uniqid(microtime()), true) . $ext;
$attachment = new Part($this->file->read($file['tmp_name']));
$attachment->disposition = Zend_Mime::TYPE_OCTETSTREAM;
$attachment->encoding = Zend_Mime::ENCODING_BASE64;
$attachment->filename = $fileName;
return $attachment;
}
}
MessageInterface::getBody
Метод підпис показує строковий тип повертається значення . Можливо, вам доведеться копатися у вашому TransportInterface
об’єкті, але я можу вам сказати, що addPart
метод існує на Zend\Mime\Message
об’єкті. Оскільки Маженто, ймовірно, продовжив цей клас на свій Message
клас, я думаю, було б розумно спробувати$transport->getMessage()->addpart($part);
Як уже згадувалося в попередніх відповідях, magento2 не має функції поза скринькою для надсилання повідомлень із вкладеннями.
Я не знаю, чи це найкраща практика, але ви можете зателефонувати безпосередньо Zend_Mail
класу, щоб це зробити, без створення спеціальної функції та перестановки Magento\Framework\Mail\Template\TransportBuilder
, як нижче
$mail = new \Zend_Mail('utf-8');
$mail->setFrom($senderEmail);
$mail->addTo($receiverEmail);
$mail->setSubject($subject);
$mail->setBodyHtml($text);
$content = file_get_contents($attachmentAbsolutePath);
$attachment = new \Zend_Mime_Part($content);
$attachment->type = 'text/xml'; // attachment's mime type
$attachment->disposition = \Zend_Mime::DISPOSITION_ATTACHMENT;
$attachment->encoding = \Zend_Mime::ENCODING_BASE64;
$attachment->filename = $filename;
$mail->addAttachment($attachment);
$mail->send();