1

How to create a custom form for sending email in Magento 2

Fields are like

  • First name
  • Last name
  • Address
  • City
  • State
  • Zip code
  • Email
  • Phone
  • Product type: checkbox Option like (1) One (2) Two
  • File upload
  • comment
3

4 Answers 4

18

Try below code in your controller

vendorname/modulename/controller/Index/index.php

<?php
/**
 *
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Vendor\Module\Controller\Index;


use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem;
use Magento\Framework\App\Request\DataPersistorInterface;


class Index extends Action
{
    private $dataPersistor;
    /**
     * @return \Magento\Framework\Controller\Result\Redirect|\Magento\Framework\View\Result\Page
     */

    protected $context;
    private $fileUploaderFactory;
    private $fileSystem;


    /**
     * @var \Magento\Framework\Mail\Template\TransportBuilder
     */
    protected $_transportBuilder;

    /**
     * @var \Magento\Framework\Translate\Inline\StateInterface
     */
    protected $inlineTranslation;

    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $scopeConfig;

    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */


    /**
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
     * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation
     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
     */

     public function __construct(
        \Magento\Framework\App\Action\Context $context,
        Filesystem $fileSystem,
        \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory,
        \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder,
        \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
        \Modia\Cform\Helper\Data $helper,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    ) {
        parent::__construct($context,$transportBuilder,$inlineTranslation, $scopeConfig );
        $this->fileUploaderFactory = $fileUploaderFactory;
        $this->fileSystem          = $fileSystem;
        $this->_transportBuilder = $transportBuilder;
        $this->inlineTranslation = $inlineTranslation;
        $this->helper = $helper;
        $this->scopeConfig = $scopeConfig;
    }

    public function execute()
    {

        $post = $this->getRequest()->getPostValue();
        $filesData = $this->getRequest()->getFiles('upload_document');

        if ($filesData['name']) {
         $uploader = $this->fileUploaderFactory->create(['fileId' => 'upload_document']);
         $uploader->setAllowRenameFiles(true);
         $uploader->setFilesDispersion(true);
         $uploader->setAllowCreateFolders(true);
         $path = $this->fileSystem->getDirectoryRead(DirectoryList::MEDIA)->getAbsolutePath('test-doc');
         $result = $uploader->save($path);
         $upload_document = 'test-doc'.$uploader->getUploadedFilename();
         $filePath = $result['path'].$result['file'];
         $fileName = $result['name'];
    } else {
         $upload_document = '';
         $filePath = '';
         $fileName = '';
    }

        $txt='<table>';

        if($post['fname']){         
            $txt.='<tr><td><strong>Client Name</strong>:'.$post['fname'].'</td></tr>';          
        }
        if($post['address']){           
            $txt.='<tr><td><strong>Address</strong>:'.$post['address'].'</td></tr>';            
        }
        if($post['city']){
            $txt.='<tr><td><strong>City</strong>:'.$post['city'].'</td></tr>';
        }
        if($post['state']){
            $txt.='<tr><td><strong>State/Province</strong>:'.$post['state'].'</td></tr>';
        }
        if($post['zipcode']){
            $txt.='<tr><td><strong>Zip Code</strong>:'.$post['zipcode'].'</td></tr>';
        }
        if($post['phone']){
            $txt.='<tr><td><strong>Phone</strong>:'.$post['phone'].'</td></tr>';
        }
        if($post['email']){
            $txt.='<tr><td><strong>Email</strong>:'.$post['email'].'</td></tr>';
        }
        if(!empty($post['project_type'])){      
            $projecttypearray = implode(",",$post['project_type']);     
            $txt.='<tr><td><strong>Project Type</strong>:'.$projecttypearray.'</td></tr>';          
        }

        if($post['comment']){
            $txt.='<tr><td><strong>Comment</strong>:'.$post['comment'].'</td></tr>';
        }
        $txt.='</table>';
        //echo $txt;



        $customerName='Demo Form';
        $message=$txt;

        $userSubject= 'Demo From ';     
        $fromEmail= '[email protected]';
        $fromName = 'Test Demo Form';

         $templateVars = [
                    'store' => 1,
                    'customer_name' => $customerName,
                    'subject' => $userSubject,
                    'message'   => $message
                ];
        $from = ['email' => $fromEmail, 'name' => $fromName];
        $this->inlineTranslation->suspend();


        $to = '[email protected]';     

        $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;

         $templateOptions = [
          'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
          'store' => 1
        ];

        $transport = $this->_transportBuilder->setTemplateIdentifier(5, $storeScope)
                ->setTemplateOptions($templateOptions)
                ->setTemplateVars($templateVars)
                ->setFrom($from)
                ->addTo($to)
                ->addAttachment($filePath, $fileName)               
                ->getTransport();
        $transport->sendMessage();
        $this->inlineTranslation->resume();

        $this->messageManager->addSuccess(__('Form successfully submitted'));

        $this->_redirect('form');
    }

}

