如何从我的 Android 应用程序发送电子邮件?

How to send emails from my Android application?

提问人:Rakesh 提问时间:2/4/2010 最后编辑:Samet ÖZTOPRAKRakesh 更新时间:5/14/2023 访问量:460634

问:

我正在开发一个 Android 应用程序。我不知道如何从应用程序发送电子邮件?

Android 电子邮件

评论

0赞 Gelldur 5/27/2015
简单的 ShareBuilder gist.github.com/gelldur/9c199654c91b13478979
0赞 Alex 8/6/2020
这回答了你的问题吗?Android Studio mailto Intent 不显示主题和邮件正文
0赞 Ryan M 8/7/2020
建议的重复似乎更糟,接受的答案有一个奇怪的、不必要的意图过滤器。

答:

1018赞 Jeremy Logan 2/4/2010 #1

最好(也是最简单)的方法是使用:Intent

Intent i = new Intent(Intent.ACTION_SEND);
i.setType("message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"[email protected]"});
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();
}

否则,您将不得不编写自己的客户端。

RFC822 是 ARPA Internet 文本消息的标准。请参见 https://w3.org/Protocols/rfc822

评论

7赞 KIRAN K J 6/23/2011
在上面的代码中,没有发件人的邮件ID,那么消息是如何发送的呢?
40赞 Jeremy Logan 7/12/2011
KIRAN:你需要研究 Intents 是如何工作的,才能理解这一点。它基本上会打开一个电子邮件应用程序,其中已经填写了收件人、主题和正文。由电子邮件应用程序进行发送。
8赞 Hamza Waqas 3/26/2012
通过启动活动,电子邮件未显示在“收件人”字段中。有人知道吗?
5赞 nikib3ro 10/10/2012
是的。。。这工作得很完美,直到 Skype 也决定“支持”消息/rfc822 - 现在 Skype 也在列表中弹出。那家公司真的变得邪恶了......
28赞 Edris 10/7/2015
添加以下内容以确保选择器仅显示电子邮件应用:Intent i = new Intent(Intent.ACTION_SENDTO); i.setType("message/rfc822"); i.setData(Uri.parse("mailto:"));
13赞 Rene 2/4/2010 #2

可以使用不需要配置的 Intent 发送电子邮件。但随后它将需要用户交互,并且布局会受到一些限制。

在没有用户交互的情况下构建和发送更复杂的电子邮件需要构建自己的客户端。首先是用于电子邮件的 Sun Java API 不可用。我已经成功地利用 Apache Mime4j 库来构建电子邮件。所有这些都基于nilvec的文档。

206赞 Jeff S 12/2/2010 #3

使用 或 选择器将显示支持发送意图的所有(许多)应用程序。.setType("message/rfc822")

评论

5赞 Blundell 7/24/2011
很好,这应该有更多的投票tbh。你不会注意到模拟器上的测试,但是当你去真实设备上发送“文本/纯文本”时,它会给你一个15+应用程序的列表!所以绝对推荐“message/rfc822”(电子邮件标准)。
8赞 draw 8/13/2011
@Blundell嗨,但是改成message/rfc822
2赞 ingh.am 8/22/2011
您可以从列表中删除蓝牙吗?这也出现在这种类型中。+1 不过,巧妙的技巧!
6赞 Kevin Galligan 1/24/2012
拯救了我们的培根。无法想象向客户解释用户可能会在推特上发送支持请求而不是通过电子邮件发送。
1赞 ChallengeAccepted 8/6/2014
+1111111 这值得无穷无尽的 +1,以便其他人可以看到这一点。我错过了这部分,不得不处理这个问题一段时间!
99赞 Randy Sugianto 'Yuku' 2/27/2012 #4

我很久以前就一直在使用它,它看起来不错,没有出现非电子邮件应用程序。发送发送电子邮件意向的另一种方式:

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:[email protected]")); // 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);

评论

