28

I'm trying to send an e-mail from my Android App. With the click on a button, gmail should open and show a new email with my previously defined recipient, subject and email body. So far I've tried sending the Intent.ACTION_VIEW as well as Intent.ACTION_SENDTO. Both show my draft with the recipient only. Both subject and message are being opressed. Weird thing is when using the emulator, it works just fine. Also was trying to lock at the android errorlog. Seems like i don't have permission. Is it really a permission problem or could it be something else? I'd really appreciate any help cheers

Here is my code:

  • sending email via ACTION_VIEW
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:" + to));
intent.putExtra(intent.EXTRA_SUBJECT, subject);
intent.putExtra(intent.EXTRA_TEXT, message);
mainActivity.startActivity(intent);
  • sending email via ACTION_SENDTO
Intent email = new Intent(Intent.ACTION_SENDTO);
email.setType("message/rfc822");
email.putExtra(Intent.EXTRA_EMAIL, new String[]{to});
email.putExtra(Intent.EXTRA_SUBJECT, subject);
email.putExtra(Intent.EXTRA_TEXT, message);
mainActivity.startActivity(Intent.createChooser(email, "Choose an Email client :"));
  • error message from logcat
2019-12-13 01:30:35.172 29268-29268/? E//system/bin/webview_zygote32: failed to make and chown /acct/uid_99044: Permission denied
2019-12-13 01:30:35.172 29268-29268/? E/Zygote: createProcessGroup(99044, 0) failed: Permission denied
2019-12-13 01:30:35.206 29289-29289/? E/asset: setgid: Operation not permitted
2019-12-13 01:30:35.226 29296-29296/? E/asset: setgid: Operation not permitted
2019-12-13 01:30:35.355 29268-29268/? E/Typeface: Error mapping font file /system/fonts/NotoSansKhmer-Regular.ttf
2019-12-13 01:30:35.356 29268-29268/? E/Typeface: Error mapping font file /system/fonts/NotoSansKhmer-Bold.ttf
2019-12-13 01:30:35.356 29268-29268/? E/Minikin: Could not get cmap table size!
2019-12-13 01:30:35.356 29268-29268/? E/Typeface: Unable to load Family: null:und-Khmr
2019-12-13 01:30:35.484 29268-29268/? E/Typeface: Error mapping font file /system/fonts/LGAka_Light.ttf
2019-12-13 01:30:35.484 29268-29268/? E/Minikin: Could not get cmap table size!
2019-12-13 01:30:35.484 29268-29268/? E/Typeface: Unable to load Family: lg-lgaka:null
2019-12-13 01:30:35.816 29342-29342/? E//system/bin/webview_zygote32: failed to make and chown /acct/uid_99045: Permission denied
2019-12-13 01:30:35.816 29342-29342/? E/Zygote: createProcessGroup(99045, 0) failed: Permission denied
2019-12-13 01:30:35.842 29354-29354/? E/asset: setgid: Operation not permitted
2019-12-13 01:30:35.864 29367-29367/? E/asset: setgid: Operation not permitted
2019-12-13 01:30:36.139 29342-29342/? E/Typeface: Error mapping font file /system/fonts/NotoSansKhmer-Regular.ttf
2019-12-13 01:30:36.139 29342-29342/? E/Typeface: Error mapping font file /system/fonts/NotoSansKhmer-Bold.ttf
2019-12-13 01:30:36.139 29342-29342/? E/Minikin: Could not get cmap table size!
2019-12-13 01:30:36.139 29342-29342/? E/Typeface: Unable to load Family: null:und-Khmr
2019-12-13 01:30:36.362 29342-29342/? E/Typeface: Error mapping font file /system/fonts/LGAka_Light.ttf
2019-12-13 01:30:36.362 29342-29342/? E/Minikin: Could not get cmap table size!
2019-12-13 01:30:36.362 29342-29342/? E/Typeface: Unable to load Family: lg-lgaka:null
2019-12-13 01:30:36.523 4349-4359/? E/GBMv2: FPS Scaler: EXP
2019-12-13 01:30:36.602 29342-29342/? E/WebViewFactory: can't load with relro file; address space not reserved
2019-12-13 01:30:37.058 29220-29220/? E/Gmail: Gmail:EditWebView JS Console: b/119949571:draft.editor.onLoad; source: file:///android_asset/draft_editor_gmail_compiled.js at 89
2019-12-13 01:30:37.146 29220-29220/? E/Gmail: Gmail:EditWebView JS Console: b/119949571:draft.editor.onLoad is finished; source: file:///android_asset/draft_editor_gmail_compiled.js at 90
Paul
  • 292
  • 1
  • 3
  • 7

10 Answers10

73

I think we had the same issue. Android API 29 introduced some improvements about sending data to other apps. See more details here: Sending simple data to other apps

Here is the solution that works for me.

Intent selectorIntent = new Intent(Intent.ACTION_SENDTO);
selectorIntent.setData(Uri.parse("mailto:"));

final Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"address@mail.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "The subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "The email body");
emailIntent.setSelector( selectorIntent );

