Email Composer on iOS

June 4th, 2021

⏱ Reading Time: 4 mins

It’s often needed to add email sending functionality to iOS apps. In order to do that, there is a specific view controller to use called MFMailComposeViewController. When presented, it brings up the familiar system controller to compose and send an email. It’s possible to provide default values before its presentation, such as the subject or the recipients, even a predefined email body. In overall, sending email is a quite standard procedure, and this post will take you through the integration steps of the email composer on iOS.

Initial steps

The first step towards presenting the system controller to compose and send emails, is to import a specific framework that will make the MFMailComposeViewController class available. That is the MessageUI:

After that, it’s mandatory to check if the device can actually send emails! If we skip that and the device is unable to send emails for some reason, then the app will just crash; that’s something we don’t want to happen by any means.

Doing that check is easy, and all it takes is to call a class method in MFMailComposeViewController:

Suppose that the composeEmail() method is the place to initialize an MFMailComposeViewController instance and present it modally in the app. See that it starts by calling the canSendMail() method and verifying that the device is capable of sending emails. If not, then in this example we just present an alert reporting that, and return from the method. In real world, do whatever is appropriate to your app in order to handle this case.

Initializing and configuring a mail composer instance

The bare minimum implementation required in order to create and configure an MFMailComposeViewController instance is parted by the following two lines:

The current view controller instance is set as the delegate to the mail controller. However, notice the property of the email instance we are using to do that; the delegate property is called mailComposeDelegate. There is one delegate method to implement only, and we’ll deal with it in a while.

Before presenting the email composer controller, it’s possible to set predefined values to the various fields an email has. We can do that for just a few or all fields, depending on the needs of the app. Let’s see them one by one.

The first one is setting the subject of the email. Simply provide it as a string argument to the setSubject() method accessible through the email object:

To specify one or more recipients, simply pass as argument an array of string values to the following method, where each value is a recipient’s email address:

Note that users can add more addresses if they want to. In a similar way we can also provide addresses for the CC and BCC fields of the email. For that, use the setCcRecipients() and setBccRecipients() respectively.

It’s also possible to set an address to the From field of the email like so:

Before presenting the email composer, we can provide a predefined body. We just need to call the setMessageBody(_:isHTML:) method, providing the actual message content as the first argument, and whether that content is plain text or HTML:

Once you have finished providing default values using any of the methods demonstrated above, don’t forget to present the mail controller:

The following method contains it all in one place:

The delegate method

Regardless of whether you’ll be setting default values to email fields or not, implementing the one and only available delegate method is something that you should always do. The reason for that is that in this method we can determine two things:

  • what did the user do with the email, and therefore continue in further actions if necessary,
  • check if an error occurred and the email was not sent.

How the app should react in any of the above cases depends on the app’s requirements. For example, you may want to show an alert in case of an error, or perform UI-related operations after having sent an email successfully.

In the following snippet you can see a sample implementation of the delegate method that takes place in a view controller’s extension. No real handling happens, there are just print commands to showcase each case:

See that the result parameter value contains four cases that indicate whether the email was sent, saved, cancelled by the user, or failed for some reason to be sent. A default case to cover future potential values is also necessary to be added to the switch statement.

In the end, the email controller must be explicitly dismissed.

Summary

That was all about presenting the email composer on iOS; a straightforward task that can be synopsized in two methods; the composeEmail() demonstrated earlier, and the delegate method right above. In this post I showed you how to present the email composer in UIKit. In a future post I’ll show how to do the same in SwiftUI. Thanks for reading, and take care!

Stay Up To Date

Subscribe to my newsletter and get notifiied instantly when I post something new on SerialCoder.dev.

    We respect your privacy. Unsubscribe at any time.