Android: Sending Email using Intents
Many things on Android are as easy as starting an Activity using the right Intent. Sending an email to a specific recipient is one of those things.
Sadly, there is much bad advice out there on how to send emails using Intents. Because I write an open source email app I have a pretty good understanding of what goes on behind the scenes. That’s why I believe I know better than all those other people :)
To start the Activity to compose an email in your user’s favorite email app you use an Intent with the ACTION_SENDTO action. Unfortunately, the documentation is very sparse. It simply states:
Activity Action: Send a message to someone specified by the data.
Input: getData() is URI describing the target.
This doesn’t mention email at all because ACTION_SENDTO is very generic and can also be used to send e.g. SMS, MMS or XMPP messages.
To send an email we have to use a mailto URI as defined by RFC 6068. In its simplest form such a URI consists of “mailto:” followed by an email address, e.g. mailto:email@example.com. You might recognize this syntax from email links in HTML documents.
Creating such an Intent might look like this:
Most of the time you want to provide more data than just a recipient. And the mailto specification allows us to also specify CC and BCC recipients, a subject, and even text for the email body.
Generating such a mailto URI is a bit tedious because you have to percent-encode certain characters as you can see in the example above.
Android’s Uri.Builder class would be the perfect fit since it makes it easy to add query parameters while taking care of the encoding. Unfortunately, building Uri instances doesn’t work very well for non-hierarchical URIs like mailto URIs. One way to work around that is to manually construct the URI and dealing with the encoding.
Some code samples advocate the use of EXTRA_SUBJECT, EXTRA_TEXT, etc. Those are certainly easier to use. However, the Android API reference only mentions them in connection with ACTION_SEND and ACTION_SEND_MULTIPLE. Those are more general Intents for sharing content to nobody in particular.
The fact that the Extras also work with ACTION_SENDTO was an undocumented “feature” of AOSP Email and the Gmail app. That functionality then had to be copied by all other Android email clients because apps were and are using those Extras.
But since all major email clients support the use of query parameters in mailto URIs I see no reason to use an undocumented feature and advice against it.
It is also worth mentioning that you shouldn’t use Intent.createChooser() to launch an email Intent. Users most likely have a preferred email app that they want to be able to select as default app. The standard behavior when resolving an Intent deals with that just fine.
There are a couple of other things that need to be considered. Line breaks in the body, for example, need to be encoded as %0D%0A (CRLF).
Because it’s no fun to deal with all of that when all you want to do is send an email, I wrote a small library to take care of the dirty details for you.
EmailIntentBuilder — Making life easier
Building an email Intent is a simple matter of calling some methods on the builder:
Most of the time you also want to launch the Intent. The start() method will do that for you while also taking care of not throwing an exception if no app could be found to handle the Intent.
What about Attachments?
Unfortunately, the ACTION_SENDTO Intent doesn’t support attachments. If you need to send an email containing one or more attachments you should use Android’s more generic share mechanism, i.e. ACTION_SEND or ACTION_SEND_MULTIPLE.
A lot of people have realized that this leads to quite a few more than just email apps showing up in the app chooser dialog. How to properly deal with that is material for another post.
I’d love to hear about your experiences dealing with email on Android. Let me know on Twitter.