Gmail REST API:400错误请求+失败的前提条件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gmail REST API:400错误请求+失败的前提条件相关的知识,希望对你有一定的参考价值。

我正在尝试使用google java api服务发送基于Gmail REST API的邮件。我已通过Google Develover Console配置了应用程序客户端并下载了p12和json文件。

我用过这个示例程序,https://developers.google.com/gmail/api/guides/sending#sending_messages ......

此示例有效,但这是基于GoogleAuthorizationCodeFlow。我只想从服务器到服务器工作,直接调用,而不是打开浏览器来获取访问令牌......我得到了它(访问令牌)但最后我收到了错误请求....为什么? ?我收到的信息不仅仅是“Bad Request”和“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();

在这里,我必须指出,我有很多问题需要使用ClientID而不是ClientMail。它必须使用@ developer.gserviceaccount.com帐户而不是.apps.googleusercontent.com。如果你不发送这个参数确定,你得到一个“无效授予”错误。这在这里解释:https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtAuthorization

  1. 第二步:根据凭据创建Gmail服务: Gmail gmailService = new Gmail.Builder(httpTransport, jsonFactory, credential) .setApplicationName(APP_NAME) .build();
  2. 第三步从MimmeMessage创建Google原始消息: 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. 第四步调用服务: Message message = _createMessageWithEmail(email); message = service.users() .messages() .send(userId,message) .execute();
  4. 第五步:执行后获得结果......这里我收到例外:

线程“main”中的异常

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)

知道什么是错的或哪个是前提条件失败?

答案

这就是我设法让它与Google Apps域一起使用的方法:

1.-使用谷歌应用程序用户打开developer console

2.-创建一个新项目(即MyProject)

3.-转到[Apis&auth]> [凭据]并创建新的[服务帐户]客户端ID

4.-复制[服务帐户]的[客户端ID](类似xxx.apps.googleusercontent.com)以供日后使用

5.-现在你需要Delegate domain-wide authority to the service account才能授权你的appl代表Google Apps域中的用户访问用户数据...所以转到你的google apps domain admin console

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.-创建一个谷歌凭证

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 = "xxxx@developer.gserviceaccount.com";

    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("user@example.com")
                                                .build();    
    credential.refreshToken();
    return credential;
}

注意:在setServiceAccountUser()方法中,使用谷歌应用程序域中的任何用户

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

现在,您可以使用GmailService执行任何操作,例如发送电子邮件;-),如https://developers.google.com/gmail/api/guides/sending所述

另一答案

非常感谢您的详细解答。我试图让这个工作为asp.net MVC。但是在遵循给定步骤的所有内容之后,我的代码给出了同样的错误。

花了两天时间来解决这个错误,我可以通过以下方式解决这个问题。在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;

                }
另一答案

我在现有线程上进行标记,因为我正面临同样的问题,并且在执行上述操作后仍然遇到同样的错误:

screenshot of node console error

就我而言,我正在整理一个将发送电子邮件的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是我在创建服务帐户时下载的。我还经历了以下步骤:

还是没有解决。我能错过什么?

以上是关于Gmail REST API:400错误请求+失败的前提条件的主要内容,如果未能解决你的问题,请参考以下文章

使用服务帐户的 Gmail API 集转发

Gmail REST API:400 Bad Request + Failed Precondition

Firebase 动态链接 REST API 返回 400 错误请求

Google API (Gmail) 因失败的前提条件 400 而失败

JavaScript SDK 上的 Parse Push Rest API 出现 400 错误请求错误

SharePoint REST API。在 SharePoint 列表上进行 AJAX 调用时出现 400 错误请求