Andy
Andy

Reputation: 1421

GmailApiQuickstart -

I am embarrassed that I'm simply failing with an example piece of code, but I'll blame it on the fact that it is late...

I have taken a copy and paste of: https://developers.google.com/gmail/api/quickstart/quickstart-java and downloaded the client libraries: https://code.google.com/p/google-api-java-client/ and https://developers.google.com/api-client-library/java/apis/gmail/v1

When I run the sample, I get the following exception:

Exception in thread "main" java.lang.IllegalArgumentException
    at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:76)
    at com.google.api.client.util.Preconditions.checkArgument(Preconditions.java:37)
    at com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets.getDetails(GoogleClientSecrets.java:82)
    at com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow$Builder.<init>(GoogleAuthorizationCodeFlow.java:195)
    at com.emailreply.musterion.GmailApiQuickstart.main(GmailApiQuickstart.java:40)

Googling, I can't find a simple answer, so am assuming stupidity or a library missing/incorrect.

The libraries as I have them are:

/libs/commons-logging-1.1.1.jar
/libs/google-api-client-1.19.0.jar
/libs/google-api-client-android-1.19.0.jar
/libs/google-api-client-appengine-1.19.0.jar
/libs/google-api-client-gson-1.19.0.jar
/libs/google-api-client-jackson2-1.19.0.jar
/libs/google-api-client-java6-1.19.0.jar
/libs/google-api-client-servlet-1.19.0.jar
/libs/google-http-client-1.19.0.jar
/libs/google-http-client-android-1.19.0.jar
/libs/google-http-client-appengine-1.19.0.jar
/libs/google-http-client-gson-1.19.0.jar
/libs/google-http-client-jackson2-1.19.0.jar
/libs/google-http-client-jdo-1.19.0.jar
/libs/google-oauth-client-1.19.0.jar
/libs/google-oauth-client-appengine-1.19.0.jar
/libs/google-oauth-client-java6-1.19.0.jar
/libs/google-oauth-client-jetty-1.19.0.jar
/libs/google-oauth-client-servlet-1.19.0.jar
/libs/gson-2.1.jar
/libs/httpclient-4.0.1.jar
/libs/httpcore-4.0.1.jar
/libs/jackson-core-2.1.3.jar
/libs/jdo2-api-2.3-eb.jar
/libs/jetty-6.1.26.jar
/libs/jetty-util-6.1.26.jar
/libs/jsr305-1.3.9.jar
/libs/transaction-api-1.1.jar
google-api-services-gmail-v1-rev10-1.19.0.jar

The example mentioned above:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleOAuthConstants;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.model.ListThreadsResponse;
import com.google.api.services.gmail.model.Thread;


public class GmailApiQuickstart {

  // Check https://developers.google.ciom/gmail/api/auth/scopes for all available scopes
  private static final String SCOPE = "https://www.googleapis.com/auth/gmail.readonly";
  private static final String APP_NAME = "Gmail API Quickstart";
  // Email address of the user, or "me" can be used to represent the currently authorized user.
  private static final String USER = "me";
  // Path to the client_secret.json file downloaded from the Developer Console
  private static final String CLIENT_SECRET_PATH = "./client_secret.json";


  public static void main (String [] args) throws IOException {
    HttpTransport httpTransport = new NetHttpTransport();
    JsonFactory jsonFactory = new JacksonFactory();

    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(jsonFactory,  new BufferedReader(new InputStreamReader(GmailApiQuickstart.class.getResourceAsStream(CLIENT_SECRET_PATH))));

    // Allow user to authorize via url.
    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
        httpTransport, jsonFactory, clientSecrets, Arrays.asList(SCOPE))
        .setAccessType("online")
        .setApprovalPrompt("auto").build();

    String url = flow.newAuthorizationUrl().setRedirectUri(GoogleOAuthConstants.OOB_REDIRECT_URI).build();


    System.out.println("Please open the following URL in your browser then type the authorization code:\n" + url);

    // Read code entered by user.
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String code = br.readLine();

    // Generate Credential using retrieved code.
    GoogleTokenResponse response = flow.newTokenRequest(code)
        .setRedirectUri(GoogleOAuthConstants.OOB_REDIRECT_URI).execute();
    GoogleCredential credential = new GoogleCredential()
        .setFromTokenResponse(response);

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

    // Retrieve a page of Threads; max of 100 by default.
    ListThreadsResponse threadsResponse = service.users().threads().list(USER).execute();
    List<Thread> threads = threadsResponse.getThreads();

    // Print ID of each Thread.
    for (Thread thread : threads) {
        System.out.println("Thread ID: " + thread.getId());
    }
  }

}

I replaced the reference to CLIENT_SECRET_PATH with:

new BufferedReader(new InputStreamReader(GmailApiQuickstart.class.getResourceAsStream(CLIENT_SECRET_PATH)))

for no other reason than to try something different. It does work and reads the file correctly.

Any ideas?

Upvotes: 19

Views: 8038

Answers (2)

Alex
Alex

Reputation: 2649

here is a working example of non-interactive auth for Google Non-interactive authorization with Google OAuth2 the problem is not in "web" tag in the client json, but rather in the fact that their example is for web authentication while their suggested way of generating credentials is for non-interactive "service account". they have multiple problems with their documentation.

Upvotes: 5

Andy
Andy

Reputation: 1421

Right, after some more research (asking a colleague/genius), I found the problem. Basically the GoogleClientSecrets object was not being properly bound with the information from my client_secrets.json file. This meant that during authentication, objects were null resulting in the IllegalArgumentException.

So the original file which looked like this:

{
      "private_key_id": "zzz",
      "private_key": "-----BEGIN PRIVATE KEY-----\nxyz\n-----END PRIVATE KEY-----\n",
      "client_email": "[email protected]",
      "client_id": "1wdfghyjmp.apps.googleusercontent.com",
      "type": "service_account"
}

was edited to look like this:

{
    "web" : {
      "private_key_id": "zzz",
      "private_key": "-----BEGIN PRIVATE KEY-----\nxyz\n-----END PRIVATE KEY-----\n",
      "client_email": "[email protected]",
      "client_id": "1wdfghyjmp.apps.googleusercontent.com",
      "type": "service_account"
    }
}

This allowed me to progress through the code with authentication.

Hope this helps.

Upvotes: 54

Related Questions