1

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);
 },
 () => { 
 });
 }
 }
asked Sep 25, 2017 at 9:14
7
  • 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 api Commented 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. Commented 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 key Commented 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... Commented 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 action Commented Sep 25, 2017 at 13:26

2 Answers 2

0

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 :

Plugin interceptors

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.

answered Sep 25, 2017 at 13:47
0

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>
answered Oct 5, 2017 at 7:36

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.