I created a custom API that collects information from a form. How can I send that information to the admin's email ?
The API is working fine, but I don't know how to combine it with the email function.
This is my API interface in /vendor_name/module_name/Api/ConfiguratorPrint.php
<?php
namespace ConfiguratorPrint\Rest\Api;
interface ConfiguratorInterface
{
/**
* Returns user configurator
*
* @api
* @param string $config_name Users name.
* @param string $config_email Users email.
* @param string $config_phone Users phone.
* @param string $config_shape Users shape.
* @param string $config_message Users message.
* @param string $config_upload Users upload.
* @return string return user configurator.
*/
public function getConfigData($config_name,$config_email,$config_phone,$config_shape,$config_message,$config_upload);
}
This is my API model in /vendor_name/module_name/Model/Configurator.php
<?php
namespace ConfiguratorPrint\Rest\Model;
use ConfiguratorPrint\Rest\Api\ConfiguratorInterface;
class Configurator implements ConfiguratorInterface
{
/**
* Returns user configurator
*
* @api
* @param string $config_name Users name.
* @param string $config_email Users email.
* @param string $config_phone Users phone.
* @param string $config_shape Users shape.
* @param string $config_message Users message.
* @param string $config_upload Users upload.
* @return string return user configurator.
*/
public function getConfigData($config_name, $config_email, $config_phone, $config_shape, $config_message, $config_upload) {
try {
// Put incomming data in array
$configFields = array();
if($config_name){$configFields['config_name'] = $config_name;}
if($config_email){$configFields['config_email'] = $config_email;}
if($config_phone){$configFields['config_phone'] = $config_phone;}
if($config_shape){$configFields['config_shape'] = $config_shape;}
if($config_message){$configFields['config_message'] = $config_message;}
if($config_upload){$configFields['config_upload'] = json_decode($config_upload);}
// Looping trough upladed images and decoding
$length = count($configFields['config_upload']);
for ($i=0; $i<$length; $i++) {
$imgData = $configFields['config_upload'][$i];
list($type, $imgData) = explode(';', $imgData);
list(, $imgData) = explode(',', $imgData);
$imgData = base64_decode($imgData);
}
}
catch(Exception $e){
throw $e;
}
}
}
And this is my send email code in /vendor_name/module_name/Controller/Index/send_email.php
<?php
namespace ConfiguratorPrint\Controller\Index;
use Magento\Framework\App\RequestInterface;
class Sendemail extends \Magento\Framework\App\Action\Action
{
/**
* @var \Magento\Framework\App\Request\Http
*/
protected $_request;
/**
* @var \Magento\Framework\Mail\Template\TransportBuilder
*/
protected $_transportBuilder;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $_storeManager;
public function __construct(
\Magento\Framework\App\Action\Context $context
, \Magento\Framework\App\Request\Http $request
, \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
, \Magento\Store\Model\StoreManagerInterface $storeManager
)
{
$this->_request = $request;
$this->_transportBuilder = $transportBuilder;
$this->_storeManager = $storeManager;
parent::__construct($context);
}
public function execute()
{
$store = $this->_storeManager->getStore()->getId();
$transport = $this->_transportBuilder->setTemplateIdentifier('configurator_email_template')
->setTemplateOptions(['area' => 'frontend', 'store' => $store])
->setTemplateVars(
[
'store' => $this->_storeManager->getStore(),
]
)
->setFrom('[email protected]')
// you can config general email address in Store -> Configuration -> General -> Store Email Addresses
->addTo('[email protected]', 'Store Name')
->getTransport();
$transport->sendMessage();
return $this;
}
}
And this the code that POST's data to API, I'm using angular.
configurate(model, isValid:boolean) {
if(isValid) {
let headers = new Headers({ 'Content-Type': 'application/json' });
let body = {
"config_name": model.name,
"config_email": model.email,
"config_phone": model.phone,
"config_shape": model.shape,
"config_message": model.message,
"config_upload": JSON.stringify(this.imageSrc)
};
return this.http.post(this.baseApiUrl + 'rest/V1/configurator', body, {headers: headers}
).map(res => res.json()).subscribe(
data => {
console.log("Configurator", data);
$('.loader').hide();
$('.success-message').show();
setTimeout(function() {
$('.success-message').hide();
}, 5000);
},
err => {
console.log(err);
},
() => {
});
}
}
-
Just a question. You say you collect it from a form. But where do you sync your api? Can i see that code? Because you will need to make a model that sends the mail but is triggered by your apiCompactCode– CompactCode2017年09月25日 09:28:41 +00:00Commented Sep 25, 2017 at 9:28
-
thank you for your fast reply, I edited the above code, I allready have a Model for my API, do I need a Model for the send mail function ? I'm a frontend developer so this is all new stuff for me.Sylaratty– Sylaratty2017年09月25日 09:40:07 +00:00Commented Sep 25, 2017 at 9:40
-
Well first off all your namespaces are a bit weird. lets say your module is Test_Api then you need to have the folders Test/Api/... And your namespaces are Test/Api/... Secondly what kind of API are you using? I succesfully made a REST API connection to another database and imported that into Magento but it was done trough an Controller since you need a callback URL to obtain the data with an API keyCompactCode– CompactCode2017年09月25日 11:06:05 +00:00Commented Sep 25, 2017 at 11:06
-
I'm using REST API, and its working fine, but I don't know how to trigger the mail sending function, or if its even possible...Sylaratty– Sylaratty2017年09月25日 11:28:15 +00:00Commented Sep 25, 2017 at 11:28
-
oh sure its possible. I'm using a command do to so , i will tell you in an answer how i do it. It won't be about how to send a mail but how to trigger an actionCompactCode– CompactCode2017年09月25日 13:26:19 +00:00Commented Sep 25, 2017 at 13:26
2 Answers 2
So from my understanding you need to send a mail. I'm not an expert but i know how to do this on a time frame base.
So what i did was create a console command (ssh command).
This by creating a file :
Vendor/Namespace/Console/Command/CommandSomething.php
<?php
namespace Vendor\Namespace\Console\Command;
use Vendor\Namespace\Model\YourCustomSendingModel;
use Magento\Framework\App\Area;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputInterface;
use Magento\Framework\App\State;
class CommandSomething extends Command
{
protected $_state;
protected $_YourCustomSendingModel;
public function __construct(
State $state,
YourCustomSendingModel $YourCustomSendingModel,
$name = null
)
{
$state->setAreaCode(Area::AREA_WEBAPI_REST);
$this->_YourCustomSendingModel = $YourCustomSendingModel ;
parent::__construct($name);
}
protected function configure()
{
$this->setName('command:subcommand')->setDescription('Send mail');
}
protected function execute(
InputInterface $input,
OutputInterface $output
)
{
$output->writeln('Sending Mails ...');
$mail= $this->_YourCustomSendingModel->SendMail();
$output->writeln($mail);
}
}
Now we need to register that ssh command
Vendor/Module/etc/di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\Console\CommandList">
<arguments>
<argument name="commands" xsi:type="array">
<item name="subcommand" xsi:type="object">Vendor\Module\Console\Command\CommandSomething</item>
</argument>
</arguments></type>
</config>
This is to trigger something on action (ssh command action). We can now set a timeframe with our .crontab file (provided by host or you need to configure cron yourself on your own server):
*/5 * * * * php -d "memory_limit=2048M" /site/www/bin/magento command:subcommand >> /site/www/var/log/mailsend.cron.log&
If you wish to do it after an event you can use a plugin with After method instead of all this :
Long story short you will need something to trigger everything. I use this for syncing products
Just add your Custom mail sending model there.
Now i do not know which Model or Controller or anything you need to extend to send out a Mail but there is a fille that is responsible for sending out mails within Magento. A quick Google will provide you that information.
In your CustomSendingModel :
Vendor/Namespace/Model/CustomSendingModel.php
<?php
namespace Vendor/Namespace/Model;
use ** class that is responsible for sending mails which we will call 'MailSendClass' for now **
use ** the class that you made to get the Rest API information which we will call GetApi for now **
class CustomSendingModel extends MailSendClass {
$protected $_getapi;
public function __construct(
GetApi $getapi,
parent construct here)
{
$this->_getapi = $getapi;
parent::....
}
// note : if you don't know how to construct constructors i highly recommend buying Magicento for PhP storm that will autocomplete that for you
public function SendMail(){
$data = $this->_getapi->FunctionThatReturnsData();
.....
// use mailsending functions from here to past in the data and return that and execute the mailsending from that class.
}
I know that i'm not giving you a copy/paste solution but that would require me to develop your module. Which i won't do. But this is the logistics that you need. You need a trigger (cron trigger or plugin trigger) that triggers the mailsending where you give your data from your REST ApI. Mailsending is usually done with Cron to prevent overload.
So I found a solution, probably not best practice, but it works. I added code from controller to the API model, and now it send emails with multiple attachments after you call API.
Here is API model code:
namespace VendorName\ModuleName\Model;
use VendorName\ModuleName\Api\ConfiguratorInterface;
use Magento\Framework\App\RequestInterface;
class Configurator extends \Magento\Framework\App\Action\Action implements
ConfiguratorInterface
{
/**
* @var \Magento\Framework\App\Request\Http
*/
protected $_request;
/**
* @var \Magento\Framework\Mail\Template\TransportBuilder
*/
protected $_transportBuilder;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $_storeManager;
/**
* @param \Magento\Framework\App\Action\Context $context
* @param \Magento\Framework\App\Request\Http $request
* @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\App\Request\Http $request,
\Magento\Framework\Mail\Template\TransportBuilder $transportBuilder,
\Magento\Store\Model\StoreManagerInterface $storeManager
)
{
$this->_request = $request;
$this->_transportBuilder = $transportBuilder;
$this->_storeManager = $storeManager;
parent::__construct($context);
}
/**
* Returns user configurator
*
* @api
* @param string $config_name Users name.
* @param string $config_email Users email.
* @param string $config_phone Users phone.
* @param string $config_shape Users shape.
* @param string $config_message Users message.
* @param string $config_upload Users upload.
* @return string return user configurator.
*/
public function getConfigData($config_name, $config_email, $config_phone, $config_shape, $config_message, $config_upload) {
try {
// Put incomming data in array
global $configFields;
$configFields = array();
if($config_name){$configFields['config_name'] = $config_name;}
if($config_email){$configFields['config_email'] = $config_email;}
if($config_phone){$configFields['config_phone'] = $config_phone;}
if($config_shape){$configFields['config_shape'] = $config_shape;}
if($config_message){$configFields['config_message'] = $config_message;}
if($config_upload){$configFields['config_upload'] = json_decode($config_upload);} else {$configFields['config_upload'] = null;}
return $this->execute();
}
catch(Exception $e){
throw $e;
}
}
/**
* Send configurator email
*
* @return string
* @throws \Exception
*/
public function execute()
{
try {
global $configFields;
// Looping trough upladed images and decoding
$length = count($configFields['config_upload']);
for ($i=0; $i<$length; $i++) {
$imgData = $configFields['config_upload'][$i];
list($type, $imgData) = explode(';', $imgData);
list(, $imgData) = explode(',', $imgData);
$imgData = base64_decode($imgData);
// Add images to mail
$this->_transportBuilder->addAttachment($imgData,'Attachment'. $i);
}
$store = $this->_storeManager->getStore()->getId();
$sender = [
'name' => $configFields['config_name'],
'email' => $configFields['config_email'],
];
$transport = $this->_transportBuilder->setTemplateIdentifier('configurator_email_template')
->setTemplateOptions(['area' => 'frontend', 'store' => $store])
->setTemplateVars(
[
'store' => $this->_storeManager->getStore(),
'phone' => $configFields['config_phone'],
'shape' => $configFields['config_shape'],
'message' => $configFields['config_message'],
]
)
->setFrom($sender)
// you can config general email address in Store -> Configuration -> General -> Store Email Addresses
->addTo('general')
->getTransport();
$transport->sendMessage();
return 'Message sent!';
}
catch(\Exception $e){
echo 'Message: ' .$e->getMessage();
}
}
}
And here is code for sending attachment:
namespace VendorName\ModuleName\Model\Mail\Template;
class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
/**
* @param string $imgString
* @param string $filename
* @return mixed
*/
public function addAttachment($imgString, $filename)
{
If ($filename == '') {
$filename="attachment";
}
$this->message->createAttachment(
$imgString,
'application/png',
\Zend_Mime::DISPOSITION_ATTACHMENT,
\Zend_Mime::ENCODING_BASE64,
$filename.'.png'
);
return $this;
}
}
And here is 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="VendorName\ModuleName\Api\ConfiguratorInterface"
type="VendorName\ModuleName\Model\Configurator" />
<preference for="Magento\Framework\Mail\Template\TransportBuilder"
type="VendorName\ModuleName\Model\Mail\Template\TransportBuilder" />
</config>