vendorname/modulename/etc/di.xml

 <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="\Vendorname\Modulename\Magento\Mail\Template\TransportBuilder" />
</config>

Vendorname/Modulename/Magento/Mail/Template/TransportBuilder.php

<?php
namespace Vendorname\Modulename\Magento\Mail\Template;

class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
    public function addAttachment($file, $name)
    {
        if (!empty($file) && file_exists($file)) {
            $this->message
            ->createAttachment(
                file_get_contents($file),
                \Zend_Mime::TYPE_OCTETSTREAM,
                \Zend_Mime::DISPOSITION_ATTACHMENT,
                \Zend_Mime::ENCODING_BASE64,
                basename($name)
            );
        }
        return $this;
    }
}

Vendorname/Modulename/view/frontend/templates/test.phtml

 <div class="container">
    <form class="form-horizontal" method="post" enctype="multipart/form-data" action="url/cform/index/index">
        <div class="form-group">    
            <div class="row">
                <div class="col-sm-12">
                    <label for="">Name</label>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-6">
                    <input class="form-control" type="text" id="" name="fname" placeholder="first name">
                </div>
                <div class="col-sm-6">
                    <input class="form-control" type="text" id="" name="lname" placeholder="last name">
                </div>          
            </div>
        </div>

        <div class="form-group">
            <label for="">Address</label>
            <textarea class="col-sm-12 form-control" rows="3" placeholder="" name="address"></textarea>
        </div>

        <div class="form-group">
            <div class="row">
                <div class="col-sm-5">
                    <label for="">City</label>
                    <input class="form-control" type="text" name="city" id="" placeholder="">
                </div>
                <div class="col-sm-4">
                    <label for="">State/Province</label>
                    <input class="form-control" type="text" name="state" id="" placeholder="">
                </div>
                <div class="col-sm-3">
                    <label for="">Zip Code</label>
                    <input class="form-control" type="text" name="zipcode" id="" placeholder="">
                </div>
            </div>
        </div>

        <div class="form-group">
            <div class="row">
                <div class="col-sm-8">
                    <label for="">Phone</label>
                        <div class="row">
                            <div class="col-sm-5">
                                <input class="form-control" type="text" id="" name="phone" placeholder="">
                            </div>  
                            <div class="col-sm-2 phone-or">
                                <span>OR</span>
                            </div>  
                            <div class="col-sm-5">
                                <input class="form-control" type="text" id="" placeholder="">
                            </div>  
                        </div>
                </div>
                <div class="col-sm-4">
                    <label for="">Email</label>
                    <input class="form-control" type="email" id="email" name="email" placeholder="">
                </div>
            </div>
        </div>

        <div class="form-group">
            <div class="row">
                <div class="col-sm-2">
                    <label for="">Project Type :</label>
                </div>
                <div class="col-sm-10">
                    <label class="checkbox-inline"> 
                        <input type="checkbox" id="" value="One1" name="project_type[]"> <span>Residential</span> 
                    </label> 
                    <label class="checkbox-inline"> 
                        <input type="checkbox" id="" value="One2" name="project_type[]"> <span>Commercial</span>
                    </label>        
                </div>      
            </div>
        </div>

        <div class="col-md-4 col-xs-12">
            <input accept="image/*" name="upload_document" type="file" value="" />
        </div>

        <div class="form-group">
            <div class="row">
                <div class="col-sm-2">
                    <label for="">Comment :</label>
                </div>
                <div class="col-sm-10">
                    <textarea class="form-control comment" rows="3" name="comment" placeholder="additional information about your project"></textarea>  
                </div>
            </div>
        </div>

        <div class="row">
                <button type="submit" class="btn btn-primary">SUBMIT</button>
        </div>

    </form>
