1
votes

I am trying to modify labels of a message by implementing a server to server authentication, so I need the scope GMAIL_MODIFY which will give me permission to do other things (Read/write). When I do implement this change, I get a NullPointerException as soon I try the first request.

For the sake of simplicity, I'm using a simple code of listing threads from my gmail account.

I did setup a project on my account's developers console and all of that jazz.

Here is my Java code:

  public static void main (String [] args) throws IOException {

      Collection<String> scopesArray = new ArrayList<String>();
      scopesArray.add(GmailScopes.GMAIL_MODIFY);
      //scopesArray.add(GmailScopes.GMAIL_READONLY);
      {

          try {
              httpTransport = GoogleNetHttpTransport.newTrustedTransport();
              credential = new GoogleCredential.Builder()
              .setTransport(httpTransport)
              .setJsonFactory(JSON_FACTORY)
              .setServiceAccountId(email_address)
              .setServiceAccountPrivateKeyFromP12File(new File("myfile.p12"))
              .setServiceAccountScopes(scopesArray)
              .setServiceAccountUser(USER)
              .build();
          }
          catch (IOException | GeneralSecurityException e)
          {
              throw new RuntimeException(e);
          }

      }


    // Create a new authorized Gmail API client
    Gmail service = new Gmail.Builder(httpTransport, JSON_FACTORY, credential)
        .setApplicationName(APP_NAME).build();

    try {

        ListThreadsResponse threadsResponse = service.users().threads().list(USER).execute();
        List<com.google.api.services.gmail.model.Thread> threads = threadsResponse.getThreads();
        for (com.google.api.services.gmail.model.Thread thread : threads) {
          System.out.println("Thread ID: " + thread.getId());
        }


    } catch (GoogleJsonResponseException e) {
        GoogleJsonError error = e.getDetails();
        System.err.println("Error code:  "+ error.getCode());
        System.err.println("Error message: " + error.getMessage());
    } catch (HttpResponseException e) {
        // No Json body was returned by the API.
        System.err.println("HTTP Status code: "+ e.getStatusCode());
        System.err.println("HTTP Reason: " + e.getMessage());
    } catch (IOException e) {
        e.printStackTrace();
    }

this returns: Exception in thread "main" java.lang.NullPointerException at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkNotNull(Preconditions.java:191) at com.google.api.client.util.Preconditions.checkNotNull(Preconditions.java:127) at com.google.api.client.json.jackson2.JacksonFactory.createJsonParser(JacksonFactory.java:96) at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:85) at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:81) at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:88) at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287) at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307) at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:268) at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489) at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:217) at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460) at core.crescent.gmail.GmailApiQuickstart.main(GmailApiQuickstart.java:228)

When I use the scope GMAIL_READONLY scope it works. Why doesn't it work with the scope modify even though according to the GMAIL API documentation it supposed to work (https://developers.google.com/gmail/api/v1/reference/users/threads/list)?

Thank you

2
Thank you for the response. the problem I am describing has to do more with read/write permissions for the user's account than about authentication.HBizzle

2 Answers

0
votes

Yes I too experienced the same issue. I also needed to create a service account that could access my @gmail.com account, read an email, then remove and add a label. This was suppose to be simple, but applying the scope modify would result in a error. I tried pulling down the latest 1.20 but it did not make a difference other than the error that was displayed. Rather than seeing Preconditions.checkNotNull(Preconditions.java:191), it now displays 401 Authentication Error. This makes me think its something on the server side that's not permitting service account scope modify for @gmail.com accounts.

So I tried things from another direction, I have my own gmail hosted domain, so via the google api console, I recreated the API, Access, p12, etc... Gave it Gmail.api access and sure enough, I got the same error: 401. Poking around in my gmail "Manage this Domain", under security "advance options" > "Manage API client access", I put the service account email with the two scopes read and modify. It still didn't work. Finally one more setting under "security" > "advance options" > "Manage OAuth key and secret for this domain", I enabled "Two-legged OAuth access control" and Youreka It worked!. My Service Account is now adding and removing labels :)

0
votes

@Michael Taylor's post put me on the right track.

Ensure you have your Client ID and Scopes listed here: https://admin.google.com/AdminHome?chromeless=1#OGX:ManageOauthClients

I found the instructions for this here (it's a Ruby client, but still relevant): https://github.com/googleapis/google-api-ruby-client/blob/master/docs/oauth-server.md#delegating-domain-wide-authority-to-the-service-account

This is what I entered into scopes to make this work: https://www.googleapis.com/auth/gmail,https://www.googleapis.com/auth/gmail.modify,https://www.googleapis.com/auth/gmail.readonly