Réponses:
M2 n'est pas livré avec, mais c'est une fonctionnalité intégrée au framework zend. Voici une bonne référence pour ajouter cette fonctionnalité dans magento: https://blog.bitexpert.de/blog/sending-mails-with-attachments-in-magento-2/
Dans le cas où le lien devient mort, créez ce qui suit
<?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;
}
}
puis ajoutez à 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>
Maintenant, vous pouvez utiliser addAttachment()
tout au long de votre site.
Depuis Magento 2.2.7, les solutions décrites ci-dessus ne fonctionnent plus depuis l' \Magento\Framework\Mail\Message
extension abandonnée \Zend_Mail
.
Pour contourner le manque d'un moyen facile d'ajouter des pièces jointes via le constructeur de transport (qui semble actuellement être le bon endroit pour une telle fonction), il faut créer un remplacement pour TransportBuilder et utiliser \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;
}
}
N'oubliez pas de remplacer l'original \Magento\Framework\Mail\Template\TransportBuilder
par votre implémentation via di.xml
.
Notez que cette implémentation rompra probablement avec une prochaine version de Magento car elle \Magento\Framework\Mail\MessageInterface::setBody()
est obsolète et peut être supprimée bientôt.
HTH
Magento 2 Courriel personnalisé du module, ne fournit pas de pièce jointe d'image.
Si vous souhaitez utiliser la pièce jointe Image avec des modèles d'e-mail dans Magento 2, vous devez remplacer la classe, Magento \ Framework \ Mail \ Template \ TransportBuilder
Magento Out-of-box ne fournit pas de fonction de pièce jointe pour les e-mails. Vous pouvez parrainer des blogs pour envoyer des images jointes en détail,
Vous devez ajouter une logique comme ci-dessous,
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;
}
Voici la réponse parfaite pour envoyer un pdf par e-mail dans 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();
Ce fut ma réponse pour Magento 2.3 car c'était une question majeure sur Google et il semble y avoir beaucoup de gens dans les commentaires.
Il semble y avoir beaucoup de désir dans d'autres articles sur le remplacement de la TransportBuilder
classe par défaut viaetc/di.xml
, mais le module sur lequel je travaille est si petit que je ne veux pas qu'il soit responsable de la valeur par défaut TransportBuilder
, j'ai donc construit une classe Helper (devrait être probablement un modèle basé sur la façon dont il est couplé au modèle d'e-mail déclaré - mais je m'écarte).
Le TransportBuilder
n'a pas d'accès public à TransportInterface
, mais génère à la place un clone à chaque fois, puis réinitialise le générateur. J'ai trouvé plus facile de créer mon TransportInterface
instance, puis d'attacher mes Part
objets attachés au message du transport. Si vous trouvez nécessaire d'écraser la valeur TransportBuilder
par défaut via la préférence d'injection de dépendance, faites attention à la mise à jour des méthodes publiques. N'oubliez pas de pratiquer le O lorsque vous gardez votre code SOLIDE !
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
signature de méthode montre un type de retour de chaîne. Vous devrez peut-être fouiller dans votre TransportInterface
objet, mais je peux vous dire que la addPart
méthode existe sur un Zend\Mime\Message
objet. Puisque magento a probablement étendu cette classe pour leur propre Message
classe, je pense qu'il serait intelligent d'essayer$transport->getMessage()->addpart($part);
Comme mentionné dans les réponses précédentes, magento2 n'a pas de fonction prête à l'emploi pour envoyer des e-mails avec des pièces jointes.
Je ne sais pas si c'est une meilleure pratique, mais vous pouvez appeler directement la Zend_Mail
classe pour le faire, sans créer de fonction personnalisée et remplacer Magento\Framework\Mail\Template\TransportBuilder
, comme ci-dessous
$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();