Loopback Email Connector not sending emails - node.js

I have a Loopback Application with a REST API.
I want to make a REST API Enpoint /Email/sendEmail which sends an email. I did this tutorial: https://loopback.io/doc/en/lb3/Email-connector.html, but it's not working for me somehow.
When I open https://localhost:3000/explorer , I can see the API Endpoint and I can press the button "Try it out". But then it just loads forever and after a while I get a Timeout error in the console.
File: datasource.json
{
"db": {
"host": "localhost",
"port": 27017,
"url": "",
"database": "siemens",
"password": "",
"name": "db",
"user": "",
"useNewUrlParser": true,
"connector": "mongodb"
},
"email": {
"name": "email",
"connector": "mail",
"transports": [{
"type": "SMTP",
"host": "smtp.gmail.com",
"secure": true,
"port": 465,
"auth": {
"user": "xbit.dany#gmail.com",
"pass": "XXX"
}
}]
}
}
File: model-config.json
"Email": {
"dataSource": "email",
"public": true
}
File: email.js
module.exports = function(Email) {
// send an email
Email.sendEmail = function(cb) {
console.log("Sending Email");
Email.app.models.Email.send({
to: 'siemens.dany#gmail.com',
from: 'xbit.dany#gmail.com',
subject: 'my subject',
text: 'my text',
html: 'my <em>html</em>'
}, function(err, mail) {
console.log('email sent!');
cb(err);
});
}
Email.remoteMethod(
'sendEmail', {
http: {
path: '/sendEmail',
verb: 'get'
},
returns: {
}
}
);
};
File: models/email.json
{
"name": "Email",
"base": "Model",
"properties": {
"to": {"type": "String", "required": true},
"from": {"type": "String", "required": true},
"subject": {"type": "String", "required": true},
"text": {"type": "String"},
"html": {"type": "String"}
}
}

The mail is now working. This is the code of email.js
module.exports = function(emailDS) {
// send an email
emailDS.sendEmail = function(cb) {
console.log("Sending Email");
emailDS.app.models.Email.send({
to: 'siemens.dany#gmail.com',
from: 'xbit.dany#gmail.com',
subject: 'my subject',
html: 'my <em>html</em>'
}, function(err, mail) {
console.log("Mail: " + mail);
console.log("Error: " + err);
cb(null, mail);
});
}
emailDS.remoteMethod(
'sendEmail', {
http: {
path: '/sendEmail',
verb: 'get'
},
returns: {
arg: 'Status', type:'string'
}
}
);
};

Related

got confused in loopback

hello guys i m new to loopback so please, can anyone help me with this following this
1. i know how to render html page from loopback server for eg:-
<form method="post" action="register">
<input type="text" name="name">
<input type="text" name="lastname">
</form>
how to can request name or lastname in my model user
'use strict';
module.exports = function(User) {
// how i can receive requested of name or lastname for eg :-
console.log(req.name)
};
2.how i can insert this data to my postgres table(table name :-register) in column "name"
3.last one is that how to differentiate table name and model name using automigrate
module.exports = function(User) {
User.show = function(name,lastName) {
console.log(name);
console.log(lastName);
}
User.remoteMethod('show', {
accepts: [
{ arg: 'name', type: 'string' },
{ arg: 'lastName', type: 'string' }
],
returns: {arg: 'result', type: 'string'}
});
}
for the insert something like :
var yourVar = name;
pg.connect(dbUrl, function(err, client, done) {
client.query(
'INSERT into yourTable(name) VALUES ($1)',
['title'],
function(err, result) {
if (err) {
console.log(err);
} else {
console.log('row inserted');
}
});
});
depending on your table and log credentials
Edit :
to use auto migrate, you must first :
create a data source in /server/datasources.json :
"mydb": {
"name": "mydb",
"connector": "postgresql"
}
Connect to UNIX domain socket in /var/run/postgresql/.s.PGSQL.5432 :
{
"postgres": {
"host": "/var/run/postgresql/",
"port": "5432",
"database": "dbname",
"username": "dbuser",
"password": "dbpassword",
"name": "postgres",
"debug": true,
"connector": "postgresql"
}
}
define your models in /common/models/model.json, it shoud look like this :
var schema={
"name": "User",
"options": {
"idInjection": true,
"postgresql": {
"schema": "yourShema",
"table": "USER"
}
},
"properties": {
"id": {
"type": "Number",
"required": true,
"length": 64,
"precision": null,
"scale": null,
"postgresql": {
"columnName": "id",
"dataType": "integer",
"dataLength": 64,
"dataPrecision": null,
"dataScale": null,
"nullable": "NO"
}
},
"name": {
"type": "String",
"required": false,
"length": 40,
"precision": null,
"scale": null,
"postgresql": {
"columnName": "name",
"dataType": "character varying",
"dataLength": 40,
"dataPrecision": null,
"dataScale": null,
"nullable": "YES"
}
},
"lastName": {
"type": "String",
"required": false,
"length": 40,
"precision": null,
"scale": null,
"postgresql": {
"columnName": "lastName",
"dataType": "character varying",
"dataLength": 40,
"dataPrecision": null,
"dataScale": null,
"nullable": "YES"
}
}
}
then you must call Model.automigrate() or Model.autoupdate() in your code like this :
ds.createModel(schema);
ds.autoupdate(schema) {
ds.discoverModelProperties('USER', function (err, props) {
console.log(props);
});
});
You will certainly have yo change some things but I hope you will achieve what you want ;)

