วิธีส่งอีเมลพร้อมไฟล์แนบ
วิธีส่งอีเมลพร้อมไฟล์แนบ
คำตอบ:
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()
ทั่วทั้งไซต์ของคุณ
ในฐานะของวีโอไอพี 2.2.7 การแก้ปัญหาที่อธิบายไว้ข้างต้นไม่ทำงานอีกต่อไปตั้งแต่ลดลงขยาย\Magento\Framework\Mail\Message
เพื่อหลีกเลี่ยงการขาดวิธีง่ายๆในการเพิ่มสิ่งที่แนบผ่านตัวสร้างการขนส่ง (ซึ่งปัจจุบันดูเหมือนจะเป็นสถานที่ที่ถูกต้องสำหรับฟังก์ชั่นดังกล่าว) เราจำเป็นต้องสร้างสิ่งทดแทนสำหรับ TransportBuilder และใช้งาน:\Zend_Mail
\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\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();