2赞 erdomester 3/26/2012
Unsopported 操作:当前不支持此操作
4赞 sachit 10/9/2012
lgor G->请从 setType“(plain/text”) 更改为 setType(“text/plain”)
2赞 The Hungry Androider 4/22/2014
.setType(“message/rfc822”) 不是 text/plain
1赞 Erum 2/7/2015
此代码将打开电子邮件意图吗?如何在不向用户显示意图的情况下发送电子邮件 @yuku 我想向电子邮件发送密码
2赞 Nick Volynkin 3/14/2017
这个答案很有影响力。:)
2赞 NagarjunaReddy 10/4/2012 #5

简单试试这个

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    buttonSend = (Button) findViewById(R.id.buttonSend);
    textTo = (EditText) findViewById(R.id.editTextTo);
    textSubject = (EditText) findViewById(R.id.editTextSubject);
    textMessage = (EditText) findViewById(R.id.editTextMessage);

    buttonSend.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            String to = textTo.getText().toString();
            String subject = textSubject.getText().toString();
            String message = textMessage.getText().toString();

            Intent email = new Intent(Intent.ACTION_SEND);
            email.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
            // email.putExtra(Intent.EXTRA_CC, new String[]{ to});
            // email.putExtra(Intent.EXTRA_BCC, new String[]{to});
            email.putExtra(Intent.EXTRA_SUBJECT, subject);
            email.putExtra(Intent.EXTRA_TEXT, message);

            // need this to prompts email client only
            email.setType("message/rfc822");

            startActivity(Intent.createChooser(email, "Choose an Email client :"));

        }
    });
}

评论

3赞 Sam 6/25/2015
这比您发布此内容时已经存在的答案更好吗?它看起来就像是包装在活动中的已接受答案的副本。
58赞 tiguchi 10/10/2012 #6

我正在使用与当前接受的答案类似的东西,以便发送带有附加二进制错误日志文件的电子邮件。GMail 和 K-9 发送得很好,它也很好地到达了我的邮件服务器。唯一的问题是我选择的邮件客户端 Thunderbird,它在打开/保存附加的日志文件时遇到了问题。事实上,它根本没有在没有抱怨的情况下保存文件。

我看了一下这些邮件的源代码之一,并注意到日志文件附件具有(可以理解的)mime 类型。当然,该附件不是附加的电子邮件。但是 Thunderbird 无法优雅地处理这个微小的错误。所以这有点令人沮丧。message/rfc822

经过一番研究和实验,我提出了以下解决方案:

public Intent createEmailOnlyChooserIntent(Intent source,
    CharSequence chooserTitle) {
    Stack<Intent> intents = new Stack<Intent>();
    Intent i = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto",
            "[email protected]", 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 方法可以很容易地提供正确的意图和正确的 mime 类型。

然后,它会遍历响应ACTION_SENDTO协议意向的可用活动列表(仅限电子邮件应用),并根据该活动列表和具有正确 MIME 类型的原始ACTION_SEND意向构造选择器。mailto

另一个优点是 Skype 不再列出(这恰好响应 rfc822 mime 类型)。

评论

1赞 Alex Cio 1/19/2013
我刚刚插入了您的代码片段,它工作正常。之前有列出的应用程序,如Google Drive,Skype等。但是,有没有办法在不调用其他应用程序的情况下从应用程序发送邮件?我刚刚阅读了上面@Rene有关电子邮件客户端的文章,但对于仅发送简单的电子邮件来说似乎太复杂了
0赞 darrenp 9/5/2013
很好的答案。我也想出了Skype和Google Drive,这很好地解决了它。ACTION_SEND
1赞 Denis Kutlubaev 12/27/2013
上面最流行的解决方案也返回了 Skype 和 Vkontakte。这个解决方案更好。
0赞 Noufal 2/6/2014
什么是crashLogFile?它在哪里初始化?pease sepecify
0赞 tiguchi 2/6/2014
@Noufal 这只是我自己的代码库中的一些剩余部分。这是一个实例,指向我的 Android 应用程序在后台创建的崩溃日志文件,以防出现未捕获的异常。该示例应该只是说明如何添加电子邮件附件。您还可以附加外部存储中的任何其他文件(例如图像)。您还可以删除该行以获得工作示例。FilecrashLogFile
39赞 wildzic 4/2/2014 #7

让 JUST LET EMAIL APPS 解析您的意图,您需要将 ACTION_SENDTO 指定为 Action,将 mailto 指定为 Data。

private void sendEmail(){

    Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
    emailIntent.setData(Uri.parse("mailto:" + "[email protected]")); // 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();
    }

}
23赞 Sam 6/25/2015 #8