GeoJSON parse node

I am getting an 500 error 'unexpected problem has occurred' when I parse the GeoJSON data from this weather API site using node app.
The code is a simple proxy server to receive request from client for weather info on a particular site and process an async request to the weatherAPI, when the response is received its send to the client. When I replace the URL with something that returns JSON it works. The issue is when the response data is GeoJSON.
Appreciate if anyone help shed some light on how to parse the GeoJSON response in node JavaScript.
Thank you in advance.
Here is my node app code:
function initialize() {
// Setting URL and headers for request
var options = {
url: 'https://api.weather.xxx/points/39.7456,-97.0892',
headers: {
'User-Agent': 'request'
}
};
// Return new promise
return new Promise(function(resolve, reject) {
// Do async job
request.get(options, function(err, resp, body) {
if (err) {
reject(err);
} else {
resolve(JSON.parse(body));
}
})
})
}
http.createServer(function (req, res) {
var initializePromise = initialize();
initializePromise.then(function(result) {
var geoDetails = result;
console.log("Initialized Geo details");
// Use user details from here
console.log(geoDetails);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('request successfully proxied!' + '\n' +
JSON.stringify(geoDetails, true, 2));
res.end();
}, function(err) {
console.log(err);
})
}).listen(9000);
Here is the GeoJSON data :
{
"#context": [
"...",
{
"wx": "...",
"s": "...",
"geo": "...",
"unit": "...",
"#vocab": "...",
"geometry": {
"#id": "s:GeoCoordinates",
"#type": "geo:wktLiteral"
},
"city": "s:addressLocality",
"state": "s:addressRegion",
"distance": {
"#id": "s:Distance",
"#type": "s:QuantitativeValue"
},
"bearing": {
"#type": "s:QuantitativeValue"
},
"value": {
"#id": "s:value"
},
"unitCode": {
"#id": "s:unitCode",
"#type": "#id"
},
"forecastOffice": {
"#type": "#id"
},
"forecastGridData": {
"#type": "#id"
},
"publicZone": {
"#type": "#id"
},
"county": {
"#type": "#id"
}
}
],
"id": "...api.weather.xxx/points/39.7456,-97.0892",
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-97.0892,
39.7456
]
},
"properties": {
"#id": "...api.weather.xxx/points/39.7456,-97.0892",
"#type": "wx:Point",
"cwa": "TOP",
"forecastOffice": "...api.weather.xxx/offices/TOP",
"gridX": 31,
"gridY": 80,
...
"relativeLocation": {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-97.086661,
39.679376
]
},
"properties": {
"city": "Linn",
"state": "KS",
"distance": {
"value": 7366.9851976444,
"unitCode": "unit:m"
},
"bearing": {
"value": 358,
"unitCode": "unit:degrees_true"
}
}
},
...
}
}
I am interested in getting all the Properties in plain text or JSON.
Modify your headers to accept JSON.
var options = {
url: 'https://api.weather.gov/points/39.7456,-97.0892',
headers: {
'user-agent': 'request',
'accept': 'application/json'
}
};

Can AWS Cognito adminCreateUser send a temporary password?

