1

I'm trying to create a custom mail form on Magento 2.2.x. I have looked at several instructions for Magento 2.0.x and/or Magento 2.1.x but they dont seem to work anymore for Magento 2.2.x. Perhaps someone can shed some light on this. The code of my controller in /app/code/Vendor/Module/controller/index/post.php looks like this:

namespace Vendor\Module\Controller\Index;

use Magento\Framework\App\Action\Context;
use Magento\Framework\Mail\Template\TransportBuilder;

class Post extends \Magento\Framework\App\Action\Action
{
    /**
     * @var TransportBuilder
     */
    private $transportBuilder;

    /**
     * @param Context $context
     * @param TransportBuilder $transportBuilder
     */
    public function __construct(
        Context $context,
        TransportBuilder $transportBuilder
    ) {
        parent::__construct($context);
        $this->transportBuilder = $transportBuilder;
    }

    /**
     * Post user question.
     *
     * @return void
     */
    public function execute()
    {
        $post = $this->getRequest()->getPostValue();
        if (!$post) {
            $this->_redirect('*/*/');
            return;
        }

        try {
            $postObject = new \Magento\Framework\DataObject();
            $postObject->setData($post);

            $error = false;

            if (!\Zend_Validate::is(trim($post['name']), 'NotEmpty')) {
                $error = true;
            }
            if (!\Zend_Validate::is(trim($post['comment']), 'NotEmpty')) {
                $error = true;
            }
            if (!\Zend_Validate::is(trim($post['email']), 'EmailAddress')) {
                $error = true;
            }
            if (\Zend_Validate::is(trim($post['hideit']), 'NotEmpty')) {
                $error = true;
            }
            if ($error) {
                throw new \Exception();
            }

            $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;
            $transport = $this->transportBuilder
                ->setTemplateIdentifier($this->scopeConfig->getValue(self::XML_PATH_EMAIL_TEMPLATE, $storeScope))
                ->setTemplateOptions(
                    [
                        'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE,
                        'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID,
                    ]
                )
                ->setTemplateVars(['data' => $postObject])
                ->setFrom($this->scopeConfig->getValue(self::XML_PATH_EMAIL_SENDER, $storeScope))
                ->addTo($this->scopeConfig->getValue(self::XML_PATH_EMAIL_RECIPIENT, $storeScope))
                ->setReplyTo($post['email'])
                ->getTransport();

            $transport->sendMessage();

            $this->messageManager->addSuccessMessage(
                __('Thanks for contacting us with your feedback or questions. We\'ll respond to you very soon.')
            );
            $this->_redirect($post['redirect']);
            return;
        } catch (\Exception $e) {
            $this->messageManager->addErrorMessage(
                __('We can\'t process your request right now. Sorry, that\'s all we know.')
            );
            $this->messageManager->addErrorMessage($e->getMessage());
            $this->_redirect($post['redirect']);
            return;
        }
    }

}

This generates the error:

Fatal error: Uncaught ArgumentCountError: Too few arguments to function Vendor\Module\Controller\Index\Feedback::__construct(), 1 passed in \generated\code\Vendor\Module\Controller\Index\Feedback\Interceptor.php on line 14 and exactly 2 expected in \app\code\Vendor\Module\Controller\Index\Post.php:29 Stack trace: #0 \generated\code\Vendor\Module\Controller\Index\Feedback\Interceptor.php(14): Vendor\Module\Controller\Index\Feedback->__construct(Object(Magento\Framework\App\Action\Context)) #1 \lib\internal\Magento\Framework\ObjectManager\Factory\AbstractFactory.php(111): Vendor\Module\Controller\Index\Feedback\Interceptor->__construct(Object(Magento\Framework\App\Action\Context)) #2 \lib\internal\Magento\Framework\ObjectMa in \app\code\Vendor\Module\Controller\Index\Post.php on line 29

