0

全て

サービス アカウントで 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 スコープを含む) を設定しました。

なにが問題ですか?

ありがとう!

4

1 に答える 1

2

アプリケーションがユーザー データにアクセスする場合、作成したサービス アカウントには、アクセスする Google Apps ドメインのユーザー データへのアクセス権を付与する必要があります。

次の手順は、Google Apps ドメインの管理者が実行する必要があります: Google Apps ドメインの管理コンソールに移動します。

コントロールのリストから [セキュリティ] を選択します。[セキュリティ] が一覧に表示されない場合は、ページの下部にある灰色のバーから [その他のコントロール] を選択し、コントロールの一覧から [セキュリティ] を選択します。

オプションのリストから [詳細設定] を選択します。

[認証] セクションで [サード パーティの OAuth クライアント アクセスを管理する] を選択します。

[クライアント名] フィールドに、サービス アカウントのクライアント ID を入力します。

[1 つ以上の API スコープ] フィールドに、アプリケーションにアクセスを許可するスコープのリストを入力します。たとえば、Google Drive API と Google Calendar API へのドメイン全体のアクセスが必要な場合は、次のように入力します: https://www.googleapis.com/auth/drive , https://www.googleapis.com/auth/calendar

[承認] をクリックします。

また、アプリケーションがアクセスしようとしているコードにすべてのスコープが含まれているかどうかを確認してください。

問題が解決しない場合はお知らせください。

于 2014-11-20T19:55:30.043 に答える