Expo React-native Email with Attachment

Learn how to send emails using device OS UI in Expo React-Native

Charles Effiong
Level Up Coding

--

Hi guys, welcome to another React tutorial where I’m going to show you how to send emails using the OS (Android or IOS) UI in Expo React-native. In addition, this tutorial covers how to include attachments in the email. This tutorial assumes some basic React/React-native know-how. However, it's simple enough for a complete beginner, so hang in there.

What we'll be building

The app will allow users to send emails with/without an attachments. This does a lot of heavy lifting, as you do not require a backend or some paid email APIs in order to implement sending emails with pre-filled fIelds. You can use this approach to enable users report in-app bug in your mobile app. The animation below shows the running application. Let’s look at the source codes in the next section. You can find the complete source code on my Github.

Setup expo react native

This project uses Expo for development. What is Expo you might ask? The following quote is taking from the official expo documentation:

Expo is a framework and a platform for universal React applications. It is a set of tools and services built around React Native and native platforms that help you develop, build, deploy, and quickly iterate on iOS, Android, and web apps from the same JavaScript/TypeScript codebase.

Expo makes developing, testing, and deploying React-native application a breeze. You’ll have a higher appreciation for Expo if you have tried developing mobile app using bare React-native —you won’t like it! It’s simply a great tool for developing Android/IOS apps using React-native.

# Install the expo command line tools
npm install --global expo-cli
# Create a new project
expo init email-app

The above code snippet is all you need to setup and get started with developing React-native app using Expo. The second command creates a new app called email-app. You need to first have node if you haven’t.

We'll need two expo-packages: one for sending email using the OS UI and the second for selecting images for attachment.

# Install mail package
expo install expo-mail-composer
# Install image picker package
expo install expo-image-picker

The code snippets above installs the neccessary packages. Let's start using the packages.

Send email user interface

We only need a button to trigger the event that launches the OS UI (as seen in the animation). The following code in the App component (App.js source) takes care of that.

import * as ImagePicker from 'expo-image-picker';
import * as MailComposer from 'expo-mail-composer';
export default function App() {
const [status, setStatus] = useState(null)
return (
<View style={styles.container}>
<TouchableOpacity onPress={showAlert}>
<Text>Send email</Text>
</TouchableOpacity>
{status !== null &&
<View>
<Text>{status}</Text>
</View>
}
</View>
);
}

I have abstracted away some import statements and UI styling in order to keep things simple. You can find the complete source codes on Github as stated earlier. The output of the code (assuming all other imports and styling are included) is shown below.

Left: Base UI. Right: Alert prompt when the send email button is clicked.

The UI code snippet is pretty self explanatory. We are calling the showAlert function when the button is pressed. The code snippet for the function is given below:

const showAlert = () =>
Alert.alert(
"Add a file",
"Do you want to attach a file?", [
{
text: "No",
onPress: () => {sendEmail([])},
style: "cancel"
},
{ text: "Yes", onPress: sendEmailWithAttachment }
]
);

Send email without an attachment

If the user chooses not to attach a file i.e. the No button on the Alert is pressed, the sendEmail function is called. Let’s see the function implementation.

const sendEmail = async(file) => {
var options = {}
if(file.length < 1){
options = {
subject: "Sending email with attachment",
recipients: ["talkwithcharles@gmail.com"],
body: "Enter email body here..."
}
}else{
options = {
subject: "Sending email with attachment",
recipients: ["talkwithcharles@gmail.com"],
body: "Enter email body here...",
attachments: file
}
let promise = new Promise((resolve, reject) => {
MailComposer.composeAsync(options)
.then((result) => {
resolve(result)
})
.catch((error) => {
reject(error)
})
})
promise.then(
result => setStatus("Status: email " + result.status),
error => setStatus("Status: email " + error.status)
)
}

The code snippet above shows the function implementation. First we check if a file is included the function call. Remember the MailComposer object that was imported earlier? This object has a function i.e. composeAsync that allows us to compose a message with options such as message subject, body, recipient and attachments. The function returns a result or error with a status when it is done executing. For example, if the message was successfully sent, it returns a status sent object. The UI is updated with the mail status in order to keep the user informed.

Left: Sending message without attachment with IOS UI. Middle: App UI updated with status. Right: Phone email client showing that the email is indeed received.

Now for the fun path. What happens when a user selects the Yes button on the Alert prompt? In this case, we want the user to be able to select a file to be attached to the email. Let's discuss this next.

Send email with an attachment

When the Yes button on the Alert prompt is pressed, the sendEmailWithAttachment function is called. Let's take a look at the function implementation.

const sendEmailWithAttachment = async() => {
//get the image to attach.
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: false,
aspect: [4, 3],
quality: 1,
});
if (!result.cancelled) {
sendEmail([result.uri]); // file path
}else{
sendEmail([])
}
}

The function uses the ImagePicker object to select an image to attach to the email. The object calls the launchImageLibraryAsync function. This function launches the phone’s image gallery. Next we check the returned object. If the process was cancelled i.e. no file was selected. We can still send an email by calling the sendEmail function with an empty array (meaning no attachment.) On the other hand, if a user indeed select a file, we get the file path from the result i.e. result.uri and pass that to the sendEmail function.

Left: Phone image gallery is opened. Middle: Selected image is included in the email UI. Right: Email is received.

The selected image is included in the email body as shown in the image above.

Summary

You have learned how to send emails using the device OS UI in Expo React-native. We have also covered file attachments with the help of the Image picker library. One limitation of the image picker library is that it only allows for selecting a single image. This project can be extended to include multiple files selection if your use case requires it or for the fun of learning by doing. You can use the expo-image-picker-multiple for this purpose — yes, give it a shot.

I hope you’ve learned something in this tutorial.

Feel free to download/clone the project source code on Github.

Check out my other React/React-Native tutorials.

Happy coding!

--

--

I love programming and passionate about helping learners get up to speed with programming.