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

我正在尝试使用谷歌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();
    

在这里,我必须指出,我有很多问题来使用ClientID而不是ClientMail。它必须使用 @developer.gserviceaccount.com 帐户而不是 .apps.googleusercontent.com 。如果你不发送这个参数 ok ,你会得到一个“无效的授权”错误。这里对此进行了解释: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. 第五步:执行后获取结果...在这里,我收到异常:

线程“主”中的异常

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)

任何想法什么是错的,或者哪个是前提条件失败了??


答案 1

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

1.- 使用谷歌应用程序用户打开开发人员控制台

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

3.- 转到 [Apis & auth] > [Credentials] 并创建新的 [Service Account] 客户端 ID

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

5.- 现在,您必须将域范围的权限委托给服务帐户,以授权您的应用程序代表Google Apps域中的用户访问用户数据...所以去你的谷歌应用域管理控制台

6.- 转到[安全性]部分并找到[高级设置](它可能被隐藏,因此您必须单击[显示更多..])

7.- 单击 con [管理 API 客户端访问]

8.- 将您之前在 [4] 处复制的 [客户端 ID] 粘贴到 [客户端名称] 文本框中。

9.-要授予您的应用程序对gmail的完全访问权限,请在[API范围]文本框中输入:https://mail.google.comhttps://www.googleapis.com/auth/gmail.composehttps://www.googleapis.com/auth/gmail.modify https://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() 方法使用您的 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;
}

现在,您可以使用Gmail服务做任何您想做的事情,例如发送电子邮件;-)如 https://developers.google.com/gmail/api/guides/sending 所述


答案 2

非常感谢您的详细回答。我试图为 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 = credential,
                        ApplicationName = "Enquiry Email Sender"
                    });
    
                    var list = service.Users.Messages.List("me").Execute();
                    var count = "Message Count is: " + list.Messages.Count();
    
                    return count;
    
                }

推荐