1

Trying to send email using the Gmail API into GAE. Previously I created a Service account key into Credentials page, it generates a .P12 file which is in setServiceAccountPrivateKeyFromP12File parameter. It has a ID key joined to the account example@appspot.gserviceaccount.com into Service account page. The code:

    /* Application name. */
    private static final String APPLICATION_NAME = "appnamefromappengine";

    String emailAddress = "somename@appspot.gserviceaccount.com";
    JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    try {
        HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();

        Set<String> scopes = new HashSet<String>();
        scopes.add(GmailScopes.GMAIL_SEND);
        scopes.add(GmailScopes.GMAIL_COMPOSE);
        scopes.add(GmailScopes.MAIL_GOOGLE_COM);
        scopes.add("https://www.googleapis.com/auth/admin.directory.user");

        GoogleCredential credential = new GoogleCredential.Builder()
            .setTransport(httpTransport)
            .setJsonFactory(JSON_FACTORY)
            .setServiceAccountId(emailAddress)
            .setServiceAccountPrivateKeyFromP12File(new File("/home/myuser/Test/src/main/webapp/resources/**somename**cd30e7118ad5.p12"))
            .setServiceAccountScopes(scopes)
            .setServiceAccountUser("somename@appspot.gserviceaccount.com")
            .build();
        Gmail gmail = new Gmail
            .Builder(httpTransport, JSON_FACTORY, credential)
            .setApplicationName(APPLICATION_NAME)
            .build();

        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        MimeMessage message = new MimeMessage(session);
        message.setFrom(new InternetAddress("someemail@gmail.com"));
        message.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress("recipient@gmail.com"));
        message.setSubject("Test Mail");
        message.setText("Test Mail");

        Message msg = createMessageWithEmail(message); //createMessageWithEmail function from Gmail API
        msg = gmail.users().messages().send(emailAddress, msg).execute();

        System.out.println("Mail was sent. Message id: " + msg.getId());

    } catch (GeneralSecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (MessagingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

It returns me this error:

com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request { "code" : 400,
"errors" : [ { "domain" : "global", "message" : "Bad Request", "reason" : "failedPrecondition" } ],
"message" : "Bad Request" }

I'm not sure which parameter I'm setting wrong here in code or into Google cloud console. What else can I try ?

Angel Cuenca
  • 1,637
  • 6
  • 24
  • 46
  • 2
    Check this SO question [Gmail REST API : 400 Bad Request + Failed Precondition](http://stackoverflow.com/questions/29327846/gmail-rest-api-400-bad-request-failed-precondition) if it can help you :) – KENdi Jun 25 '16 at 08:49
  • Was the link provided by @KENdi helpful? Have you been able to narrow down or address the failing precondition? – Nicholas Jun 29 '16 at 20:10
  • 1
    It was @Nicholas. The problem was that I didn't configure Delegate domain-wide authority to the service account into admin console. Either way all the code is completely working if someone wants to send an email using Gmail API. The question could be complemented answer how to use Email API authorized senders into the code. Once someone registered an email in that section, how to reference that email. Thanks for all. – Angel Cuenca Jun 30 '16 at 20:18
  • 1
    Thanks for clarifying the issue. Feel free to post it as an answer and I'll upvote it. – Nicholas Jun 30 '16 at 21:02

2 Answers2

2

The problem was that I didn't configure Delegate domain-wide authority to the service account into Admin console.

  1. Go to your Google Apps domain’s Admin console.

  2. Select Security from the list of controls. If you don't see Security listed, select More controls from the gray bar at the bottom of the page, then select Security from the list of controls. If you can't see the controls, make sure you're signed in as an administrator for the domain.

  3. Select Show more and then Advanced settings from the list of options.

  4. Select Manage API client access in the Authentication section.

  5. In the Client Name field enter the service account's Client ID. You can find your service account's client ID in the Service accounts section of the Developers Console's Permissions page.

  6. In the One or More API Scopes field enter the list of scopes that your application should be granted access to. For example, if your application needs domain-wide access to the Google Drive API and the Google Calendar API, enter: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.

  7. Click Authorize.

All the documentation:
https://developers.google.com/identity/protocols/OAuth2ServiceAccount

Angel Cuenca
  • 1,637
  • 6
  • 24
  • 46
  • the problem with this is that it gives the service account access to all accounts in such domain within the specified scope, which might not be ideal. Google doesn't provide a way to only limit it to a single or a number of specific accounts within that domain. Also, it is only available to G Suite customers. Normal Gmail accounts don't have this. – Eric Castro Apr 25 '19 at 16:43
0

Optionally you could use a library like this one, who will do all of the set up for you: https://github.com/3wks/spring-gae-gmail

afcastano
  • 548
  • 3
  • 17