Photo from Unsplash.com

Send email content from your iOS App with MFMailComposeViewController

Jen Sipila
iOS App Development
5 min readJul 21, 2016

--

Letting users share content by email from within your app is a wonderful way to get the word out about your apps unique features and functionality. At first glance, building email implementation can seem like a complicated task. But luckily Apple has provided a framework, class and delegate which make it very simple to add email sharing to any iOS project.

Sample email implementation screen for sending an image.

Here I will show you step-by-step how to add this functionality to your app and implement the To/CC/BCC Recipients, Subject, Message Body and Attachment settings provided by Apple.

Before you start make sure you have a sample project set up that has at the very minimum one button to trigger the email screen. In addition, if your app produces content like photos you can practice sending data as attachments.

Here is a link to a complete sample project that implements email sharing: https://github.com/jen2/Email-Demo

  1. First go to the .h file of your view controller and set it to conform to the MFMailComposeViewControllerDelegate protocol. This delegate will come in handy when assembling and dismissing the message.
@interface ViewController : UIViewController <MFMailComposeViewControllerDelegate>

2. Go to the view controller where the sharing will be triggered and import the MessageUI framework.

#import <MessageUI/MessageUI.h>

3. Now that you have access to the MessageUI framework you can implement the MFMailComposeViewController class methods.

First, it is best to check if a device has the ability to send mail. This check prevents unmanaged errors if, by chance, a user tries to use this functionality on a device that does not support mail. You can run this check with a simple if statement.

if ([MFMailComposeViewController canSendMail]) {
//Your code will go here
} else {
//This device cannot send email
}

Just to be extra clear, this statement should be placed inside a method that will be called when you want to kick off the email screen, for example inside the body of an IBAction connected to a ‘share’ button on your View Controller.

(IBAction)emailShareButtonTapped:(UIButton *)sender 
{
if ([MFMailComposeViewController canSendMail]) {
//Your code will go here
} else {
//This device cannot send email
}
}

4. Once that check is complete, allocate an instance of the MRMailViewController.

MFMailComposeViewController *mailVC = [[MFMailComposeViewController alloc] init];

4. Then set the delegate to self inside the view controller.

mailVC.mailComposeDelegate = self;

5. Next deal with the class methods that specify default values for the parts of the email. The following methods can be pre-defined or left blank.

setSubject:
setToRecipients:
setCcRecipients:
setBccRecipients:
setMessageBody:isHTML:
addAttachmentData:mimeType:fileName:

For example, if you wish to fill in a default subject line and message body for the email form, use the following:

[mailVC setSubject:@"Look what I found using Demo App!"];
[mailVC setMessageBody:@"Found and sent using Demo App!" isHTML:NO];

When your app runs the email form will appear like the image at the beginning of this post.

Sample email implementation screen for sending an image.

You can also specify a default email address for testing:

[mailVC setToRecipients:@[@"myTestEmail@myEmail.com"];

Something to note about the setToRecipients: method is that it takes an array of strings. So if you do set a default value here make sure you enclose it in the array literal syntax @[];.

Add Data Attachments

Most often you will want your users to share some kind of data from your app. Here is where you can add a data attachment for your user to share.

The last class method addAttachmentData:mimeType:fileName: allows you to pre-define some user generated data of type NSData to send. A very common type of data is image/photo data.

If your app has camera functionality, you may have images on hand that you can allow a user to share. For example, your user may have captured a photo it will be assigned to myNewImage. Before attempting to attach it to an email you will need to convert it into NSData.

NSData *dataForImage = UIImagePNGRepresentation(myNewImage);

Then you will be able include it as a default attachment.

You will notice mimeType and fileName as part of this method. mimeType is an unusual name for the type of file it should ultimately become when it reaches the recipient of the email.

Some possible mimeTypes are:

@”image/jpeg”;
@”image/png”;
@”image/gif”;
@”image/tiff”;
@”application/pdf”;
@”application/vnd”;
@”text/plain”;
@”application/octet-stream”;

Make sure to choose one and add it as an NSString argument to the addAttachmentData method.

The fileName argument is also a string and can be anything you choose for the image. One the image arrives via email it will keep this file name when downloaded or opened on the recipients computer.

So you complete method call for attaching data should look something like this:

[mailVC  addAttachmentData: dataForImage mimeType: @”image/jpeg”; fileName: @”My image”];

6. The last thing to include with in the body of the method is a call to present the view controller.

[self presentViewController:mailVC animated:YES completion:nil];

The complete code within the method should look like this:

if ([MFMailComposeViewController canSendMail]) {     
MFMailComposeViewController *mail =
[[MFMailComposeViewController alloc] init];
mail.mailComposeDelegate = self;
[mail setSubject:@”Sample Subject”];
[mail setMessageBody:@”Sample body message" isHTML:NO];
[mail setToRecipients:@[@”testingEmail@example.com”]];
[mailVC addAttachmentData: dataForImage mimeType: @”image/jpeg”; fileName: @”My image”];
[self presentViewController:mail animated:YES completion:NULL];
} else {
NSLog(@”This device cannot send email”);
}

7. Lastly, the delegate has one instance method that is called when the email has been sent, saved, cancelled or failed and the email form will be dismissed. It can be used to handle these events in a custom way if necessary.

- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error 
{
switch (result) {
case MFMailComposeResultSent:
//Email sent
break;
case MFMailComposeResultSaved:
//Email saved
break;
case MFMailComposeResultCancelled:
//Handle cancelling of the email
break;
case MFMailComposeResultFailed:
//Handle failure to send.
break;
default:
//A failure occurred while completing the email
break;
}
[self dismissViewControllerAnimated:YES completion:NULL];
}

The method call dismissViewControllerAnimated:completion: is made to dismiss the email form and bring you back to the original view controller.

Once all of these steps are complete email implementation in your app will be running smoothly.

Thank you for reading!

Here is the link, again, for the complete project: https://github.com/jen2/Email-Demo

Resources:

--

--