使用或似乎也匹配非电子邮件客户端的应用程序(例如 Android Beam蓝牙)的策略。.setType("message/rfc822")ACTION_SEND

使用 和 URI 似乎可以完美地工作,建议在开发人员文档中使用。但是,如果您在官方模拟器上执行此操作,并且没有设置任何电子邮件帐户(或没有任何邮件客户端),则会收到以下错误:ACTION_SENDTOmailto:

不支持的操作

目前不支持该操作。

如下图所示:

Unsupported action: That action is not currently supported.

事实证明,模拟器将 intent 解析为一个名为 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 <[email protected]>" })
        .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();
}

有关详细信息,请参阅开发人员文档

29赞 Pedro Varela 7/22/2015 #9

解决方案很简单: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***

顺便说一句,如果你发送一个 空的 ,最后将不起作用,应用程序将无法启动电子邮件客户端。Extraif()

根据 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);
    }
}
2赞 silentsudo 12/28/2015 #10

其他解决方案可以是

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
emailIntent.setType("plain/text");
emailIntent.setClassName("com.google.android.gm", "com.google.android.gm.ComposeActivityGmail");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"[email protected]"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Yo");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Hi");
startActivity(emailIntent);

假设大多数 android 设备已经安装了 GMail 应用程序。

评论

0赞 silentsudo 8/24/2016
@PedroVarela,我们总是可以检查未发现异常的活动。
1赞 Pedro Varela 8/24/2016
是的,我们能。但您的解决方案不是正确的。Android 文档清楚地说明了您必须执行哪些操作才能在 intent 选择器中仅显示邮件应用程序。你写了“假设大多数安卓设备已经安装了Gmail应用程序”;如果它是 root 设备并且用户删除了 Gmail 客户端怎么办?假设您正在创建自己的电子邮件应用程序,如果用户要发送电子邮件,则您的应用程序将不在该列表中。如果 gmail 更改了包裹名称会怎样?你要更新你的应用吗?
4赞 Dog Lover 6/15/2016 #11

我就是这样做的。很好,很简单。

String emailUrl = "mailto:[email protected]?subject=Subject Text&body=Body Text";
        Intent request = new Intent(Intent.ACTION_VIEW);
        request.setData(Uri.parse(emailUrl));
        startActivity(request);
5赞 lomza 9/21/2016 #12

我在我的应用程序中使用以下代码。这准确地显示了电子邮件客户端应用程序,例如 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)));
2赞 Manish 10/24/2016 #13

用它来发送电子邮件...

boolean success = EmailIntentBuilder.from(activity)
    .to("[email protected]")
    .cc("[email protected]")
    .subject("Error report")
    .body(buildErrorReport())
    .start();

使用 build gradle :

compile 'de.cketti.mailto:email-intent-builder:1.0.0'
5赞 A P 1/31/2017 #14

