Send email throught Gmail API Google App Engine

1,741 views
Skip to first unread message

Angel Sanchez

unread,
Jun 24, 2016, 12:18:03 PM6/24/16
to Google App Engine

Trying to send email using the Gmail API into App Engine. 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 some...@appspot.gserviceaccount.com into Service account page. The code:

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

 
String emailAddress = "some...@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("some...@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("some...@gmail.com"));
 message
.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress("reci...@gmail.com"));
 message
.setSubject("Test Mail");
 message
.setText("Test Mail");
 sendMessage
(gmail, "some...@appspot.gserviceaccount.com", message);

 
Message message = createMessageWithEmail(email); //createMessageWithEmail function from Gmail API
 message
= service.users().messages().send(userId, message).execute();

 
} 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" }




 

Nick (Cloud Platform Support)

unread,
Jun 24, 2016, 4:10:32 PM6/24/16
to Google App Engine
Hey Angel,

This forum is meant for high level discussion of the platform and services rather than specific-issue technical support. A question like this should be posted to Stack Overflow, where we are also very active. You are likely to be in touch with a much larger number of potentially-helpful users there. My advice from looking at the code, to help either resolve the issue or improve your post to Stack Overflow:

1. service is used but doesn't seem to be defined. Where is it defined? Shouldn't you call the method on: 


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

2. Does your service account have domain-wide-delegation for the address you're attempting to sending the mail from? "reason" : "failedPrecondition" can sometimes mean this.

Let me know if you have any questions, otherwise feel free to post the link to your Stack question here once you've made it. I'll be happy to take a look. This forum, as mentioned, can be used for more high level architecture question and general advice on accomplishing specific use-cases on the platform.

Cheers,

Nick
Cloud Platform Community Support

On Friday, June 24, 2016 at 12:18:03 PM UTC-4, Angel Sanchez wrote:

Trying to send email using the Gmail API into App Engine. 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 somename@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("somena...@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");

 sendMessage
(gmail, "somename@appspot.gserviceaccount.com", message);


 
Message message = createMessageWithEmail(email); //createMessageWithEmail function from Gmail API
 message
= service.users().messages().send(userId, message).execute();

 
} 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();
 
}

Nick (Cloud Platform Support)

unread,
Jun 24, 2016, 4:34:05 PM6/24/16
to Google App Engine

Angel Sanchez

unread,
Jun 24, 2016, 5:03:51 PM6/24/16
to Google App Engine
Thank you for answer Nick. Sorry I didn't know very well what's the purpose of this forum. I have posted this question to Stackoverflow.
For your point number one I modified the name of variables in Stackoverflow I forget to change here, I currently use service instance, it is gmail variable.
For your point two I guess yes, I described more details about this on Stackoverflow question.
Thanks for all.

Angel Sanchez

unread,
Jun 24, 2016, 5:06:09 PM6/24/16
to Google App Engine
Thanks.


El viernes, 24 de junio de 2016, 15:34:05 (UTC-5), Nick (Cloud Platform Support) escribió:
Link to doc on domain-wide delegation.

On Friday, June 24, 2016 at 4:10:32 PM UTC-4, Nick (Cloud Platform Support) wrote:
Hey Angel,

This forum is meant for high level discussion of the platform and services rather than specific-issue technical support. A question like this should be posted to Stack Overflow, where we are also very active. You are likely to be in touch with a much larger number of potentially-helpful users there. My advice from looking at the code, to help either resolve the issue or improve your post to Stack Overflow:

1. service is used but doesn't seem to be defined. Where is it defined? Shouldn't you call the method on: 

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

2. Does your service account have domain-wide-delegation for the address you're attempting to sending the mail from? "reason" : "failedPrecondition" can sometimes mean this.

Let me know if you have any questions, otherwise feel free to post the link to your Stack question here once you've made it. I'll be happy to take a look. This forum, as mentioned, can be used for more high level architecture question and general advice on accomplishing specific use-cases on the platform.

Cheers,

Nick
Cloud Platform Community Support

On Friday, June 24, 2016 at 12:18:03 PM UTC-4, Angel Sanchez wrote:

Trying to send email using the Gmail API into App Engine. 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 some...@appspot.gserviceaccount.com into Service account page. The code:

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


 
String emailAddress = "some...@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("somena...@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("some...@gmail.com"));
 message
.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress("reci...@gmail.com"));

 message
.setSubject("Test Mail");
 message
.setText("Test Mail");

 sendMessage
(gmail, "some...@appspot.gserviceaccount.com", message);


 
Message message = createMessageWithEmail(email); //createMessageWithEmail function from Gmail API
 message
= service.users().messages().send(userId, message).execute();

 
} 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();
 
}

Nick (Cloud Platform Support)

unread,
Jun 27, 2016, 9:45:48 AM6/27/16
to Google App Engine
Great, I'll follow that thread and provide advice if possible. The other user has linked another question which mentions what I was saying about "domain-wide delegation" for your service account. You'll need to do that in order to send mail from an address on a domain.
Reply all
Reply to author
Forward
0 new messages