Business logic with custom event to add a Mailgun trigger

Hi,
I am migrating from Parse. I have there a trigger to invoke a function (sendEmail) through Cloud Code and then to send a request to Mailgun. The trigger is very simple:

// function to send emails via Mailgun
Parse.Cloud.define("sendMail", function(request, response) {


var mailgun = require('mailgun');
mailgun.initialize('example.com', 'key-example');


mailgun.sendEmail({
to: request.params.toEmail,
from: request.params.fromEmail,
subject: request.params.subject,
text: request.params.text
}, {
success: function(httpResponse) {
console.log(httpResponse);
response.success("Email sent!");
},
error: function(httpResponse) {
console.error(httpResponse);
response.error("Uh oh, something went wrong");
}
});


});

This function, I call it through iOS and Android frontends to send emails.
Now, I would like to add the same functionality in Backendless. I know that I have the Business Logic feature to do this. I noticed that JS is added recently, like Mark Piller said in the last videoconference that I joined recently.
In Backendless website I go to Business Logic, then to Custom Events, and I add a new one “sendEmail”. Then, I download it, and I have a zip with the structure. OK, I go then to sendEmail.js and edit it with:

Backendless.ServerCode.customEvent('sendMail', function(request, response) {
 //add your code here
 var mailgun = require('mailgun');
 mailgun.initialize('example.com', 'key example');
 
 mailgun.sendEmail({
 to: request.params.toEmail,
 from: request.params.fromEmail,
 subject: request.params.subject,
 text: request.params.text
 }, {
 success: function(httpResponse) {
 console.log(httpResponse);
 response.success("Email sent!");
 },
 error: function(httpResponse) {
 console.error(httpResponse);
 response.error("Uh oh, something went wrong");
 }
 });



}, true);

Please, could you confirm this code is right to upload it to Backendless?
After this, I read in the docs, that I have to deploy this code and upload to Backendless. The way is using Code Runner.
I see in the docs that I have Code Runner in the Backendless website in PHP and Java. But, my question is:
If I would like to deploy and edited .js file, I have to use a Code Runner utility, how? Because Code Runners are in Java and PHP.
Thanks.
King regards,
Jose

Hi

Your code should be adjusted a bit. Try something like this:

Backendless.ServerCode.customEvent('sendMail', function(request) {
  return new Promise((resolve, reject) => {
    var Mailgun = require('mailgun').Mailgun;
    var mg = new Mailgun('api-key');


    mg.sendText(
      request.args.fromEmail,
      [request.args.toEmail],
      request.args.subject,
      request.args.text,
      function(err) {
        if (err) {
          console.log(err.message);
          reject('Uh oh, something went wrong');
        } else {
          resolve('Email sent');
        }
      });
  });
});

To deploy your code into production just run npm run deploy

But first, make sure it works in debug mode

Also, please read the Custom JS Business Logic Quick Start Guide

Vitaly, thank you for your help.

Finally, I used Intellij IDEA to deploy my custom trigger to backendless business logic like the Docs examples.
I achieve it.

Now, in my iOS front end I am using this method to call the function sendMail in Custom Business Logic:

   NSDictionary *eventArg = @{@"toEmail":@"jmgalvan@tagorito.com"};
    [backendless.events dispatch:@"sendMail" args:eventArg response:^(NSDictionary *data) {
        
        
    } error:^(Fault *fault) {
        
    }];

But, I am receiving a fault with the message = “Cannot find module ‘mailgun’”

My question is, how can I upload to Backendless the Mailgun module also? In a .js file?

Please, can you help me to solve this?

Thanks.

Jose

Hi Hose

mailgun is a thirdparty node.js module you want to use in your business logic.
You have to install it locally using ‘npm install’ command:

npm install mailgun --save

All modules installed with --save option will automatically be included into deployment scope

Here are some links to read :

Hi Vitaly,

I installed locally the mailgun module.
Now, I still receiving a fault object in my iOS front end.
Do you know where could be the problem? I deployed exactly the js trigger that you recommend me before.
I attach the fault description.
Thanks!

Jose,

Now it’s a timeout problem which may be caused either by :

  • too long email sending procedure (over 5 sec in production)
  • async operation in business logic not included into returned Promise

