1

I am trying to use Gmail API from a backend java. starting from my maven dependencies

    <dependency>
        <groupId>com.google.apis</groupId>
        <artifactId>google-api-services-gmail</artifactId>
        <version>v1-rev20200406-1.30.9</version>

    </dependency>
    <dependency>
        <groupId>com.google.auth</groupId>
        <artifactId>google-auth-library-oauth2-http</artifactId>
        <version>0.20.0</version>
    </dependency>  

I have downloaded a p12 Keystore from the google API manager and I created a service account

PrivateKey key = (PrivateKey)keystore.getKey("privatekey", "somepass".toCharArray()); 
ServiceAccountCredentials serviceAccountCredentials = ServiceAccountCredentials.newBuilder()
                 .setClientEmail("somestuff@developer.gserviceaccount.com")                                                                                         
                 .setServiceAccountUser("somestuff@developer.gserviceaccount.com")                                                                                                
                 .setClientId("somenumber")                                                                                                  
                 .setScopes(SCOPES)                                                                                                  
                 .setPrivateKey(key).build();

now this seems to be working

serviceAccountCredentials.refresh();

generate a token on the form of

ya29.c.Ko8BygeNYc2Onx2IZpK-ocaHKTiCxOcYYK7nbTg8uE0gyqc8rXROuiVJ7oXCfnYD1pDOyHXiy_K5Eyk3aV3epgjtnr2WVCP_xpWCxq-BExh4i1aIXW9m7gkkUtbteXaD1nETUwIc6n9Uz2oCJSU4jrodFv4n4drxlSGd7my0LcxrMk_E5cFY7jo-Vt40i58g5QY

Now the part I can not get to work

HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(serviceAccountCredentials);

Gmail service = new Gmail.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), requestInitializer).setApplicationName(APPLICATION_NAME).build();
Gmail.Users.Labels.List list = service.users().labels().list("b@someemail")
                               .setAccessToken(credential.getAccessToken().getTokenValue());

I have also done all gmail configuration suggested by Gmail REST API : 400 Bad Request + Failed Precondition

But I keep to get

com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
  "code" : 401,
  "errors" : [ {
    "domain" : "global",
    "location" : "Authorization",
    "locationType" : "header",
    "message" : "Invalid Credentials",
    "reason" : "authError"
  } ],
  "message" : "Invalid Credentials"
}

Regards

Balint
  • 295
  • 2
  • 11

1 Answers1

1

Note

You are using domain delegation you should follow this guide to authorize the service account to use the Gmail Service with this particular scope.

Approach

Once you created the credentials object starting from your service account key, just proceed to create the Gmail service builder this way:

private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final String SERVICE_ACCOUNT_ID = "your-service-account-id";
private static final String APPLICATION_NAME = "your-app-name";

PrivateKey key = (PrivateKey)keystore.getKey("privatekey", "somepass".toCharArray()); 

HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();

GoogleCredential credential = new GoogleCredential.Builder()
                .setTransport(httpTransport)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountId(SERVICE_ACCOUNT_ID)
                .setServiceAccountScopes(SCOPES)
                .setServiceAccountPrivateKey(key)
                .setServiceAccountEmail("user@email")
                .build();

Gmail service =  new Gmail.Builder(httpTransport, JSON_FACTORY, credential)
                .setApplicationName(APPLICATION_NAME).build();

Now you can use the Gmail service directly without the need to specify again the access token nor the credentials. Just like this:

ListLabelsResponse listResponse = service.users().labels().list("b@somemail").execute();

Reference

Java Gmail

Service Account Java

Alessandro
  • 2,848
  • 1
  • 8
  • 16
  • @alessndro the signature for the method the builder has now Builder(http.HttpTransport transport, jsonFactory, com.google.api.client.http.HttpRequestInitializer httpRequestInitializer) what dependency are you using ? – Balint May 08 '20 at 16:37
  • I'm using the last version available at: https://developers.google.com/resources/api-libraries/documentation/gmail/v1/java/latest/. `'com.google.apis:google-api-services-gmail:v1-rev110-1.25.0'` – Alessandro May 13 '20 at 10:15