New In iPhone 3.0 Tutorial Series, Part 2: In App Email, MessageUI
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:
- Open a terminal and change to the directory where you want the code
- 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:
- 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:
- In the Groups & Files panel of the project, expand the InAppEmail project branch
- Control-click or right-click the Frameworks folder
- Choose Add > Existing Frameworks…
- Expand the Frameworks folder
- Choose MessageUI.framework and click Add
- Click Add once more
Next, import the framework in the header:
- 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:
- Adopt the protocol in our InAppEmailViewController
- Set ourselves up as the delegate to receive the callbacks
- 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.
Isn’t the additional [controller release] in mailComposeController:didFinishWithResult:error: crashing your app?
Christian: Ack. You’re right. Tried to sneak a change in at the last minute. Fixed.
do we need to create a seperate view for this??
Who can you place this action of the button in a action sheet button?
thanks
More sample code here shows how to set recipients and more:
MailComposer
Is there a way to send an email automatically — i.e. without bringing up the interface?
Raul: nope. The user can send or cancel it; it’s in their control.
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.
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
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
this doesn’t seem to work for me, any idea why this might be?
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?
How do you send the email to an address that cant be changed? Like a contact us address.
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
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.
Great job and very well written i must say!
Well this tutorial is really impressive i must say š thanks for sharing
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
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.
Great tutorial – many thanks.
-Simon
Thanks for the good reference. Saved me a lot of time!!!!!
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
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,