Sending email via Google API - Failed precondition

Viewed 146

I'm trying to use my Google Workspace account to send emails in my Spring Boot application. I went to the Google console and I:

  1. created a new project and selected it (namely APPLICATION_NAME_FROM_GOOGLE_CONSOLE)
  2. enabled the Gmail API
  3. created a OAuth consent screen
  4. navigated to "Credentials" and created a new "Service account credentials", which gave me a new email I will call EMAIL_ADDRESS_CREATED_WHEN_CREATING_THE_SERVICE_ACCOUNT

Then I have this code which causes a FAILED PRECONDITION error:

// invoking code
...
Gmail service = buildEmailService();
Message message = createMessage(fromEmailAddress, toEmailAddress, subject, text);
_sendMessage(service, message);
...


private Gmail buildEmailService() throws MessagingException {
    GoogleCredentials credentials = null;
    try {
        String serviceAccountJson = "{\n" +
                "  \"type\": \"service_account\",\n" +
                "  \"project_id\": \"lybro-355514\",\n" +
                "  \"private_key_id\" ..........
        ;

        InputStream targetStream = new ByteArrayInputStream(serviceAccountJson.getBytes());
        credentials = ServiceAccountCredentials.fromStream(targetStream)
                .createScoped(Collections.singletonList(GmailScopes.GMAIL_SEND))
           .createDelegated(EMAIL_ADDRESS_CREATED_WHEN_CREATING_THE_SERVICE_ACCOUNT);

    } catch (IOException e) {
        e.printStackTrace();
        throw new MessagingException(e.getMessage());
    }
    HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);

    Gmail service = new Gmail.Builder(new NetHttpTransport(),
            GsonFactory.getDefaultInstance(),
            requestInitializer)
            .setApplicationName(APPLICATION_NAME_FROM_GOOGLE_CONSOLE)
            .build();

    return service;
}


private void _sendMessage(Gmail service, Message message) throws MessagingException {
    try {
        // Create send message
        message = service.users().messages().send(EMAIL_ADDRESS_CREATED_WHEN_CREATING_THE_SERVICE_ACCOUNT, message).execute();
        System.out.println("Message id: " + message.getId());
        System.out.println(message.toPrettyString());
    } catch (GoogleJsonResponseException e) {
        // TODO(developer) - handle error appropriately
        GoogleJsonError error = e.getDetails();
        if (error != null && error.getCode() == 403) {
            System.err.println("Unable to send message: " + e.getDetails());
        } else {
            e.printStackTrace();
            throw new MessagingException(e.getMessage());
        }
    } catch (IOException e) {
        e.printStackTrace();
        throw new MessagingException(e.getMessage());
    }
}

With this code, I get the following error:

javax.mail.MessagingException: 400 Bad Request POST https://gmail.googleapis.com/gmail/v1/users/lybro-512@lybro-355514.iam.gserviceaccount.com/messages/send { "code": 400, "errors": [ { "domain": "global", "message": "Precondition check failed.", "reason": "failedPrecondition" } ], "message": "Precondition check failed.", "status": "FAILED_PRECONDITION" }

1 Answers
createDelegated(EMAIL_ADDRESS_CREATED_WHEN_CREATING_THE_SERVICE_ACCOUNT)

The email you should be setting this to is the email of the user on your workspace account that you have configured delegation for.

createDelegated("no-reply@Yourdomain.com")

Send should also be sent from the user on your domain. The way service accounts you preconfigure them to work impersonate a user on your domain. In this way the service account is pretending to be that user.

If you have not already read this: Perform Google Workspace Domain-Wide Delegation of Authority I can highly recommend doing so.

Related