How to use async and await in gmail read message API - async-await

I tried using async/await instead of the callback for reading the Gmail
Here is the code snippet
const {google} = require('googleapis');
async function getRecentMessageBody(auth) {
const gmail = google.gmail({version: 'v1', auth});
try{
const messageId = await gmail.users.messages.list({
userId: 'me',
labelIds: 'INBOX',
maxResults: 1
});
const message = await gmail.users.messages.get({
userId: 'me',
id: messageId.data.messages[0].id,
format : 'full'
});
const value = base64url.decode(message.data.payload.body.data);
console.log(messageId);
//return value ;
}
catch(error) {
console.log('Error occurs while reading mail :'+ error);
throw error;
}
}
But the messageId is undefined
whereas if i use
gmail.users.labels.list({
userId: 'me',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const labels = res.data.labels;
if (labels.length) {
console.log('Labels:');
labels.forEach((label) => {
console.log(`- ${label.name}`);
});
} else {
console.log('No labels found.');
}
});
how to fix the issue??

use promisfy to convert callback to promises

Related

`next.js` api is resolved before promise fullfill?

I want to achieve something like this:
call my website url https://mywebsite/api/something
then my next.js website api will call external api
get external api data
update external api data to mongodb database one by one
then return respose it's status.
Below code is working correctly correctly. data is updating on mongodb but when I request to my api url it respond me very quickly then it updates data in database.
But I want to first update data in database and then respond me
No matter how much time its take.
Below is my code
export default async function handler(req, res) {
async function updateServer(){
return new Promise(async function(resolve, reject){
const statusArray = [];
const apiUrl = `https://example.com/api`;
const response = await fetch(apiUrl, {headers: { "Content-Type": "application/json" }});
const newsResults = await response.json();
const articles = await newsResults["articles"];
for (let i = 0; i < articles.length; i++) {
const article = articles[i];
try {
insertionData["title"] = article["title"];
insertionData["description"] = article["description"];
MongoClient.connect(mongoUri, async function (error, db) {
if (error) throw error;
const articlesCollection = db.db("database").collection("collectionname");
const customQuery = { url: article["url"] };
const customUpdate = { $set: insertionData };
const customOptions = { upsert: true };
const status = await articlesCollection.updateOne(customQuery,customUpdate,customOptions);
statusArray.push(status);
db.close();
});
} catch (error) {console.log(error);}
}
if(statusArray){
console.log("success", statusArray.length);
resolve(statusArray);
} else {
console.log("error");
reject("reject because no statusArray");
}
});
}
updateServer().then(
function(statusArray){
return res.status(200).json({ "response": "success","statusArray":statusArray }).end();
}
).catch(
function(error){
return res.status(500).json({ "response": "error", }).end();
}
);
}
How to achieve that?
Any suggestions are always welcome!

NextJs - Node - API resolved without sending a response for /api/xxx

I have a nextjs app with a backend api where I am sending an email out.
I have seen a couple of other posts with the same issue, have tried their resolutions and not sure what I am missing.
Any insight is appreciated.
The code in the API is below.
const nodemailer = require('nodemailer');
export default function (req, res) {
const mailData = {
from: 'xxxxx',
to: req.body.email,
subject: 'Message to Full On Consulting',
text: req.body.message,
html: '<div>'+req.body.message+'</div>'
}
sendMail(mailData)
.then((result) => {
console.log('Email sent...', result);
res.status(200).json({ status: 'SUCCESS' })
})
.catch((error) => console.log('Error ... ' + error.message));
}
async function sendMail(mailData) {
try {
let transport = nodemailer.createTransport({
host: "mail.xxxxxxxxxx.com",
port: 587,
secure: false,
auth: {
user: process.env.GMAIL_UID,
pass: process.env.GMAIL_PW
}
});
const result = await transport.sendMail(mailData)
return result;
} catch (error) {
console.log("CATCH ERROR: " + error)
return error;
}`enter code here`
}
I wrapped the sendmail call in a promise and that seems to have worked.
var promise = new Promise( (resolve, reject) => {
let result = transport.sendMail(mailData);
});
promise.then( result => {
console.log("PRomise Success ...");
}, function(error) {
console.log("Promise Failure...");
});

