1

I have a GSuite account for my organization. I want to use Gmail API to send mail in my Java app but I don't want to use Oauth2 authent. I follow this documentation to delegate authority to a service account https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority.

I followed these steps:

  • configure a new account service
  • activate Gmail API in the dev console
  • associate rights between my client ID and the API

My Kotlin code to be able to initialize the Gmail service is below (the code is equivalent in Java)

@Configuration
class MixitApplication {

  @Bean
  fun jacksonFactory() = JacksonFactory.getDefaultInstance()

  @Bean
  fun dataStoreFactory() = MemoryDataStoreFactory.getDefaultInstance()

  @Bean
  fun httpTransport() = GoogleNetHttpTransport.newTrustedTransport()

  @Bean
  fun authorize(): Credential {

    val jsonConfig = "{\n" +
            "  \"type\": \"service_account\",\n" +
            "  \"project_id\": \"mixit-EeAZEAZE\",\n" +
            "  \"private_key_id\": \"FAKE\",\n" +
            "  \"private_key\": \"-----BEGIN PRIVATE KEY-----\\FAKE\\n-----END PRIVATE KEY-----\\n\",\n" +
            "  \"client_email\": \"website@FAKE.iam.gserviceaccount.com\",\n" +
            "  \"client_id\": \"FAKE\",\n" +
            "  \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n" +
            "  \"token_uri\": \"https://accounts.google.com/o/oauth2/token\",\n" +
            "  \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n" +
            "  \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/website%40mixit-196820.iam.gserviceaccount.com\"\n" +
            "}"



    return GoogleCredential
            .fromStream(jsonConfig.byteInputStream())
            .createScoped(listOf(GmailScopes.GMAIL_SEND))
  }

  @Bean
  fun gmailService() = Gmail.Builder(httpTransport(), jacksonFactory(), authorize()).build()

}

In my service when I try to end an email with this code

val result = gmailService.users().messages().send("me", emailMessage).execute();

I have always this error

  400 Bad Request { "code" : 400, "errors" : [ { "domain" : "global", "message" : "Bad Request", "reason" : "failedPrecondition" } ], "message" : "Bad Request" }

I found several posts about similar problem. But it's often because the account is not a Gsuite account

I tried to find Google support for this problem but I had no solution for the moment. There' no information on the Google API console. I just know that I had a bad request.

My email function to send mail is very simple. EmailMessage is a custom object with email infos (to, subject and content)

fun send(email: EmailMessage) {
    val session = Session.getDefaultInstance(Properties(), null)
    val message = MimeMessage(session)

    message.setFrom(InternetAddress("me"))
    message.addRecipient(javax.mail.Message.RecipientType.TO, InternetAddress(email.to))
    message.subject = email.subject
    message.setContent(email.content, MediaType.TEXT_HTML_VALUE)

    val buffer = ByteArrayOutputStream()
    message.writeTo(buffer)
    val emailMessage = Message()
    emailMessage.encodeRaw(buffer.toByteArray())

    val result = gmailService.users().messages().send("me", emailMessage).execute();

    System.out.println(result.toPrettyString())
}

When I try to send this message by the test api console I https://developers.google.com/apis-explorer/?hl=en_GB#p/gmail/v1/gmail.users.messages.send the message is sent

Can you help me?

abielita
  • 13,147
  • 2
  • 17
  • 59

1 Answers1

0

Using Gmail API requires OAuth2 authorization, even service accounts uses Oauth2.0:

All requests to the Gmail API must be authorized by an authenticated user. Gmail uses the OAuth 2.0 protocol for authenticating a Google account and authorizing access to user data. You can also use Google+ Sign-in to provide a "sign-in with Google" authentication method for your app.

In short, you need to use OAuth2.0. You can check the implemenation of service account in this SO post.

ReyAnthonyRenacia
  • 17,219
  • 5
  • 37
  • 56
  • Thanks for the links. I followed the different steps but the new error is now com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request { "error" : "invalid_grant", "error_description" : "Invalid JWT Signature." } – Guillaume Ehret Mar 08 '18 at 22:23