web-dev-qa-db-ja.com

Gmail REST API:400 Bad Request + Failed Precondition

Gmailに基づいてメールを送信しようとしていますREST Googleを使用したAPI Java APIサービス。GoogleDevelover Consoleを介してアプリケーションクライアントを設定し、p12をダウンロードしました。 jsonファイル。

私はこのサンプルプログラムを使用しました https://developers.google.com/gmail/api/guides/sending#sending_messages ...

このサンプルは機能しますが、これはGoogleAuthorizationCodeFlowに基づいています。サーバー間で直接作業し、ブラウザを開かずにアクセストークンを取得するだけで、アクセストークンを取得したいのですが(アクセストークン)取得しましたが、最終的に不正なリクエストを受け取りました...なぜですか? ? "Bad Request" and "Precondition Failed"]よりも多くの情報を受け取りません

これに基づいて、私は次のステップに従います:

  1. 最初のステップ:クライアントアカウントのメールとp12で生成されたファイルに基づいてGoogleCredentialオブジェクトを作成します。

    GoogleCredential  credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport())
                                        .setJsonFactory(new JacksonFactory())
                                        .setServiceAccountId(serviceAccountUserEmail)
                                        .setServiceAccountScopes(scopes)
                                        .setServiceAccountPrivateKeyFromP12File(
                                                    new Java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))                             
                                                            .build();
    

ここで、ClientMailの代わりにClientIDを使用することで多くの問題があったことを指摘する必要があります。 .apps.googleusercontent.comではなく@ developer.gserviceaccount.comアカウントを使用する必要があります。このパラメータをokに送信しないと、「無効な許可」エラーが発生します。これはここで説明されています: https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtAuthorization

  1. 2番目のステップ:認証情報に基づいてGmailサービスを作成します。

    Gmail gmailService = new Gmail.Builder(httpTransport,
                                                  jsonFactory,
                                                  credential)
                                                .setApplicationName(APP_NAME)
                                                    .build();
    
  2. 3番目のステップMimmeMessageからGoogle rawメッセージを作成します。

    private static Message _createMessageWithEmail(final MimeMessage email) throws MessagingException, IOException {
    
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    email.writeTo(bytes);
    String encodedEmail =       Base64.encodeBase64URLSafeString(bytes.toByteArray());      
    Message message = new Message();    
    message.setRaw(encodedEmail);
    return message;
    

    }

  3. 4番目のステップサービスを呼び出します。

        Message message = _createMessageWithEmail(email);
    message = service.users()
    .messages()
    .send(userId,message)
    .execute();
    
  4. 5番目のステップ:実行後に結果を取得...ここで例外を受け取ります:

スレッド「メイン」の例外

com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
  "code" : 400,
  "errors" : [ {
    "domain" : "global",
    "message" : "Bad Request",
    "reason" : "failedPrecondition"
  } ],
  "message" : "Bad Request"
}
    at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.Java:145)

何が間違っているのか、または前提条件が失敗したのか?

15
Azimuts

これが、Google Appsドメインで機能させる方法です。

1.- Google Appsユーザーを使用して開発者コンソールを開きます

2.-新しいprojectを作成します(つまりMyProject

3. APIと認証]> [認証情報]に移動し、新しい[サービスアカウント]クライアントIDを作成します

4.- [サービスアカウント]の[クライアントID](xxx.apps.googleusercontent.comのようなもの)を後で使用するためにコピーします

5.-これで、--- [ドメイン全体の権限をサービスアカウントに委任するを実行して、アプリがユーザーにアクセスすることを承認する必要があります。 Google Appsドメインのユーザーに代わってデータを取得する...google apps domain管理コンソールに移動します

6. セキュリティ]セクションに移動し、[詳細設定]を見つけます(非表示になっている可能性があるため、[もっと見る...]をクリックする必要があります)。

7.-クリック[APIクライアントアクセスの管理]

8.- [4]で前にコピーした[クライアントID]を[クライアント名]テキストボックスに貼り付けます。

