Android 11环境下发送邮件触发java.lang.VerifyError问题求助
解决Android 11下JavaMail的VerifyError问题
这个问题我之前也踩过坑,本质是Android 11引入的包可见性限制和你用的旧版JavaMail依赖不兼容导致的。下面是具体的解决方案:
问题原因
Android 11开始严格限制应用对第三方库内部包的访问权限,而com.sun.mail:android-mail:1.6.0版本比较老旧,没有适配这个新规则,导致系统阻止了com.sun.mail.handlers.text_plain这类内部类的加载,直接抛出了VerifyError。
解决方案
1. 升级JavaMail依赖到适配Android 11的版本
旧版本的JavaMail完全没考虑Android 11的包可见性问题,建议直接升级到最新稳定版(目前推荐1.6.7),修改你的Gradle依赖:
implementation 'com.sun.mail:android-mail:1.6.7' implementation 'com.sun.mail:android-activation:1.6.7'
2. 在AndroidManifest.xml中添加包可见性声明
Android 11+要求应用明确声明需要访问的第三方包,在AndroidManifest.xml的根标签下添加<queries>标签,允许访问JavaMail的相关内部包:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="your.package.name"> <!-- 声明需要访问的JavaMail包 --> <queries> <package android:name="com.sun.mail" /> <package android:name="com.sun.mail.handlers" /> </queries> <application ...> <!-- 你的应用原有配置 --> </application> </manifest>
3. 优化邮件发送的线程等待逻辑(可选但强烈推荐)
你当前代码里用while (!loading[0]) {}自旋等待的方式会死死阻塞主线程,很容易触发ANR(应用无响应)。建议改成回调的方式处理发送结果,示例代码如下:
先定义一个回调接口:
public interface MailSendCallback { void onSendSuccess(); void onSendFailure(); }
然后修改发送方法:
public static void sendEmail(String subject, String content, String[] recipients, MailSendCallback callback) { Properties properties = new Properties(); properties.put("mail.smtp.auth", "true"); properties.put("mail.smtp.starttls.enable", "true"); properties.put("mail.smtp.host", "smtp.gmail.com"); properties.put("mail.smtp.port", "587"); Session session = Session.getInstance(properties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(USERNAME, PASSWORD); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress(USERNAME)); InternetAddress[] addressTo = new InternetAddress[recipients.length]; for (int i = 0; i < recipients.length; i++) { addressTo[i] = new InternetAddress(recipients[i]); } message.setRecipients(Message.RecipientType.TO, addressTo); message.setSubject(subject); message.setText(content); new Thread(() -> { try { Transport.send(message); // 回到主线程通知成功 new Handler(Looper.getMainLooper()).post(callback::onSendSuccess); } catch (MessagingException e) { e.printStackTrace(); new Handler(Looper.getMainLooper()).post(callback::onSendFailure); } }).start(); } catch (MessagingException e) { e.printStackTrace(); callback.onSendFailure(); } }
调用时可以这样用:
sendEmail("测试邮件", "这是测试内容", new String[]{"test@example.com"}, new MailSendCallback() { @Override public void onSendSuccess() { Toast.makeText(context, "邮件发送成功", Toast.LENGTH_SHORT).show(); } @Override public void onSendFailure() { Toast.makeText(context, "邮件发送失败", Toast.LENGTH_SHORT).show(); } });
额外注意事项(Gmail专用)
如果用Gmail作为SMTP服务器:
- 若账号开启了2FA(双重验证),必须使用应用专用密码代替普通登录密码
- 若未开启2FA,需要在Google账号设置中临时开启"允许低安全性应用访问"(不推荐长期使用,建议优先启用2FA并使用应用密码)
内容的提问来源于stack exchange,提问作者Marco Chiavaroli
相关产品推荐
相关产品推荐