The Amazon Cognito adminCreateUser documentation on TemporaryPassword states:
This parameter is not required. If you do not specify a value, Amazon
Cognito generates one for you.
How does the user ever get it? At first I thought it would get emailed to the user, but that doesn't seem to be the case. Then I thought maybe it would come back in the response. Nope.
Here's the code I'm calling in my node JS Lambda function:
adminCreateUser(
{
"UserPoolId": "us-east-1_XXXXXXXX",
"Username": "roger__mailinator.com",
"DesiredDeliveryMediums": [
"EMAIL"
],
"ForceAliasCreation": false,
"MessageAction": "SUPPRESS",
"UserAttributes": [
{
"Name": "given_name",
"Value": "Rodger"
},
{
"Name": "family_name",
"Value": "Ribbit"
},
{
"Name": "name",
"Value": "Rodger Ribbit"
},
{
"Name": "email",
"Value": "roger#mailinator.com"
},
{
"Name": "custom:title",
"Value": "Animation Designer"
},
{
"Name": "custom:company",
"Value": "76"
}
]
}, function(error, data) {
if (error) {
console.log("Error adding user to cognito: " + error, error.stack);
//...
} else {
console.log("Received back from cognito: " + JSON.stringify(data));
//...
}
});
and here's the response I get:
Received back from cognito:
{
"User": {
"Username": "roger__mailinator.com",
"Attributes": [
{
"Name": "custom:title",
"Value": "Animation Designer"
},
{
"Name": "sub",
"Value": "1cd612a0-0da0-4e7b-84c7-30570fab80a9"
},
{
"Name": "name",
"Value": "Rodger Ribbit"
},
{
"Name": "given_name",
"Value": "Rodger"
},
{
"Name": "family_name",
"Value": "Ribbit"
},
{
"Name": "email",
"Value": "roger#mailinator.com"
},
{
"Name": "custom:company",
"Value": "76"
}
],
"UserCreateDate": "2017-03-30T18:31:34.283Z",
"UserLastModifiedDate": "2017-03-30T18:31:34.283Z",
"Enabled": true,
"UserStatus": "FORCE_CHANGE_PASSWORD"
}
}
Where does the password go? Are we supposed to guess it? :-)
I think it's because you are passing "MessageAction": "SUPPRESS". That would suppress the sending of the email.
The temporary password is emailed to the user and he needs to reset it upon the first login.
The answer is that the user email needs to be verified before they'll receive it. So you need to modify the user attribute on email to be verified. See: https://stackoverflow.com/a/43033722/491553

PayPal Client Authentication Failed

Since I switched from the sandbox mode to the real deal I get a client authentication failed error.
Config:
{
"port": 5000,
"api": {
"host": "api.paypal.com/v1/",
"port": "",
"client_id": "-",
"client_secret": "-"
}
}
I've double checked my client id and secret, they are enabled and aren't for the sandbox mode.
Code:
paypalService.getPaypalMethodOption(req.body.paymentMethodOptionId).then(function (paymentMethodOption) {
var invoiceId = uuid.v4();
var payment = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"transactions": [{
"amount": {
"currency": 'USD',
"total": paymentMethodOption.Price
},
"description": paymentMethodOption.Description,
"invoice_number": invoiceId
}]
};
payment.payer.payment_method = 'paypal';
payment.redirect_urls = {
"return_url": "http://localhost:3000/paypal/execute",
"cancel_url": "http://localhost:3000/donate/cancelled"
};
paypal.payment.create(payment, function (error, payment) {
// error
});
});
What can be the problem?
After searching for a few hours i found out that i needed another property.
Apparently you need to add the property mode with the value "live". The documentation isn't very clear on this part, neither are there any live example codes in the node sdk github repository.
My config now looks like the following:
{
"port": 5000,
"api": {
"mode": "live",
"host": "api.paypal.com",
"port": "",
"client_id": "-",
"client_secret": "-"
}
}

Using build in model accessToken not working in loopback