Leaving TransportBuilder out of the constructor gives the following error:

Notice: Undefined property: Vendor\Module\Controller\Index\Post\Interceptor::$transportBuilder in E:\Localhost\www\magento2\versie22\app\code\Vendor\Module\Controller\Index\Post.php on line 68

Any help to get a custom email form on Magento 2.2.x working is appreciated.

2
  • can you say why you are building the custom mail form?
    – Ahdee
    Sep 25, 2017 at 0:35
  • I'm creating a feedback form on the checkout success page allowing customers that have made an order to send feedback through this email form.
    – Solide
    Sep 25, 2017 at 16:52

1 Answer 1

1

Probably not the most elegant solution but this is how I got it working on Magento v2.2.x

namespace Vendor\Module\Controller\Index;

use Magento\Framework\App\Action\Context;
use Magento\Contact\Model\ConfigInterface;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Translate\Inline\StateInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\App\ObjectManager;

class Post extends \Magento\Contact\Controller\Index
{

    const XML_PATH_EMAIL_RECIPIENT = 'contact/email/recipient_email';
    const XML_PATH_EMAIL_SENDER = 'contact/email/sender_email_identity';
    const XML_PATH_EMAIL_TEMPLATE = 'contact/email/email_template';

    private $context;
    private $transportBuilder;
    private $inlineTranslation;
    protected $scopeConfig;
    private $storeManager;

    public function __construct(
        Context $context,
        ConfigInterface $contactsConfig,
        TransportBuilder $transportBuilder,
        StateInterface $inlineTranslation,
        ScopeConfigInterface $scopeConfig,
        StoreManagerInterface $storeManager = null
    ) {
        parent::__construct($context, $contactsConfig);
        $this->context = $context;
        $this->transportBuilder = $transportBuilder;
        $this->inlineTranslation = $inlineTranslation;
        $this->scopeConfig = $scopeConfig;
        $this->storeManager = $storeManager ?:
            ObjectManager::getInstance()->get(StoreManagerInterface::class);
    }

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

        $this->inlineTranslation->suspend();

        try {
            $postObject = new \Magento\Framework\DataObject();
            $postObject->setData($post);

            $error = false;

            if (!\Zend_Validate::is(trim($post['name']), 'NotEmpty')) {
                $error = true;
            }
            if (!\Zend_Validate::is(trim($post['comment']), 'NotEmpty')) {
                $error = true;
            }
            if (!\Zend_Validate::is(trim($post['email']), 'EmailAddress')) {
                $error = true;
            }
            if (\Zend_Validate::is(trim($post['hideit']), 'NotEmpty')) {
                $error = true;
            }
            if ($error) {
                throw new \Exception();
            }

            $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;
            $transport = $this->transportBuilder
                ->setTemplateIdentifier($this->scopeConfig->getValue(self::XML_PATH_EMAIL_TEMPLATE, $storeScope))
                ->setTemplateOptions(
                    [
                        'area' => 'frontend',
                        'store' => $this->storeManager->getStore()->getId()
                    ]
                )
                ->setTemplateVars(['data' => $postObject])
                ->setFrom($this->scopeConfig->getValue(self::XML_PATH_EMAIL_SENDER, $storeScope))
                ->addTo($this->scopeConfig->getValue(self::XML_PATH_EMAIL_RECIPIENT, $storeScope))
                ->setReplyTo($post['email'], $post['name'])
                ->getTransport();

            $transport->sendMessage();
            $this->inlineTranslation->resume();
            $this->messageManager->addSuccessMessage(
                __('Thanks for contacting us with your feedback or questions. We\'ll respond to you very soon.')
            );
            $this->_redirect($post['redirect']);
            return;
        } catch (\Exception $e) {
            $this->messageManager->addErrorMessage(
                __('We can\'t process your request right now. Sorry, that\'s all we know.')
            );
            $this->_redirect($post['redirect']);
            return;
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.