I'm trying to create a very simple script to automate some stuff ON MY OWN GMAIL ACCOUNT
All the tutorials on google to use GMAIL API focus on accessing someones else data so it right goes through an OAuth access request in the browser, but i'm trying to read my own mails and i'm using an ubuntu server so i have no access to graphical browser.
How can I do that?
please do not answer to say "is impossible, google requires it bla bla bla security" I've done something similar in the past I just don't have the previous code...
I believe if I create a service account and grant some permission to this account i would be able to do this, but i cant find which permission i need to grant or what step i'm missing currently i get
public static Gmail createGmailServiceClient(final List<String> scopes, final String jsonCredentials) throws GeneralSecurityException, IOException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
return new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, GoogleCredential.fromStream(new ByteArrayInputStream(jsonCredentials.getBytes())).createScoped(scopes)).build();
}
Gmail gmail = SimpleGmail.createGmailServiceClient(Arrays.asList(GmailScopes.GMAIL_READONLY), json);
ListMessagesResponse mails = gmail.users().messages().list("me").execute();
System.out.println(mails);
but when doing this i get
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Precondition check failed.",
"reason" : "failedPrecondition"
} ],
"message" : "Precondition check failed.",
"status" : "FAILED_PRECONDITION"
}
CodePudding user response:
Using a Service Account you need to declare impersonation, are you doing that in your code? There's a similar question that was answered here that corresponds to the same error you are getting.
Basically, as instructed you need to make sure impersonation is done as:
private static GoogleCredential _createCredentialUsingServerToken(final HttpTransport httpTransport,
final JsonFactory jsonFactory) throws IOException,
GeneralSecurityException {
// Use the client ID when making the OAuth 2.0 access token request (see Google's OAuth 2.0 Service Account documentation).
String serviceAccountClientID = "327116756300-thcjqf1mvrn0geefnu6ef3pe2sm61i2q.apps.googleusercontent.com";
// Use the email address when granting the service account access to supported Google APIs
String serviceAccountUserEmail = "[email protected]";
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(serviceAccountUserEmail) // requesting the token
.setServiceAccountPrivateKeyFromP12File(new File(SERVER_P12_SECRET_PATH))
.setServiceAccountScopes(SCOPES) // see https://developers.google.com/gmail/api/auth/scopes
.setServiceAccountUser("[email protected]")
.build();
credential.refreshToken();
return credential;}
CodePudding user response:
Precondition check failed.
Means that you are trying to use a service account but did not declare which user you would like to delegate to. What its trying to do is access the service accounts gmail account, google wont let you do that. This is normally done by using the setServiceAccountUser
method.
However if i understand you correctly you are using a standard gmail account. To use service accounts with gmail you need to have a google workspace domain account. Then the admin of your domain will be able to set up domain wide delegation for you. It will only work with domain emails.
You can not use a service account with a standard google gmail account.
Here is the section of the documentation that relats to service accounts and delegation Managing Delegates
Google Workspace organizations can use the Delegates resource to manage the delegates of accounts in their organization. This requires use of a service account that has been delegated domain-wide authority.
The solution to your problem is to use oauth2.
I recommend following the official tutorial.
private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
// Load client secrets.
InputStream in = GmailQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
if (in == null) {
throw new FileNotFoundException("Resource not found: " CREDENTIALS_FILE_PATH);
}
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setAccessType("offline")
.build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
//returns an authorized Credential object.
return credential;
}