这将仅显示电子邮件客户端(以及出于某种未知原因的PayPal)

 public void composeEmail() {

    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:"));
    intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"[email protected]"});
    intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
    intent.putExtra(Intent.EXTRA_TEXT, "Body");
    try {
        startActivity(Intent.createChooser(intent, "Send mail..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(MainActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
    }
}

评论

1赞 CoolMind 4/16/2018
不错的解决方案!它避免了许多不合适的应用程序(主要用作“共享”)。不要在此处添加,因为它会导致异常。intent.type = "message/rfc822"; intent.type = "text/html";
3赞 Shohan Ahmed Sijan 5/16/2017 #15

此功能首先直接意图 gmail 用于发送电子邮件,如果找不到 gmail,则提升意图选择器。我在许多商业应用程序中使用了此功能,并且运行良好。希望它能帮助你:

public static void sentEmail(Context mContext, String[] addresses, String subject, String body) {

    try {
        Intent sendIntentGmail = new Intent(Intent.ACTION_VIEW);
        sendIntentGmail.setType("plain/text");
        sendIntentGmail.setData(Uri.parse(TextUtils.join(",", addresses)));
        sendIntentGmail.setClassName("com.google.android.gm", "com.google.android.gm.ComposeActivityGmail");
        sendIntentGmail.putExtra(Intent.EXTRA_EMAIL, addresses);
        if (subject != null) sendIntentGmail.putExtra(Intent.EXTRA_SUBJECT, subject);
        if (body != null) sendIntentGmail.putExtra(Intent.EXTRA_TEXT, body);
        mContext.startActivity(sendIntentGmail);
    } catch (Exception e) {
        //When Gmail App is not installed or disable
        Intent sendIntentIfGmailFail = new Intent(Intent.ACTION_SEND);
        sendIntentIfGmailFail.setType("*/*");
        sendIntentIfGmailFail.putExtra(Intent.EXTRA_EMAIL, addresses);
        if (subject != null) sendIntentIfGmailFail.putExtra(Intent.EXTRA_SUBJECT, subject);
        if (body != null) sendIntentIfGmailFail.putExtra(Intent.EXTRA_TEXT, body);
        if (sendIntentIfGmailFail.resolveActivity(mContext.getPackageManager()) != null) {
            mContext.startActivity(sendIntentIfGmailFail);
        }
    }
}

评论

1赞 androCoder-BD 5/16/2017
多谢。救我一命
1赞 psycho 11/27/2017 #16

这种方法对我有用。它打开Gmail应用程序(如果已安装)并设置mailto。

public void openGmail(Activity activity) {
    Intent emailIntent = new Intent(Intent.ACTION_VIEW);
    emailIntent.setType("text/plain");
    emailIntent.setType("message/rfc822");
    emailIntent.setData(Uri.parse("mailto:"+activity.getString(R.string.mail_to)));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, activity.getString(R.string.app_name) + " - info ");
    final PackageManager pm = activity.getPackageManager();
    final List<ResolveInfo> matches = pm.queryIntentActivities(emailIntent, 0);
    ResolveInfo best = null;
    for (final ResolveInfo info : matches)
        if (info.activityInfo.packageName.endsWith(".gm") || info.activityInfo.name.toLowerCase().contains("gmail"))
            best = info;
    if (best != null)
        emailIntent.setClassName(best.activityInfo.packageName, best.activityInfo.name);
    activity.startActivity(emailIntent);
}
7赞 Sridhar Nalam 1/17/2018 #17

这是在android设备中打开邮件应用程序并在撰写邮件中自动填充“收件人地址”和“主题”的示例工作代码。

protected void sendEmail() {
    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:[email protected]"));
    intent.putExtra(Intent.EXTRA_SUBJECT, "Feedback");
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}

评论

0赞 CoolMind 4/17/2018
谢谢。与 @Avi Parshan 的解决方案相比,您在 中设置了一封电子邮件,而 Avi 在 中设置了 。两种变体都可以工作。但是如果仅删除并使用,则会有一个 .setData()putExtra()setDataintent.putExtra(Intent.EXTRA_EMAIL, new String[]{"[email protected]"});ActivityNotFoundException
4赞 Faris Muhammed 4/29/2018 #18

