Gmail API +服务帐户返回403错误

时间:2014-11-20 09:12:15

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

所有

我尝试使用服务帐户的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范围)。

有什么问题?

谢谢!

1 个答案:

答案 0 :(得分: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

点击授权。

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

如果您仍然看到问题,请告诉我。