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('customer@gmail.com')
        // you can config general email address in Store -> Configuration -> General -> Store Email Addresses
        ->addTo('admin@gmail.com', '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 api – CompactCode Sep 25 '17 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 Sep 25 '17 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 – CompactCode Sep 25 '17 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 Sep 25 '17 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 – CompactCode Sep 25 '17 at 13:26
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.

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>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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