【问题标题】:How to use service account to send email through GMAIL API using Java?如何使用服务帐户通过 GMAIL API 使用 Java 发送电子邮件?
【发布时间】:2020-04-05 10:57:29
【问题描述】:

我正在尝试使用服务帐户通过 GMAIL API 从 google 计算实例发送电子邮件。我按照this documentation 执行了所有步骤,但仍然收到一条错误消息,提示“com.google.api.client.auth.oauth2.TokenResponseException: 401 Unauthorized”。

下面是相同的代码sn-p。

public static void main( String[] args ) throws GeneralSecurityException, IOException, MessagingException
{
    final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
    GoogleCredential credentialFromJson = GoogleCredential
            .fromStream(new FileInputStream(
                    "/Users/souravc/Documents/MySpaceSRV6100/Java_Samples/EmailTest/mail-auth.json"))
            .createScoped(Collections.singletonList(GmailScopes.GMAIL_SEND));

    GoogleCredential credential = new GoogleCredential.Builder()
            .setTransport(HTTP_TRANSPORT)
            .setJsonFactory(JSON_FACTORY)
            .setServiceAccountId(credentialFromJson.getServiceAccountId())
            .setServiceAccountPrivateKey(credentialFromJson.getServiceAccountPrivateKey())
            .setServiceAccountScopes(SCOPES)
            .setServiceAccountUser("exampleemail").build();         

    //credential.refreshToken();

    Gmail service = new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build();

    String user = "me";
    Message123 obj = new Message123();
    obj.sendMessage(service, "me", obj.createEmail("exampleemail", "exampleemail",
            "Test", "Hi,\n\nTest Email\n\nThanks,\nSourav"));
}

在名为“Message123”的类中,我编写了 sendMessage()。下面是相同的代码。

public Message sendMessage(Gmail service, String userId, MimeMessage emailContent) throws MessagingException, IOException 
{
    Message message = createMessageWithEmail(emailContent);
    message = service.users().messages().send(userId, message).execute();
    System.out.println("Message id: " + message.getId());
    System.out.println(message.toPrettyString());
    return message;
}

注意:委派域范围的权限尚未授予服务帐户

你能帮忙吗?在这里我想再问一个问题,即使我只是发送电子邮件而不读取/获取任何其他用户数据,我们是否需要为服务帐户分配域范围的授权?

提前感谢您的帮助

【问题讨论】:

  • 哪个语句抛出异常?
  • 最后一条语句。 "obj.sendMessage(service, "me", obj.createEmail("exampleemail", "exampleemail", "Test", "Hi,\n\nTest Email\n\nThanks,\nSourav"));"
  • SCOPES 变量的值是多少?
  • @guillaume blaquiere 值是https://www.googleapis.com/auth/gmail.send
  • 您在 GSuite 域中吗?您的电子邮件的发件人不是电子邮件地址.setServiceAccountUser("exampleemail"),我不知道这是否是问题。

标签: google-cloud-platform google-compute-engine gmail-api google-oauth google-api-java-client


【解决方案1】:

问题出在这里

注意:委派域范围的权限尚未授予服务帐户

在您的用例中,您希望服务帐户代表您发送电子邮件。与documentation中提供的描述接近

例如,使用 Google Calendar API 将事件添加到 G Suite 域中所有用户的日历的应用程序将使用服务帐户代表用户访问 Google Calendar API

401 错误表示服务帐户已通过身份验证(您将拥有 403)但无权执行该操作,代表您发送电子邮件

【讨论】:

  • 感谢您的意见。所以我必须向同一个服务帐户授予 Delegating domain-wide 权限?
  • 是的,如果你愿意的话。如果此服务帐户仅用于此目的,则可以。如果它被多个事物共享,请优先选择最低权限模式,并仅为该任务创建另一个。
  • 是的,因为要能够模拟任何用户,您需要一个domain-wide authority 的服务帐户。
  • 似乎您想要的只是代表特定帐户发送电子邮件的权限,或者在最坏的情况下,代表几个特定帐户。有没有办法做到这一点?将电子邮件“作为”应用程序发送是一个相当典型的用例,例如noreply@myapp.example.com。你是怎么做到的?
  • 感谢所有输入。我会在授予全域权限后重试,并会及时通知您
猜你喜欢
  • 2020-09-30
  • 1970-01-01
  • 2016-01-18
  • 2016-04-20
  • 2012-03-30
  • 1970-01-01
  • 2021-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多