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

时间:2015-03-29 10:07:37

标签: java rest google-cloud-endpoints gmail-api

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

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

此示例有效,但这是基于GoogleAuthorizationCodeFlow。我只想从服务器到服务器工作,直接调用,而不是打开浏览器来获取访问令牌......我得到了它(访问令牌)但最后我收到了错误请求....为什么? ?我收到的信息不仅仅是 "错误请求"和"前提条件失败"

基于此,我按照以下步骤操作:

  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();
    
  2. 在这里我必须指出,我在使用ClientID而不是ClientMail时遇到了很多问题。它必须使用@ developer.gserviceaccount.com帐户而不是.apps.googleusercontent.com。如果你不发送这个参数,你会得到一个" INVALID GRANT"错误。这在此解释: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. 第五步:执行后获取结果...此处我收到例外:
    5. 线程中的异常" 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)
      

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

3 个答案:

答案 0 :(得分:21)

这就是我设法让它与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.-创建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 = "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()方法中,使用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;
}

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

答案 1 :(得分:0)

非常感谢您提供详细的答案。我正在尝试使此功能适用于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;

                }

答案 2 :(得分:0)

我正面临着同样的问题,因此正在对现有线程进行标记,并且在遵循上述步骤后仍然遇到相同的错误:

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是我在创建服务帐户时下载的。我还完成了以下步骤:

仍然没有解决。我会缺少什么?