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

Java应用通过Gmail发邮件遇认证失败,求谷歌新规下的实现方案

解决Gmail第三方应用登录认证失败问题

谷歌自2022年5月30日起,已彻底禁用低安全应用访问权限,同时不再支持仅通过用户名+密码的方式登录谷歌账户的第三方应用/设备,这就是你遇到535-5.7.8 Username and Password not accepted认证错误的原因。目前有两种可靠的解决方案:

方案一:使用应用专用密码(个人场景首选)

这种方式操作简单,适合个人开发者使用,但前提是你的谷歌账户必须开启两步验证。

操作步骤:

  1. 登录谷歌账户,进入「安全」设置页面
  2. 在「登录谷歌」板块找到「应用专用密码」选项
  3. 选择应用类型为「邮件」,设备类型选「其他」(自定义名称即可),点击生成密码
  4. 将Java/Spring配置中原来的账户密码替换为这个生成的16位应用专用密码

Spring配置示例(application.properties):

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=your-gmail@gmail.com
spring.mail.password=生成的应用专用密码
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

方案二:OAuth 2.0认证(企业/多用户场景首选)

如果是面向多用户的应用,或者需要更高的安全性,推荐使用OAuth2认证方式,这也是谷歌官方推荐的第三方应用接入方式。

操作流程:

  1. 登录谷歌云平台,创建新的项目
  2. 在项目中启用「Gmail API」
  3. 创建OAuth客户端ID,应用类型根据你的场景选择:桌面应用/后端服务选「桌面应用」,Web应用选「Web应用」
  4. 下载客户端密钥文件(credentials.json),放置在项目资源目录中
  5. 通过授权流程获取刷新令牌,后续可自动刷新访问令牌

Spring整合OAuth2的代码示例:

首先添加Maven依赖:

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>
<dependency>
    <groupId>com.google.oauth-client</groupId>
    <artifactId>google-oauth-client-java6</artifactId>
    <version>1.34.1</version>
</dependency>
<dependency>
    <groupId>com.google.apis</groupId>
    <artifactId>google-api-services-gmail</artifactId>
    <version>v1-rev110-1.25.0</version>
</dependency>

然后编写配置类:

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.gmail.GmailScopes;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;

import javax.mail.Session;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.Properties;

@Configuration
public class GmailOAuth2Config {
    private static final String APP_NAME = "你的应用名称";
    private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
    private static final String TOKEN_STORAGE_PATH = "tokens";
    private static final String CREDENTIALS_PATH = "/credentials.json";
    private static final String SCOPE = GmailScopes.GMAIL_SEND;

    private Credential getOAuthCredential() throws IOException, GeneralSecurityException {
        var credentialStream = GmailOAuth2Config.class.getResourceAsStream(CREDENTIALS_PATH);
        if (credentialStream == null) {
            throw new IOException("未找到credentials.json文件");
        }
        var clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(credentialStream));

        var authFlow = new GoogleAuthorizationCodeFlow.Builder(
                GoogleNetHttpTransport.newTrustedTransport(), JSON_FACTORY, clientSecrets, Collections.singletonList(SCOPE))
                .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKEN_STORAGE_PATH)))
                .setAccessType("offline") // 允许获取刷新令牌
                .build();

        var localReceiver = new LocalServerReceiver.Builder().setPort(8888).build();
        return new AuthorizationCodeInstalledApp(authFlow, localReceiver).authorize("user");
    }

    @Bean
    public JavaMailSender gmailSender() throws IOException, GeneralSecurityException {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost("smtp.gmail.com");
        mailSender.setPort(587);
        mailSender.setUsername("your-gmail@gmail.com");

        Properties mailProps = mailSender.getJavaMailProperties();
        mailProps.put("mail.smtp.auth", "true");
        mailProps.put("mail.smtp.starttls.enable", "true");
        mailProps.put("mail.smtp.auth.mechanisms", "XOAUTH2");

        Session session = Session.getInstance(mailProps, new javax.mail.Authenticator() {
            @Override
            protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
                try {
                    String accessToken = getOAuthCredential().getAccessToken();
                    return new javax.mail.PasswordAuthentication("", accessToken);
                } catch (Exception e) {
                    throw new RuntimeException("获取OAuth2令牌失败", e);
                }
            }
        });

        mailSender.setSession(session);
        return mailSender;
    }
}

注意事项:

  • 应用专用密码仅适用于开启两步验证的账户,若关闭两步验证,该密码会立即失效
  • OAuth2方式首次运行时会弹出浏览器授权页面,授权后会在本地生成tokens目录存储刷新令牌,后续无需重复授权
  • 谷歌云平台的项目必须启用Gmail API,否则会出现权限不足的错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:45:59