我使用此代码通过直接启动默认邮件应用程序撰写部分来发送邮件。

    Intent i = new Intent(Intent.ACTION_SENDTO);
    i.setType("message/rfc822"); 
    i.setData(Uri.parse("mailto:"));
    i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"[email protected]"});
    i.putExtra(Intent.EXTRA_SUBJECT, "Subject");
    i.putExtra(Intent.EXTRA_TEXT   , "body of email");
    try {
        startActivity(Intent.createChooser(i, "Send mail..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
    }
1赞 Gal Rom 12/21/2018 #19
/**
 * Will start the chosen Email app
 *
 * @param context    current component context.
 * @param emails     Emails you would like to send to.
 * @param subject    The subject that will be used in the Email app.
 * @param forceGmail True - if you want to open Gmail app, False otherwise. If the Gmail
 *                   app is not installed on this device a chooser will be shown.
 */
public static void sendEmail(Context context, String[] emails, String subject, boolean forceGmail) {

    Intent i = new Intent(Intent.ACTION_SENDTO);
    i.setData(Uri.parse("mailto:"));
    i.putExtra(Intent.EXTRA_EMAIL, emails);
    i.putExtra(Intent.EXTRA_SUBJECT, subject);
    if (forceGmail && isPackageInstalled(context, "com.google.android.gm")) {
        i.setPackage("com.google.android.gm");
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);
    } else {
        try {
            context.startActivity(Intent.createChooser(i, "Send mail..."));
        } catch (ActivityNotFoundException e) {
            Toast.makeText(context, "No email app is installed on your device...", Toast.LENGTH_SHORT).show();
        }
    }
}

/**
 * Check if the given app is installed on this devuice.
 *
 * @param context     current component context.
 * @param packageName The package name you would like to check.
 * @return True if this package exist, otherwise False.
 */
public static boolean isPackageInstalled(@NonNull Context context, @NonNull String packageName) {
    PackageManager pm = context.getPackageManager();
    if (pm != null) {
        try {
            pm.getPackageInfo(packageName, 0);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }
    return false;
}
2赞 Tousif Akram 7/15/2019 #20
 Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
            "mailto","[email protected]", null));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Forgot Password");
    emailIntent.putExtra(Intent.EXTRA_TEXT, "this is a text ");
    startActivity(Intent.createChooser(emailIntent, "Send email..."));
1赞 Dan Bray 8/8/2019 #21

试试这个:

String mailto = "mailto:[email protected]" +
    "?cc=" + "[email protected]" +
    "&subject=" + Uri.encode(subject) +
    "&body=" + Uri.encode(bodyText);

Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setData(Uri.parse(mailto));

try {
    startActivity(emailIntent);
} catch (ActivityNotFoundException e) {
    //TODO: Handle case where no email app is available
}

上面的代码将打开用户最喜欢的电子邮件客户端,该客户端预装了准备发送的电子邮件。

1赞 Merthan Erdem 4/18/2021 #22

Kotlin 版本,仅显示电子邮件客户端(无联系人等):

    with(Intent(Intent.ACTION_SEND)) {
        type = "message/rfc822"
        data = Uri.parse("mailto:")
        putExtra(Intent.EXTRA_EMAIL, arrayOf("[email protected]"))
        putExtra(Intent.EXTRA_SUBJECT,"YOUR SUBJECT")
        putExtra(Intent.EXTRA_TEXT, "YOUR BODY")
        try {
            startActivity(Intent.createChooser(this, "Send Email with"))
        } catch (ex: ActivityNotFoundException) {
            // No email clients found, might show Toast here
        }
    }
1赞 RaphaelNdonga 5/26/2021 #23

以下代码适用于 Android 10 及更高版本的设备。它还设置主题、正文和收件人(To)。

val uri = Uri.parse("mailto:$EMAIL")
                .buildUpon()
                .appendQueryParameter("subject", "App Feedback")
                .appendQueryParameter("body", "Body Text")
                .appendQueryParameter("to", EMAIL)
                .build()

            val emailIntent = Intent(Intent.ACTION_SENDTO, uri)

            startActivity(Intent.createChooser(emailIntent, "Select app"))
0赞 Omkar T 9/8/2021 #24
import androidx.core.app.ShareCompat
import androidx.core.content.IntentCompat

ShareCompat.IntentBuilder(this)
                .setType("message/rfc822")
                .setEmailTo(arrayOf(email))
                .setStream(uri)
                .setSubject(subject)
                .setText(message + emailMessage)
                .startChooser()
