In this iOS SDK tutorial, I'll demonstrate how to allow your users to send e-mail without leaving your application using the MFMailComposeViewController class. We will setup an e-mail template with recipients, a subject, body text, and even an image attachment.
The iOS SDK provides an easy to use, standard interface to allow your users to send and edit e-mail from within your own application. To do so, you will need to use the MFMailComposeViewController
class. This view controller displays a standard mail interface and also provides the functionality to respond to user events performed on that interface. For instance, you the class will notify you if the user hit "send" or "cancel".
Note: MFMailComposeViewController is only available on iOS 3.0 or later.
So, how does it work? Follow the steps in this tutorial to find out.
Step 1: Create a New Xcode Project
Open Xcode and select “Create a new Xcode project”. Select View-based Application and then click Next. Enter a name for your project. I called mine @”Mail”. Enter your Company Identifier and make sure you selected "iPhone" for Device Family, because we are going to make an iPhone app. If you are done, click Next. Choose a place to save your project and click Create.
Step 2: Add the Mail Button
Open the "MailViewController.xib" file and drag a button into the view. Set the title of the button to "Mail". Now select the middle button of the Editor to show the “Assistant editor”, so we can add an action to the button we just created.
Select the button and CTRL-drag to the “MailViewController.h”. In the pop-up that is displayed, enter “openMail” for name and make sure to set the connection type to “Action”, because we want to make an action and not an outlet.
Step 3: Import the MessageUI Framework
In the navigator area of Xcode 4, select the project name. Next, select the current target (“Mail” in this case), and then select the “Build Phases” tab. Expand the “Link Binary With Libraries” option, and then click the “+” button to add a new framework. Type “message″ into the search box, and select the MessageUI.framework option that appears in the list. Click “Add” to include this framework in the linking phase of your project.
Now that you have added the MessageUI framework into your project, you need to import that framework into the view controller that will use the MFMailComposeViewController
, so, in our case, MailViewController.h.
Go to this file and modify the code to read as follows:
#import <UIKit/UIKit.h> #import <MessageUI/MessageUI.h> @interface MailViewController : UIViewController <MFMailComposeViewControllerDelegate> - (IBAction)openMail:(id)sender; @end
As you can see, we also declared the MFMaileComposeViewControllerDelegate
in the above code. We will use this delegate to see the result of the mail.
Step 4: Add Project Resources
Drag the following image to the “Supporting Files” folder in your project. Make sure “Copy items into destination group’s folder (if needed)” is checked before clicking finish.
Step 5: Check if Device is Able to Send E-mail
Open the “MailViewController.m” file and scroll down to the openMail:
action and modify the code to read as follows:
- (IBAction)openMail:(id)sender { if ([MFMailComposeViewController canSendMail]) { } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failure" message:@"Your device doesn't support the composer sheet" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; } }
Here we check if the current device is able to send e-mail with the canSendMail
class method of MFMailComposeViewController
. You should always call this method before you open the mail interface. If the device is not able to send e-mail, you should notify the user (I've used a UIAlertView
for this).
Step 6: Show the Mail Interface
If the device is able to send e-mail, we display the mail interface. Go to the openMail:
action and modify the code to read as follows:
- (IBAction)openMail:(id)sender { if ([MFMailComposeViewController canSendMail]) { MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init]; mailer.mailComposeDelegate = self; [mailer setSubject:@"A Message from MobileTuts+"]; NSArray *toRecipients = [NSArray arrayWithObjects:@"[email protected]", @"[email protected]", nil]; [mailer setToRecipients:toRecipients]; UIImage *myImage = [UIImage imageNamed:@"mobiletuts-logo.png"]; NSData *imageData = UIImagePNGRepresentation(myImage); [mailer addAttachmentData:imageData mimeType:@"image/png" fileName:@"mobiletutsImage"]; NSString *emailBody = @"Have you seen the MobileTuts+ web site?"; [mailer setMessageBody:emailBody isHTML:NO]; [self presentModalViewController:mailer animated:YES]; [mailer release]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failure" message:@"Your device doesn't support the composer sheet" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; [alert show]; [alert release]; } }
First we create a MFMaileComposeViewController
and call it “mailer”. We set the mailComposeDelegate
to self, so we can see the result of the mail. The subject is set to “A Message from MobileTuts+”. As you can see, the toRecipients
is of the type NSArray
. This is because you can add multiple recipients. I added two fake email addresses, but of course you can put any address you like. After that, we store an image as an NSData
object, because we cant send a UIImage
directly. Then we add the NSData
object as an attachment to our e-mail. We set the type to a png image and the fileName to “mobiletutsImage”. This means that when the receiver saves the image, it will be saved under the name "mobiletutsImage". The last thing we do is show the mailer before releasing the mailer object.
Step 7: Check the Result and Dismiss the View
You need to manually dismiss the mail interface in response to a delegate method call. Add the following code under the openMail:
action:
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error { switch (result) { case MFMailComposeResultCancelled: NSLog(@"Mail cancelled: you cancelled the operation and no email message was queued."); break; case MFMailComposeResultSaved: NSLog(@"Mail saved: you saved the email message in the drafts folder."); break; case MFMailComposeResultSent: NSLog(@"Mail send: the email message is queued in the outbox. It is ready to send."); break; case MFMailComposeResultFailed: NSLog(@"Mail failed: the email message was not saved or queued, possibly due to an error."); break; default: NSLog(@"Mail not sent."); break; } // Remove the mail view [self dismissModalViewControllerAnimated:YES]; }
In this delegate method, we check the result of having displayed the mail view controller with a switch statement and then dismiss the view controller with an animation. In the above code, I've simply printed an NSLog
message with the results, but the point is that you could respond dynamically to the user's action.
BONUS: Make it Work for iPad
On an iPad it looks nice to show the mail interface in a page sheet presentation. You can do that by adding the following line of code just above [self presentModalViewController:mailer animated:YES];
:
mailer.modalPresentationStyle = UIModalPresentationPageSheet;
Wrap Up
I hope you enjoyed this tutorial. If you have any feedback or requests for additional iOS content from me, please leave a comment below!
Comments