9.-アプリにGmailへのフルアクセスを付与するには、[APIスコープ]テキストボックスに次のように入力します。--- [https:// mail。 google.comhttps://www.googleapis.com/auth/gmail.composehttps://www.googleapis.com/auth/gmail.modifyhttps://www.googleapis.com/auth/gmail.readonly(すべてのスコープを入力することが非常に重要です)


これですべての設定が完了しました...次のコード:

1.- HttpTransportを作成する

private static HttpTransport _createHttpTransport() throws GeneralSecurityException,
                                                           IOException { 
    HttpTransport httpTransport = new NetHttpTransport.Builder()                                                 
                                                      .trustCertificates(GoogleUtils.getCertificateTrustStore())
                          .build();
    return httpTransport;
}

2.- JSonFactoryを作成する

private static JsonFactory _createJsonFactory() {
    JsonFactory jsonFactory = new JacksonFactory();
    return jsonFactory;
}

3.- Google認証情報を作成する

private static GoogleCredential _createCredentialUsingServerToken(final HttpTransport httpTransport,
                                                                  final JsonFactory jsonFactory) throws IOException,
                                                                                                        GeneralSecurityException {
    // Use the client ID when making the OAuth 2.0 access token request (see Google's OAuth 2.0 Service Account documentation).
    String serviceAccountClientID = "327116756300-thcjqf1mvrn0geefnu6ef3pe2sm61i2q.apps.googleusercontent.com"; 

    // Use the email address when granting the service account access to supported Google APIs 
    String serviceAccountUserEmail = "[email protected]";

    GoogleCredential credential = new GoogleCredential.Builder()
                                                .setTransport(httpTransport)
                                                .setJsonFactory(jsonFactory)
                                                .setServiceAccountId(serviceAccountUserEmail)    // requesting the token
                                                .setServiceAccountPrivateKeyFromP12File(new File(SERVER_P12_SECRET_PATH))
                                                .setServiceAccountScopes(SCOPES)    // see https://developers.google.com/gmail/api/auth/scopes
                                                .setServiceAccountUser("[email protected]")
                                                .build();    
    credential.refreshToken();
    return credential;
}

注:setServiceAccountUser()メソッドで、Google Appsドメインの任意のユーザーを使用します

4.- Gmailサービスを作成する

private static Gmail _createGmailService(final HttpTransport httpTransport,
                                         final JsonFactory jsonFactory,
                                         final GoogleCredential credential) {
    Gmail gmailService = new Gmail.Builder(httpTransport,
                                            jsonFactory,
                                            credential)
                                   .setApplicationName(APP_NAME)
                                   .build();
    return gmailService;
}

https://developers.google.com/gmail/api/guides/sending で説明されているように、メールを送信するなど、GmailServiceで好きなことができます。

23

同じ問題に直面しているため、既存のスレッドにタグを付けていますが、上記の手順を実行しても同じエラーが発生します。

ノードコンソールエラーのスクリーンショット

私の場合は、メールを送信するnodeJSサービスを作成しています。私はgoogleapis npmモジュールを使用しています。コードのチャンクの例は次のようになります。

const { google } = require("googleapis");
const gmailCredentials = require("./credentials.json");

const SCOPES = [
    "https://mail.google.com/",
    "https://www.googleapis.com/auth/gmail.modify",
    "https://www.googleapis.com/auth/gmail.compose",
    "https://www.googleapis.com/auth/gmail.readonly",
];

const jwtClient = new google.auth.JWT(
    gmailCredentials.client_email,
    null,
    gmailCredentials.private_key,
    SCOPES
);

//authenticate
jwtClient.authorize((err, tokens) => {
    if (err) {
        console.log(err);
        return;
    } else {
        console.log("Successfully connected!");

        const gmail = google.gmail("v1");

        gmail.users.messages.list({
            auth: jwtClient,
            userId: "me",
        });
    }
});

gmailCredentialsは、サービスアカウントの作成時にダウンロードしたものです。次の手順も実行しました。

まだ解決していません。何が欠けているのでしょうか?

0
FerBorVa

詳しい回答ありがとうございました。私はasp.net MVCでこれを機能させようとしていました。しかし、与えられたステップからすべてを実行した後、私のコードは同じエラーを出していました。

このエラーを解決するために2日を費やした後、私は次の方法でこれを解決できました。 ServiceAccountCredential.Initializerコンストラクターでは、このサービスアカウントで偽装しようとしているユーザーIDを指定する必要があります。

    ServiceAccountCredential credential = new ServiceAccountCredential(
               new ServiceAccountCredential.Initializer(serviceAccountEmail)
               {
                   User = "<USER@YOUR_GSUIT_DOMAIN.COM>",
                   Scopes = new[] { GmailService.Scope.MailGoogleCom }
               }.FromPrivateKey(<YOUR_PRIVATE_KEY>);

    if (credential != null)
                {
                    var service = new GmailService(new BaseClientService.Initializer
                    {
                        HttpClientInitializer = result,
                        ApplicationName = "Enquiry Email Sender"
                    });

                    var list = service.Users.Messages.List("me").Execute();
                    var count = "Message Count is: " + list.Messages.Count();

                    return count;

                }
0
mangeshkt