Rewrite file in Theme Frontend app/design/frontend/VENDER_NAME/YOUR_THEME/Magento_Contact/templates/form.phtml
OR
Rewrite the form.phtml file in custom module Vendor/Module/view/frontend/layout/contact_index_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="contactForm">
<action method="setTemplate">
<argument name="template" xsi:type="string">Vendor_Module::form.phtml</argument>
</action>
</referenceBlock>
</body>
</page>
and create file inside module Vendor/Module/view/frontend/templates/form.phtml
form.phtml file will be in 'Frontend Theme' or 'Custom Module' (as explained above) and then add following content in form.phtml:
-> add enctype="multipart/form-data" in form.phtml action
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/** @var \Magento\Contact\Block\ContactForm $block */
?>
<form class="form contact"
action="<?= $block->escapeUrl($block->getFormAction()) ?>"
id="contact-form"
method="post"
data-hasrequired="<?= $block->escapeHtmlAttr(__('* Required Fields')) ?>"
data-mage-init='{"validation":{}}'
enctype="multipart/form-data">
<fieldset class="fieldset">
<legend class="legend"><span><?= $block->escapeHtml(__('Write Us')) ?></span></legend><br />
<div class="field note no-label"><?= $block->escapeHtml(__('Jot us a note and we’ll get back to you as quickly as possible.')) ?></div>
<div class="field name required">
<label class="label" for="name"><span><?= $block->escapeHtml(__('Name')) ?></span></label>
<div class="control">
<input name="name" id="name" title="<?= $block->escapeHtmlAttr(__('Name')) ?>" value="<?= $block->escapeHtmlAttr($this->helper(\Magento\Contact\Helper\Data::class)->getPostValue('name') ?: $this->helper(\Magento\Contact\Helper\Data::class)->getUserName()) ?>" class="input-text" type="text" data-validate="{required:true}"/>
</div>
</div>
<div class="field email required">
<label class="label" for="email"><span><?= $block->escapeHtml(__('Email')) ?></span></label>
<div class="control">
<input name="email" id="email" title="<?= $block->escapeHtmlAttr(__('Email')) ?>" value="<?= $block->escapeHtmlAttr($this->helper(\Magento\Contact\Helper\Data::class)->getPostValue('email') ?: $this->helper(\Magento\Contact\Helper\Data::class)->getUserEmail()) ?>" class="input-text" type="email" data-validate="{required:true, 'validate-email':true}"/>
</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" title="<?= $block->escapeHtmlAttr(__('Phone Number')) ?>" value="<?= $block->escapeHtmlAttr($this->helper(\Magento\Contact\Helper\Data::class)->getPostValue('telephone')) ?>" class="input-text" type="text" />
</div>
</div>
<div class="field comment required">
<label class="label" for="comment"><span><?= $block->escapeHtml(__('What’s on your mind?')) ?></span></label>
<div class="control">
<textarea name="comment" id="comment" title="<?= $block->escapeHtmlAttr(__('What’s on your mind?')) ?>" class="input-text" cols="5" rows="3" data-validate="{required:true}"><?= $block->escapeHtml($this->helper(\Magento\Contact\Helper\Data::class)->getPostValue('comment')) ?></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" title="<?= $block->escapeHtmlAttr(__('Submit')) ?>" class="action submit primary">
<span><?= $block->escapeHtml(__('Submit')) ?></span>
</button>
</div>
</div>
</form>
Vendor/Module/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
<preference for="Magento\Contact\Controller\Index\Post" type="Vendor\Module\Rewrite\Magento\Contact\Controller\Index\Post"/>
</config>
Vendor/Module/etc/email_templates.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Email:etc/email_templates.xsd">
<template id="contact_email_attachment_email_template" label="Contact Form with Attachment" file="submitted_form.html" type="html" module="Vendor_Module" area="frontend"/>
</config>
Vendor/Module/etc/frontend/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">
<type name="Magento\Contact\Block\ContactForm">
<plugin name="contactus-attachment-form" type="Vendor\Module\Plugin\AddFieldToContactForm" />
</type>
</config>
Vendor/Module/view/frontend/email/submitted_form.html
<!--@subject {{trans "Contact Form with Attachment"}} @-->
<!--@vars {
"var data.comment":"Comment",
"var data.email":"Sender Email",
"var data.name":"Sender Name",
"var data.telephone":"Sender Telephone",
"var data.attachment":"Sender Attachment"
} @-->
{{template config_path="design/email/header_template"}}
<table class="message-details">
<tr>
<td><strong>{{trans "Name"}}</strong></td>
<td>{{var data.name}}</td>
</tr>
<tr>
<td><strong>{{trans "Email"}}</strong></td>
<td>{{var data.email}}</td>
</tr>
<tr>
<td><strong>{{trans "Phone"}}</strong></td>
<td>{{var data.telephone}}</td>
</tr>
<tr>
<td><strong>{{trans "Attachment"}}</strong></td>
<td>{{var data.attachment}}</td>
</tr>
</table>
<p><strong>{{trans "Message"}}</strong></p>
<p>{{var data.comment}}</p>
{{template config_path="design/email/footer_template"}}
Vendor/Module/view/frontend/templates/contactus/attachment.phtml
<p style="font-size: 15px;">
<b>Attachment</b>
(Upload any relevant file e.g. screenshot of website error)
</p>
<p id="file_error" class="message-error error message" style="display:none;">
File is too large
</p>
<p class="file">
File must be less than 2MB and in any of these formats: .png, .jpg, .gif, .jpeg
</p>
<input id="attachment" accept=".png, .jpg, .gif, .jpeg/*" name="attachment" type="file" value="<?= $block->escapeHtmlAttr($this->helper('Magento\Contact\Helper\Data')->getPostValue('attachment')) ?>">
<script type="text/javascript" xml="space">
require(['jquery'], function ($) {
jQuery(document).ready(function($){
var uploadField = document.getElementById("attachment");
uploadField.onchange = function() {
if(this.files[0].size > 44362048){
$('#file_error').show();
this.value = "";
}else{
$('#file_error').hide();
};
};
});
});
</script>
Vendor/Module/Rewrite/Magento/Framework/Mail/Template/TransportBuilder.php
<?php
namespace Vendor\Module\Rewrite\Magento\Framework\Mail\Template;
use Magento\Framework\App\TemplateTypesInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\MailException;
use Magento\Framework\Mail\EmailMessageInterface;
use Magento\Framework\Mail\EmailMessageInterfaceFactory;
use Magento\Framework\Mail\AddressConverter;
use Magento\Framework\Mail\Exception\InvalidArgumentException;
use Magento\Framework\Mail\MessageInterface;
use Magento\Framework\Mail\MessageInterfaceFactory;
use Magento\Framework\Mail\MimeInterface;
use Magento\Framework\Mail\MimeMessageInterfaceFactory;
use Magento\Framework\Mail\MimePartInterfaceFactory;
use Magento\Framework\Mail\Template\FactoryInterface;
use Magento\Framework\Mail\Template\SenderResolverInterface;
use Magento\Framework\Mail\TemplateInterface;
use Magento\Framework\Mail\TransportInterface;
use Magento\Framework\Mail\TransportInterfaceFactory;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Phrase;
use Zend\Mime\Mime;
use Zend\Mime\PartFactory;
class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
protected $templateIdentifier;
protected $templateModel;
protected $templateVars;
protected $templateOptions;
protected $transport;
protected $templateFactory;
protected $objectManager;
protected $message;
protected $_senderResolver;
protected $mailTransportFactory;
private $messageData = [];
private $emailMessageInterfaceFactory;
private $mimeMessageInterfaceFactory;
private $mimePartInterfaceFactory;
private $addressConverter;
protected $attachments = [];
protected $partFactory;
public function __construct(
FactoryInterface $templateFactory,
MessageInterface $message,
SenderResolverInterface $senderResolver,
ObjectManagerInterface $objectManager,
TransportInterfaceFactory $mailTransportFactory,
MessageInterfaceFactory $messageFactory = null,
EmailMessageInterfaceFactory $emailMessageInterfaceFactory = null,
MimeMessageInterfaceFactory $mimeMessageInterfaceFactory = null,
MimePartInterfaceFactory $mimePartInterfaceFactory = null,
AddressConverter $addressConverter = null
) {
$this->templateFactory = $templateFactory;
$this->objectManager = $objectManager;
$this->_senderResolver = $senderResolver;
$this->mailTransportFactory = $mailTransportFactory;
$this->emailMessageInterfaceFactory = $emailMessageInterfaceFactory ?: $this->objectManager
->get(EmailMessageInterfaceFactory::class);
$this->mimeMessageInterfaceFactory = $mimeMessageInterfaceFactory ?: $this->objectManager
->get(MimeMessageInterfaceFactory::class);
$this->mimePartInterfaceFactory = $mimePartInterfaceFactory ?: $this->objectManager
->get(MimePartInterfaceFactory::class);
$this->addressConverter = $addressConverter ?: $this->objectManager
->get(AddressConverter::class);
$this->partFactory = $objectManager->get(PartFactory::class);
parent::__construct($templateFactory, $message, $senderResolver, $objectManager, $mailTransportFactory, $messageFactory, $emailMessageInterfaceFactory, $mimeMessageInterfaceFactory,
$mimePartInterfaceFactory, $addressConverter);
}
public function addCc($address, $name = '')
{
$this->addAddressByType('cc', $address, $name);
return $this;
}
public function addTo($address, $name = '')
{
$this->addAddressByType('to', $address, $name);
return $this;
}
public function addBcc($address)
{
$this->addAddressByType('bcc', $address);
return $this;
}
public function setReplyTo($email, $name = null)
{
$this->addAddressByType('replyTo', $email, $name);
return $this;
}
public function setFrom($from)
{
return $this->setFromByScope($from);
}
public function setFromByScope($from, $scopeId = null)
{
$result = $this->_senderResolver->resolve($from, $scopeId);
$this->addAddressByType('from', $result['email'], $result['name']);
return $this;
}
public function setTemplateIdentifier($templateIdentifier)
{
$this->templateIdentifier = $templateIdentifier;
return $this;
}
public function setTemplateModel($templateModel)
{
$this->templateModel = $templateModel;
return $this;
}
public function setTemplateVars($templateVars)
{
$this->templateVars = $templateVars;
return $this;
}
public function setTemplateOptions($templateOptions)
{
$this->templateOptions = $templateOptions;
return $this;
}
public function getTransport()
{
try {
$this->prepareMessage();
$mailTransport = $this->mailTransportFactory->create(['message' => clone $this->message]);
} finally {
$this->reset();
}
return $mailTransport;
}
protected function reset()
{
$this->messageData = [];
$this->templateIdentifier = null;
$this->templateVars = null;
$this->templateOptions = null;
return $this;
}
protected function getTemplate()
{
return $this->templateFactory->get($this->templateIdentifier, $this->templateModel)
->setVars($this->templateVars)
->setOptions($this->templateOptions);
}
protected function prepareMessage()
{
$template = $this->getTemplate();
$content = $template->processTemplate();
switch ($template->getType()) {
case TemplateTypesInterface::TYPE_TEXT:
$part['type'] = MimeInterface::TYPE_TEXT;
break;
case TemplateTypesInterface::TYPE_HTML:
$part['type'] = MimeInterface::TYPE_HTML;
break;
default:
throw new LocalizedException(
new Phrase('Unknown template type')
);
}
$mimePart = $this->mimePartInterfaceFactory->create(['content' => $content]);
$parts = count($this->attachments) ? array_merge([$mimePart], $this->attachments) : [$mimePart];
$this->messageData['body'] = $this->mimeMessageInterfaceFactory->create(
['parts' => $parts]
);
$this->messageData['subject'] = html_entity_decode(
(string)$template->getSubject(),
ENT_QUOTES
);
$this->message = $this->emailMessageInterfaceFactory->create($this->messageData);
return $this;
}
private function addAddressByType(string $addressType, $email, ?string $name = null): void
{
if (is_string($email)) {
$this->messageData[$addressType][] = $this->addressConverter->convert($email, $name);
return;
}
$convertedAddressArray = $this->addressConverter->convertMany($email);
if (isset($this->messageData[$addressType])) {
$this->messageData[$addressType] = array_merge(
$this->messageData[$addressType],
$convertedAddressArray
);
}
}
public function addAttachment(?string $content, ?string $fileName, ?string $fileType)
{
$attachmentPart = $this->partFactory->create();
$attachmentPart->setContent($content)
->setType($fileType)
->setFileName($fileName)
->setDisposition(Mime::DISPOSITION_ATTACHMENT)
->setEncoding(Mime::ENCODING_BASE64);
$this->attachments[] = $attachmentPart;
return $this;
}
}
Vendor/Module/Rewrite/Magento/Contact/Controller/Index/Post.php
<?php
namespace Vendor\Module\Rewrite\Magento\Contact\Controller\Index;
use Vendor\Module\Rewrite\Magento\Framework\Mail\Template\TransportBuilder; //replace vendor module
use Magento\Store\Model\StoreManagerInterface;
use Magento\Contact\Model\ConfigInterface;
use Magento\Contact\Model\MailInterface;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Area;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\App\Request\DataPersistorInterface;
use Magento\Framework\Controller\Result\Redirect;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filesystem;
use Magento\Framework\Translate\Inline\StateInterface;
use Psr\Log\LoggerInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\DataObject;
use Magento\MediaStorage\Model\File\UploaderFactory;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Filesystem\Io\File;
/**
* Post controller class
*/
class Post extends \Magento\Contact\Controller\Index\Post
{
const FOLDER_LOCATION = 'contactattachment';
private $dataPersistor;
private $context;
private $mail;
private $logger;
private $fileUploaderFactory;
private $fileSystem;
private $inlineTranslation;
private $contactsConfig;
private $transportBuilder;
private $storeManager;
public function __construct(
Context $context,
MailInterface $mail,
DataPersistorInterface $dataPersistor,
LoggerInterface $logger = null,
UploaderFactory $fileUploaderFactory,
Filesystem $fileSystem,
StateInterface $inlineTranslation,
ConfigInterface $contactsConfig,
TransportBuilder $transportBuilder,
StoreManagerInterface $storeManager,
ScopeConfigInterface $scopeConfig,
File $file
) {
$this->context = $context;
$this->mail = $mail;
$this->dataPersistor = $dataPersistor;
$this->logger = $logger ?: ObjectManager::getInstance()->get(LoggerInterface::class);
$this->fileUploaderFactory = $fileUploaderFactory;
$this->fileSystem = $fileSystem;
$this->inlineTranslation = $inlineTranslation;
$this->contactsConfig = $contactsConfig;
$this->transportBuilder = $transportBuilder;
$this->storeManager = $storeManager;
$this->scopeConfig = $scopeConfig;
$this->file = $file;
parent::__construct($context, $contactsConfig, $mail, $dataPersistor, $logger);
}
public function execute()
{
if (!$this->getRequest()->isPost()) {
return $this->resultRedirectFactory->create()->setPath('*/*/');
}
try {
$this->sendEmail($this->validatedParams());
$this->messageManager->addSuccessMessage(
__('Thanks for contacting us with your comments and questions. We\'ll respond to you very soon.')
);
$this->dataPersistor->clear('contact_us');
} catch (LocalizedException $e) {
$this->messageManager->addErrorMessage($e->getMessage());
$this->dataPersistor->set('contact_us', $this->getRequest()->getParams());
} catch (\Exception $e) {
$this->logger->critical($e);
$this->messageManager->addErrorMessage(
__('An error occurred while processing your form. Please try again later.')
);
$this->dataPersistor->set('contact_us', $this->getRequest()->getParams());
}
return $this->resultRedirectFactory->create()->setPath('contact/index');
}
private function sendEmail($post)
{
$this->send(
$post['email'],
['data' => new DataObject($post)]
);
}
public function send($replyTo, array $variables)
{
$filePath = null;
$fileName = null;
$uploaded = false;
try {
$fileCheck = $this->fileUploaderFactory->create(['fileId' => 'attachment']);
$file = $fileCheck->validateFile();
$attachment = $file['name'] ?? null;
} catch (\Exception $e) {
$attachment = null;
}
$filesData = $this->getRequest()->getFiles();
if ($attachment) {
$upload = $this->fileUploaderFactory->create(['fileId' => 'attachment']);
$upload->setAllowRenameFiles(true);
$upload->setFilesDispersion(true);
$upload->setAllowCreateFolders(true);
$upload->setAllowedExtensions(['txt', 'jpg', 'jpeg', 'gif', 'png']);
$path = $this->fileSystem
->getDirectoryRead(DirectoryList::MEDIA)
->getAbsolutePath(self::FOLDER_LOCATION);
$result = $upload->save($path);
$uploaded = self::FOLDER_LOCATION . $upload->getUploadedFilename();
$filePath = $result['path'] . $result['file'];
$fileName = $result['name'];
}
/** @see \Magento\Contact\Controller\Index\Post::validatedParams() */
$replyToName = !empty($variables['data']['name']) ? $variables['data']['name'] : null;
$this->inlineTranslation->suspend();
$storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;
$transport = $this->transportBuilder
->setTemplateIdentifier($this->contactsConfig->emailTemplate())
->setTemplateOptions(
[
'area' => Area::AREA_FRONTEND,
'store' => $this->storeManager->getStore()->getId(),
]
)
->setTemplateVars($variables)
->setFrom($this->contactsConfig->emailSender())
->addTo($this->contactsConfig->emailRecipient())
->setReplyTo($replyTo, $replyToName)
->getTransport();
if ($uploaded && !empty($filePath) && $this->file->fileExists($filePath)) {
$mimeType = mime_content_type($filePath);
$transport = $this->transportBuilder
->setTemplateIdentifier($this->contactsConfig->emailTemplate())
->setTemplateOptions(
[
'area' => Area::AREA_FRONTEND,
'store' => $this->storeManager->getStore()->getId(),
]
)
->addAttachment($this->file->read($filePath), $fileName, $mimeType)
->setTemplateVars($variables)
->setFrom($this->contactsConfig->emailSender())
->addTo($this->contactsConfig->emailRecipient())
->setReplyTo($replyTo, $replyToName)
->getTransport();
}
$transport->sendMessage();
$this->inlineTranslation->resume();
}
private function validatedParams()
{
$request = $this->getRequest();
// if (trim($request->getParam('hideit')) !== '') {
// throw new LocalizedException(__('Error'));
// }
return $request->getParams();
}
}
Vendor/Module/Plugin/AddFieldToContactForm.php
<?php
namespace Vendor\Module\Plugin;
use Vendor\Module\Block\Attachment as CommentBlock; //replace vendor module*emphasized text*
use Magento\Contact\Block\ContactForm as Subject;
use Magento\Framework\View\Element\Template;
/**
* Class AddFieldToContactForm
*
*/
class AddFieldToContactForm
{
/**
* @param Subject $subject
* @param string $html
*
* @return string
*/
public function afterToHtml(Subject $subject, string $html) : string
{
$commentBlock = $this->getChildBlock(CommentBlock::class, $subject);
$commentBlock->setAddress($subject->getAddress());
$html = $this->appendBlockBeforeFieldsetEnd($html, $commentBlock->toHtml());
return $html;
}
/**
* @param string $html
* @param string $childHtml
*
* @return string
*/
private function appendBlockBeforeFieldsetEnd(string $html, string $childHtml) : string
{
$pregMatch = '/\<\/fieldset>/';
$pregReplace = $childHtml . '\0';
$html = preg_replace($pregMatch, $pregReplace, $html, 1);
return $html;
}
/**
* @param string $blockClass
* @param Template $parentBlock
*
* @return mixed
*/
private function getChildBlock(string $blockClass, Template $parentBlock)
{
$blockId = str_replace('\\', '_', $blockClass);
return $parentBlock->getLayout()->createBlock($blockClass, $blockId);
}
}
Vendor/Module/Block/Attachment.php
<?php
namespace Vendor\Module\Block;
use Magento\Framework\View\Element\Template;
/**
* Class Comment
*
*/
class Attachment extends Template
{
/**
* @var string
*/
protected $_template = 'contactus/attachment.phtml';
}