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


Answers:


978

最好(也是最简单)的方法是使用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();
}

否则,您将必须编写自己的客户端。


6
在上面的代码中,没有发件人的电子邮件ID。那么消息如何发送?
KIRAN KJ 2011年

38
KIRAN:您需要研究Intent如何工作以了解这一点。基本上,它将打开一个电子邮件应用程序,其中已填写了收件人,主题和正文。由电子邮件应用程序进行发送。
杰里米·洛根

8
通过启动活动,电子邮件未显示在“收件人”字段中。有谁知道?
Hamza Waqas 2012年

11
该评论的最大贡献是:message / rfc822
Guilherme Oliveira

22
添加以下内容以确保选择器仅显示电子邮件应用程序: Intent i = new Intent(Intent.ACTION_SENDTO); i.setType("message/rfc822"); i.setData(Uri.parse("mailto:"));
Edris

194

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


5
好的,这应该有更多的待定票。您不会注意到在模拟器上进行测试,但是当您在真实设备上发送“文本/纯文本”时,它将为您提供15种以上应用程序的列表!因此绝对推荐使用“ message / rfc822”(电子邮件标准)。
Blundell

7
@Blundell喜,但我没有看到改变后有什么区别message/rfc822

2
您可以从列表中删除蓝牙吗?这种类型也显示出来。+1,整洁的把戏!
ingh.am 2011年

4
保存了我们的培根。无法想象向客户说明用户可能会鸣叫支持请求,而不是通过电子邮件发送请求。
凯文·加里根

1
+1111111这值得无休止的+1,以便其他人可以看到。我错过了这一部分,不得不解决了一段时间!
挑战

89

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

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@recipient.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);

1
Unsopported行动:目前不支持这一行动
erdomester

4
lgor G-> plz从setType“(plain / text”)更改为setType(“ text / plain”)
sachit 2012年

2
.setType(“ message / rfc822”)不是text / plain
Hungry Androider 2014年

1
此代码是否会打开电子邮件意图?我如何在不向用户@yuku显示意图的情况下发送电子邮件,我想向电子邮件发送密码
Erum,2015年

2
这个答案很有影响力。:)
Nick Volynkin

54

我正在使用一些当前接受的答案,以便发送带有附加的二进制错误日志文件的电子邮件。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@domain.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方法可以轻松地输入正确的意图和正确的mime类型。

然后,它会浏览响应ACTION_SENDTO mailto协议意图的可用活动列表(仅电子邮件应用程序),并基于该活动列表和原始ACTION_SEND意图并以正确的mime类型构造一个选择器。

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


1
我只是插入了您的代码段,所以效果很好。在没有列出诸如Google Drive,Skype等应用程序之前。但是,没有一种方法可以在不调用另一个应用程序的情况下从应用程序发送邮件吗?我刚刚阅读了有关@Rene postet上面的电子邮件客户端的文章,但似乎对于发送简单的电子邮件来说太复杂了
Alex Cio

极好的答案。我也想出了Skype和Google云端硬盘ACTION_SEND,这使它看起来很漂亮。
darrenp

1
上面最受欢迎的解决方案还返回了Skype和Vkontakte。此解决方案更好。
Denis Kutlubaev 2013年

什么是crashLogFile?它在哪里初始化?请点缀一下-Noufal 2014
6:03

@Noufal这只是我自己的代码库的一部分。这是一个File实例,指向我的Android应用在后台创建的崩溃日志文件,以防万一发生未捕获的异常。该示例仅说明如何添加电子邮件附件。您还可以附加外部存储中的任何其他文件(例如图像)。您也可以删除该行crashLogFile以获取有效的示例。
tiguchi 2014年

37

要仅删除电子邮件应用程序即可解决您的意图,您需要将ACTION_SENDTO指定为Action,将mailto指定为Data。

private void sendEmail(){

    Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
    emailIntent.setData(Uri.parse("mailto:" + "recipient@example.com")); 
    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

如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);
    }
}

21

使用.setType("message/rfc822")ACTION_SEND似乎还与非电子邮件客户端应用匹配的策略,例如Android BeamBluetooth

使用ACTION_SENDTOmailto:URI似乎可以很好地工作,并且在开发人员文档中建议使用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();
}

开发人员文档中查找更多信息。


13

可以使用Intents发送电子邮件,而无需进行配置。但是,这将需要用户交互,并且布局会受到一些限制。

在没有用户交互的情况下构建和发送更复杂的电子邮件需要构建自己的客户端。第一件事是电子邮件的Sun Java API不可用。我已经成功利用Apache Mime4j库构建电子邮件。全部基于nilvec上的文档。


6

这是示例工作代码,该代码在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);
    }
}

谢谢。与@Avi Parshan的解决方案相比,您在中设置了电子邮件setData(),而Avi中设置了putExtra()。两种变体都能正常工作。但是如果setData仅删除和使用intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"hi@example.com"});,将会有一个ActivityNotFoundException
CoolMind

5

我在应用程序中使用以下代码。这将准确显示电子邮件客户端应用程序,例如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)));

5

这只会向您显示电子邮件客户端(以及某些未知原因的PayPal)

 public void composeEmail() {

    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:"));
    intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"hi@example.com"});
    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
不错的解决方案!它避免了许多不合适的应用程序(通常用作“共享”)。不要在intent.type = "message/rfc822"; intent.type = "text/html";这里添加,因为这会导致异常。
CoolMind

3

这就是我做的。漂亮又简单。

String emailUrl = "mailto:email@example.com?subject=Subject Text&body=Body Text";
        Intent request = new Intent(Intent.ACTION_VIEW);
        request.setData(Uri.parse(emailUrl));
        startActivity(request);

3

此功能首先直接发送意图电子邮件,如果找不到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

2

简单尝试这个

 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
与您发布此内容时已经存在的答案相比,这有什么好处吗?它看起来就像是包裹在活动中的已接受答案的副本。
山姆

2

其他解决方案可以是

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[]{"someone@gmail.com"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Yo");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Hi");
startActivity(emailIntent);

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


@PedroVarela我们可以随时检查活动未找到异常。
–silentsudo

1
我们可以。但是您的解决方案不是正确的。Android文档清楚地说明了要在意图选择器中仅显示邮件应用程序的操作。您写道:“假设大多数android设备已安装Gmail应用程序”;如果它是根设备,并且用户删除了Gmail客户端怎么办?假设您要创建自己的电子邮件应用程序?,如果用户要发送电子邮件,则您的应用程序将不在该列表中。如果gmail更改软件包名称会怎样?您要更新您的应用程序吗?
Pedro Varela

2

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

boolean success = EmailIntentBuilder.from(activity)
    .to("support@example.org")
    .cc("developer@example.org")
    .subject("Error report")
    .body(buildErrorReport())
    .start();

使用build gradle:

compile 'de.cketti.mailto:email-intent-builder:1.0.0'

2

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

    Intent i = new Intent(Intent.ACTION_SENDTO);
    i.setType("message/rfc822"); 
    i.setData(Uri.parse("mailto:"));
    i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"test@gmail.com"});
    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

这种方法对我有用。它将打开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);
}

1
/**
 * 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;
}

1
 Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
            "mailto","ebgsoldier@gmail.com", null));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Forgot Password");
    emailIntent.putExtra(Intent.EXTRA_TEXT, "Write your Pubg user name or Phone Number");
    startActivity(Intent.createChooser(emailIntent, "Send email..."));**strong text**

1

尝试这个:

String mailto = "mailto:bob@example.org" +
    "?cc=" + "alice@example.com" +
    "&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
}

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

资源

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.