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

Azi*_*uts 12 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.我只想从服务器到服务器工作,直接调用,而不是打开浏览器来获取访问令牌......我得到了它(访问令牌)但最后我收到了错误请求....为什么? ?我收到的信息不仅仅是"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();
    
    Run Code Online (Sandbox Code Playgroud)

在这里,我必须指出,我有很多问题需要使用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();
    
    Run Code Online (Sandbox Code Playgroud)
  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;
    
    Run Code Online (Sandbox Code Playgroud)

    }

  3. 第四步调用服务:

        Message message = _createMessageWithEmail(email);
    message = service.users()
    .messages()
    .send(userId,message)
    .execute();
    
    Run Code Online (Sandbox Code Playgroud)
  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)
Run Code Online (Sandbox Code Playgroud)

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

fut*_*ics 23

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

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

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

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

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

5.-现在您必须将域范围的权限委派给服务帐户才能授权您的appl代表Google Apps域中的用户访问用户数据...所以转到您的Google Apps域管理控制台

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

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

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

9.-授予您的应用程序完全访问 Gmail时,在[API范围]文本框中输入:https://mail.google.com,https://www.googleapis.com/auth/gmail.compose,HTTPS: //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;
}
Run Code Online (Sandbox Code Playgroud)

2.-创建一个JSonFactory

private static JsonFactory _createJsonFactory() {
    JsonFactory jsonFactory = new JacksonFactory();
    return jsonFactory;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

注意:在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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这似乎需要在步骤5中使用g-suite.除了个人电子邮件之外,我不需要访问任何内容.应该是一个简单的要求的沉重,复杂和昂贵的解决方案. (4认同)
  • 在第4步中,您说"像xxx.apps.googleusercontent.com这样的人"."服务帐户ID"看起来像(如电子邮件),但如果您在步骤8中粘贴它,它似乎工作并列出客户端ID(数字)和范围,但您将收到"failedPrecondition"和"bad"请求",如果您尝试模拟"客户端未经授权使用此方法检索访问令牌".修复方法是在步骤8中使用客户端ID(数字)而不是服务帐户ID(看起来像电子邮件). (2认同)