Google停用低安全应用后javax.mail IMAP读取邮件认证失败问题
问题说明
Google已于2022年5月30日正式停用「低安全性应用访问」功能,使用javax.mail组件通过IMAP协议读取Gmail邮箱邮件时会出现认证失败,无法正常获取邮件内容。
触发的报错信息
internal.qaauto.framework.exceptions.EmailDriverException: javax.mail.AuthenticationFailedException: [AUTHENTICATIONFAILED] Invalid credentials (Failure) at internal.qaauto.framework.drivers.email.ImapsEmailDriver.connect(ImapsEmailDriver.java:55) at certainwebapptests.CreateSubAccount.setUp(CreateSubAccount.java:53) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:86) at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:514) at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:215) at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:142) at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:178) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108) at org.testng.TestRunner.privateRun(TestRunner.java:782) at org.testng.TestRunner.run(TestRunner.java:632) at org.testng.SuiteRunner.runTest(SuiteRunner.java:366) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319) at org.testng.SuiteRunner.run(SuiteRunner.java:268) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1244) at org.testng.TestNG.runSuitesLocally(TestNG.java:1169) at org.testng.TestNG.run(TestNG.java:1064) at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66) at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:109) Caused by: javax.mail.AuthenticationFailedException: [AUTHENTICATIONFAILED] Invalid credentials (Failure) at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:661) at javax.mail.Service.connect(Service.java:295) at internal.qaauto.framework.drivers.email.ImapsEmailDriver.connect(ImapsEmailDriver.java:45) ... 24 more
原有实现代码
try { Properties connectionProperties = new Properties(); // Set IMAPS as store protocol connectionProperties.put("mail.store.protocol", "imaps"); connectionProperties.put("mail.imaps.ssl.checkserveridentity", "false"); // Create a session with mail server session = Session.getDefaultInstance(connectionProperties); // Get the Store, which is JavaMail name for the entity that holds the mails. store = session.getStore("imaps"); // Connect the recently created Store reporter.debug("Connecting to " + MAIL_HOSTNAME + ":" + IMAP_PORT + " using " + MAIL_USER + "/" + MAIL_PASSWORD); store.connect(MAIL_HOSTNAME, IMAP_PORT, MAIL_USER, MAIL_PASSWORD); // Check that connection was successful checkConnection(); // Select Inbox folder selectFolder("Inbox"); } catch (MessagingException e) { reporter.error( "Unable to connect to mail server " + MAIL_HOSTNAME + " through port " + IMAP_PORT + ". Using " + MAIL_USER + "/" + MAIL_PASSWORD + ". Reason: " + e.getMessage() ); throw new RuntimeException(e); }
合规接入方案
原账号明文密码直连IMAP的方式已被Google拦截,目前有两种官方认可的合规接入方式:
方案一:应用专用密码(改动最小,适合测试/个人临时场景)
- 前置条件:对应Gmail账号已开启两步验证
- 操作流程:进入Google账号安全设置页,找到应用专用密码生成入口,选择「邮件」应用和对应的使用设备,生成16位长度的应用专用密码
- 代码改动:无需调整原有连接逻辑,仅将代码中
MAIL_PASSWORD变量的值从原账号登录密码替换为刚生成的16位应用专用密码即可,Gmail IMAP连接地址固定为imap.gmail.com,端口993,保持原有SSL配置即可正常连接。
方案二:OAuth2.0认证(官方推荐,适合生产/长期自动化场景)
该方案是Google当前主推的标准认证方式,无需依赖账号两步验证,权限管控粒度更细,安全性更高。
- 前置准备:在Google云控制台创建对应项目,开启Gmail API权限,给目标邮箱账号授权IMAP访问范围,拿到对应的访问令牌(access_token)和刷新令牌(refresh_token)
- 代码改动:调整连接配置,启用XOAUTH2认证机制,替换原有明文密码为OAuth2认证凭证,修改后的核心连接代码如下:
try { Properties connectionProperties = new Properties(); connectionProperties.put("mail.store.protocol", "imaps"); connectionProperties.put("mail.imaps.ssl.checkserveridentity", "false"); // 新增OAuth2相关SASL配置 connectionProperties.put("mail.imaps.sasl.enable", "true"); connectionProperties.put("mail.imaps.sasl.mechanisms", "XOAUTH2"); connectionProperties.put("mail.imaps.auth.login.disable", "true"); connectionProperties.put("mail.imaps.auth.plain.disable", "true"); // 注意不要用getDefaultInstance,避免和其他邮件配置冲突 session = Session.getInstance(connectionProperties); store = session.getStore("imaps"); // 拼接XOAUTH2认证串,格式固定 String oauth2Credential = String.format("user=%s\u0001auth=Bearer %s\u0001\u0001", MAIL_USER, accessToken); store.connect(MAIL_HOSTNAME, IMAP_PORT, MAIL_USER, oauth2Credential); checkConnection(); selectFolder("Inbox"); } catch (MessagingException e) { reporter.error( "Unable to connect to mail server " + MAIL_HOSTNAME + " through port " + IMAP_PORT + ". Using " + MAIL_USER + ". Reason: " + e.getMessage() ); throw new RuntimeException(e); }
- 注意事项:access_token有效期通常为1小时,需要通过refresh_token定期刷新,避免认证过期。
内容的提问来源于stack exchange,提问作者Neha Goyal
相关产品推荐
相关产品推荐

