How should I create the node js sendinblue email api? - node.js

I have attached here my sendinblue node js typescript api, I am
getting error only not getting any mail in my gmail. I am using this
package for mail send sib-api-v3-sdk. below is my api code, what is
the issue. what i have to add in my api.
const Sib = require('sib-api-v3-sdk');
const loginemail = async (req: Request) => {
const connection = await createConnection()
try{
const client=Sib.ApiClient.instance;
let apiKey = client.authentications['apiKey'];
apiKey.apiKey = process.env.API_KEY;
let transEmailApi = new Sib.TransactionalEmailsApi();
let sender ={
email: 'jagadeeshwaran907#gmail.com'}
let reciever = [{
email: 'jagadeeshwaran907#gmail.com'
}]
let v= transEmailApi.sendTransacEmail( {
sender,
to: reciever,
subject:"transactional mail has been sent successfully",
textContent: `successfully`
}).then(console.log("error"))
return v;
} catch(error){
await connection.end()
throw error
}
}

Related

How do you query data using Mongoose within a service function?

I have a service in my node application where I am trying to use nodemailer to send an email with a link to clients. The issue I am having is that when I try to query the recipient email address using Mongoose in the service I get this response message in the console log Promise { <pending> } and obviously my email does not send because I am not returning an email address. I am using the code below as the service that is called from my controller. It looks like everything is working fine in the controller because when I use a test email address as the recipient email the message is sent and function returns no errors. Am I writing the function to query the email wrong or is there a better way I should be setting this up?
var nodemailer = require('nodemailer');
const Obrf = require("../models/Obrf");
const sendLink = (x) => {
var id = x;
const offerid = id.toString();
const url = 'http://localhost:3000/offerletter/' + offerid
async function returnEmail (y) {
const email = await Obrf.findById(y, 'email_address').exec();
return email;
};
const sendToEmail = returnEmail(id);
console.log(sendToEmail);
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'sender#gmail.com',
pass: 'password'
}
});
var mailOptions = {
from: 'sender#gmail.com',
to: sendToEmail,
subject: 'Congratulations on your offer!',
text: 'Go to: ' + url + ' to sign your offer letter!'
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
};
module.exports = {
sendLink,
};
async before a function makes the function return a promise:
are you sure if Obrf.findById(y, 'email_address').exec() returning promise ?
if not remove the aysnc await
function returnEmail (y) {
const email = Obrf.findById(y, 'email_address').exec();
return email;
};
const sendToEmail = returnEmail(id);
if its returning the promise then do something like this
const sendToEmail = returnEmail(id).then(id=>id);

Firebase cloud function doesn't send push notification with async

