如何判断通过下述Android代码发送的邮件是否已成功发出?
嘿,我看你用Android的Intent.ACTION_SEND调用系统邮件应用发反馈邮件,想知道怎么判断邮件是否真的发送成功对吧?其实这里有个小坑——系统邮件应用不会把最终的发送结果返回给你的App,毕竟这是两个独立的应用,遵循Android的沙箱机制。不过咱们可以用两个变通的办法来应对:
方法一:通过Activity结果判断用户操作(仅能确认用户是否提交发送)
这个方法只能知道用户是完成了邮件应用的发送操作,还是中途取消了,但没法确认邮件是否真的被服务器成功发送。
如果你的App适配的是Android 10及以下(API < 30),可以用startActivityForResult:
// 启动邮件选择器时传入requestCode startActivityForResult(Intent.createChooser(email, "Send Email"), 1001); // 在Activity中重写onActivityResult处理结果 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1001) { if (resultCode == RESULT_OK) { // 用户点击了发送按钮并返回App,但不代表邮件已成功发出 Toast.makeText(this, "邮件已提交发送,请留意发送状态", Toast.LENGTH_SHORT).show(); } else if (resultCode == RESULT_CANCELED) { // 用户取消了发送操作 Toast.makeText(this, "发送已取消", Toast.LENGTH_SHORT).show(); } } }
如果是Android 11及以上,要改用registerForActivityResult(因为startActivityForResult已被废弃):
// 先注册结果回调 ActivityResultLauncher<Intent> emailLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == RESULT_OK) { Toast.makeText(this, "邮件已提交发送,请留意发送状态", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "发送已取消", Toast.LENGTH_SHORT).show(); } } ); // 启动邮件选择器时调用launch方法 emailLauncher.launch(Intent.createChooser(email, "Send Email"));
方法二:自己实现邮件发送逻辑(能拿到精确的发送状态)
如果需要准确知道邮件是否真的被服务器成功发送,最好不要依赖系统邮件应用,而是直接在自己的App里用SMTP协议发送。可以用JavaMail API来实现,记得要在后台线程执行(不能在主线程操作网络):
new Thread(() -> { // 配置SMTP服务器参数 Properties props = new Properties(); props.put("mail.smtp.host", "smtp.your-server.com"); // 比如smtp.gmail.com props.put("mail.smtp.port", "587"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); // 创建邮件会话,传入你的邮箱账号和密码 Session session = Session.getInstance(props, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("your-email@example.com", "your-password"); } }); try { // 构建邮件内容 Message message = new MimeMessage(session); message.setFrom(new InternetAddress("your-email@example.com")); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); message.setSubject(subject); message.setText(bodyTxt); // 发送邮件 Transport.send(message); // 发送成功,回到主线程提示用户 runOnUiThread(() -> Toast.makeText(this, "邮件发送成功!", Toast.LENGTH_SHORT).show()); } catch (MessagingException e) { e.printStackTrace(); // 发送失败,提示用户 runOnUiThread(() -> Toast.makeText(this, "邮件发送失败,请检查网络或配置", Toast.LENGTH_SHORT).show()); } }).start();
注意:这种方式需要添加网络权限(<uses-permission android:name="android.permission.INTERNET"/>),如果用Gmail的话,可能需要开启低安全性应用访问或者使用应用专用密码。
补充说明
为什么系统Intent没法返回精确的发送结果?因为系统邮件应用只是接收你的发送请求,它的发送过程是在自身应用内完成的,甚至可能在后台异步发送,不会把最终的发送状态回调给你的App。所以如果只是想知道用户有没有提交发送操作,用方法一;如果需要100%确认邮件是否成功发出,必须用方法二自己实现发送逻辑。
内容的提问来源于stack exchange,提问作者user616076

