New In iPhone 3.0 Tutorial Series, Part 2: In App Email, MessageUI

By
On June 23, 2009

Welcome back! In the first part of this series, I showed how to implement Shake To Undo/Redo and NSUndoManager in an iPhone app.

This time, we’ll add in-app email to a simple iPhone application using the new-in-3.0 MessageUI framework.

Technically neither mail from an app nor MessageUI are new. MessageUI was a private framework prior to 3.0, and apps could send mail using mailto:// URLs, though in a limited way.

In any case, with 3.0 and MessageUI, sending messages is straightforward and full featured.

We’ll start with working code for a simple app with a UI containing a single button. We’ll add code that shows the compose-an-email message UI and pre-fills the subject and content when the button is pressed.

Source/GitHub

The code for this tutorial is available on GitHub. To download a copy for yourself, close the repository:

  1. Open a terminal and change to the directory where you want the code
  2. Clone the repo by typing git clone git://github.com/dcgrigsby/InAppEmail.git

I’ve made two separate commits to the repository — an initial commit without in-app email, and a second one with those capabilities added. If you’re following along step-by-step, you’ll want to revert to the earlier commit. From the source directory:

  1. Type git checkout 0019071d855e6d3a9f263b8a02d9c7d93dc5dcd2

Orientation

InAppEmail is about as simple an application as it’s possible to construct. The single “Send Email” button — which is disabled, for now — triggers the buttonPressed message when pressed.

Adding The MessageUI Framework

As part of the MessageUI Framework, Apple provides a ready-made compose-a-message UI called MFMailComposeViewController for our use. In order to use it, we need to add the MessageUI Framework to our project:

  1. In the Groups & Files panel of the project, expand the InAppEmail project branch
  2. Control-click or right-click the Frameworks folder
  3. Choose Add > Existing Frameworks…
  4. Expand the Frameworks folder
  5. Choose MessageUI.framework and click Add
  6. Click Add once more

Next, import the framework in the header:

  1. Add #import <MessageUI/MessageUI.h> to InAppEmailViewController.h

Showing The MFMailComposeViewController UI

MFMailComposeViewController is just like any other view controller; we can use presentModalViewController from our InAppEmailViewController class to slide it onto the screen modally.

Replace the puttonPressed method in InAppEmailController.m with this:

- (IBAction)buttonPressed {
	MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
	[controller setSubject:@"In app email..."];
	[controller setMessageBody:@"...a tutorial from mobileorchard.com" isHTML:NO];
	[self presentModalViewController:controller animated:YES];
	[controller release];
}

Running the app in its current form would be disappointing. The “Send Email” message button is disabled. It’s a simple matter to enable it but, but we should do so only if the iPhone or iPod touch the app is running on has been configured to send mail. To do so, add code for aviewDidLoad method to InAppEmailViewController.m:

- (void)viewDidLoad {
	if ([MFMailComposeViewController canSendMail])
		button.enabled = YES;
}

Dismissing the MFMailComposeViewController UI

We’re most of the way there. Run the app at this juncture and it mostly works: clicking the button brings up the compose UI pre-filled with our sample message. Add an email address in the “To” field and away you go — mostly:

We’re missing one piece: we need to know when to dismiss the mail composer UI. The MFMailComposeViewControllerDelegate protocol provides a callback mechanism to accomplish this.

To receive the callback, we’ll need:

  1. Adopt the protocol in our InAppEmailViewController
  2. Set ourselves up as the delegate to receive the callbacks
  3. Implement the callback method

To adopt the protocol update InAppEmailViewController.h. Changes are bold:

#import <UIKit/UIKit.h>

@interface InAppEmailViewController : UIViewController <MFMailComposeViewControllerDelegate> {
	IBOutlet UIButton *button;
}

- (IBAction)buttonPressed;

@end

To set ourselves up as the delegate to receive the callbacks update buttonPressed in InAppEmailViewController.m. Changes are bold:

- (IBAction)buttonPressed {
	MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
	controller.mailComposeDelegate = self;
	[controller setSubject:@"In app email..."];
	[controller setMessageBody:@"...a tutorial from mobileorchard.com" isHTML:NO];
	[self presentModalViewController:controller animated:YES];
	[controller release];
}

