【问题标题】:Gmail API + Service accounts return 403 errorGmail API + 服务帐户返回 403 错误
【发布时间】:2015-01-18 01:58:19
【问题描述】:

全部

我尝试了使用服务帐户的 Gmail API。 我实现了以下代码:

package mywork.gmail.api;

import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.GmailScopes;
import com.google.api.services.gmail.model.ListMessagesResponse;
import com.google.api.services.gmail.model.Message;

public class GmailApi {
    /** Email of the Service Account */
    private static final String SERVICE_ACCOUNT_EMAIL = "******@developer.gserviceaccount.com";

    /** Path to the Service Account's Private Key file */
    private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "src/main/resources/*******-privatekey.p12";

    public static void main(String[] args) throws Exception {
        GmailApi app = new GmailApi();

        String userId = "****@example.com";
        String labelId = "INBOX";

        app.listMessage(userId, labelId);
    }

    public void listMessage(String userId, String labelId) throws Exception {
        Gmail service = initService(userId);

        ListMessagesResponse response = service.users().messages().list(userId)
                .setLabelIds(Arrays.asList(labelId)).execute();

        List<Message> messages = new ArrayList<Message>();
        while (response.getMessages() != null) {
            messages.addAll(response.getMessages());
            if (response.getNextPageToken() != null) {
                String pageToken = response.getNextPageToken();
                response = service.users().messages().list(userId)
                        .setPageToken(pageToken).execute();
            } else {
                break;
            }
        }

        for (Message message : messages) {
            System.out.println(message.toPrettyString());
        }
    }

    private Gmail initService(String userId) throws GeneralSecurityException,
            IOException {

        HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        JacksonFactory jsonFactory = JacksonFactory.getDefaultInstance();
        GoogleCredential credential = new GoogleCredential.Builder()
                .setTransport(httpTransport)
                .setJsonFactory(jsonFactory)
                .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
                .setServiceAccountScopes(Arrays.asList(GmailScopes.MAIL_GOOGLE_COM))
                .setServiceAccountUser(userId)
                .setServiceAccountPrivateKeyFromP12File(new File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
                .build();

        Gmail service = new Gmail.Builder(httpTransport, jsonFactory, credential)
                .setApplicationName("Gmail API sample").build();

        return service;
    }
}

但该代码返回 403 错误:

Exception in thread "main" com.google.api.client.auth.oauth2.TokenResponseException: 403 Forbidden
    {
      "error" : "access_denied",
      "error_description" : "Requested client not authorized."
    }

当然,我通过 Google Developer Console 启用了 Gmail API,并通过管理控制台设置了权限(包括 Gmail 范围)。

怎么了?

谢谢!

【问题讨论】:

    标签: google-oauth gmail-api google-oauth-java-client


    【解决方案1】:

    如果您的应用程序访问用户数据,则需要授予您创建的服务帐户访问您要访问的 Google Apps 域的用户数据的权限。

    以下步骤必须由 Google Apps 域的管理员执行: 转到您的 Google Apps 域的管理控制台。

    从控件列表中选择安全。如果您没有看到列出的安全性,请从页面底部的灰色栏中选择更多控件,然后从控件列表中选择安全性。

    从选项列表中选择高级设置。

    在身份验证部分选择管理第三方 OAuth 客户端访问。

    在“客户名称”字段中输入服务帐户的客户 ID。

    在一个或多个 API 范围字段中,输入应授予您的应用程序访问权限的范围列表。例如,如果您需要在域范围内访问 Google Drive API 和 Google Calendar API,请输入:https://www.googleapis.com/auth/drivehttps://www.googleapis.com/auth/calendar

    点击授权。

    另外,请检查您的代码中是否包含了应用程序尝试访问的所有范围。

    如果您仍然发现问题,请告诉我。

    【讨论】:

    • 感谢您的回复。我被授予对我的 Google Apps 域的访问权限,并且我确认范围包括 Gmail 范围,但该应用程序返回 403 错误。但是,我尝试通过相同的凭据访问谷歌日历和谷歌驱动器(除了范围设置),然后我可以正常访问。为什么...?
    • 如果你的应用程序访问驱动器,那么范围应该包括在内。否则它会抛出这个错误
    猜你喜欢
    • 2023-04-09
    • 2014-09-13
    • 2020-09-23
    • 2011-01-26
    • 1970-01-01
    • 2016-12-19
    • 2020-08-28
    • 2014-07-19
    • 2017-07-18
    相关资源
    最近更新 更多