电子邮件是任何电子商务网站的重要组成部分。

Magento 2 默认提供许多电子邮件模板。我们可以在 Magento 2 管理面板中的 Sales > Communications > Email Templates 下查看所有可用电子邮件模板。单击添加模板。在加载默认模板下,可以看到模板列表

我们可以根据需要覆盖任何默认模板。也可以通过自定义模块来创建自定义电子邮件模板发送电子邮件。在本文中我们将创建新的示例模块,在模块中,我们将创建一个表单,在提交表单时,我们将通过发送自定义电子邮件发送表单信息。

模块设置:

我们将创建一个名为 Custom_Email 自定义模块。下面列出了该模块的目录结构:

  • app/code/Custom/Email/etc/module.xml  - 模块配置文件
  • app/code/Custom/Email/etc/frontend/routes.xml - 模块前端路由文件
  • app/code/Custom/Email/registration.php - 模块注册文件
  • app/code/Custom/Email/Controller - 模块控制器目录
  • app/code/Custom/Email/Block - Block文件目录
  • app/code/Custom/Email/view/frontend/layout - 布局文件目录
  • app/code/Custom/Email/view/frontend/templates - 模板文件目录
  • app/code/Custom/Email/view/frontend/email - 自定义电子邮件模板目录

介绍完模块目录结构后开始一步步的完成这个模块。

  • app/code/Custom/Email/etc 目录下创建 module.xml 文件:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Custom_Email" setup_version="0.0.1"/>
</config>

  • app/code/Custom/Email 目录下创建 registration.php 文件:
<?php
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Custom_Email',
        __DIR__
    );
    ```
  • app/code/Custom/Email/etc/frontend 目录下创建 routes.xml 路由文件:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="customemail" frontName="customemail">
            <module name="Custom_Email"/>
        </route>
    </router>
</config>

通过这个路由文件我们将模块的前端路由命名为 customemail 。每当我们访问 www.example.com/customemail/controllername 时,Magento 2 都会从模块中查找控制器文件。

  • app/code/Custom/Email/Controller/Index 目录下创建 Index.php 控制器文件:
<?php
namespace Custom\Email\Controller\Index;

class Index extends \Magento\Framework\App\Action\Action
{
    protected $resultPageFactory;

    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory)
    {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context);
    }

    public function execute()
    {
        return $this->resultPageFactory->create();
    }
}
  • app/code/Custom/Email/Block/Index 目录下创建 Index.php 块文件:
<?php
namespace Custom\Email\Block;

use Magento\Framework\View\Element\Template\Context;

class Index extends \Magento\Framework\View\Element\Template
{
    public function __construct(Context $context, array $data = [])
    {
        parent::__construct($context, $data);
    }

    public function _prepareLayout()
    {
        return parent::_prepareLayout(); // TODO: Change the autogenerated stub
    }
}
  • app/code/Custom/Email/view/frontend/layout 目录下创建 customemail_index_index 布局文件:
<?xml version="1.0" encoding="utf-8" ?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <title>Custom Contact Form</title>
    </head>
    <body>
        <referenceContainer name="content">
            <block class="Custom\Email\Block\Index" name="custom_email_index_index" template="Custom_Email::custom/email/index.phtml"/>
        </referenceContainer>
    </body>
</page>
  • app/code/Custom/Email/view/frontend/templates/custom/email 目录下创建 index.phtml 模板文件:
<?php
  /**@var Custom\Email\Block\Index $block*/
  $actionUrl = $block->getBaseUrl() . 'customemail/index/post';
?>

<form action="<?php echo $actionUrl;?>"
      name="customData"
      method="post"
      id="contactForm-1"
      data-hasrequired="<?php echo __('* Required Fields') ?>"
      data-mage-init='{"validation":{}}'>
    <fieldset class="fieldset">
        <div class="field email required">
            <label class="label" for="email"><span><?php  echo __('Name') ?></span></label>
            <div class="control">
                <input name="name"
                       id="name"
                       title="<?php echo __('Name') ?>"
                       class="input-text"
                       type="text"
                       data-validate="{required:true}"/>
            </div>
        </div>
        <div class="field email required">
            <label class="label" for="email"><span><?php  echo __('Email') ?></span></label>
            <div class="control">
                <input name="email"
                       id="email"
                       title="<?php echo __('Email') ?>"
                       class="input-text"
                       type="email"
                       data-validate="{required:true, 'validate-email':true}"/>
            </div>
        </div>
    </fieldset>
    <div class="actions-toolbar">
        <div class="primary">
            <input type="hidden" name="hideit" id="hideit" value="" />
            <button type="submit" title="<?php echo __('Submit') ?>" class="action submit primary">
                <span><?php echo __('Submit') ?></span>
            </button>
        </div>
    </div>
</form>
  • app/code/Custom/Email/etc 目录下创建 email_templates.xml 用来声明电子邮件模板:
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Email:etc/email_templates.xsd">
    <template id="customemail_email_template"
              label="Email Form"
              file="customemail.html"
              type="html"
              module="Custom_Email"
              area="frontend"/>
</config>

在这个文件中,我们声明了一个电子邮件模板 customemail.html 并声明它的ID为 customemail_email_template 。接下来创建电子邮件模板的 HTML 文件。

  • app/code/Custom/Email/view/frontend/email 目录下创建 customemail.html 文件:
  • app/code/Custom/Email/Controller/Index 目录下创建 Post.php 用来处理表单提交的数据以及发送电子邮件逻辑:
<?php
namespace Custom\Email\Controller\Index;

use Magento\Framework\App\Action\Context;
use Magento\Framework\Translate\Inline\StateInterface;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Escaper;
use Psr\Log\LoggerInterface;

class Post extends \Magento\Framework\App\Action\Action
{
    const XML_PATH_EMAIL_RECIPIENT_NAME  = 'trans_email/ident_support/name';
    const XML_PATH_EMAIL_RECIPIENT_EMAIL = 'trans_email/ident_support/email';
    const TEMPLATE_IDENTIFIER = 'customemail_email_template';

    /**
     * @var StateInterface
     */
    protected $_inlineTranslation;

    /**
     * @var TransportBuilder
     */
    protected $_transportBuilder;

    /**
     * @var ScopeConfigInterface
     */
    protected $_scopeConfig;

    /**
     * @var Escaper
     */
    protected $_escaper;

    /**
     * @var LoggerInterface
     */
    protected $_logLogger;

    /**
     * Post constructor.
     * @param Context $context
     * @param StateInterface $_inlineTranslation
     * @param TransportBuilder $_transportBuilder
     * @param ScopeConfigInterface $_scopeConfig
     * @param Escaper $_escaper
     * @param LoggerInterface $_logLoggerInterface
     */
    public function __construct(
        Context $context,
        StateInterface $_inlineTranslation,
        TransportBuilder $_transportBuilder,
        ScopeConfigInterface $_scopeConfig,
        Escaper $_escaper,
        LoggerInterface $_logLogger
    )
    {
        $this->_inlineTranslation = $_inlineTranslation;
        $this->_transportBuilder = $_transportBuilder;
        $this->_scopeConfig = $_scopeConfig;
        $this->_escaper = $_escaper;
        $this->_logLogger = $_logLogger;

        parent::__construct($context);
    }

    public function execute()
    {
        $post = $this->getRequest()->getPost();
        if (!$post) {
            return $this->_redirect('*/*/');
        }

        $this->_inlineTranslation->suspend();
        try{
            $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;

            $sender = [
                'name'  => $this->_scopeConfig->getValue(self::XML_PATH_EMAIL_RECIPIENT_NAME, $storeScope),
                'email' => $this->_scopeConfig->getValue(self::XML_PATH_EMAIL_RECIPIENT_EMAIL, $storeScope),
            ];

            $sentToEmail = $this->_escaper->escapeHtml($post['email']);
            $sentToName  = $this->_escaper->escapeHtml($post['name']);

            $transport = $this->_transportBuilder
                              ->setTemplateIdentifier(self::TEMPLATE_IDENTIFIER)
                              ->setTemplateOptions([
                                  'area'  => \Magento\Framework\App\Area::AREA_FRONTEND,
                                  'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID
                              ])
                              ->setTemplateVars([
                                  'name'  => $post['name'],
                                  'email' => $post['email'],
                              ])
                              ->setFrom($sender)
                              ->addTo($sentToEmail, $sentToName)
                              ->getTransport();
            $transport->sendMessage();

            $this->_inlineTranslation->resume();
            $this->messageManager->addSuccessMessage(
                __('Email sent successfully.')
            );
        } catch (\Exception $e) {
            $this->_inlineTranslation->resume();
            $this->messageManager->addErrorMessage($e->getMessage());
            $this->_logLogger->debug($e->getMessage());
        }

        return $this->_redirect('*/*/');
    }
}

execute 方法下,我们使用 transportBuilder 对象来编写电子邮件发送代码,我们在构造函数中注入了该对象。使用此对象,我们调用了以下几种方法来设置 相关参数。

  • setTemplateIdentifier:设置店址邮件模板标识符为 email_templates.xml
  • setTemplateOptions: 设置 area 和 当前商店代码。area 取值为 frontend (从前端发送邮件)、 admin (从后台发送邮件)。
  • setTemplateVars: 设置我们在电子邮件模板中调用的变量。
  • setFrom: 设置发件人信息。
  • addTo:添加收件人信息。
到此就完成了该模块的所有编码,接下来验证电子邮件流程。

首先运行如下命令:

php bin/magento module:enable Custom_Email
php bin/magento setup:upgrade
php bin/magento cache:clean

使用上述命令启用模块,并清除相关缓存。

  • 打开浏览器输入 www.example.com/customemail/index:
  • r