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

2022年5月30日谷歌停用SMTP网关后 Java用Gmail API+Servlet/JSP发邮件

Java Servlet/JSP 环境下通过Gmail API实现邮件发送方案

谷歌2022年5月30日停止普通账号SMTP网关服务后,原有基于JavaMail直连smtp.gmail.com的方案已经失效,你可以按照以下步骤迁移到Gmail API实现发信,全程兼容传统Servlet、JSP开发环境,原有邮件内容构造逻辑基本不需要修改。

前置准备

  • 登录谷歌云控制台创建新项目,搜索并启用「Gmail API」服务
  • 进入「API和服务-凭据」页面创建服务账号,为服务账号分配邮件发送权限,下载生成的JSON格式凭据文件,存放到Web项目的WEB-INF/conf目录下,不要放在静态资源可公开访问的路径
  • 个人Gmail账号需要在邮箱设置中把服务账号添加为授权发件人;企业Workspace账号直接在管理后台给服务账号分配全域邮件发送权限即可

引入项目依赖

如果使用Maven管理依赖,在pom.xml中添加以下配置:

<!-- Gmail API 核心依赖 -->
<dependency>
    <groupId>com.google.api-client</groupId>
    <artifactId>google-api-client</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>com.google.oauth-client</groupId>
    <artifactId>google-oauth-client-jetty</artifactId>
    <version>1.34.1</version>
</dependency>
<dependency>
    <groupId>com.google.apis</groupId>
    <artifactId>google-api-services-gmail</artifactId>
    <version>v1-rev20240109-2.0.0</version>
</dependency>
<!-- 兼容原有JavaMail的MIME消息构造依赖,无需重写邮件内容生成逻辑 -->
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

非Maven项目直接下载对应jar包放到WEB-INF/lib目录即可。

封装Gmail发送工具类

工具类做全局单例初始化,避免重复创建客户端连接浪费资源,同时兼容原有JavaMail的邮件构造逻辑:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
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.GmailScopes;
import com.google.api.services.gmail.model.Message;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.Base64;

public class GmailSendUtil {
    // 替换为你自己的凭据文件实际路径、发件人邮箱
    private static final String CREDENTIAL_PATH = "/你的项目部署路径/WEB-INF/conf/gmail-credential.json";
    private static final String SENDER_EMAIL = "你的发件人邮箱@gmail.com";
    private static final GsonFactory GSON_FACTORY = GsonFactory.getDefaultInstance();
    private static final List<String> SCOPES = Collections.singletonList(GmailScopes.GMAIL_SEND);
    private static Gmail gmailService;

    // 静态块初始化Gmail客户端,项目启动时执行一次
    static {
        try {
            NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
            GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(CREDENTIAL_PATH))
                    .createScoped(SCOPES);
            // 企业Workspace账号可删除下一行,个人账号必须指定授权发件人
            credential = credential.createDelegated(SENDER_EMAIL);
            gmailService = new Gmail.Builder(httpTransport, GSON_FACTORY, credential)
                    .setApplicationName("你的Web项目名称")
                    .build();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 邮件发送方法,调用逻辑和原有JavaMail写法一致
     * @param to 收件人邮箱
     * @param subject 邮件主题
     * @param htmlContent 邮件正文,支持HTML格式
     * @throws Exception 发送异常
     */
    public static void sendMail(String to, String subject, String htmlContent) throws Exception {
        // 以下MimeMessage构造逻辑和你之前SMTP方案的写法基本一致
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        MimeMessage mimeMessage = new MimeMessage(session);
        mimeMessage.setFrom(new InternetAddress(SENDER_EMAIL));
        mimeMessage.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to));
        mimeMessage.setSubject(subject, "UTF-8");
        mimeMessage.setContent(htmlContent, "text/html;charset=UTF-8");

        // 转换为Gmail API要求的编码格式
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        mimeMessage.writeTo(baos);
        String encodedEmail = Base64.getUrlEncoder().encodeToString(baos.toByteArray());
        Message message = new Message();
        message.setRaw(encodedEmail);

        // 调用接口发送
        gmailService.users().messages().send("me", message).execute();
    }
}

在Servlet/JSP中调用

直接在业务逻辑层调用工具类即可,不要在JSP页面中直接写凭据加载、客户端初始化逻辑,避免凭据泄露。Servlet中调用示例:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("UTF-8");
    String receiveMail = request.getParameter("to");
    String mailSubject = request.getParameter("subject");
    String mailContent = request.getParameter("content");
    try {
        GmailSendUtil.sendMail(receiveMail, mailSubject, mailContent);
        request.setAttribute("result", "邮件发送成功");
    } catch (Exception e) {
        request.setAttribute("result", "邮件发送失败:" + e.getMessage());
    }
    request.getRequestDispatcher("/result.jsp").forward(request, response);
}

注意事项

  • JSON凭据文件必须放在WEB-INF等外部无法直接访问的目录,一旦泄露他人可以直接操作你的Gmail发信
  • 原有JavaMail的附件添加、抄送、密送等逻辑完全不需要修改,只要保留MimeMessage的构造部分即可,迁移成本极低
  • 如果需要让访问用户用自己的Gmail账号发信,可以把服务账号模式换成OAuth2用户授权模式,第一次登录授权后保存refreshToken即可长期使用
  • 生产环境建议给Gmail客户端初始化加异常重试逻辑,避免接口临时波动导致发信失败

内容的提问来源于stack exchange,提问作者Troll Liên quân

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:01:04