activity.startActivity(Intent.createChooser(emailIntent, "Send email..."));

In few words, with this you are asking for the Android standard app chooser and, in addition, you specify that you want to send an email. So, as result, email clients will appear only. If user has one email client installed only, the intent will redirect to it instantly.

Hope this helps you too.

zak.antonio
  • 831
  • 1
  • 6
  • 3
  • 8
    Finally. I had code for this that has worked with Gmail for the past 10-11 years before it suddenly stopped working. Doing like this was the way to go. :) – Roy Solberg Jan 18 '20 at 20:26
  • Worked for me as well. Intent.createChooser is optional and the emailIntent can be passed directly. – melbic Feb 17 '20 at 09:17
  • Worked like a charm, saved me a few minutes of head-scratching. Thanks a lot – ibyte Feb 22 '20 at 13:13
  • 1
    It kinda works but it requires the user to choose "Gmail" and also gives options "copy" and "Paypal" which just result in weird or no behavior – pete Aug 06 '20 at 09:47
  • @pete That's due to the broad scope of 'ACTION_SEND' intent, I agree it's a bit confusing for the user. I haven't tried this, but I believe you can specify a MIME data type in extras and that should further filter down the list of apps that show up. – Bryan W Aug 22 '20 at 18:44
17

try out this code, it worked for me.

Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:")); // only email apps should handle this
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{email});
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject here");
intent.putExtra(Intent.EXTRA_TEXT,"Body Here");
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
}

also add intent filter in android manifest.

<activity ...>
<intent-filter>
    <action android:name="android.intent.action.SENDTO" />
    <data android:scheme="mailto" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
SMR
  • 6,628
  • 2
  • 35
  • 56
Siddharth Vaish
  • 402
  • 3
  • 4
  • Could you please add some explanation about the answer? – Yonlif Dec 14 '19 at 18:37
  • Thank you very much, I can even choose to use one E-Mail Client as standard. had to put the intent-filter Tag inside of a service-tag and give it the MainActivity as a name. So it looks like this:`` – Paul Dec 15 '19 at 23:06
  • 3
    It still doesn't show the subject and body ! – Ahmed Elsayed Apr 28 '21 at 08:49
15

In order to get it to work on Samsung and Pixel devices, we had to add the parameters on both the url and the extras

val email = "xxxx@xxxx.com"
val subject = "xxxx"
val body = "xxxx"

val selectorIntent = Intent(Intent.ACTION_SENDTO)
val urlString = "mailto:" + Uri.encode(email) + "?subject=" + Uri.encode(subject) + "&body=" + Uri.encode(body)
selectorIntent.data = Uri.parse(urlString)

val emailIntent = Intent(Intent.ACTION_SEND)
emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject)
emailIntent.putExtra(Intent.EXTRA_TEXT, body)
emailIntent.selector = selectorIntent

startActivity(Intent.createChooser(emailIntent, "Send email"))
Fran Sevillano
  • 8,103
  • 4
  • 31
  • 45
6

Our old code for emails stopped working some days ago.

It was the following:

public static void shareTextToEmail(Context context, String[] email, String subject, String text)
    Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" + TextUtils.join(",", email)));
    emailIntent.putExtra(Intent.EXTRA_EMAIL, email);
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
    emailIntent.putExtra(Intent.EXTRA_TEXT, text);
    try {
        context.startActivity(Intent.createChooser(emailIntent, context.getString(R.string.share_email_title)));
    } catch (android.content.ActivityNotFoundException e) {
        Toast.makeText(context, context.getString(R.string.share_no_intent_handler_found), Toast.LENGTH_SHORT).show();
    }
}

I've adopted it according to the Zak.Antonio answer:

public static void shareTextToEmail(Context context, String[] email, String subject, String text)
    Intent selectorIntent = new Intent(Intent.ACTION_SENDTO);
    selectorIntent.setData(Uri.parse("mailto:"));

    final Intent emailIntent = new Intent(Intent.ACTION_SEND);
    emailIntent.putExtra(Intent.EXTRA_EMAIL, email);
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
    emailIntent.putExtra(Intent.EXTRA_TEXT, text);
    emailIntent.setSelector(selectorIntent);

    try {
        context.startActivity(Intent.createChooser(emailIntent, context.getString(R.string.share_email_title)));
    } catch (android.content.ActivityNotFoundException e) {
        Toast.makeText(context, context.getString(R.string.share_no_intent_handler_found), Toast.LENGTH_SHORT).show();
    }
}

The key points are:

  • Replace Intent.ACTION_SENDTO with Intent.ACTION_SEND in emailIntent
  • Move Intent.ACTION_SENDTO to a selectorIntent
  • Do not put emails in intent data, put them only in extras at Intent.EXTRA_EMAIL
Artem Mostyaev
  • 3,874
  • 10
  • 53
  • 60
4

This answer worked for me using parsing using Uri

Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:?subject=" + subject + "&to=" + to));
 context.startActivity(emailIntent);
Ahmed Elsayed
  • 231
  • 3
  • 23
4