Does it work in debug mode ?

Thanks

Vitaly,

I am sending this simple email:

NSDictionary *eventArg = @{@“toEmail”:@“jmgalvan@tagorito.com”, @“text”:@“Prueba”};
I test it in debug model, and it did not work either. This the output of the terminal in the Intellij IDE:

> NuestraGente-servercode@1.0.0 debug /Users/josemiguelgalvan/Desktop/NuestraGente
> coderunner debug


18:28:35.963 - CodeRunner(tm) Backendless Debugging Utility v1.5.5
18:28:35.966 - Copyright(C) 2016 Backendless Corp. All rights reserved. 
18:28:36.281 - Starting Debug Code Runner...
18:28:36.306 - Building Model..
18:28:36.310 - Model Build completed
18:28:36.310 - Event handlers (1):
18:28:36.310 -   custom.sendMail  (app/handlers/custom-events/sendMail.js)
18:28:36.833 - Registering Code Runner on https://api.backendless.com
18:28:37.575 - Runner successfully registered.
18:28:37.576 - Registering Model on https://api.backendless.com
18:28:38.115 - Model successfully registered
18:28:38.115 - Waiting for Server Code tasks..
18:29:05.125 - [E36E83B7-7809-00D1-FFC7-589806F16800] New task arrived!
400
18:29:06.310 - Error: Uh oh, something went wrong
18:29:06.311 - [E36E83B7-7809-00D1-FFC7-589806F16800] Processing finished

I also checked that I have not selected async option in the custom business logic web console due to sendMail function.
In Parse it works perfectly, I hope in Backendless it works also.
Do you think the problem maybe could be in the trigger?

Thanks.

mailgun has returned 400 (Bad Request) error to your request

Please, double check your arguments that you pass to mailgun :

Backendless.ServerCode.customEvent('sendMail', function(request) {
	console.log("sendMail:args", request.args);
 
	return Promise(...

Do you specify fromEmail and subject fields ?

Hi Vitaly,

I am testing hardcoding the trigger like this:

Backendless.ServerCode.customEvent('sendMail', function(request) {
    return new Promise((resolve, reject) => {
        var api_key = 'example';
        var Mailgun = require('mailgun').Mailgun;
        var mg = new Mailgun(api_key);
        mg.sendText(
            'no-reply@cajasiete.com',
            ['jmgalvan@tagorito.com'],
            'Prueba',
            'Prueba',
            function(err) {
                if (err) {
                    console.log(err.message);
                    reject('Uh oh, something went wrong');
                } else {
                    resolve('Email sent');
                }
            });
    });
});

And now I am able to send emails but only in the debug mode.
When I code in the Intellij IDE terminal ‘npm run debug’ and the server is ready to receive a request, then I call the sendMail function from my iOS frontend, and then I am able to send an email.
The problem is when after this, I code ‘npm run deploy’ and the mode is in production, the email is no sent and I receive a fault:

message	__NSCFString *	@"Custom business logic execution has been terminated because it did not complete in permitted time - 5 seconds"

It´s a weird behaviour, am I doing something wrong?
Is there other command to leave the production mode ready in the server?

Thanks!
Jose

Hi Jose

Got it.

The problem with a http request to an external host which is forbidden for custom business logic in production by default.
When the business logic tries to connect to forbidden external host it gets ‘connection refused’ error.

I just checked and confirmed that mailgun module doesn’t call a callback function in case of connect errors. That’s why your promise remains unresolved in this case which leads to the timeout error.

To enable an access to an external host from business logic you have to register them.
This should resolve the problem.

There is also an alternative (native) way of sending emails from Backendless.

Cheers

Hi Vitaly,

Understood.

So, I have to ask for permission to Backendless to use Mailgun URL in production mode.

Please, can you confirm me if the URL to ask for permission is (the URL to add to the Hostname in Backendless web platform function “Add New Host”):

https://api.mailgun.net/v3

Thanks!

Jose

Hi Vitaly,

I read the docs and I better ask for permission to the hostname “Mailgun”.

When the permission would be confirmed I will test the production mode.

Thank you for your help.

Jose

Hi Jose,

Can you please confirm that this problem has been solved for you?