我正在开发一款安卓应用程序。我不知道如何从应用程序中发送电子邮件?
最好(也是最简单)的方法是使用一个 Intent
:
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL , new String[]{"recipient@example.com"});
i.putExtra(Intent.EXTRA_SUBJECT, "subject of email");
i.putExtra(Intent.EXTRA_TEXT , "body of email");
try {
startActivity(Intent.createChooser(i, "Send mail..."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(MyActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}
Intent i = new Intent(Intent.ACTION_SENDTO);
i.setType("message/rfc822");
i.setData(Uri.parse("mailto:"));
- Edris如果不使用 .setType("message/rfc822")
,那么选择器将显示所有支持发送intent的应用程序(非常多)。
message/rfc822
后,我没有看到任何区别。 - draw我之前一直在使用这个方法,效果不错,没有出现非电子邮件类型的应用程序。这只是发送电子邮件意图的另一种方式:
Intent intent = new Intent(Intent.ACTION_SENDTO); // it's not ACTION_SEND
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject of email");
intent.putExtra(Intent.EXTRA_TEXT, "Body of email");
intent.setData(Uri.parse("mailto:default@example.com")); // or just "mailto:" for blank
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // this will make such that when user returns to your app, your app is displayed, instead of the email app.
startActivity(intent);
我曾使用与当前被接受的答案类似的方法来发送附加有二进制错误日志文件的电子邮件。Gmail和K-9可以成功发送并且在我的邮件服务器上也收到了。唯一的问题是我的邮件客户端Thunderbird,它无法打开/保存附加的日志文件。事实上,它根本没有任何投诉就没有保存该文件。
我查看了其中一封邮件的源代码并注意到日志文件附件有一个(可以理解的)mime类型message/rfc822
。当然,那个附件不是一封附加的电子邮件。但是Thunderbird不能优雅地处理这个小错误。所以这有点糟糕。
经过一些研究和实验,我想出了以下解决方案:
public Intent createEmailOnlyChooserIntent(Intent source,
CharSequence chooserTitle) {
Stack<Intent> intents = new Stack<Intent>();
Intent i = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto",
"info@example.com", null));
List<ResolveInfo> activities = getPackageManager()
.queryIntentActivities(i, 0);
for(ResolveInfo ri : activities) {
Intent target = new Intent(source);
target.setPackage(ri.activityInfo.packageName);
intents.add(target);
}
if(!intents.isEmpty()) {
Intent chooserIntent = Intent.createChooser(intents.remove(0),
chooserTitle);
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
intents.toArray(new Parcelable[intents.size()]));
return chooserIntent;
} else {
return Intent.createChooser(source, chooserTitle);
}
}
可以按以下方式使用:
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("*/*");
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(crashLogFile));
i.putExtra(Intent.EXTRA_EMAIL, new String[] {
ANDROID_SUPPORT_EMAIL
});
i.putExtra(Intent.EXTRA_SUBJECT, "Crash report");
i.putExtra(Intent.EXTRA_TEXT, "Some crash report details");
startActivity(createEmailOnlyChooserIntent(i, "Send via email"));
你可以看到,createEmailOnlyChooserIntent方法很容易通过正确的intent和正确的mime类型进行调用。
它接着会遍历所有可响应ACTION_SENDTO协议的intent(即只有电子邮件应用程序才会响应),并基于这些活动和原始的ACTION_SEND意图及正确的mime类型构建一个chooser。
另一个优点是Skype不再列出(因为它响应rfc822 mime类型)。
ACTION_SEND
,但这个方法解决了我的问题。 - darrenpFile
实例,我的Android应用程序在后台创建该文件以防止出现未捕获的异常。这个例子只是说明如何添加电子邮件附件。您还可以附加来自外部存储的任何其他文件(例如图像)。您也可以删除带有crashLogFile
的行,以获取可工作的示例。 - tiguchi若要让电子邮件应用程序解决您的意图,您需要将ACTION_SENDTO指定为操作,并将mailto指定为数据。
private void sendEmail(){
Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setData(Uri.parse("mailto:" + "recipient@example.com")); // You can use "mailto:" if you don't know the address beforehand.
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "My email's subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "My email's body");
try {
startActivity(Intent.createChooser(emailIntent, "Send email using..."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(Activity.this, "No email clients installed.", Toast.LENGTH_SHORT).show();
}
}
解决方法很简单:Android文档已经对此进行了说明。
(https://developer.android.com/guide/components/intents-common.html#Email)
最重要的是标志:它是ACTION_SENDTO
,而不是ACTION_SEND
另一行重要的内容是:
intent.setData(Uri.parse("mailto:")); ***// only email apps should handle this***
顺便提一下,如果您发送了一个空的Extra
,那么末尾的if()
将不起作用,应用程序将无法启动电子邮件客户端。
根据Android文档。如果您想确保意图仅由电子邮件应用程序处理(而不是其他短信或社交应用程序),则使用ACTION_SENDTO
操作并包含“mailto:
”数据方案。例如:
public void composeEmail(String[] addresses, String subject) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:")); // only email apps should handle this
intent.putExtra(Intent.EXTRA_EMAIL, addresses);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
.setType("message/rfc822")
或者 ACTION_SEND
的策略似乎也会匹配非电子邮件客户端的应用程序,比如 Android Beam 和 Bluetooth。ACTION_SENDTO
和 mailto:
URI 似乎可以完美地工作,并且在开发者文档中推荐使用。但是,在官方模拟器上执行此操作且没有设置任何电子邮件帐户(或没有邮件客户端)时,您将收到以下错误:
如下所示: 原来模拟器将意图解析为名为不支持的操作
当前不支持该操作。
com.android.fallback.Fallback
的活动,该活动显示上述消息。 显然这是设计如此。
如果您希望您的应用程序绕过此问题,以便在官方模拟器上正常工作,您可以在尝试发送电子邮件之前检查它:private void sendEmail() {
Intent intent = new Intent(Intent.ACTION_SENDTO)
.setData(new Uri.Builder().scheme("mailto").build())
.putExtra(Intent.EXTRA_EMAIL, new String[]{ "John Smith <johnsmith@yourdomain.com>" })
.putExtra(Intent.EXTRA_SUBJECT, "Email subject")
.putExtra(Intent.EXTRA_TEXT, "Email body")
;
ComponentName emailApp = intent.resolveActivity(getPackageManager());
ComponentName unsupportedAction = ComponentName.unflattenFromString("com.android.fallback/.Fallback");
if (emailApp != null && !emailApp.equals(unsupportedAction))
try {
// Needed to customise the chooser dialog title since it might default to "Share with"
// Note that the chooser will still be skipped if only one app is matched
Intent chooser = Intent.createChooser(intent, "Send email with");
startActivity(chooser);
return;
}
catch (ActivityNotFoundException ignored) {
}
Toast
.makeText(this, "Couldn't find an email app and account", Toast.LENGTH_LONG)
.show();
}
在开发者文档中查找更多信息。
发送电子邮件可以使用意图(Intents)完成,无需配置。但这样做需要用户交互,而且布局会有些受限。
如果要构建和发送更复杂的电子邮件且不需要用户交互,则需要构建自己的客户端。首先要知道的是,用于电子邮件的Sun Java API不可用。我成功地利用了Apache Mime4j库来构建电子邮件。所有基于这里的文档。
以下是示例工作代码,可在Android设备上打开邮件应用程序,并自动填写收件人地址和主题以进行撰写邮件。
protected void sendEmail() {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:feedback@gmail.com"));
intent.putExtra(Intent.EXTRA_SUBJECT, "Feedback");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
setData()
中设置了电子邮件,而Avi则在putExtra()
中设置了电子邮件。两种变体都可以工作。但是,如果删除setData
并仅使用intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"hi@example.com"});
,将会出现ActivityNotFoundException
。 - CoolMind我在我的应用程序中使用以下代码。这将显示电子邮件客户端应用程序,例如 Gmail。
Intent contactIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", getString(R.string.email_to), null));
contactIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.email_subject));
startActivity(Intent.createChooser(contactIntent, getString(R.string.email_chooser)));