3
votes

I'm trying to set up Google's push PubSub to my server to receive Gmail push notifications.

I'm getting the following scopes:

It works to create a topic, subscribe to that topic, grant access to the Gmail API on that topic but it fails when I'm trying to watch my inbox. I have followed this guide: https://developers.google.com/gmail/api/guides/push and this is the code I'm using to do the steps above:

var rp = require('request-promise');

// Step 1. Create a topic
rp({
   url: 'https://pubsub.googleapis.com/v1/projects/projectId/topics/mailSync',
   method: 'PUT',
   headers: {
     Authorization: 'Bearer accessToken'
   }
 }).then(function(response) {
   console.log(response);
   res.send(response);
 })
 .catch(function(error) {
   console.log(error.message);
   res.send(error.message);
 });

// Step 2. Create a subscription:
rp({
   url: 'https://pubsub.googleapis.com/v1/projects/projectId/subscriptions/mailSync',
   method: 'PUT',
   headers: {
     Authorization: 'Bearer accessToken'
   },
   json: {
     topic: 'projects/projectId/topics/mailSync',
     pushConfig: {
       pushEndpoint: 'https://developers.example.com/mailSyncHandler'
     }
   }
 }).then(function(response) {
   console.log(response);
   res.send(response);
 })
 .catch(function(err) {
   console.error(err);
   res.status(err.statusCode).send(err.error.error.message);
 });

// Step 3. Grant the Gmail API publish rights on our topic
rp({
   url: "https://pubsub.googleapis.com/v1beta2/projects/projectId/topics/mailSync:setIamPolicy",
   method: 'POST',
   headers: {
     Authorization: 'Bearer accessToken'
   },
   data: {
     policy: {
       bindings: [{
         role: "roles/pubsub.publisher",
         members: ["serviceAccount:[email protected]"]
       }]
     }
   },
   json: true
 }).then(function(response) {
   console.log(response);
   res.send(response);
 })
 .catch(function(error) {
   console.log(error.message);
   res.send(error.message);
 });

// Step 4. Watch my Inbox
rp({
  url: "https://www.googleapis.com/gmail/v1/users/me/watch",
  method: "POST",
  headers: {
    Authorization: 'Bearer accessToken'
  },
  json: {
    topicName: "projects/projectId/topics/mailSync",
    labelIds: ["INBOX"]
  }
}).then(function(response) {
  console.log(response);
  res.send(response);
})
.catch(function(error) {
  console.error(error);
  res.send(error.message);
});
1
"but it fails when I'm trying to watch my inbox", please elaborate. Do you get some kind of error message/exception on watch() call or is it something else. Please share the exception/error if any.Furhan S.
Have you granted publish rights on your topic?Takashi Matsuo
@TakashiMatsuo I have no idea, how do I check if I've granted the publish right?jwanglof
@FurhanShabir Sorry about that, the error-message I get from the API is: Error sending test message to Cloud PubSub projects/projectId/topics/mailSync : User not authorized to perform this action.. Statuscode 403jwanglof
@TakashiMatsuo If I use cloud.google.com/pubsub/reference/rest/v1/projects.topics/… it will give me an etag which step 3 returned when I logged the response on that request so I guess I have granted Gmail the publish rights on that topic?jwanglof

1 Answers

1
votes

Figured out why I got the error and it was because I didn't send the data as JSON in step 4.

The correct code in step 4 is (notice that I'm using json: instead of body: on row 8):

// Step 4. Watch my Inbox
rp({
  url: "https://www.googleapis.com/gmail/v1/users/me/watch",
  method: "POST",
  headers: {
    Authorization: 'Bearer accessToken'
  },
  json: {     <-----
    topicName: "projects/projectId/topics/mailSync",
    labelIds: ["INBOX"]
  }
}).then(function(response) {
  console.log(response);
  res.send(response);
})
.catch(function(error) {
  console.error(error);
  res.send(error.message);
});