If your app targets Android 11 (API level 30) or higher then we require to add :

Set the queries in the Manifest file like this:

<manifest package="com.example.app">
    ...
    <!-- Package visibility -->
    <queries>
        <!-- Mail -->
        <intent>
            <action android:name="android.intent.action.SENDTO" />
            <data android:scheme="mailto" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent>
    </queries>
    ...
</manifest>

Kotlin method to open Email apps :

fun composeEmail(recipient: String, subject: String, body: String) {
    val selectorIntent = Intent(Intent.ACTION_SENDTO).apply{
        data = Uri.parse("mailto:") // only email apps should handle this
    }
    val emailIntent = Intent(Intent.ACTION_SEND).apply {
        putExtra(Intent.EXTRA_EMAIL, arrayOf(recipient))
        putExtra(Intent.EXTRA_SUBJECT, subject)
        putExtra(Intent.EXTRA_TEXT, body)
        selector = selectorIntent
    }
    if (emailIntent.resolveActivity(packageManager) != null) {
        startActivity(emailIntent)
    }
}
Nikunj
  • 3,937
  • 19
  • 33
  • 1
    In fact, the queries tag in AndroidManifest.xml, like in your example, is the only thing missing for API 30+. The intent used for opening an e-mail app doesn't even need to be changed. I use the same code that already worked for API 29. So the queries tag is the right fix. – Rado Jan 05 '22 at 17:31
3

Neither adding Extras to the SENDTO intent nor using a selectorIntent seemed to work on a Samsung running Android 10. Uri encoding the email address, subject, and body seemed to work best across multiple devices running Android 10 and below. The EmailIntentLibrary was a big help in ironing out the finer points of getting the URI encoding to work for complex body content.

val email = Uri.encode("xxxx@xxxx.com")
val subject = Uri.encode("xxxx")
val body = Uri.encode("some body. one two & more. \n new line \n &%>?")
val uri = "mailto:$email?subject=$subject&body=$body"
val intent = Intent(Intent.ACTION_SENDTO)
intent.type = "text/plain"
intent.data = Uri.parse(uri)
startActivity(intent)

If you're ok with having quite a few options in the chooser, the example below from the Android Development Guide does work (the ACTION_SENDTO example meant to filter those options did not work for me)

fun composeEmail(addresses: Array<String>, subject: String, attachment: Uri) {
    val intent = Intent(Intent.ACTION_SEND).apply {
        type = "*/*"
        putExtra(Intent.EXTRA_EMAIL, addresses)
        putExtra(Intent.EXTRA_SUBJECT, subject)
        putExtra(Intent.EXTRA_STREAM, attachment)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}
Kris Pena
  • 487
  • 1
  • 5
  • 9
2

try this code

    val emailIntent = Intent(Intent.ACTION_SEND)
    emailIntent.setType("text/plain")
    emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf("jon@example.com")) 
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject")
    emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text")
    val packageManager = packageManager
    val activities = packageManager.queryIntentActivities(emailIntent, 0)
    val isIntentSafe = activities.size > 0
    if (isIntentSafe) {
        startActivity(emailIntent);
    }else{
        Log.d("MainActivty","Email App not installed");
    }
vinodaw
  • 117
  • 6
  • What language is this? I've tried to translate it to Java, but I don't know what type the variables packageManager and activities are – Paul Dec 14 '19 at 15:51
  • This is Kotlin. packageManager is of type android.content.pm.PackageManager – vinodaw Dec 14 '19 at 16:56
1

I had issues with the other solutions, here is what worked for me:

    val selectorIntent = Intent(Intent.ACTION_SENDTO).apply {
        data = Uri.parse("mailto:")
    }

    val emailIntent = Intent(Intent.ACTION_SEND).apply {
        selector = selectorIntent
        putExtra(
            Intent.EXTRA_EMAIL,
            arrayOf(resources.getString(R.string.support_email_address))
        )
        putExtra(
            Intent.EXTRA_SUBJECT,
            resources.getString(R.string.support_email_subject)
        )
        putExtra(
            Intent.EXTRA_TEXT,
            resources.getString(R.string.support_email_body)
        )
        putExtra(
            Intent.EXTRA_STREAM,
            latestLogFileUri
        )
    }

    emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

    if (selectorIntent.resolveActivity(packageManager) != null) {
        Handler(Looper.getMainLooper()).postDelayed({
            startActivity(
                Intent.createChooser(
                    emailIntent,
                    resources.getString(R.string.support_email_chooser_title)
                )
            )
        }, 2000)
    }

and don't forget to put this into your AndroidManifest.xml:

    <queries>
        <intent>
            <action android:name="android.intent.action.SENDTO" />
            <data android:scheme="mailto" />
        </intent>
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="*/*" />
        </intent>
    </queries>
SqAR.org
  • 557
  • 6
  • 15
0

Best solution for this problem

val intent = Intent(Intent.ACTION_SENDTO)
        intent.data = Uri.parse("mailto:example@gmail.com?bcc=exampleEmail2@gmail.com&subject=subject text...!&body= extra text ..")
        startActivity(intent)