Have you wanted to send an e-mail from your app and pre-populate the fields like the recipient, subject, or body text? Apple made it pretty easy with MFMailComposeViewController. There is a bit of setup, but most of its actual implementation is pretty easy.
Loading MessageUI, MFMailComposeViewController’s framework
So, firstly, we have to load a framework. This functionality isn’t built in, so we have to get it from somewhere.
Click on your project in the Project Navigator. In there, click on your Target application. Then go to the “Build Phases” tab, and then open the “Link Binary With Libraries” section. There are probably a few things here already like UIKit. You will then click on the + button in the lower left corner (in Xcode 5). In there, you can either scroll down and look, or just search for message, and then highlight the MessageUI.framework option, and click Add. This will add the framework to your project.
Next, we need to add a couple things to the top of your class, the import for this, and a protocol we’ll need for later:
#import <MessageUI/MessageUI.h> @interface yourViewController ()
Where I am saying that you add the <MFMailComposeViewControllerDelegate> to your classes beginning interface area.
MFMailComposeViewController’s Mail Field Settings
Here you set the default settings for the various fields in your email.
The available settings are:
- setSubject:
- setToRecipients:
- setCcRecipients:
- setBccRecipients:
- setMessageBody:isHTML:
- addAttachmentData:mimeType:fileName:
For my app, I just needed the subject, toRecipients, so that is what I’ll show here. You also need to determine if the user is even capable of sending email, like if they have an email account set up in the mail app. Luckily for us, there is a class method that shows us just that.
Finally presenting the MFMailComposeViewController
Here is the actual code to show the email composer:
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
mail.mailComposeDelegate = self;
[mail setSubject:@"Sample Subject"];
[mail setMessageBody:@"Here is some main text in the email!" isHTML:NO];
[mail setToRecipients:@[@"testingEmail@example.com"]];
[self presentViewController:mail animated:YES completion:NULL];
}
else
{
NSLog(@"This device cannot send email");
}
So first, we check that class method to see if the user can even send email. This will return a BOOL, and if not, we log something to the console for debugging.
If the user can, we create an instance of MFMailComposeViewController, and set its delegate to self. I will show you momentarily how to properly respond to this delegate call.
Then, we set the subject to some string, set the message body to some string (and say whether it is HTML or not, in my case it is not), and the recipients.
Now, notice that I said recipients plural. It actually takes an NSArray of NSStrings for that method. In this case I am just using the Objective-C Literal syntax (see Clang Documentation for more information) to create an NSArray of objects separated by commas (but since I only have one, that is unnecessary).
After that, just tell self to present the view controller we just added all of these settings to and voilà!
MFMailComposeViewControllerDelegate
Now we have to set up what to do when the delegate is called. This delegate has only one instance method, and it is called when the user is ready (one way or another) to dismiss the mail composer.
Here is a sample of how to respond to the delegate:
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
switch (result) {
case MFMailComposeResultSent:
NSLog(@"You sent the email.");
break;
case MFMailComposeResultSaved:
NSLog(@"You saved a draft of this email");
break;
case MFMailComposeResultCancelled:
NSLog(@"You cancelled sending this email.");
break;
case MFMailComposeResultFailed:
NSLog(@"Mail failed: An error occurred when trying to compose this email");
break;
default:
NSLog(@"An error occurred when trying to compose this email");
break;
}
[self dismissViewControllerAnimated:YES completion:NULL];
}
So the result contains some MFMailComposeResult, and it allows you to handle it however you see fit, such as if they save it, maybe you could increment a count of emails saved by your app, I guess. Just for demonstration, I am just logging them out to the console for now.
Conclusion
There you have MFMailComposeViewController in all its glory. It is a very simple view controller, but it lets you get the job done efficiently, and in a very easy to read manner. To make this a bit easier, I have created a sample project on GitHub that shows how this works in context. To test this fully though, you do need to run it on a device.
I hope you found this article helpful. If you did, don’t hesitate to share this post on twitter or your social media of choice. The blog is still pretty new, and every share helps. Of course, if you have any questions, don’t hesitate to contact me on twitter @CodingExplorer, and I’ll see what I can do. Thanks!