</div>

Now call in cms page

{{block class="Magento\Framework\View\Element\Template" template="Vendorname_Modulename::test.phtml" }}
2
  • I tried this code but it's not working
    – kiran
    Commented Oct 4, 2018 at 16:43
  • 1
    This answer is very lacking in context and it has multiple errors in it, but I eventually debugged every error and filled in all the gaps to get it to work somehow.
    – Asitis
    Commented Nov 15, 2019 at 13:54
2

app/code/Vendor/Cform/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="Vendor_Cform" setup_version="2.2.0">
        
    </module>
</config>

app/code/Vendor/Cform/registration.php

<?php

    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Vendor_Cform',
        __DIR__
    );

app/code/Vendor/Cform/etc/frontend/routes.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="standard">
        <route id="cform" frontName="cform">
            <module name="Vendor_Cform" />
        </route>
    </router>
</config>

app/code/Vendor/Cform/Setup/InstallSchema.php

<?php
namespace Vendor\Cform\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;

/**
 * @codeCoverageIgnore
 */
class InstallSchema implements InstallSchemaInterface
{
    
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;
        $installer->startSetup();
        /**
         * Create table 'vendor_contect'
         */
        $table = $installer->getConnection()->newTable(
            $installer->getTable('vendor_contect')
        )->addColumn(
            'contect_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
            null,
            ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
            'Contect Id'
        )->addColumn(
            'name',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            ['nullable' => false],
            'Name'
        )->addColumn(
            'email',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            ['nullable' => false],
            'Email Id'
        )->addColumn(
            'telephone',
            \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
            null,
            ['nullable'=> false],
            'Phone Number'
        )->addColumn(
            'comment',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            ['nullable' => false],
            'What’s on your mind?'
        );
        $installer->getConnection()->createTable($table);
    }
}

app/code/Vendor/Cform/view/frontend/templates/form.phtml

<form id="contact-form" class="form-horizontal" method="post" enctype="multipart/form-data" action="<?php echo $this->getUrl("cform/index/index")?>">
    <h1><?= $block->escapeHtml(__('Contact Form')) ?></h1>
    <fieldset class="fieldset">
        <div class="field name">
            <label class="label" for="name"><span><?= $block->escapeHtml(__('Name')) ?></span></label>
            <div class="control">
                <input name="name" id="name" class="input-text" type="text" />
            </div>
        </div>
        <div class="field email">
            <label class="label" for="email"><span><?= $block->escapeHtml(__('Email')) ?></span></label>
            <div class="control">
                <input name="email" id="email" class="input-text" type="email" />
            </div>
        </div>
        <div class="field telephone">
            <label class="label" for="telephone"><span><?= $block->escapeHtml(__('Phone Number')) ?></span></label>
            <div class="control">
                <input name="telephone" id="telephone" class="input-text" type="text" />
            </div>
        </div>
        <div class="field comment">
            <label class="label" for="comment"><span><?= $block->escapeHtml(__('What’s on your mind?')) ?></span></label>
            <div class="control">
                <textarea name="comment" id="comment" class="input-text" cols="5" rows="3" ></textarea>
            </div>
        </div>
        <?= $block->getChildHtml('form.additional.info') ?>
    </fieldset>
    <div class="actions-toolbar">
        <div class="primary">
            <input type="hidden" name="hideit" id="hideit" value="" />
            <button type="submit" id="add" title="" class="action submit primary">
                <span><?= $block->escapeHtml(__('Submit')) ?></span>
            </button>
        </div>
    </div>