Finally, we implement the callback method. Add this code for a mailComposeController:didFinishWithResult:error: method to InAppEmailViewController.m:

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
	[self becomeFirstResponder];
	[self dismissModalViewControllerAnimated:YES];
}

Conclusion

That covers the basics. This tutorial doesn’t demonstrate setting recipients, adding attachments, or composing HTML email — all of which are straightforward once you’ve got the basics down.

Finally, one limitation that’s worth noting: you can’t force a user to send mail; they can always click the cancel button.

0 responses to “New In iPhone 3.0 Tutorial Series, Part 2: In App Email, MessageUI”

  1. Isn’t the additional [controller release] in mailComposeController:didFinishWithResult:error: crashing your app?

  2. Dan Grigsby says:

    Christian: Ack. You’re right. Tried to sneak a change in at the last minute. Fixed.

  3. vibhor goyal says:

    do we need to create a seperate view for this??

  4. Edgard Rodriguez says:

    Who can you place this action of the button in a action sheet button?

    thanks

  5. Mike Berg says:

    More sample code here shows how to set recipients and more:
    MailComposer

  6. Raul Masfrio says:

    Is there a way to send an email automatically — i.e. without bringing up the interface?

  7. Dan Grigsby says:

    Raul: nope. The user can send or cancel it; it’s in their control.

  8. arvind says:

    Hi Dan,
    Thanks a lot. Your post has helped me in my iPhone application.
    Sending the mail from iTouch was a breeze. šŸ™‚
    Thanks for so many people who are sharing their knowledge.

  9. DavidStannard says:

    Hi Dan,

    Great stuff!

    Any suggestions to newbies on how to correctly attach property lists and SQLite files? It seems that one requires the appropriate MIME type and not just simply sending the file

    Thanks

    David

  10. Tom says:

    Hi Dan,

    Great post!. Any idea if it is possible to add extra headers with email.
    I have a requirement to send custom header with email but I couldn’t find a wy to do this.

    Thanks & Regards
    Tom

  11. Chris Parcel says:

    this doesn’t seem to work for me, any idea why this might be?

  12. Macarov says:

    MFMailComposeViewController displaying only bar at the top of the screen with the cancel and send buttons. Code for landscape:
    MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
    controller.mailComposeDelegate = self;
    [controller setSubject:@”In app email…”];
    [controller setMessageBody:@”…a tutorial from mobileorchard.com” isHTML:NO];
    //[self presentModalViewController:controller animated:YES];
    controller.view.frame = CGRectMake(0,0,480,320);
    [self.view addSubview:controller.view];
    [controller release];

    What is problem?

  13. Daniel says:

    How do you send the email to an address that cant be changed? Like a contact us address.

  14. Thanks Dan!

    I had a bit of difficulty figuring out how to find the framework to include it but after that it was all really easy.

    The trick I needed to find the MessageUI.framework was that it was in /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/System/Library/Frameworks and I need to navigate to this directory from within the Add Existing Frameworks dialog box.

    Bart

  15. Inka says:

    GREAT TUTORIAL!!! question.. what if iā€™m on the iphone version of site and i made a link for people to view the site in full website view? how do i make this possible, since it has the redirect. I see it all the time like foxnews.com has the link on bottom, for full view of website.

  16. Great job and very well written i must say!

  17. Well this tutorial is really impressive i must say šŸ™ thanks for sharing

  18. Tim says:

    Once they press the Send button, is it possible to intercept the email before it is sent? I’m writting a childrens email program and want to check if they are allowed to send the email to that contact.

    Thanks

    Tim

  19. Dan Grigsby says:

    Tim: nope. Apple is very specific about you not being able to get into the flow — they’re afraid of apps being spammy, stealing contact info, etc.

  20. Simon says:

    Great tutorial – many thanks.
    -Simon

  21. robm says:

    Thanks for the good reference. Saved me a lot of time!!!!!

  22. ray says:

    Great article:
    But I don’t have a MessageUI framework on my machine even through I am running the latest and greatest xcode.. Any thoughts on why this would be.. How could this have happened..

    ray

  23. Rahul K says:

    This is really great help! One question though! How do you set the recipient automatically? In my app I am trying to load the address book in table view cell and once user selects the recipient I want email address to be populated automatically in the To: field of the mail composer.
    Any idea?
    Thanks,