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

Android Studio中Java调用Gmail SMTP发送邮件失败解决方案咨询

Gmail SMTP邮件发送失败的解决方案

核心问题分析

你的代码逻辑本身无语法错误,但发送失败主要源于以下三点:

  1. 主线程执行网络操作:Android从API 11开始禁止在主线程发起网络请求,直接在点击事件中调用Transport.send()会被系统拦截,导致静默失败
  2. Gmail认证方式错误:当前Gmail不再支持用普通密码通过SMTP登录,必须启用两步验证后生成应用专用密码(不推荐开启"不太安全的应用访问")
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:01:16