My goal is to send a push notification when a user sends a message. I am trying to do this by retrieving all of the push tokens from the firestore database, and sending a multicast message using these tokens each time a new message is added to the realtime database.
Works
This first example works. There is no token retrieval, the tokens are hardcoded. I do receive the notifications.
exports.notifyUsers = functions.database.ref('/messages/{messageId}').onCreate((liveSnapshot, context) => {
const name = context.params.messageId;
const message = liveSnapshot.val().toString();
const tokens = [
"e6erA_qM...",
"ePU9p_CI...",
];
const payload = {
notification: {
title: `New message from ${name}`,
body: message,
badge: '1',
sound: 'default'
},
tokens: tokens,
}
const res = admin.messaging().sendMulticast(payload);
console.log(`response: ${res}`);
Doesn't work
This doesn't work, I don't receive any notifications.
exports.notifyUsers = functions.database.ref('/messages/{messageId}').onCreate(async (liveSnapshot, context) => {
const name = context.params.messageId;
const message = liveSnapshot.val().toString();
const snapshot = await admin.firestore().collection('users').get();
const tokens = snapshot.docs.map(doc => doc.data().token);
const payload = {
notification: {
title: `New message from ${name}`,
body: message,
badge: '1',
sound: 'default'
},
tokens: tokens,
}
const res = await admin.messaging().sendMulticast(payload);
console.log(`response: ${res}`);
I have verified that the tokens retrieved from the database are the same as the hardcoded ones with the following code.
exports.notifyUsers = functions.database.ref('/messages/{messageId}').onCreate(async (liveSnapshot, context) => {
const hardcodedTokens = [
"e6erA_qM...",
"ePU9p_CI...",
];
const snapshot = await admin.firestore().collection('users').get();
const tokens = snapshot.docs.map(doc => doc.data().token);
let same = true;
hardcodedTokens.forEach(el => {
if (!tokens.includes(el)) {
same = false;
}
});
console.log(same);
})
This logs true in the firebase cloud functions console.
The function uses Node 12.
I experienced a similar problem recently, and solved it by breaking out Android and iOS specific fields according to the Firebase docs :
const message = {
"notification": {
"title": `New message from ${name}`,
"body": message,
},
'apns': {
'payload': {
'aps': {
'badge': 1,
},
},
},
'android':{
'notification':{
'notificationCount': 1,
},
},
"tokens": tokens,
}
The following code works.
async function getTokens() {
const snapshot = await admin.firestore().collection('users').get();
return snapshot.docs.map(doc => doc.data().token);
}
exports.notifyUsers = functions.database.ref('/messages/{messageId}').onCreate(async (snapshot, context) => {
const name = context.params.messageId;
const message = snapshot.val().toString();
const tokens = await getTokens();
const payload = {
notification: {
title: `New message from ${name}`,
body: message,
},
tokens: tokens,
};
await admin.messaging().sendMulticast(payload);
})
I logged my response like below:
const res = await admin.messaging().sendMulticast(payload);
console.log('response:', JSON.stringify(res));
This logged the following:
response: {"responses":[{"success":false,"error":{"code":"messaging/invalid-argument","message":"Invalid JSON payload received. Unknown name \"sound\" at 'message.notification': Cannot find field."}},{"success":false,"error":{"code":"messaging/invalid-argument","message":"Invalid JSON payload received. Unknown name \"sound\" at 'message.notification': Cannot find field."}}],"successCount":0,"failureCount":2}
Based on this, I believe the problem was the sound argument in the notification part of the payload. It works after removing it.

Variable not picking up returned value from function

I'm trying to collect the of returned values of two functions, send-mail and sendsms, into a variable(var ordermessage). It picks up the returned value from send-sms just fine.
I'm using the mailgun api for send-mail, and ordermessage just picks up 'undefined'. But send-mail keeps running.
I've tried `await mailgun.messages().send(...)`
I've tried `const myvar = await mailgun.messages().send(...)`
and also `let myvar = await mailgun.messages().send...`
Nada.
I tried using a function that had the api call as a callback. Still got undefined. The email and sms both get sent, but I need the reply from the email server. I'm using Mailgun trial so I need to return a response.
send-mail.js
var mailgun = require('mailgun-js')({apiKey: process.env.MAILGUN_API_KEY, domain: process.env.MAILGUN_DOMAIN});
var processresponse = "\n";
var data = {
from: 'Zigy Demo Store <admin_demo#zigy.com>',
to: email,
subject: 'You have placed an order.',
text: body
};
console.log("\n----------START EMAIL-------------\n");
mailgun.messages()
.send(data, function (error, body) {
console.log("\nFinally running MAILGUN. Return body is\n", body);
if (body == undefined || body == false) {
console.log("Got nothing from server.");
} else {
processresponse += body.message;
console.log("***********************Gotten reply from Mailgun server.*******************************\n", processresponse);
}
});
OrderController function
module.exports = {
neworder: async function(req, res) {
var sendemail = require('./send-mail');
var sendtext = require('./send-sms');
var orderdetails = 'New order created at '+ new Date() + '\nItem ---> Price'; //Message that will be sent to users.
var item;
var printcart = await Shoppingcart.findOne({
where: {
id: req.body.cart,
owner: req.body.user
}
}).populate('product');
var ordermessage = '';
for (items in printcart.product) {
item = printcart.product[items];
orderdetails += '\n' + item.name + ' ---> ' + item.price;
}
console.log(orderdetails);
//to get email addr and phone number
phone = req.body.phone;
var email = req.body.email;
var user = await User.findOne({id:printcart.owner});
ordermessage += await sendemail(email, orderdetails);
console.log("\nAfter email, the message is ", ordermessage);
ordermessage += await sendtext(phone, orderdetails);
console.log("\nAfter text, Printing order message to be returned to browser ", ordermessage);
console.log("Final message ", ordermessage);
res.send(ordermessage);
}
};
Terminal
----------START EMAIL-------------
Calling test function
After email, the message is
Finally running MAILGUN. Return body is
{ id:
'<20190222062410.1.FD7A4868FA0ADF5E#sandbox612cf746219c46ad93d5dc588f9341ff.mailgun.org>',
message: 'Queued. Thank you.' }
***********************Gotten reply from Mailgun server.*******************************
Queued. Thank you.
Checking list of verified numbers...
Found the phonenumber!
You will receive an SMS message with your order details soon.
After text, Printing order message to be returned to browser
You will receive an SMS message with your order details soon.
Final message
You will receive an SMS message with your order details soon.
SM9bc04208f9354834a153fb1ffd7dc8bb
Any help will be greatly appreciated.
Edit: I called res.write from inside send-mail.js and send-sms.js instead and got rid of the variable ordermessage.
This is a guess: I think the mailgun.messages().send(...) method doesn't return anything as it uses a classic callback. So you will always get undefined from it.
But you get the result from the body parameter in the callback. You could use Promisify to transform the callback into a promise style method.
const util = require('util');
const fs = require('fs');
const messages = mailgun.messages();
const sendPromisified = util.promisify(messages.send());
sendPromisified(data).then((body) => {
// Do something with `body`
}).catch((error) => {
// Handle mailgun error
});
// Async / await style
try {
const mailBody = await sendPromisified(data);
} catch (err) {
// handle mailgun error `err`
}

NodeJs TypeError: Cannot read property 'key' of undefined

i want to create a cloud function which sends email if some data where added to my database. Unfortunately while trying to deploy my function i receive this error:
TypeError: Cannot read property 'key' of undefined
Here is my function:
const functions = require('firebase-functions')
const nodemailer = require('nodemailer')
const postmarkTransport = require('nodemailer-postmark-transport')
const admin = require('firebase-admin')
// 2. Admin SDK can only be initialized once
try {admin.initializeApp(functions.config().firebase)} catch(e) {
console.log('dbCompaniesOnUpdate initializeApp failure')
}
// 3. Google Cloud environment variable used:
const postmarkKey = functions.config().postmark.key
const mailTransport = nodemailer.createTransport(postmarkTransport({
auth: {
apiKey: postmarkKey
}
}))
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-
functions
//
exports.sendingEmailForlocationsRequests =
functions.database.ref('/clubs/{clubId}/{pushId}')
.onWrite((event) => {
//I want to retrieve the pushID
return sendEmail();
})
function sendEmail() {
// 5. Send welcome email to new users
const mailOptions = {
from: '"Dave" <noreply#clate.de>',
to: 'locations#clate.de',
subject: 'Welcome!',
html: `<Test>`
}
// 6. Process the sending of this email via nodemailer
return mailTransport.sendMail(mailOptions)
.then(() => console.log('dbCompaniesOnUpdate:Welcome
confirmation email'))
.catch((error) => console.error('There was an error while
sending the email:', error))
}
It looks like 'postmark' isn't set in your firebase configuration. You can set what's retrieved by functions.config() using the CLI: https://firebase.google.com/docs/functions/config-env

Promise not returning value on request

I have been trying to get this to work, but am new to NodeJS. I suspect the issue is due to async, but am not familiar with how it works.
The idea behind this code is that it monitors a firebase database change and sends an email to the users. I am getting everything from the change snapshot, and using the values to check another table for user data. The request is not returning before the email gets sent and I am unsure why.
Edit I should specify that the email function sgMail is firing off before I get the results from the requests. I've tried putting a delay, but I am still not getting the result to return in time.
Here's my index.js
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
var requestify = require('requestify');
//SendGrid
const SENDGRID_API_KEY = functions.config().sendgrid.key;
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(SENDGRID_API_KEY);
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.packingListEmail = functions.database.ref('Order/{orderID}')
.onUpdate(event => {
// Grab the current value of what was written to the Realtime Database.
const eventSnapshot = event.data;
//Here You can get value through key
var shipperInfo = eventSnapshot.child("fk_shipper_id").val();
var travelerInfo = eventSnapshot.child("fk_traveler_id").val();
//Print value of string
console.log(shipperInfo);
//Get Shipper Info
const shipperPath = 'https://shlep-me-f516e.firebaseio.com/User/'+shipperInfo+'.json';
requestify.get(shipperPath)
.then(function(response) {
// Get the response body (JSON parsed or jQuery object for XMLs)
shipperResult = response.getBody();
console.log(shipperResult.email);
return shipperResult;
});
function getTravelerData() {
return new Promise(resolve => {
requestify.get('https://shlep-me-f516e.firebaseio.com/User/' + travelerInfo + '.json')
.then(function (response) {
resolve(response.getBody())
});
});
}
var TravelD = getTravelerData();
//Send an email
const msg = {
to: 'andrew#shlepme.com',
from: 'support#shlepme.com',
subject: 'New Follower',
// text: `Hey ${toName}. You have a new follower!!! `,
// html: `<strong>Hey ${toName}. You have a new follower!!!</strong>`,
// custom templates
templateId: 'd1ccfeb9-2e2d-4979-a3ca-c53975fe486e',
substitutionWrappers: ['%', '%'],
substitutions: {
'%shipper_name%': "Test",
'traveler_name': TravelD.name
// and other custom properties here
}
};
console.log('Sending email');
console.log(TravelD);
return sgMail.send(msg)
});
Any ideas? I have been trying to figure this out.
It seems that you need to understand about Promises first.
When you start using promises you will need to ALWAYS use them and chain one with the other.
So I would rewrite your code like this: (not tested)
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require("firebase-functions");
var requestify = require("requestify");
//SendGrid
const SENDGRID_API_KEY = functions.config().sendgrid.key;
const sgMail = require("#sendgrid/mail");
sgMail.setApiKey(SENDGRID_API_KEY);
// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
exports.packingListEmail = functions.database
.ref("Order/{orderID}")
.onUpdate(event => {
// Grab the current value of what was written to the Realtime Database.
const eventSnapshot = event.data;
//Here You can get value through key
var shipperInfo = eventSnapshot.child("fk_shipper_id").val();
var travelerInfo = eventSnapshot.child("fk_traveler_id").val();
//Print value of string
console.log(shipperInfo);
//Get Shipper Info
const shipperPath = "https://shlep-me-f516e.firebaseio.com/User/" + shipperInfo + ".json";
requestify.get(shipperPath)
.then(function(response) {
// Get the response body (JSON parsed or jQuery object for XMLs)
var shipperResult = response.getBody();
console.log(shipperResult.email);
return shipperResult;
})
.then(function (shipperResult) {
//Send an email
const msg = {
to: "andrew#shlepme.com",
from: "support#shlepme.com",
subject: "New Follower",
// text: `Hey ${toName}. You have a new follower!!! `,
// html: `<strong>Hey ${toName}. You have a new follower!!!</strong>`,
// custom templates
templateId: "d1ccfeb9-2e2d-4979-a3ca-c53975fe486e",
substitutionWrappers: ["%", "%"],
substitutions: {
"%shipper_name%": "Test",
traveler_name: shipperResult.name
// and other custom properties here
}
};
console.log("Sending email");
console.log(shipperResult);
return sgMail.send(msg);
});
});

Resources