마 젠토 2 : 첨부 파일로 이메일 보내기


답변:


19

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()전체 사이트에서 사용할 수 있습니다.


8
나는 아직도 젠토의 TransportBuilder이 방법이없는 이유를 궁금해
Murtuza Zabuawala

4
어떻게 사용자 정의 이메일 magento 2.3에 파일을 첨부 할 수 있습니까? zendframework 2를 사용하고이 답변이 더 이상 작동하지 않기 때문에
Manish Maheshwari

3
Magento 2.3에서 첨부 파일로 이메일을 보내는 방법은 무엇입니까?
Dhaduk Mitesh

@ManishMaheshwari & Mitesh 해결책이 있습니까?
Sameer Bhayani

1
이 솔루션은 더 이상 Magento2.3에서 작동하지 않습니다. 누구든지 첨부 파일에 대한 대안이 있습니까?
nishu

8

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\Framework\Mail\MessageInterface::setBody()되지 않을 Magento 릴리스에서 중단 될 수 있으며 곧 제거 될 수 있습니다.

HTH


안녕하세요! 코드에 addAttachment 메소드가 있지만 어디에서 호출 했습니까? 나는 그것을 보지 못한다.
Nikolai Silin

감사! PreparingMessage 메소드와 everithing 작업에 루프를 추가했습니다.
Nikolai Silin

@NikolaiSilin PNG 또는 다른 파일을 보내는 방법.
sumeet bajaj 2016 년

1

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;
    }

1
당신은 magento 2.3에서 동일한 달성을 도울 수 있습니까?
Sameer Bhayani

2.2.7까지 이러한 방식으로 첨부 파일을 작성했습니다. 2.2.8 및 2.3+가 작동하지 않음
Matthias Kleine

난 단지 인 2.3.x @MatthiasKleine에 대한 답변을 게시
domdambrogia

안녕하세요, base64 인코딩 문자열이 있으면 어떻게 첨부 할 수 있습니까?
Ketan Borada

1

magetno 2.3의 이메일로 pdf를 보내려면 완벽한 답변이 있습니다.

$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();

안녕하세요, 그것은 치명적인 오류를 던지고있다 : catch되지 않은 오류 : 전화 멤버 함수 generateMessage ()에 널 (null)에
gajjala하기 Sandeep

트랜스 포트에 이미 메시지가있을 때 불필요한 새 메시지를 작성 중입니다. 왜 제자리에 부품을 추가하지 않습니까? 이것은 지저분하고 따르기가 어렵습니다. 이 문제를 해결하는 데 필요한 작업과 메모리를 두 배로 늘리는 것은 말할 것도 없습니다.
domdambrogia

1

마 젠토 2.3.x 호환 :

이것은 구글에서 가장 인기있는 질문이므로 Magento 2.3에 대한 나의 대답이었습니다. 댓글에 많은 사람들이있는 것처럼 보입니다.

TransportBuilder를 통해 기본 클래스를 덮어 쓰는 것에 대한 다른 게시물에는 많은 욕망이있는 것 같습니다 etc/di.xml.하지만 작업중 인 모듈이 너무 작아서 기본값을 담당하지 않기 TransportBuilder위해 도우미 클래스를 만들었습니다. 아마도 선언 된 전자 메일 템플릿과 어떻게 연결되어 있는지에 따라 모델 일 수 있습니다.

에 대한 TransportBuilder공개 액세스 권한이 TransportInterface없지만 대신 클론을 생성 한 다음 빌더를 재설정합니다. TransportInterface인스턴스 를 구축 한 다음 첨부 파일 Part을 전송 메시지에 첨부 하는 것이 더 쉽다는 것을 알았습니다 . TransportBuilder종속성 주입 환경 설정을 통해 기본값을 겹쳐 써야하는 경우 공용 메소드 업데이트에주의하십시오. 코드를 SOLID로 유지할 때는 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;
    }
}

나는 그것이 제대로 작동하도록 할 수 없다, 나는 항상 "잡히지 않는 오류 : 문자열에서 멤버 함수 addPart ()에 대한 호출"이라는 예외를 얻는다 ... 그것에 대한 어떤 생각? : /
hallleron

1
@hallleron 이상하게도 이것이 내가 얻는 것과는 다르지만, 당신이 옳은 것처럼 보입니다. MessageInterface::getBody메소드 서명은 문자열 반환 형식을 보여줍니다. TransportInterface객체 를 파헤쳐 야 할 수도 있지만 addPart메소드가 Zend\Mime\Message객체 에 있다고 말할 수 있습니다 . 마 젠토 때문에 가능성 자체에 대한 클래스 것으로 확장 Message클래스는, 나는 그것을 시도하는 스마트있을 거라고 생각$transport->getMessage()->addpart($part);
domdambrogia

0

이전 답변에서 언급했듯이 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();

-1을주기 전에,이 코멘트 텍스트 영역을 사용하는 것이 좋습니다. 그러면 모든 사람들이 무엇이 잘못되었는지 이해할 수 있습니다
LucScu

$ transport-> getMessage ()-> setBody ($ bodyPart);
imtiazau

이 catch되지 않은 오류가 점점 : 정의되지 않은 메서드 젠토 \\ 프레임 워크 \\ 메일 \\ EmailMessage에 전화 : setBody를 ()
imtiazau

이 의견은 답변과 관련이 없습니다
LucScu

나는 magento 2.3.3 에서이 오류가 발생합니다
imtiazau
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.