当前位置: 首页 > 知识库问答 >
问题:

如何在Spring Boot 2中调用gmail api。x使用服务帐户?

冯亮
2023-03-14

我有一个GSuite服务帐户,配置为访问公司用户gmail帐户,我在G Suite管理控制台中为其提供了所有权限,包括全域访问权限。我创建了一个服务帐户,现在想使用凭据代表他们发送电子邮件。

以下是我目前的代码:

  public void gmailTest(){
  log.info("Gmail test");

  List<String> SCOPES = new ArrayList<String>(GmailScopes.all());
  // List<String> SCOPES = GmailScopes.all();
  InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("Program Name-12345678.json");

  try {
  if(resourceAsStream != null) {
    NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();

    log.info("Reading credential file");
    GoogleCredential credential = GoogleCredential.fromStream(resourceAsStream);
    log.info("Creating scopes");
    credential = credential.createScoped(SCOPES);

    log.info("building gmail api service");
    Gmail gmailService = new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName("ept-mailer").build();
    String user = "deusrex@mygenericdomain.com";

    log.info("calling gmail api");
    ListLabelsResponse listResponse = gmailService.users().labels().list(user).execute();
    log.info("call did not error");
    List<Label> labels = listResponse.getLabels();
    if (labels.isEmpty()) {
      System.out.println("No labels found.");
    } else {
      System.out.println("Labels:");
      for (Label label : labels) {
        System.out.printf("- %s\n", label.getName());
      }
    }
  }
  }
  catch (IOException | GeneralSecurityException ex) {
  log.error(ex.getMessage());
  }

以下是我的特权:

 Email (Manage labels)  https://www.googleapis.com/auth/gmail.labels 
 https://www.googleapis.com/auth/gmail.metadata 
 Email (Read/Write)  https://www.googleapis.com/auth/gmail.modify 

这是我得到的错误:

 400 Bad Request
 {
   "code" : 400,
   "errors" : [ {
     "domain" : "global",
     "message" : "Bad Request",
     "reason" : "failedPrecondition"
   } ],
   "message" : "Bad Request"
 }

共有2个答案

李跃
2023-03-14

我也有同样的问题,最后我解决了。我希望这个解决方案能帮助其他人。

创建服务号并将权限委托给谷歌办公套件。

  1. 转到谷歌云控制台转到服务帐户
@Value("${gcp.credentials.file}")
private String CREDENTIALS_FILE_PATH;


private static Credentials getCredentials(String CREDENTIALS_FILE_PATH) throws IOException {
    InputStream in = FileLoaderImpl.getStream(CREDENTIALS_FILE_PATH);
    if (in == null) {
        throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
    }
    GoogleCredentials credentials = GoogleCredentials
            .fromStream(in)
            .createDelegated(EMAIL_FROM)
            .createScoped(List.of(GmailScopes.GMAIL_SEND, GmailScopes.GMAIL_LABELS));
    return credentials;
}

private Gmail getGmailService() throws IOException, GeneralSecurityException {
    NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
    return new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY,
            new HttpCredentialsAdapter(getCredentials(CREDENTIALS_FILE_PATH)))
            .setApplicationName(APPLICATION_NAME)
            .build();
}

@Override
public Message sendMailWithTemplate(StarMail starMail, boolean isHtml) {
    try {
        MimeMessage mimeMessage = EmailUtils.createEmailMessage(starMail, isHtml);
        // MimeMessage mm = EmailUtils.createEmail(toEmail, USER_ID, subject, bodyText);
        Gmail service = getGmailService();
        Message message = EmailUtils.sendMessage(service, USER_ID, mimeMessage);
        LOGGER.info("Message id: {} ", message.getId());
        LOGGER.info(message.toPrettyString());
        return message;
    } catch (IOException | MessagingException | GeneralSecurityException e) {
        LOGGER.error("sending email failed {}", e);
        throw new RuntimeException("sending email failed " + e.getMessage());
    }
}
濮阳默
2023-03-14

好的,答案是在创建凭证时必须指定用户。在较新版本的API中,此调用已更改为:。createDelegate()。只要把你想冒充的用户邮件放在那里就行了。

 GoogleCredential credential = GoogleCredential.fromStream(resourceAsStream).createDelegated("deusrex@mygenericdomain.com");
 类似资料:
  • 我正面临着以下问题:我已经创建了一个谷歌服务帐户,现在我正在尝试使用c#对谷歌API和YouTube数据API进行授权API调用。以下是我的示例代码: 代码生成成功,但当我启动程序时,我收到以下错误消息: 系统.IO.File未发现异常:“无法加载文件或程序集”弹跳卡思加密,版本=1.7.4137.9688,区域性=非特定,公钥令牌=a4292a325f69b123“或其依赖项之一。系统找不到指定

  • 我试图使用我的应用程序的服务帐户访问我域中所有用户的所有文档,遵循以下指示: https://developers.google.com/drive/development但是它没有工作。你能帮我解决这个问题吗??我试着跟着网址- http://iambusychangingtheworld.blogspot.co.uk/2013/12/google-drive-api-how-work-with

  • 我有两个服务运行在谷歌计算引擎。这些服务是用GO编写的。每个服务都有单独的GCP服务帐户。在调用另一个服务时,我可以使用此服务帐户对一个服务进行身份验证吗?有没有适合它的API? 我不知道如何验证访问令牌的身份?正如其中一个答案所指出的,我无法向GCP IAM添加自定义权限(角色+资源)。 有大量关于验证Google云平台API调用的文档,但没有任何关于使用服务帐户来保护自己的endpoint的文

  • 我必须使用证书调用服务器API,所以我已经将cer文件导入到密钥库中并完成编码,但仍然得到了javax.net.ssl.SSLHandShakeException:Sun.Security.Validator.ValidatoreXception:PKIX路径构建失败:Sun.Security.Provider.CertPath.SunCertPathBuilderException:找不到请求目

  • 问题内容: }); 我正在尝试下载google.com主页并重新打印,但收到“发送后无法使用可变标头API”。错误 有人知道为什么吗?或如何拨打http电话? 问题答案: 退房的例子在这里对Node.js的文档。 该方法是一种便捷的方法,它处理GET请求的许多基本内容,通常没有任何内容。以下是如何发出简单HTTP GET请求的示例。

  • 问题内容: 我是Android开发的新手,我有一个用php制作的Web服务,现在我想在android中使用它,任何人都可以指导我如何实现这一目标。 我已经在网上尝试了许多代码示例,但未能实现此目标。我在ADT中使用Eclipse。 任何帮助都会得到应用。 问题答案: 请通过以下链接。您将在此处找到代码示例 http://www.anddev.org/calling_a_web_service_fr