</form>


<script>
require(['jquery'],function($){
    $(document).ready(function(){
        $("#add").click(function(){
        var customurl = "<?php echo $this->getUrl("cform/index/index") ?>";
        $.ajax({
            url: customurl,
            type: "POST",
            data: $(this).closest('form').serialize(),
            dataType: "json",
            success: function(result){
                console.log(result);
            }
        });
        $('#contact-form')[0].reset(); 
        return false;
        });
    });
}); 
</script>

app/code/Vendor/Cform/Controller/Index/index.php

<?php

namespace Vendor\Cform\Controller\Index;

use Magento\Framework\App\Action\Action;


class Index extends Action
{
    public function __construct(
        \Magento\Framework\App\Action\Context $context
    ) {
        parent::__construct($context);
    }   
    public function execute()
    {
        $post = $this->getRequest()->getPostValue();
        
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();       
        $data = $objectManager->create('Vendor\Cform\Model\Cform');
        $data->setData($post);
        $data->save();
        /* echo "hello";
        exit; */
        
        $this->messageManager->addSuccess(__('Form successfully submitted'));
             
    }
}

app/code/Vendor/Cform/Model/Cform.php

<?php

namespace Vendor\Cform\Model;

class Cform extends \Magento\Framework\Model\AbstractModel
{
    /**
     * Initialize resource model
     *
     * @return void
     */
    
    protected function _construct()
    {
        $this->_init('Vendor\Cform\Model\ResourceModel\Cform');
    }

}

app/code/Vendor/Cform/Model/ResourceModel/Cform.php

<?php

namespace Vendor\Cform\Model\ResourceModel;

class Cform extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    protected $storeManager;
    
    public function __construct(
        \Magento\Framework\Model\ResourceModel\Db\Context $context,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        $connectionName = null
    ) {
        parent::__construct($context, $connectionName);
        $this->storeManager = $storeManager;
    }
    
    protected function _construct()
    {
        $this->_init('vendor_contect', 'contect_id');
    }
}

app/code/Vendor/Cform/Model/ResourceModel/Cform/Collection.php

<?php
namespace Vendor\Cform\Model\ResourceModel\Cform;
 
use \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
 
class Collection extends AbstractCollection
{
 
    protected $_idFieldName = \Vendor\Cform\Model\Cform::CONTECT_ID;
     