async await , nodejs readfile and then do other

I tried to read file through async/await and update the credentials , But i got response HI first and then hello in console.And Credentials also not updated in oauthClient2.
const getFile = async (req, res, next) => {
await fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return null;
console.log("hello")
console.log(JSON.parse(token));
oauth2Client.credentials = JSON.parse(token);
});
console.log("HI")
var service = google.drive({
version: 'v3',
encoding: null
});
console.log(oauth2Client);
await service.files.get({
auth: oauth2Client,
fileId: "1ZR8kkvb2JYVxcUjmlgfBJD2IYnisaiFn",
alt: 'media'
}, function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
responder(res)(null,response);
});
}
Is there a way in which everything should run in a order?
Thank You.
The reason you are experiencing the error you see, is because the method you are running is asynchronous. You should instead use the alternative synchronous version:
let token;
try {
token = fs.readFileSync(TOKEN_PATH, 'utf8');
} catch (err) {
console.error(err)
}
if(!token){ return; }
oauth2Client.credentials = token;
const service = google.drive({
version: 'v3',
encoding: null
});
await service.files.get({
auth: oauth2Client,
fileId: "1ZR8kkvb2JYVxcUjmlgfBJD2IYnisaiFn",
alt: 'media'
}, function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
responder(res)(null,response);
});
Ref: https://nodejs.dev/learn/reading-files-with-nodejs

Apollo Server: How can I send a response based on a callback?

I am currently trying to validate iOS receipts for in app purchases using this package: https://github.com/Wizcorp/node-iap
This is my incomplete resolver:
export default {
Query: {
isSubscribed: combineResolvers(
isAuthenticated,
async (parent, args, { models, currentUser }) => {
const subscription = await models.Subscription.find({ user: currentUser.id });
const payment = {
...
};
iap.verifyPayment(subscription.platform, payment, (error, response) => {
/* How do I return a response here if it is async and I don't have the response object? */
});
}
),
},
};
How do I return a response here if it is async and I don't have the response object? Normally, I'm just used to returning whatever the model returns. However, this time I'm using node-iap and it's callback based.
You can use a Promise:
const response = await new Promise((resolve, reject) => {
iap.verifyPayment(subscription.platform, payment, (error, response) => {
if(error){
reject(error);
}else{
resolve(response);
}
});
});

Google recaptcha v3 always returning error

Following the instructions I get a valid token from my front end (can see in dev tools):
window.grecaptcha
.execute(captchaPkey, { action: 'contact' })
.then((token) => {
// this is what I POST to my API
So in my React front end:
send = (event) => {
event.preventDefault()
this.setState({ busy: true })
window.grecaptcha.ready(() => {
window.grecaptcha
.execute(captchaPkey, { action: 'contact' })
.then((token) => {
// successfully get token
const payload = {
token,
name: this.state.name,
to: this.props.to,
email: this.state.email,
message: this.state.message,
}
// now I'm sending the payload to my API
// My API
update(`${api}/contact/`, {
method: 'POST',
body: JSON.stringify(payload)
}, null)
.then(data => {
this.setState({ busy: false, result: 'Email sent' });
})
.catch(error => {
this.setState({ busy: false, error: error.message });
});
})
})
}
my API controller
async function verifyCaptcha(token) {
return await axios.post('https://www.google.com/recaptcha/api/siteverify', {
secret: process.env.CAPTCHA_PKEY,
response: token
})
}
async function contact({ token, to, name, email, message }) {
const result = await verifyCaptcha(token)
if (!result || !result.data || !result.data.success) {
// always get an error here
throw new Error('Invalid captcha')
}
let targetEmail = 'default#emailaddress'
if (to !== 'admin') {
const user = await User.findOne({ username: to }, { email }).exec()
if (!user) {
throw new Error('User does not exist')
}
targetEmail = user.email
}
// rest of send
}
On my API POST endpoint sends to https://www.google.com/recaptcha/api/siteverify with the body of:
{
secret: process.env.CAPTCHA_PKEY,
response: token
}
Yet I always get "missing-input-response", "missing-input-secret" error. Is this because v3 is new? Still bugs?
Realised in the documentation it states "post params" not post body haha.

Resources