Android Studio中Java调用Gmail SMTP发送邮件失败解决方案咨询
Gmail SMTP邮件发送失败的解决方案
核心问题分析
你的代码逻辑本身无语法错误,但发送失败主要源于以下三点:
- 主线程执行网络操作:Android从API 11开始禁止在主线程发起网络请求,直接在点击事件中调用
Transport.send()会被系统拦截,导致静默失败 - Gmail认证方式错误:当前Gmail不再支持用普通密码通过SMTP登录,必须启用两步验证后生成应用专用密码(不推荐开启"不太安全的应用访问")
- UI更新线程错误:子线程中无法直接调用
Toast.makeText(),必须切换回主线程更新UI
最优解决方案步骤
1. 配置Gmail账号认证
- 登录你的Gmail账号,开启两步验证(强制要求)
- 进入Google账号安全中心,生成一个应用专用密码(选择“邮件”应用,设备选“其他”并自定义名称)
- 用生成的16位密码替换代码中的
password字段
2. 异步执行邮件发送
将邮件发送逻辑放到子线程中执行,避免主线程阻塞;发送完成后切换回主线程更新Toast提示。
3. 优化SMTP配置(可选)
除465端口+SSL的配置外,也可使用587端口+STARTTLS,兼容性更好:
p.setProperty("mail.smtp.port","587"); p.setProperty("mail.smtp.starttls.enable", "true");
修正后的完整代码
依赖项(保留你的配置,可按需更新版本)
dependencies { implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.sun.mail:android-mail:1.6.2' implementation 'com.sun.mail:android-activation:1.6.2' implementation 'com.google.android.material:material:1.6.1' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' }
MainActivity.java
import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.View; import android.widget.Button; import android.widget.Toast; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.util.Properties; public class MainActivity extends AppCompatActivity { String msg = "hello"; String subject = "test"; String to = "收件人邮箱"; String from = "你的Gmail邮箱"; String host = "smtp.gmail.com"; // 替换为你的Gmail应用专用密码 String appPassword = "生成的16位应用专用密码"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = findViewById(R.id.send); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 在子线程执行邮件发送 new Thread(new Runnable() { @Override public void run() { Properties p = System.getProperties(); p.setProperty("mail.smtp.host", host); p.setProperty("mail.smtp.port", "465"); p.setProperty("mail.smtp.ssl.enable", "true"); p.setProperty("mail.smtp.auth", "true"); Session session = Session.getInstance(p, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(from, appPassword); } }); session.setDebug(true); MimeMessage message = new MimeMessage(session); try { message.setFrom(new InternetAddress(from)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.setSubject(subject); message.setText(msg); Transport.send(message); // 切换回主线程显示成功提示 new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "邮件发送成功", Toast.LENGTH_SHORT).show(); } }); } catch (Exception e) { e.printStackTrace(); // 切换回主线程显示失败提示 new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "邮件发送失败:" + e.getMessage(), Toast.LENGTH_LONG).show(); } }); } } }).start(); } }); } }
AndroidManifest.xml(无需修改,已包含必要权限)
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.DDPL" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.app.lib_name" android:value="" /> </activity> </application> </manifest>
内容的提问来源于stack exchange,提问作者Rohit Kumar
相关产品推荐
相关产品推荐