3赞 Adelino 12/9/2021 #25

这是在 Android 上发送电子邮件的最干净的方式。

 val intent = Intent(Intent.ACTION_SENDTO).apply {
    data = Uri.parse("mailto:")
    putExtra(Intent.EXTRA_EMAIL, arrayOf("[email protected]"))
    putExtra(Intent.EXTRA_SUBJECT, "Subject")
    putExtra(Intent.EXTRA_TEXT, "Email body")
}
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
}

还需要在清单中指定(在应用程序标记之外)处理电子邮件的应用程序的查询 (mailto)

<queries>
    <intent>
        <action android:name="android.intent.action.SENDTO" />
        <data android:scheme="mailto" />
    </intent>
</queries>

如果您需要在电子邮件正文中发送 HTML 文本,请将“电子邮件正文”替换为您的电子邮件字符串,如下所示(请注意 Html.fromHtml 可能已被弃用,这仅用于向您展示如何操作)

Html.fromHtml(
    StringBuilder().append("<b>Hello world</b>").toString()
)
1赞 Krabbe 1/24/2023 #26

今天,过滤“真正的”电子邮件应用程序仍然是一个问题。正如上面提到的许多人,现在其他应用程序也报告支持 mime 类型“message/rfc822”。因此,此 mime 类型不再适合用于筛选真正的电子邮件应用程序。

如果要发送简单的文本邮件,则只需使用具有适当数据类型的 intent 操作即可,如下所示:ACTION_SENDTO

Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, recipients);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_TEXT, text);
Intent chooser = Intent.createChooser(intent, "Send Mail");
context.startActivity(chooser);

这将过滤所有可用的应用程序,以查找支持“mailto”协议的应用程序,该协议更适合发送电子邮件。

但可悲的是,如果您想发送带有(多个)附件的邮件,事情就会变得复杂。ACTION_SENDTO操作不支持 intent 上的额外操作。如果要使用它,则必须使用该操作,该操作不能与数据类型 Uri.parse(“mailto:”) 一起使用。EXTRA_STREAMACTION_SEND_MULTIPLE

现在,我找到了一个解决方案,它包括以下步骤:

  • 声明您的应用想要查询设备上支持 mailto 协议的应用(对 Android 11 之后的所有应用都很重要)
  • 实际查询所有支持mailto协议的应用程序
  • 对于每个支持应用:构建您实际想要启动的意图,以该应用为目标
  • 构建应用选择器并启动它

这是它在代码中的样子:

将此内容添加到 AndroidManifest

<queries>
    <intent>
        <action android:name="android.intent.action.SENDTO" />
        <data android:scheme="mailto" />
    </intent>
</queries>

这是 Java 代码:

/* Query all Apps that support the 'mailto' protocol */
PackageManager pm = context.getPackageManager();
Intent emailCheckerIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"));
List<ResolveInfo> emailApps = pm.queryIntentActivities(emailCheckerIntent, PackageManager.MATCH_DEFAULT_ONLY);

/* For each supporting App: Build an intent with the desired values */
List<Intent> intentList = new ArrayList<>();
for (ResolveInfo resolveInfo : emailApps) {
    String packageName = resolveInfo.activityInfo.packageName;
    Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
    intent.setPackage(packageName);
    intent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name));
    intent.putExtra(Intent.EXTRA_EMAIL, recipients);
    intent.putExtra(Intent.EXTRA_SUBJECT, subject);
    intent.putExtra(Intent.EXTRA_TEXT, text);
    intent.putExtra(Intent.EXTRA_STREAM, attachmentUris);
    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //IMPORTANT to give the E-Mail App access to your attached files
                
    intentList.add(intent);
}

/* Create a chooser consisting of the queried apps only */
Intent chooser = Intent.createChooser(intentList.remove(intentList.size() - 1), "Send Mail");
Intent[] extraIntents = intentList.toArray(new Intent[0]);
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
context.startActivity(chooser);

注意:如果只有一个项目,Android 将自动跳过选择器并自动运行唯一的应用程序。itentList