Gmail API nodejs messages.list labelIds not working - node.js

I am using node.js in a server to access a user's Gmail Inbox. The OAuth2 part works great, but when I try to specify the INBOX to get a message list, it seems to be ignored. I get the complete array of message ids, not just ones in the INBOX. In every attempt I get an array of the first 100 message ids, but the INBOX has only 5 messages. I've also tried with other labels such as 'UNREAD' with the same results.
It seems as though the 'labelIds' parameter is not being passed in the request (or is being ignored). Keep in mind that this is using the Node.js API without using Express.js.
Here are code snippets. What am I missing?
var http = require("http");
var url = require("url");
var fs = require('fs')
var google = require('googleapis');
var googleAuth = require('google-auth-library');
...
var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
var gmail = google.gmail('v1');
gmail.users.messages.list ({
auth:oauth2Client,
userId:'me',
labelIds:"INBOX"}, function (err, result)
{
... etc.

User.message.list takes a label id. So first we search the users labels. Link
GET https://www.googleapis.com/gmail/v1/users/me/labels?fields=*&key={YOUR_API_KEY}
Response:
{
"id": "INBOX",
"name": "INBOX",
"messageListVisibility": "hide",
"labelListVisibility": "labelShow",
"type": "system"
},
So now we know the correct value to pass is INBOX link
GET https://www.googleapis.com/gmail/v1/users/me/messages?labelIds=INBOX&fields=*&key={YOUR_API_KEY}
Your code uses inbox when the proper value to pass is INBOX. You say you have tried this i suggest you try again and edit your question and post any errors you using INBOX should work.

Related

Can't receive email with attachment from mailgun

I create router from mailgun to forward emails to my website endpoint www.example.com/messages
and I received emails successfully when it only text but when i attach file to this email, I don't receive any thing and the request body is empty
export const incomingEmails = async (req, res) => {
const from = req.body.from.split('<')[0].trim();
const sender = req.body.sender;
const recipient = req.body.recipient;
const subject = req.body.subject;
const html = req.body['stripped-html'];
try {
const incomingEmail = new Support({
from,
sender,
recipient,
subject,
html
})
await incomingEmail.save();
res.sendStatus(200)
} catch (error) {
res.status(500)
next(new Error('something went wrong'))
}}
i'm using url encoded middle ware
app.use(express.urlencoded())
note the stack I use is node and express at at backend
I ran into the same issue and I figured out why. I used the forward method to receive emails on my backend. The forward method only works when there is no attachment. With attachments, Mailgun will return an empty body because Mailgun has to first store the attachments, which is asynchronous.
In order to solve this issue, you have to use the store method instead of the forward method:
store(notification endpoint)
Stores the message temporarily (for up to 3 days) on Mailgun’s servers
so that you can retrieve it later. This is helpful for large
attachments that may cause time-outs or if you just want to retrieve
them later to reduce the frequency of hits on your server.
You have to edit your route in the Mailgun web app: go under "Receiving" in the menu and then edit your existing route.
Instead of entering:
forward("http://example.com/callback")
You enter:
store(notify="http://example.com/callback")

Is there a way to instantiate a new client on server side by firebase cloud function?

I am developing an app and trying to implement news feed by getstream.io using react native and firebase.
Is there a way to generate user token by using firebase cloud function. If there is, would you please give me a pointer how i can do so? (the snippet of codes in cloud function side and client side would be super helpful..)
I have seen similar questions, only to find out no specific tutorial.. any help is appreciated!
For the cloud function side you need to create a https.onRequest endpoint that calls createUserToken like so:
const functions = require('firebase-functions');
const stream = require('getstream');
const client = stream.connect('YOUR_STREAM_KEY', 'YOUR_STREAM_SECRET', 'YOUR_STREAM_ID');
exports.getStreamToken = functions.https.onRequest((req, res) => {
const token = client.createUserToken(req.body.userId);
return { token };
});
After that, deploy with firebase deploy --only functions in the terminal & get the url for the function from your firebase dashboard.
Then you can use the url in a POST request with axios or fetch or whatever like this:
const { data } = axios({
data: {
userId: 'lukesmetham', // Pass the user id for the user you want to generate the token for here.
},
method: 'POST',
url: 'CLOUD_FUNC_URL_HERE',
});
Now, data.token will be the returned stream token and you can save it to AsyncStorage or wherever you want to store it. Are you keeping your user data in firebase/firestore or stream itself? With a bit more background I can add to the above code for you depending on your setup! 😊 Hopefully this helps!
UPDATE:
const functions = require('firebase-functions');
const stream = require('getstream');
const client = stream.connect('YOUR_STREAM_KEY', 'YOUR_STREAM_SECRET', 'YOUR_STREAM_ID');
// The onCreate listener will listen to any NEW documents created
// in the user collection and will only run when it is created for the first time.
// We then use the {userId} wildcard (you can call this whatever you like.) Which will
// be filled with the document's key at runtime through the context object below.
exports.onCreateUser = functions.firestore.document('user/{userId}').onCreate((snapshot, context) => {
// Snapshot is the newly created user data.
const { avatar, email, name } = snapshot.val();
const { userId } = context.params; // this is the wildcard from the document param above.
// you can then pass this to the createUserToken function
// and do whatever you like with it from here
const streamToken = client.createUserToken(userId);
});
Let me know if that needs clearing up, these docs are super helpful for this topic too 😊
https://firebase.google.com/docs/functions/firestore-events

Unable to validate Twilio request in Google cloud function

I have a Google cloud function to which Twilio sends POST requests with SMS statuses but I am unable to verify that the requests are coming from Twilio using any of the methods outlined in https://www.twilio.com/docs/usage/security
My first attempt consisted of using the validateRequest function, as shown in the code below
const twilio = require('twilio');
let url = 'https://....cloudfunctions.net/...'
let token = 'XXXX';
let header = request.headers['x-twilio-signature'];
let sortedKeys = Object.keys(request.body).sort();
let sortedParams = {};
sortedKeys.forEach(key => {
sortedParams[key] = request.body[key];
});
let validated = twilio.validateRequest(token, header, url, sortedParams);
I confirmed that the value of token matched the auth token from the Twilio account settings, sortedParams contained alphabetically sorted camel-cased Twilio request params and the url matched that which was passed to the Twilio client when creating the SMS. However, validateRequest would always return false.
My next attempt involved hashing the combination of the url and request params by copying the code from https://www.twilio.com/docs/libraries/reference/twilio-node/3.18.0/webhooks_webhooks.js.html
const crypto = require('crypto')
sortedKeys.forEach(key => {
url = `${url}${key}${request.body[key]}`;
});
let signature = crypto
.createHmac('sha1', token)
.update(Buffer.from(url, 'utf-8'))
.digest('base64');
Upon comparing the value of signature to that of the header, the two never matched.
Twilio developer evangelist here.
I recommend using the validateRequest method as that does most of the work for you.
You don't need to perform the parameter sorting that you've attempted, JavaScript objects are unordered and the library sorts and appends the parameters to the URL string already.
Things you need to check are that the URL is the exact webhook URL you set in your Twilio console, including the entire path and any query parameters that are included.
Also, have you ensured that request.body is populated and that your express app is using body-parser to parse the incoming request as url encoded form parameters?
app.use(bodyParser.urlencoded({ extended: false }));
If you are trying to validate the request as middleware, make sure that the request validation is done after body parsing.
Does any of that help at all?
It turns out that the there was nothing wrong with the validateRequest but rather the way I was declaring the token. Instead of hard-coding it in the function's code, it was being retrieved from a Google storage bucket as a buffer and then converted to a string. For unknown reasons, even though visually, the retrieved value matched the original token, a === comparison returned false. Once I hard-coded the token, everything worked.

Why the request is being save in express?

I have a problem.
I am developing an API with Node and the express framework to send transactional email using Mandril.
I download the powerdrill library to call the Mandrill API.
Everything is working fine, the emails are being sent ok, except for the problem that the request in the post is saving.
For example, if I call the API once I will send one email, and if I send a second one I will send 2 emails (the first one that I sent and the new one), and if I call the API once again I will send 3 email (the first 2 and the new one).
As you can see I sent 1 email using the request welcome. In the second one I called other request called submittedApplication but when I call the API using POSTMAN 2 emails were sent 1.-the new one and 2.- the first one again.
Does anyone know why the request is saving?
var express = require('express'),
router = express.Router(),
config = require('config'),
Message = require('powerdrill').Message;
var message = new Message();
router.get('/',function(req,res){
res.send('test ok Mandrillllll');
})
router.post('/welcomeGorn',function(req,res){
console.log(req.body);
message.apiKey(config.mandrillKey)
.subject(req.body.subject)
.template(req.body.template)
.from(config.mandrilEmail)
.to(req.body.to)
.tag('complex')
.globalMergeVar('VERIFY_EMAIL',req.body.linkVefifyEmail)
.send(function(err, resp) {
//console.log(resp);
res.send(resp).end();
});
});
router.post('/submittedApplication',function(req,res){
console.log(req.body);
message.apiKey(config.mandrillKey)
.subject(req.body.subject)
.template(req.body.template)
.from(config.mandrilEmail)
.to(req.body.to)
.tag('complex')
.globalMergeVar('RECRUITER_NAME',req.body.recruiterName)
.globalMergeVar('RECRUITER_EXTENSION',req.body.recruiterExtension)
.globalMergeVar('RECRUITER_EMAIL',req.body.recruiterEmail)
.send(function(err, resp) {
//console.log(resp);
res.send(resp);
});
});
module.exports = router;
The console is showing me this warning:
Powerdrill: Attempting to add the same email twice. Using data from first instance
You can find this warning here
I think the problem is message variable is saving all information and sending all together every time. Try to initialize it at the beginning of every method:
router.post('/welcomeGorn',function(req,res){
var message = new Message();

Getting list of messages from Twilio

I am trying to call Twilio services into my node application.
According to docs I am calling list of messages service like bellow
var accountSid = 'ACe622fda3d3cd03b3b975d8d92f7c794b';
var authToken = "your_auth_token";
var client = require('twilio')(accountSid, authToken);
client.messages.list(function(err, data) {
data.messages.forEach(function(message) {
console.log(message.body);
});
});
As a result I am getting first 50 messages with complete details.
Now my issue is how to get previous messages(pagination), conversations between two numbers and using further filters like date.
Twilio developer evangelist here.
List resources return pagination information, including the next and previous pages' URLs. You can also set the page size.
So, for a first pass you can get more than 50 messages by setting the PageSize to the maximum 1000.
client.messages.list({ PageSize: 1000 }, function(err, data) {
data.messages.forEach(function(message) {
console.log(message.body);
});
});
If you need to go beyond that, then you can use the next page url to get the next page:
var url = require("url");
client.messages.list(function(err, data) {
if (data.next_page_uri) {
// deal with page 1
var query = url.parse(data.next_page_uri, true).query;
client.messages.list(query, function(err, data) {
// and so on
}
}
});
Adam Varga shared a solution he was using on GitHub (it's for phone numbers, but lists all act the same on Twilio). Also, look out for the release of version 3 of the Node.js library, which will include pagination helpers.

Resources