I'm trying to begin programming an api for an android application and wanted to use node.js + loopback for this. But I'm running into some trouble testing/ learning the language.
Following code should generate new users in my database(and it does) but when I try to login with this user no AccessToken in created an printen to the console. Any idea what I'm doing wrong?
My Test code: create-test-data.js
var app = require('./app');
var dataSource = app.dataSources.mysql;
var loopback = require('loopback');
var User = loopback.User; // Getting User Model
var AccessToken = loopback.AccessToken; // Getting AccessTokenModel
/*
Initializing the database done by this. If already exist it will clean it.
dataSource.automigrate('user', function (err) {});
dataSource.automigrate('account', function (err) {});
dataSource.automigrate('accesstoken', function (err) {});
*/
//Creating some users in mysql database
User.create({username: 'timbo', email: 'test#gmail.com', password: 'monkey123'} , function(err, user) {console.log(user);});
User.create({username: 'timbo2', email: 'test2#gmail.com', password: 'monkey123'} , function(err,user) {console.log(user);});
User.create({username: 'timbo3', email: 'test3#gmail.com', password: 'monkey123'} , function(err,user) {console.log(user);});
User.login({username: 'timbo', password: 'monkey123'}, function(err, accesstoken) {console.log("This is the token: " + accesstoken);});
//No accesstoken created / saved in the database
datasource.json
{
"db": {
"defaultForType": "db",
"connector": "mysql",
"host": "127.0.0.1",
"database": "test",
"user": "root",
"password": "warcraft"
},
"push": {
"defaultForType": "push",
"connector": "loopback-push-notification",
"installation": "installation",
"notification": "notification",
"application": "application"
},
"mail": {
"defaultForType": "mail",
"connector": "mail"
},
"mysql": {
"connector": "mysql",
"host": "127.0.0.1",
"database": "test",
"user": "root",
"password": "warcraft"
}
}
models.json
{
"email": {
"options": {
"base": "Email"
},
"dataSource": "mail",
"public": false
},
"user": {
"options": {
"base": "User",
"relations": {
"accessTokens": {
"model": "accessToken",
"type": "hasMany",
"foreignKey": "userId"
}
}
},
"dataSource": "mysql",
"public": true
},
"accessToken": {
"options": {
"base": "AccessToken"
},
"dataSource": "mysql",
"public": true
},
"application": {
"options": {
"base": "Application"
},
"dataSource": "db",
"public": true
},
"acl": {
"options": {
"base": "ACL"
},
"dataSource": "db",
"public": false
},
"roleMapping": {
"options": {
"base": "RoleMapping"
},
"dataSource": "db",
"public": false
},
"role": {
"options": {
"base": "Role",
"relations": {
"principals": {
"type": "hasMany",
"model": "roleMapping",
"foreignKey": "roleId"
}
}
},
"dataSource": "db",
"public": false
},
"scope": {
"options": {
"base": "Scope"
},
"dataSource": "db",
"public": false
},
"push": {
"options": {
"base": "Push",
"plural": "push"
},
"dataSource": "push"
},
"installation": {
"options": {
"base": "Installation"
},
"dataSource": "db",
"public": true
},
"notification": {
"options": {
"base": "Notification"
},
"dataSource": "db",
"public": true
},
"product": {
"properties": {
"email": {
"type": "string"
},
"level": {
"type": "number"
},
"create": {
"type": "date"
},
"modified": {
"type": "date"
}
},
"public": true,
"dataSource": "db",
"plural": "products"
},
"account": {
"properties": {
"email": {
"type": "string"
},
"level": {
"type": "number"
},
"created": {
"type": "date"
},
"modified": {
"type": "date"
}
},
"public": true,
"dataSource": "mysql",
"plural": "accounts"
}
}
Console Output
{ username: 'timbo',
email: 'test#gmail.com',
password: '$2a$10$972DFwMOuOhKj5ThfbchC.ipcNaW27ccpHMRkW17uSLutaCHyZF0G',
realm: undefined,
emailVerified: undefined,
verificationToken: undefined,
credentials: [],
challenges: [],
status: undefined,
created: undefined,
lastUpdated: undefined,
id: undefined }
{ username: 'timbo2',
email: 'test2#gmail.com',
password: '$2a$10$1peSixaOIQq8umOzzEy86OQKxoPFU.Ax2/NWC1oLGjQHPp9oZdPDW',
realm: undefined,
emailVerified: undefined,
verificationToken: undefined,
credentials: [],
challenges: [],
status: undefined,
created: undefined,
lastUpdated: undefined,
id: undefined }
{ username: 'timbo3',
email: 'test3#gmail.com',
password: '$2a$10$X3fdV2dL6kjuj69Dqr.jMeVdqIMzveN7NnJP5TXag54b4tpzZ4LGW',
realm: undefined,
emailVerified: undefined,
verificationToken: undefined,
credentials: [],
challenges: [],
status: undefined,
created: undefined,
lastUpdated: undefined,
id: undefined }
This is the token: undefined
This is the token err: Error: ER_BAD_FIELD_ERROR: Unknown column 'ttl' in 'field list'
You have to attach User-related models to your datasource first:
loopback.User.attachTo(dataSource);
loopback.AccessToken.attachTo(dataSource);
loopback.Role.attachTo(dataSource);
loopback.ACL.attachTo(dataSource);
And define the relationship between User and AccessToken:
loopback.User.hasMany(loopback.AccessToken, {as: 'accessTokens'});
When creating test data, you should wait for User.create to finish before calling User.login. (Rember, Node.js is asynchronous.)
User.create(
{username: 'timbo', email: 'test#gmail.com', password: 'monkey123'},
function(err, user) {
// TODO: handle err != null
User.login(
{username: 'timbo', password: 'monkey123'},
function(err, accesstoken) {
console.log("This is the token: " + accesstoken);
});
});

Resources