How To Send Email in Android Using Intent : 10 minute guide

To send email from an Android app, build an Intent with ACTION_SENDTO and a mailto: URI, attach the recipient, subject and body as extras, then call startActivity():
val intent = Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("mailto:")
putExtra(Intent.EXTRA_EMAIL, arrayOf("someone@example.com"))
putExtra(Intent.EXTRA_SUBJECT, "Hello from my app")
putExtra(Intent.EXTRA_TEXT, "This is the message body.")
}
startActivity(intent)
Android hands this off to whichever email app the user has installed — your app never touches the network or the user's mail account, and no permission is required. Below is the full picture: why ACTION_SENDTO beats ACTION_SEND for a plain email, how to attach a file without crashing on modern Android, and how to handle the case where no email app is installed at all.
Jump to: ACTION_SENDTO vs ACTION_SEND · the extras that set recipient, subject and body · attaching a file with FileProvider · handling no email app installed · sending without opening an email app · common mistakes
ACTION_SENDTO vs ACTION_SEND: Which One to Use
Android gives you two different actions for composing email, and picking the wrong one is the most common mistake in this workflow.
ACTION_SENDTOwith amailto:URI is what Google's own documentation recommends for a plain email with no attachment. Because thedataURI uses themailto:scheme, only apps that declare an intent filter for that scheme can match — text messengers, social apps, and file managers are excluded automatically. That precision is the whole point: the system picker (if the user has more than one email app) only shows email apps.ACTION_SENDis a general-purpose share intent. It matches any app that can handle the MIME type you set, which means a plainACTION_SENDwithtype = "text/plain"can just as easily open Slack, Notes, or a messaging app as an email client. You can narrow it to email apps by setting the type tomessage/rfc822, butACTION_SENDTOis still the cleaner tool when there's no file to attach.
The reason you can't always use ACTION_SENDTO, though, is attachments: ACTION_SENDTO does not support EXTRA_STREAM at all. The moment you need to attach a file, you have to switch to ACTION_SEND (or ACTION_SEND_MULTIPLE for more than one file), typically with type = "*/*" so any app that can accept a generic attachment is eligible.
// Plain email, no attachment - use ACTION_SENDTO
val intent = Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("mailto:")
putExtra(Intent.EXTRA_EMAIL, arrayOf("someone@example.com"))
putExtra(Intent.EXTRA_SUBJECT, "Feedback")
}
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
The Extras That Set Recipient, Subject and Body
Whichever action you use, the same set of Intent extras fills in the composer fields:
Intent.EXTRA_EMAIL— anArray<String>of "To" addresses.Intent.EXTRA_CCandIntent.EXTRA_BCC— the same array-of-strings shape, for cc and bcc.Intent.EXTRA_SUBJECT— a plainStringsubject line.Intent.EXTRA_TEXT— a plainStringmessage body.
fun composeEmail(addresses: Array, subject: String, body: String) { val intent = Intent(Intent.ACTION_SENDTO).apply { data = Uri.parse("mailto:") putExtra(Intent.EXTRA_EMAIL, addresses) putExtra(Intent.EXTRA_CC, arrayOf("cc-person@example.com")) putExtra(Intent.EXTRA_SUBJECT, subject) putExtra(Intent.EXTRA_TEXT, body) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
Note that the composer opens pre-filled but not sent — the user still has to tap send themselves. That's true for every path on this page: an Intent can hand off a draft, but it can never submit it on the user's behalf.
Attaching a File: FileProvider and content:// URIs
Attachments go through Intent.EXTRA_STREAM, set to a Uri pointing at the file. This is where most implementations break, because a raw file:// URI works fine on old Android versions and then crashes on real devices:
// DON'T: raw file:// URI throws FileUriExposedException on Android 7+ val badUri = Uri.fromFile(File(context.filesDir, "report.pdf"))
Since Android 7.0 (API 24), StrictMode blocks apps from exposing a file:// URI outside their own package and throws a FileUriExposedException the instant you try to hand one to another app. The fix is to generate a content:// URI through FileProvider, which wraps the file behind a content provider that grants temporary, scoped read access instead of exposing the raw path.
1. Declare the provider in AndroidManifest.xml:
<application ...>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
2. Define which directories are shareable in res/xml/file_paths.xml:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="attachments" path="attachments/" />
<files-path name="reports" path="reports/" />
</paths>
3. Generate the content:// URI and send it with ACTION_SEND:
val file = File(context.filesDir, "reports/report.pdf")
val attachmentUri: Uri = FileProvider.getUriForFile(
context,
"${context.packageName}.fileprovider",
file
)
val intent = Intent(Intent.ACTION_SEND).apply {
type = "*/*"
putExtra(Intent.EXTRA_EMAIL, arrayOf("someone@example.com"))
putExtra(Intent.EXTRA_SUBJECT, "Your report")
putExtra(Intent.EXTRA_STREAM, attachmentUri)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
The Intent.FLAG_GRANT_READ_URI_PERMISSION flag is what actually lets the receiving email app read a file it doesn't own. Without it, the email app gets the content:// URI but a SecurityException when it tries to open the stream. No manifest permission is needed for this — the flag on the intent is enough.
For more than one file, switch to Intent.ACTION_SEND_MULTIPLE and pass an ArrayList<Uri> through putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris) instead of a single Uri.
Handling No Email App Installed (ActivityNotFoundException)
Emulators in particular often have zero email apps installed, and some real devices are the same. If you call startActivity() with an email Intent and nothing on the device can handle it, Android throws ActivityNotFoundException instead of failing silently — and if you don't catch it, your app crashes.
Guard every email Intent with resolveActivity(), and wrap the call in a try/catch as a second line of defense:
fun sendEmailSafely(context: Context, intent: Intent) {
try {
if (intent.resolveActivity(context.packageManager) != null) {
context.startActivity(intent)
} else {
Toast.makeText(context, "No email app found", Toast.LENGTH_SHORT).show()
}
} catch (e: ActivityNotFoundException) {
Toast.makeText(context, "No email app found", Toast.LENGTH_SHORT).show()
}
}
On Android 11 (API 30) and above, package visibility restrictions can make resolveActivity() return null even when an email app is installed, unless your app declares what it's looking for. Add a <queries> element to AndroidManifest.xml so the system knows to reveal matching apps:
<queries>
<intent>
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
</intent>
</queries>
Can You Send an Email Without Opening the User's Mail App?
No — not with an Intent, and this trips up a lot of people searching for this exact page. Both ACTION_SEND and ACTION_SENDTO exist specifically to hand the message to a composer the user sees and confirms; there is no flag or extra that sends it silently in the background. That's a deliberate design choice, not a missing feature.
If what you actually need is to send email without any user interaction — a signup confirmation, a password reset, a receipt — that's a different problem with a different solution: a transactional email service (SendGrid, Amazon SES, Resend, and similar) or your own SMTP backend, called from your app's server, not from the device. Baking SMTP credentials into a client app is both the wrong tool and a security risk, since anyone could extract the credentials from the APK.
Common Mistakes When Sending Email via Intent
- Using ACTION_SEND for a plain email with no attachment. It works, but it also matches non-email apps and can surface a confusing chooser. Use
ACTION_SENDTOwith amailto:URI instead when there's nothing to attach. - Passing a file:// URI to EXTRA_STREAM. This crashes with
FileUriExposedExceptionon Android 7 and above. Always generate acontent://URI throughFileProvider.getUriForFile(). - Forgetting FLAG_GRANT_READ_URI_PERMISSION. The receiving email app gets a valid
content://URI but aSecurityExceptionwhen it tries to read the attachment, because it was never granted access. - Not catching ActivityNotFoundException. This is the single most common crash reported from this feature, almost always surfacing first on emulators that have no email app installed.
- Skipping the <queries> manifest entry on Android 11+. Without it,
resolveActivity()can return null due to package visibility restrictions even though a compatible email app is actually installed. - Expecting the email to send itself. An Intent only opens a composer with the fields pre-filled; the user must tap send. If you need email sent with zero user interaction, you need a server-side/SMTP solution, not an Intent.
Read more: Android Intent Filter With Code and Jump From One Activity to Another Activity in Kotlin if you're combining this with in-app navigation.
If you have any confusion or need help, ask through the comment section and we'll help you out.
Frequently Asked Questions
How do I send an email from an Android app?
Build an Intent with ACTION_SENDTO and a mailto: URI, attach the recipient, subject and body as extras, then call startActivity(). Android hands the request to whichever email app the user has installed rather than sending it yourself, so the user still sees and confirms the message before it goes out.
What is the difference between ACTION_SENDTO and ACTION_SEND?
ACTION_SENDTO with a mailto: URI only matches email apps, which is why Android's own documentation recommends it for a plain email with no attachment. ACTION_SEND is a general share intent that can also match non-email apps unless you restrict its type to message/rfc822 — but it's required the moment you need to attach a file, since ACTION_SENDTO doesn't support EXTRA_STREAM at all.
Which Intent extras set the recipient, subject and body?
Intent.EXTRA_EMAIL takes an array of recipient addresses, Intent.EXTRA_SUBJECT takes the subject line, and Intent.EXTRA_TEXT takes the message body. Use EXTRA_CC and EXTRA_BCC the same way for cc and bcc recipients.
How do I attach a file to an email Intent?
Use ACTION_SEND with Intent.EXTRA_STREAM set to a content:// URI, not a raw file:// path. Generate that URI with FileProvider.getUriForFile(), declare a FileProvider in your manifest, and add Intent.FLAG_GRANT_READ_URI_PERMISSION so the receiving email app can actually read the file. For more than one attachment, use ACTION_SEND_MULTIPLE with an ArrayList of URIs.
Why does a file:// attachment crash on newer Android versions?
Since Android 7.0 (API 24), StrictMode blocks apps from exposing file:// URIs outside their own package and throws a FileUriExposedException if you try. Attachments must be passed as content:// URIs generated through FileProvider instead.
Do I need a permission to send email via Intent?
No. Because the Intent hands the message to another app rather than sending it directly, no permission is required for a plain email. Your app never touches the user's mail account or the network. Attachments only need the FLAG_GRANT_READ_URI_PERMISSION flag on the intent itself, not a manifest permission.
Why does nothing happen or my app crash when I launch the email Intent?
This usually means no email app is installed to handle the intent, which is common on emulators. startActivity() throws an ActivityNotFoundException in that case instead of failing silently, so wrap the call in a try/catch and show a message like "No email app found" instead of letting it crash. On Android 11+, also add a <queries> element in your manifest declaring the mailto intent, or resolveActivity() checks will fail due to package visibility restrictions.
Can I send an email without opening the user's mail app?
Not with an Intent. Both ACTION_SEND and ACTION_SENDTO deliberately show the composer so the user confirms what is being sent — there's no way to send silently in the background. Sending email without any user interaction, such as a receipt or password reset, requires calling a transactional email service or your own SMTP backend from your app's server, not from the device.



