You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Java Mail API发送邮件无报错但未收到且无发送记录求助

邮件发送成功但无踪迹?来排查这几个关键点!

嘿,我帮你梳理下这个问题——程序显示发送完成,但收件箱、发件箱都没记录,大概率是表面成功实则发送过程中出了静默异常,或者Gmail的权限配置没到位,咱们一步步来解决:

核心问题分析

你的代码里把邮件发送逻辑放到了子线程,而且子线程里的异常只做了控制台打印,在Android环境下你可能看不到这些错误输出,误以为发送成功。再加上Gmail现在的安全机制,普通密码根本没法登录第三方客户端,这是最常见的坑!

解决方案分步来

1. 搞定Gmail的权限(最关键)

Gmail早就禁用了“不太安全的应用访问”,现在必须用应用专用密码(App Password),前提是你的账户开启了两步验证(2FA)

  • 先登录你的Gmail账户,开启两步验证(在账户安全设置里找)
  • 开启后,生成一个App Password(选择“邮件”应用,“其他设备”类型)
  • 把代码里的my_password替换成这个生成的App Password

2. 修复异常捕获,让错误看得见

子线程里的异常不会触发主线程的错误提示,你得把异常信息传到主线程,用Toast或者Logcat打印出来,才能知道真实问题:
修改子线程里的catch块:

catch (Exception e) {
    Log.e("EmailSendError", "发送失败详情", e);
    // 用Handler把错误提示抛回主线程
    new Handler(Looper.getMainLooper()).post(() -> 
        Toast.makeText(context, "发送失败:" + e.getMessage(), Toast.LENGTH_LONG).show()
    );
}

同时,把Email.sendEmail()方法加上Context参数,方便在主线程显示Toast。

3. 补充SSL信任配置,避免证书问题

在Properties里加一行配置,防止SSL证书验证失败导致静默失败:

props.put("mail.smtp.ssl.trust", "smtp.gmail.com");

4. 清理冗余代码

按钮点击里的new Email();完全没用,因为sendEmail是静态方法,直接调用Email.sendEmail(getContext());就行。

修改后的完整代码示例

Email类

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

public class Email { 
    public static void sendEmail(Context context) {
        final String username = "my_email@gmail.com"; 
        final String password = "你的App Password"; // 替换成生成的应用专用密码
        Properties props = new Properties(); 
        props.put("mail.smtp.auth", "true"); 
        props.put("mail.smtp.starttls.enable", "true"); 
        props.put("mail.smtp.host", "smtp.gmail.com"); 
        props.put("mail.smtp.port", "587"); 
        props.put("mail.smtp.ssl.trust", "smtp.gmail.com"); // 新增SSL信任配置

        Session session = Session.getInstance(props, new Authenticator() { 
            @Override
            protected PasswordAuthentication getPasswordAuthentication() { 
                return new PasswordAuthentication(username, password); 
            } 
        }); 

        try { 
            final Message message = new MimeMessage(session); 
            message.setFrom(new InternetAddress(username)); 
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("my_receive_email@gmail.com")); 
            message.setSubject("Subject"); 
            message.setText("Message"); 

            Thread thread = new Thread(() -> { 
                try { 
                    Transport.send(message); 
                    // 主线程提示成功
                    new Handler(Looper.getMainLooper()).post(() -> 
                        Toast.makeText(context, "邮件发送成功", Toast.LENGTH_SHORT).show()
                    );
                    Log.d("EmailStatus", "邮件已成功发送");
                } catch (Exception e) { 
                    Log.e("EmailError", "发送失败", e);
                    // 主线程提示错误
                    new Handler(Looper.getMainLooper()).post(() -> 
                        Toast.makeText(context, "发送失败:" + e.getMessage(), Toast.LENGTH_LONG).show()
                    );
                } 
            }); 
            thread.start(); 
        } catch (MessagingException e) { 
            Log.e("EmailInitError", "邮件初始化失败", e);
            Toast.makeText(context, "邮件初始化失败:" + e.getMessage(), Toast.LENGTH_LONG).show();
        } 
    } 
}

按钮点击事件

btnSend.setOnClickListener(v -> Email.sendEmail(getContext()));

最后检查点

别忘了在AndroidManifest.xml里添加网络权限:

<uses-permission android:name="android.permission.INTERNET" />

按照这些步骤改完,你就能看到真实的发送状态,大概率是权限问题导致的,搞定App Password后应该就能正常发送了!

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

火山引擎 最新活动