Gmail API +服务帐户返回403错误 [英] Gmail API + Service accounts return 403 error

查看:139
本文介绍了Gmail API +服务帐户返回403错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

全部

我尝试使用服务帐户使用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 Apps域的用户数据.

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

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

从选项列表中选择高级设置".

在身份验证"部分中选择管理第三方OAuth客户端访问权限".

在客户名称"字段中输入服务帐户的客户ID.

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

点击授权.

此外,请检查您的代码是否已将应用程序试图访问的所有范围都包括在内.

让我知道您是否仍然看到该问题.

All

I tried Gmail API with service account. I implemented code following:

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

but that code return 403 error:

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

Of course, I enabled Gmail API via Google Developer Console and set permissions(include Gmail scope) via Admin console.

What is wrong?

Thanks!

解决方案

If your application accesses user data, the service account that you created needs to be granted access to the Google Apps domain’s user data that you want to access.

The following steps must be performed by an administrator of the Google Apps domain: Go to your Google Apps domain’s Admin console.

Select Security from the list of controls. If you don't see Security listed, select More controls from the gray bar at the bottom of the page, then select Security from the list of controls.

Select Advanced settings from the list of options.

Select Manage third party OAuth Client access in the Authentication section.

In the Client name field enter the service account's Client ID.

In the One or More API Scopes field enter the list of scopes that your application should be granted access to. For example if you need domain-wide access to the Google Drive API and the Google Calendar API enter: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar

Click Authorize.

Also, please check whether you have included all the scopes in your code which your application is trying to access.

Let me know if you still see the issue.

这篇关于Gmail API +服务帐户返回403错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