Android - 如何检查已发送邮件以确定邮件是否已发送

6

我有一个应用程序,使用以下意图发送电子邮件:

//TODO attach and send here
try {           

    Log.i(getClass().getSimpleName(), "send  task - start");

    String address = "emailHere@yahoo.com";
    String subject = "Order of " + customer + " for " + date;
    String emailtext = "Please check the attached file. Attached file contains order of " + customer;

    final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE);
    emailIntent.setType("plain/text");
    emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { address });
    emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
    emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, emailtext);

    ArrayList<Uri> uris = new ArrayList<Uri>();
    Uri uriList = Uri.fromFile(orderListFile);
    uris.add(uriList);

    emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);

    this.startActivity(Intent.createChooser(emailIntent, "Send mail..."));

} 
catch (Throwable t) {
    Toast.makeText(this, "Request failed: " + t.toString(),
    Toast.LENGTH_LONG).show();
}

现在,用户选择使用哪个应用程序来发送邮件。然而,一旦选定的电子邮件应用程序接管了控制权,我就无法知道电子邮件是否被正确发送。在这里已经讨论过多次,使用startActivityForResult()并没有帮助,因为电子邮件或Gmail应用程序从未发送RESULT_OK,所以我不知道用户是发送、丢弃还是保存了作为草稿的电子邮件。
然而,一种可能的解决方法是检查该电子邮件帐户的已发送项目,并从那里检查用户是否发送了电子邮件。现在,在Android中有没有办法知道电子邮件账户的已发送项目呢?我已经进行了谷歌搜索一个小时,但似乎没有找到任何答案。

4
1 不可能;2 曾经可能,但现在不再可能(据我所知)。使用JavaMail(即以编程方式发送电子邮件,无需用户交互)是3的有效替代方案吗?虽然它是针对不同用例的解决方案,但如果您不需要用户界面,并且电子邮件不一定必须从应用程序用户的地址发送,那么或许可以使用它。 - matiash
4
说实话,我认为您试图解决错误的问题。就我个人而言,我不想使用一款会开始在我的电子邮件中挖掘信息的应用程序。抛开技术上的困难,我的邮箱里面的内容与你无关。如果你需要这种控制来检查电子邮件是否已经发送,你应该将电子邮件提交到自己的后端系统,并从那里发送它们。 - Barend
1
由于没有通用的API来检查已发送电子邮件的状态,因此无法获得其状态。一些电子邮件客户端具有API,这将允许您检查已发送文件夹,但是由于您不知道用户使用哪个电子邮件客户端,而且只有某些客户端具有API,因此没有可靠的方法来实现您想要做的事情。 - Emanuel Moecklin
1
我也同意Barend的观点,这种方式是错误的。如果您决定使用另一个应用程序发送邮件,那么只需要一键发送即可。但如果您需要确保邮件已经被成功发送,最好搭建自己的SMTP服务器并通过该服务器发送邮件。SMTP的客户端实现相当简单,而且有很多库可供使用。 - Emanuel Moecklin
保护级别为签名。 - Moonhead
显示剩余4条评论
2个回答

6

您无法检查电子邮件ContentProvider的内容,因为这需要一个只有系统应用程序才能请求的权限。这在电子邮件的AndroidManifest中定义:

<permission
    android:name="com.android.email.permission.ACCESS_PROVIDER"
    android:protectionLevel="signature"
    android:label="@string/permission_access_provider_label"
    android:description="@string/permission_access_provider_desc"/><application><!-- This provider MUST be protected by strict permissions, as granting access to
         it exposes user passwords and other confidential information. -->
    <provider
        android:name=".provider.EmailProvider"
        android:authorities="com.android.email.provider;com.android.email.notifier"
        android:exported="true"
        android:permission="com.android.email.permission.ACCESS_PROVIDER"
        android:label="@string/app_name"
        /></application>

3
重要的部分是 protectionLevel="signature" - rds
抱歉忘记更新,但我最终使用了JavaMail。 - Razgriz

1
对于第一种选择,标准的AOSP邮件应用程序和Gmail应用程序都不会这样做。如果电子邮件已发送、保存为草稿或完全丢弃,则它们不会返回任何不同的信息。
即使它们这样做了,用户可能已安装不同的电子邮件应用程序,您不能保证它会表现良好。即使所有电子邮件应用程序都以这种方式运行,用户也可能编辑主题、正文或“收件人”字段,因此甚至不能保证“您打算发送的电子邮件”实际上已发送。
至于第二个选项,电子邮件应用程序通常不导出内容提供者。例如,AOSP电子邮件应用程序的清单显示com.android.email.permission.ACCESS_PROVIDER权限具有protectionLevel签名,这意味着只有由相同方(在本例中为Google)签署的应用程序才能访问它们。
Gmail曾经有一个内容提供者(通过com.google.android.gm.permission.READ_GMAIL权限),但这在很长时间前就已经改变了(大约在Android 2.2左右,根据this answer上的评论,也需要protectionLevel="signature"),现在只提供标签信息(请参阅文档)。
考虑到涉及的隐私风险,我认为其他电子邮件客户端不太可能在电子邮件本身上公开内容提供者。
根据您实际的用例,第三个选择是以无用户交互的方式发送这些电子邮件(例如使用JavaMail或类似库)。例如,如果您正在使用这些电子邮件作为与后端通信的一种方式(尽管如果是这种情况,http post将更加合适)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接