使用身份验证范围https://mail.google.com/访问Gmail API时的access_denied

时间:2015-07-27 11:15:03

标签: gmail-api

我正在尝试使用Gmail REST API读取/写入Gmail邮箱中的电子邮件/文件夹。添加以下Google身份验证范围时,可以从Gmail REST API中轻松读取电子邮件:

https://apps-apis.google.com/a/feeds/compliance/audit/https://www.googleapis.com/auth/admin.directory.user.readonly https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/admin.directory.group.member.readonlyhttps://www.googleapis.com/auth/admin.directory.group.readonly

注意:参数https://www.googleapis.com/auth/gmail.readonly正确地允许用户从邮箱中读取。

但是,我也需要能够删除电子邮件。因此,根据https://developers.google.com/gmail/api/auth/scopes?hl=ja处的文档,只需要包含https://mail.google.com/代替https://www.googleapis.com/auth/gmail.readonly。添加以下身份验证范围时:

https://apps-apis.google.com/a/feeds/compliance/audit/https://www.googleapis.com/auth/admin.directory.user.readonly https://mail.google.com/ https://www.googleapis.com/auth/admin.directory.group.member.readonlyhttps://www.googleapis.com/auth/admin.directory.group.readonly

...输出的错误如下:

    2015-07-27 10:27:59 i.c.s.a.cv [DEBUG] failed get labels for user
    com.google.api.client.auth.oauth2.TokenResponseException: 403 Forbidden
    {
       "error" : "access_denied",
       "error_description" : "Requested client not authorized."
    }

当然,谷歌这是不正确的?我错过了什么?文档不正确吗?需要添加什么认证范围?

我正在与Java Google API客户端库连接。请参阅:https://developers.google.com/api-client-library/java/google-api-java-client/reference/1.20.0/overview-summary

删除请求如下:

public void deleteMessages(Queue<String> messages, GoogleUserAdapter user) throws Exception {

    Gmail gmail = getService(user);

    JsonBatchCallback<Void> voidCallBack = new JsonBatchCallback<Void>() {
        @Override
        public void onSuccess(Void t, HttpHeaders responseHeaders) throws IOException {
            logger.debug("delete success");

        }
        @Override
        public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) throws IOException {
            logger.debug("failed to delete message:"+e.getMessage());
        }
    };
    while (!messages.isEmpty()) {
        if (Thread.currentThread().isInterrupted()) 
            throw new InterruptedException();

        BatchRequest batch = gmail.batch();
        for (int i = 0; i < MAX_REQUESTS; i++) {
            if (messages.isEmpty() || Thread.currentThread().isInterrupted()) 
                break;
            gmail.users().messages().delete(user.getId(), messages.poll()).queue(batch, voidCallBack);
        }

        batch.execute();
    }
}

凭证创建如下:

   private GoogleCredential getCredentials(JsonFactory jsonFactory, HttpTransport httpTransport, String impersonateAccount) throws Exception {

    Preconditions.checkNotNull(Strings.emptyToNull(impersonateAccount), "Google impersonate account is null");
     Preconditions.checkNotNull(Strings.emptyToNull(connection.getServiceAccountId()), "Service Account Email address is null");
    Preconditions.checkNotNull(connection.getServiceAccountPrivateKey(), "Service Account Private Key is null");

    GoogleCredential credential = new GoogleCredential.Builder()
          .setTransport(httpTransport)
          .setJsonFactory(jsonFactory)
          .setServiceAccountId(connection.getServiceAccountId())
          .setServiceAccountScopes(
                    Arrays.asList(DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY, GmailScopes.MAIL_GOOGLE_COM,
                            "https://apps-apis.google.com/a/feeds/compliance/audit/",
                            DirectoryScopes.ADMIN_DIRECTORY_GROUP_MEMBER_READONLY, 
                            DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY))
          .setServiceAccountUser(impersonateAccount)
          .setServiceAccountPrivateKey(connection.getServiceAccountPrivateKey().getPrivateKey())
          .build();
    setHttpTimeout(credential);
    return credential;
}

删除时发生的确切错误是:

   failed to delete message:Insufficient Permission

杰米

2 个答案:

答案 0 :(得分:5)

访问被拒绝是由Google Java客户端API定义的常量GmailScopes.MAIL_GOOGLE_COM中的拼写错误引起的。

常数回报&#34; https://mail.google.com&#34;而不是&#34; https://mail.google.com/&#34; (因为它应该是)。在字符串末尾省略反斜杠会导致拒绝访问。

因此,在上面的示例中,必须设置以下服务范围:

https://apps-apis.google.com/a/feeds/compliance/audit/&#34;,&#34; https://mail.google.com/&#34;,DirectoryScopes.ADMIN_DIRECTORY_GROUP_MEMBER_READONLY,DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY,DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY

(注意:&#34; https://mail.google.com/&#34;)的硬编码值

必须在Google Apps中的管理API客户端访问权限页面中添加以下字符串:

https://apps-apis.google.com/a/feeds/compliance/audit/https://www.googleapis.com/auth/admin.directory.user.readonlyhttps://mail.google.com/https://www.googleapis.com/auth/admin.directory.group.member.readonlyhttps://www.googleapis.com/auth/admin.directory.group.readonly

我希望这有助于其他人!

答案 1 :(得分:0)

private GoogleCredential getCredentials(JsonFactory jsonFactory, HttpTransport httpTransport, String impersonateAccount) throws Exception {

    Preconditions.checkNotNull(Strings.emptyToNull(impersonateAccount), "Google impersonate account is null");
     Preconditions.checkNotNull(Strings.emptyToNull(connection.getServiceAccountId()), "Service Account Email address is null");
    Preconditions.checkNotNull(connection.getServiceAccountPrivateKey(), "Service Account Private Key is null");

    GoogleCredential credential = new GoogleCredential.Builder()
          .setTransport(httpTransport)
          .setJsonFactory(jsonFactory)
          .setServiceAccountId(connection.getServiceAccountId())
          .setServiceAccountScopes(
                    Arrays.asList(DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY, GmailScopes.MAIL_GOOGLE_COM,
                            "https://apps-apis.google.com/a/feeds/compliance/audit/",
                            DirectoryScopes.ADMIN_DIRECTORY_GROUP_MEMBER_READONLY, 
                            DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY))
          .setServiceAccountUser(impersonateAccount)
          .setServiceAccountPrivateKey(connection.getServiceAccountPrivateKey().getPrivateKey())
          .build();
    setHttpTimeout(credential);
    return credential;
}