如何使用服务帐户在 Spring Boot 2.x 中调用 gmail api?
How do I call the gmail api in Spring Boot 2.x using a service account?
我有一个配置为访问公司用户 gmail 帐户的 GSuite 服务帐户,我在 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"
}
好的,答案是您必须在创建凭据时指定用户。在 API 的较新版本中,此调用已更改为:.createDelegated()。只需将您希望模拟的用户电子邮件放在那里即可。
GoogleCredential credential = GoogleCredential.fromStream(resourceAsStream).createDelegated("deusrex@mygenericdomain.com");
我遇到了同样的问题,最后我解决了。我希望该解决方案可以帮助其他人。
创建一个服务帐户并将权限委托给 GSuite。
- 转到google 云控制台go-to 服务帐户
- 启用 G Suite domain-wide 委派
- 复制客户 ID
- 登录您的 GSuite 帐户。转到安全 -> API 控制 ->
Domain-wide委派
- 添加您的客户端 ID 和范围。
- 和最终样本java代码:
@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());
}
}
我有一个配置为访问公司用户 gmail 帐户的 GSuite 服务帐户,我在 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"
}
好的,答案是您必须在创建凭据时指定用户。在 API 的较新版本中,此调用已更改为:.createDelegated()。只需将您希望模拟的用户电子邮件放在那里即可。
GoogleCredential credential = GoogleCredential.fromStream(resourceAsStream).createDelegated("deusrex@mygenericdomain.com");
我遇到了同样的问题,最后我解决了。我希望该解决方案可以帮助其他人。
创建一个服务帐户并将权限委托给 GSuite。
- 转到google 云控制台go-to 服务帐户
- 启用 G Suite domain-wide 委派
- 复制客户 ID
- 登录您的 GSuite 帐户。转到安全 -> API 控制 -> Domain-wide委派
- 添加您的客户端 ID 和范围。
- 和最终样本java代码:
@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());
}
}