    /**
     * Define resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('Vendor\Cform\Model\Cform', 'Vendor\Cform\Model\ResourceModel\Cform');
    }
 
}

CMS page Call

{{block class="Magento\Framework\View\Element\Template" template="Vendor_Cform::form.phtml" }}

app/code/Vendor/Cform/view/frontend/layout/contactform_index_index.xml

<?xml version="1.0"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Vendor\ContactForm\Block\Form" name="contactForm" template="Vendor_ContactForm::form.phtml">
                <container name="form.additional.info" label="Form Additional Info"/>
            </block>
        </referenceContainer>
    </body>
</page>
1
  • 1
    Is this linked to your other answer? I know in test.phtml, it refers to "cform" in the form action - I assume it's this? Commented Jan 14, 2019 at 15:48
1
  1. Create a simple html form and submit data to your controller.
  2. Get all your post values in your controller and send mail using below function.

You can send mail using Zend_Mail() function.

// Get your post values
$firstname = "Dinesh";
$lastname = "Yadav";

// Send Mail functionality starts from here 
$from = "[email protected]";
$nameFrom = "From Name";
$to = "[email protected]";
$nameTo = "To Name";
$body = "
<div>
    <b>".$firstname."</b>
    <i>".$lastname."</i>
</div>";

$email = new \Zend_Mail();
$email->setSubject("Email Subject"); 
$email->setBodyHtml($body);     // use it to send html data
//$email->setBodyText($body);   // use it to send simple text data
$email->setFrom($from, $nameFrom);
$email->addTo($to, $nameTo);
$email->send();
0

Note: Contact is vendor and Us is module.Here i am posting my form data to my frontend controller Post.php

step 1: Create email_templates.xml in app/code/Contact/Us/etc

<?xml version="1.0"?>
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Email/etc/email_templates.xsd">
<template id="send_email_email_template" label="Email Form" file="email_template.html" type="text" module="Contact_Us" area="frontend"/>

step 2: Create email_template.html in app/code/Contact/Us/view/frontend/email

<!--@subject xMage-support@-->
   <!--@vars {
     "var data.comment":"xMage-support",
     "var data.email":"[email protected]",
     "var data.name":"XMageStore"
    } @-->


  {{template config_path="design/email/header_template"}}

  {{trans "Dear %name" name=$data.name}}
  {{trans "we received your request regarding %queryregarding" 
    queryregarding=$data.requestType}}

  {{template config_path="design/email/footer_template"}}

Step 3: Create Post.php controller in app/code/Contact/Us/Controller/Post

<?php
namespace Contact\Us\Controller\Index;

class Post extends \Magento\Framework\App\Action\Action
{
/**
 * @var \Magento\Framework\Mail\Template\TransportBuilder
 */
protected $_transportBuilder;

/**
 * @var \Magento\Framework\Translate\Inline\StateInterface
 */
protected $inlineTranslation;

/**
 * @var \Magento\Framework\App\Config\ScopeConfigInterface
 */
protected $scopeConfig;

/**
 * @var \Magento\Store\Model\StoreManagerInterface
 */
protected $storeManager;
/**
 * @var \Magento\Framework\Escaper
 */
protected $_escaper;
/**
 * @param \Magento\Framework\App\Action\Context $context
 * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
 * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation
 * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
 * @param \Magento\Store\Model\StoreManagerInterface $storeManager
 */
public function __construct(
    \Magento\Framework\App\Action\Context $context,
    \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder,
    \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
    \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
    \Magento\Store\Model\StoreManagerInterface $storeManager,
    \Magento\Framework\Escaper $escaper
) {
    parent::__construct($context);
    $this->_transportBuilder = $transportBuilder;
    $this->inlineTranslation = $inlineTranslation;
    $this->scopeConfig = $scopeConfig;
    $this->storeManager = $storeManager;
    $this->_escaper = $escaper;
}

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

    $this->inlineTranslation->suspend();
    try {
        $recipientMail = $this->getRequest()->getPostValue('email');

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

        $error = false;

        $sender = [
            'name' => 'xMageStore',
            'email' => '[email protected]',
        ];

        $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;

        $transport = $this->_transportBuilder
            ->setTemplateIdentifier('send_email_email_template') // this code we have mentioned in the email_templates.xml
            ->setTemplateOptions(
                [
                    'area' => \Magento\Framework\App\Area::AREA_FRONTEND, // this is using frontend area to get the template file
                    'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID,
                ]
            )
            ->setTemplateVars(['data' => $postObject])
            ->setFrom($sender)
            ->addTo($recipientMail)
            ->getTransport();

        $transport->sendMessage();
        $this->inlineTranslation->resume();
        $this->messageManager->addSuccess(
            __('Thanks for contacting us. We\'ll respond to you very soon.')
        );
        $this->_redirect('/');
        return;
    } catch (\Exception $e) {
        $this->inlineTranslation->resume();
        $this->messageManager->addError(
            __('We can\'t process your request right now. Sorry, that\'s all we know.' . $e->getMessage())
        );
        $this->_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.