13

Here is my Gmail service configuration/factory class:

import java.io.File; import java.io.IOException; import java.security.GeneralSecurityException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.http.HttpRequestInitializer; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.services.gmail.Gmail; import com.google.api.services.gmail.GmailScopes; public class GmailServiceFactoryBean { private @Autowired Environment env; private final NetHttpTransport transport; private final JacksonFactory jacksonFactory; public GmailServiceFactoryBean() throws GeneralSecurityException, IOException { this.transport = GoogleNetHttpTransport.newTrustedTransport(); this.jacksonFactory = JacksonFactory.getDefaultInstance(); } public Gmail getGmailService() throws IOException, GeneralSecurityException { return new Gmail.Builder(transport, jacksonFactory, getCredential()) .setApplicationName(env.getProperty("gmail.api.application.name")).build(); } private HttpRequestInitializer getCredential() throws IOException, GeneralSecurityException { File p12File = new File(this.getClass().getClassLoader().getResource("google-key.p12").getFile()); Credential credential = new GoogleCredential.Builder() .setServiceAccountId(env.getProperty("gmail.api.service.account.email")) .setServiceAccountPrivateKeyId(env.getProperty("gmail.api.private.key.id")) .setServiceAccountPrivateKeyFromP12File(p12File) .setTransport(transport) .setJsonFactory(jacksonFactory) .setServiceAccountScopes(GmailScopes.all()) //.setServiceAccountUser(env.getProperty("gmail.api.user.email")) .build(); credential.refreshToken(); return credential; } } 

Here is my inner mailing service that uses previous bean under the hood:

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.List; import java.util.Properties; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage.RecipientType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64; import com.google.api.services.gmail.Gmail; import com.google.api.services.gmail.model.Message; import com.example.factory.GmailServiceFactoryBean; import com.example.service.MailService; import com.example.service.exception.MailServiceException; @Service public class MailServiceImpl implements MailService { private @Autowired GmailServiceFactoryBean gmailServiceFactoryBean; private @Autowired Environment env; @Override public void send(com.example.model.Message message, String recipient) throws MailServiceException { try { Gmail gmailService = gmailServiceFactoryBean.getGmailService(); MimeMessage mimeMessage = createMimeMessage(message, recipient); Message gMessage = createMessageWithEmail(mimeMessage); gmailService.users().messages().send("me", gMessage).execute(); } catch(MessagingException | IOException | GeneralSecurityException e) { throw new MailServiceException(e.getMessage(), e.getCause()); } } @Override public void send(com.example.model.Message message, List<String> recipients) throws MailServiceException { for (String recipient : recipients) { send(message, recipient); } } private MimeMessage createMimeMessage(com.example.model.Message message, String recipient) throws MessagingException { Session session = Session.getDefaultInstance(new Properties()); MimeMessage email = new MimeMessage(session); InternetAddress toAddress = new InternetAddress(recipient); InternetAddress fromAddress = new InternetAddress(env.getProperty("gmail.api.service.account.email")); email.setFrom(fromAddress); email.addRecipient(RecipientType.TO, toAddress); email.setSubject(message.getTitle()); email.setText(message.getContent(), env.getProperty("application.encoding")); return email; } private Message createMessageWithEmail(MimeMessage email) throws MessagingException, IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); email.writeTo(baos); return new Message().setRaw(Base64.encodeBase64URLSafeString(baos.toByteArray())); } } 

When I execute method send(Message message, String recipient) of class MailServiceImpl I get following response:

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

Does anyone know what's wrong?

2
  • does this help ? stackoverflow.com/a/29328258/4290096 Commented Feb 18, 2016 at 5:15
  • @ᴊᴀᴠʏ, step 5 requires google for work account - I don't have one Commented Feb 18, 2016 at 14:37

2 Answers 2

5
+25

For GMail API to work, you have to "Delegate domain-wide authority to the service account" within your Google Apps account.

Service account doesn't represent a human Google account. You also can't delegate authority to whole Google domain(***@gmail.com).

The other way out could be with OAuth 2.0 for Web Server Applications or Java Mail api

For more do check: GMail REST API: Using Google Credentials Without Impersonate

Sign up to request clarification or add additional context in comments.

Comments

3

Check if you have enabled gmail to send mails using 3rd party applications.

Go to my account ->Sign in and Security -> Connected Apps now scroll to the bottom of the page you will get Less secure apps ->change it to on !! Hope this will work

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.