You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java REST服务Gmail API Client Credential Flow实现配置求助

Google邮件API无人工干预对接方案(Java REST实现)

核心授权模式说明

你需要的无人工干预授权对应Google的服务账号+域范围委派模式(仅适用于Google Workspace/G Suite账户)。如果是普通Google个人账户,无法实现完全无人工干预,只能通过OAuth2授权码流让用户手动授权一次后,存储刷新令牌自动续用。以下方案优先针对Workspace账户,同时补充个人账户的替代实现。

一、Google Cloud平台配置

  • 创建Google Cloud项目,搜索并启用Gmail API
  • 生成服务账号:在「IAM与管理」→「服务账号」中创建账号,下载JSON格式的密钥文件(包含client_id、client_email、private_key等核心信息)
  • 域范围委派:
    1. 打开服务账号详情页,点击「编辑」→「显示域范围委派」,勾选「启用G Suite域范围委派」
    2. 登录Google Workspace管理控制台,进入「安全」→「API控制」→「域范围委派」,添加服务账号的client_id,授权范围填写https://www.googleapis.com/auth/gmail.send(遵循最小权限原则,仅申请发送邮件权限)

二、Java实现细节

1. 依赖配置(Maven)

<dependency>
    <groupId>com.google.oauth-client</groupId>
    <artifactId>google-oauth-client</artifactId>
    <version>1.34.1</version>
</dependency>
<dependency>
    <groupId>com.google.apis</groupId>
    <artifactId>google-api-services-gmail</artifactId>
    <version>v1-rev20230515-2.0.0</version>
</dependency>
<dependency>
    <groupId>com.google.auth</groupId>
    <artifactId>google-auth-library-oauth2-http</artifactId>
    <version>1.19.0</version>
</dependency>

2. 从数据库加载凭据

假设你的数据库为每个客户端存储以下加密后的信息:

  • 服务账号JSON密钥字符串(或密钥文件路径)
  • 目标发送邮箱(如user@client-domain.com)

3. 无人工干预获取令牌并发送邮件

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.model.Message;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Properties;

public class GoogleMailSender {

    // 从数据库读取并解密后的服务账号JSON字符串
    private static final String SERVICE_ACCOUNT_JSON = "数据库中存储的服务账号JSON内容";
    // 从数据库读取的目标发送邮箱
    private static final String TARGET_USER_EMAIL = "client-user@example.com";
    private static final String GMAIL_SCOPE = "https://www.googleapis.com/auth/gmail.send";

    public static void sendEmail(String to, String subject, String body) throws IOException, MessagingException {
        // 初始化服务账号凭据,模拟用户身份
        GoogleCredentials credentials = ServiceAccountCredentials.fromStream(
                        new StringReader(SERVICE_ACCOUNT_JSON))
                .createDelegated(TARGET_USER_EMAIL)
                .createScoped(Collections.singletonList(GMAIL_SCOPE));

        // 构建Gmail API客户端
        final NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        Gmail service = new Gmail.Builder(httpTransport, GsonFactory.getDefaultInstance(),
                        new HttpCredentialsAdapter(credentials))
                .setApplicationName("你的通知服务名称")
                .build();

        // 创建MIME格式邮件
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        MimeMessage mimeMessage = new MimeMessage(session);
        mimeMessage.setFrom(new InternetAddress(TARGET_USER_EMAIL));
        mimeMessage.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to));
        mimeMessage.setSubject(subject);
        mimeMessage.setText(body);

        // 转换为Gmail API兼容的Message格式
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        mimeMessage.writeTo(buffer);
        byte[] rawMessageBytes = buffer.toByteArray();
        String encodedEmail = java.util.Base64.getUrlEncoder().encodeToString(rawMessageBytes);
        Message message = new Message();
        message.setRaw(encodedEmail);

        // 发送邮件
        service.users().messages().send("me", message).execute();
    }

    public static void main(String[] args) {
        try {
            sendEmail("recipient@example.com", "测试通知", "这是通过Google API自动发送的邮件");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

三、普通Google个人账户的替代实现

若客户端使用普通Google账户,无法使用服务账号模式,需先引导用户手动授权一次,存储刷新令牌后自动续用:

  1. 生成授权URL,引导用户完成授权,获取授权码
  2. 用授权码交换访问令牌和刷新令牌,将刷新令牌加密存储到数据库
  3. 后续通过刷新令牌自动获取新的访问令牌,无需人工干预

核心刷新令牌代码示例:

import com.google.auth.oauth2.UserCredentials;
import java.io.IOException;

public String getAccessToken(String clientId, String clientSecret, String refreshToken) throws IOException {
    UserCredentials credentials = UserCredentials.newBuilder()
            .setClientId(clientId)
            .setClientSecret(clientSecret)
            .setRefreshToken(refreshToken)
            .build();
    credentials.refresh();
    return credentials.getAccessToken().getTokenValue();
}

四、关键注意事项

  • 令牌缓存:访问令牌有效期约1小时,建议缓存令牌避免重复请求API
  • 凭据加密:数据库中存储的服务账号密钥、刷新令牌必须加密,防止泄露
  • 权限控制:仅申请必要的API权限,避免过度授权带来的安全风险
  • Workspace验证:确保客户端的Workspace管理员已完成域范围委派的授权操作

内容的提问来源于stack exchange,提问作者Hari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 22:01:26