MFMailComposer crashes - iphone

In my app I am using MFMailComposer. It crashes when I send mail without mail configuration (without having entered mail ID and password in the Mail app on the device).
This is the line that causes the crash:
[self presentModalViewController:picker animated:YES];

-(void) showEmailModalView
{
NSLog(#"Start method <ExportStatisticsController> : <showEmailModalView> --");
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self; // <- very important step if you want feedbacks on what the
//user did with your email sheet
[picker setSubject:SendEmailSubject];
NSArray *torec=[[NSArray alloc] initWithObjects:SendEmailToEmailID, nil];
[picker setToRecipients:torec];
[torec release];
//------ message body ---
NSString *body =#"";
body=[NSString stringWithFormat:#"%# From : %#\n",body, emailTextField.text];
body=[NSString stringWithFormat:#"%# Subject : %#\n",body,subjectTextField.text];
//email contents
body = [NSString stringWithFormat:#"%# Message : \n %#", body,messageBodyTextView.text];
[picker setMessageBody:body isHTML:NO]; // depends. Mostly YES, unless you want to send it as plain text (boring)
picker.navigationBar.barStyle = UIBarStyleBlack; // choose your style, unfortunately, Translucent colors behave quirky.
[self presentModalViewController:picker animated:YES];
[picker release];
NSLog(#"End method <ExportStatisticsController> : <showEmailModalView> --");
}
// Dismisses the email composition interface when users tap Cancel or Send. Proceeds to update the message field with the result of the operation.
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
NSLog(#"Start method <ExportStatisticsController> : <didFinishWithResult> --");
// Notifies users about errors associated with the interface
switch (result)
{
case MFMailComposeResultCancelled:
NSLog(#"Message MFMailComposeResultCancelled");
break;
case MFMailComposeResultSaved:
NSLog(#"Message MFMailComposeResultSaved");
break;
case MFMailComposeResultSent:
NSLog(#"Message sent Successfuly");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Email" message:#"Mail Sent Successfully!"
delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
break;
case MFMailComposeResultFailed:
NSLog(#"Message MFMailComposeResultFailed");
break;
default:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Email" message:#"Sending Failed - Unknown Error :-("
delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
}
break;
}
[self dismissModalViewControllerAnimated:YES];
NSLog(#"End method <ExportStatisticsController> : <didFinishWithResult> --");
}

You should call
[MFMailComposeViewController canSendMail]
before presenting the view controller, eg
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
[self presentModalViewController:composer];
} else {
// Show error message maybe
}

That's true. You will have to configure your mail app and check whether the device can send mail or not. Since if it would have been possible without mail app then we would be able to send mail via simulator (which I think is not possible). The receiver of your mail must know from where he/she is getting the mail and I think the sender cannot be set from the code I might be wrong but these are my view since I was struggling the same situation.
Hope it helps.

Related

Using MFMailController in UITabbar controller

I am using UITabbarcontroller in one of the viewcontroller, In one tabbar i need to have only Mail controller, when i am doing so , then that is entering into infinite loop, how would i overcome it, The Code related to
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
if ([MFMailComposeViewController canSendMail]) {
[mailViewController setToRecipients:[NSArray arrayWithObject:#"k.sourish.k#gmail.com"]];
[mailViewController setSubject:#"Subject Goes Here."];
[mailViewController setMessageBody:#"Your message goes here." isHTML:NO];
[self presentModalViewController:mailViewController animated:YES];
}
else {
NSLog(#"Device is unable to send email in its current state.");
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Error" message:#" Please Configure Your Mail Account" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
[mailViewController release];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error { NSString *message = #"";
// Notifies users about errors associated with the interface
switch (result) {
case MFMailComposeResultCancelled:
message = #"Mail: canceled";
break;
case MFMailComposeResultSaved:
message = #"Mail: saved";
break;
case MFMailComposeResultSent:
message = #"Mail: sent";
break;
case MFMailComposeResultFailed:
message = #"Mail: failed";
break;
default:
message = #"Mail: not sent";
break;
}
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Alert" message:message delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
[controller dismissModalViewControllerAnimated:YES];
}
This is how I would do it
Drag and drop a UITabBarButton object on your UITabBar and call it "Email". Now create this IBAction
-(IBAction)composeMyEmail
{
MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
if ([MFMailComposeViewController canSendMail]) {
[mailViewController setToRecipients:[NSArray arrayWithObject:#"k.sourish.k#gmail.com"]];
[mailViewController setSubject:#"Subject Goes Here."];
[mailViewController setMessageBody:#"Your message goes here." isHTML:NO];
[self presentModalViewController:mailViewController animated:YES];
}
else {
NSLog(#"Device is unable to send email in its current state.");
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Error" message:#" Please Configure Your Mail Account" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
[mailViewController release];
}
Connect your IBAction to your "Email" button.
Remove all the code you have under viewWillAppear
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}

Sync Events to available mail accounts in iphone

I am trying to sync Events added by my code in calendar application to available mail accounts. I just wanted to confirm that, is it possible in ios5?? I am trying to search for it but not able to find good solution for this. Any one having idea about this??
And I have one more question to ask that is, I am using ios5 new function which create new calendar in iphone's calendar application. Whenever I creates calendar of type local, I am able to create it. But I cant see that calendar in calendar list. Because of some reason it gets hide. Any idea about this??
Thank you in advance
First add MessageUI framework in your poject and import these two in your file
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
Then make a button to refer mail in xid and link it with a IBAction (like below):
-(IBAction)emailSettings:(id)sender{
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
if (mailClass != nil)
{
// check whether the current device is configured for sending emails
if ([mailClass canSendMail])
{
[self displayComposerSheet];
}
else
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"EMAIL" message:#"No Settings For Email" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
}
}
-(void)displayComposerSheet
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"StampedeBreakfast!"];
// Set up recipients
NSArray *toRecipients = [NSArray arrayWithObject:#"first#example.com"];
NSArray *ccRecipients = [NSArray arrayWithObjects:#"second#example.com", nil];
NSArray *bccRecipients = [NSArray arrayWithObject:#"third#example.com"];
[picker setToRecipients:toRecipients];
[picker setCcRecipients:ccRecipients];
[picker setBccRecipients:bccRecipients];
// Fill out the email body text
NSString *emailBody = [NSString stringWithFormat:#"Hey! This is my Email Body"];
[picker setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:picker animated:YES];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
switch (result)
{
case MFMailComposeResultCancelled:
NSLog( #"Result: canceled");
break;
case MFMailComposeResultSaved:
NSLog(#"Result: saved");
break;
case MFMailComposeResultSent:
NSLog(#"Result: sent");
break;
case MFMailComposeResultFailed:
NSLog( #"Result: failed");
break;
default:
NSLog(#"Result: not sent");
break;
}
[self dismissModalViewControllerAnimated:YES];
}
hope this will help you!!

MFMailComposeViewController navigation bar buttons are disabled

I use MFMailComposeViewController to send mail in my app. But when present mail compose view controller, all of navigation buttons are disabled (except back button in select mail address screen), i must use Home button to quit app. Does anyone has idea?
Here is screen shot:
Code:
- (void)shareVieEmail
{
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
[mailViewController setSubject:#"Test subject"];
[mailViewController setMessageBody:#"Mail message body" isHTML:NO];
NSData *imageData = [NSData dataWithContentsOfFile:photourl];
[mailViewController addAttachmentData:imageData mimeType:#"image/jpg" fileName:#"example_photo"];
[self presentModalViewController:mailViewController animated:YES];
} else {
[[[UIAlertView alloc] initWithTitle:#"Cannot send mail" message:#"Device is unable to send email in its current state" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil] show];
}
}
Delegate method :
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
switch (result)
{
case MFMailComposeResultCancelled:
//NSLog(#"Result: canceled");
break;
case MFMailComposeResultSaved:
//NSLog(#"Result: saved");
break;
case MFMailComposeResultSent:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Result" message:#"Mail Sent Successfully" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
break;
case MFMailComposeResultFailed:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Result" message:#"Mail Sent Failed" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
break;
default:
//NSLog(#"Result: not sent");
break;
}
if (error) {
[[[UIAlertView alloc] initWithTitle:#"Cannot send mail" message:[NSString stringWithFormat:#"ERROR:%#", [error userInfo]] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil] show];
}
[self dismissModalViewControllerAnimated:YES];
}
And in header file, I declared implement MFMailComposeViewControllerDelegate.
I had exactly the same problem. and it took me a while to figure this out but no surprise it came down to customized UIBarButtonItem
I bet in your UIBarButtonItem.h there is a method
-(void)setEnabled:(BOOL)enabled ;
and the implementation looks like this:
-(void)setEnabled:(BOOL)enabled {
if (self.customView) {
if ([[self.customView.subviews objectAtIndex:0] isKindOfClass:[UIButton class]]) {
((UIButton*)[self.customView.subviews objectAtIndex:0]).enabled = enabled;
}
}
}
and this is causing problem so as soon as you comment out this method your problem should go away.
I also had this problem, but it my case it was because I had overridden setNavigationBarHidden:animated: from UINavigationController as proposed in this workaround for a bug in CNContactViewController. One solution that would still include the workaround and solve the problem in MFMailComposeViewController would be to use method swizzling to be able to call either the original method or the overridden one, depending on the class of the current topViewController.
In your MFMailComposeViewController's delegate you need to implement didFinishWithResult: and dismiss the modal view controller from there.
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
// you can test the result of the mail sending here if you want
[self dismissModalViewControllerAnimated:YES];
}
For swift 4.0+
func mailComposeController(controller: MFMailComposeViewController,
didFinishWithResult result: MFMailComposeResult, error: NSError?) {
// Check the result or perform other tasks.
// Dismiss the mail compose view controller.
controller.dismissViewControllerAnimated(true, completion: nil)
}

Trouble opening the MFMailComposeViewController on the device, works in simulator.

I am doing this its working in simulator but when we try to open in device then program is terminating.
Plz suggess me fast.
MFMailComposeViewController *mail=[[MFMailComposeViewController alloc]init];
mail.mailComposeDelegate=self;
[mail setToRecipients:[NSArray arrayWithObjects:#"marketing#realestateinvestar.com.au",nil]];
//[self becomeFirstResponder];
mail.navigationBar.tintColor=[UIColor blackColor];
[self presentModalViewController:mail animated:YES];
if ([MFMessageComposeViewController canSendText])
Your problem is here. You are trying to check whether device will be able to send Text messages and not email Message. you should try using
if([MFMailComposeViewController canSendMail])
The problem might be that your device is not configured to any accounts in the mail.Please check this once.
Have you implement MFMailComposeViewControllerdelegate methods in your code??
#pragma mark --------------------------------------------
#pragma mark MFMailComposeViewController delegate Methods
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
switch (result) {
case MFMailComposeResultCancelled:
NSLog(#"Mail send canceled.");
/*
Execute your code for canceled event here ...
*/
break;
case MFMailComposeResultSaved:
NSLog(#"Mail saved.");
/*
Execute your code for email saved event here ...
*/
break;
case MFMailComposeResultSent: {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Mail Sent" message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
alert.tag = 1;
alert.delegate = self;
[alert show];
[alert release];
break;
}
case MFMailComposeResultFailed: {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Mail Sending Failed" message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
alert.tag = 2;
alert.delegate = self;
[alert show];
[alert release];
break;
}
default:
break;
}
[controller dismissModalViewControllerAnimated:YES];//dismissing modal view controller
}
Your code looks ok, but did you check if the device can send mail:
if ([MFMailComposeViewController canSendText]) {
MFMailComposeViewController *mail=[[MFMailComposeViewController alloc]init];
mail.mailComposeDelegate=self;
[mail setToRecipients:[NSArray arrayWithObjects:#"marketing#realestateinvestar.com.au",nil]];
mail.navigationBar.tintColor=[UIColor blackColor];
[self presentModalViewController:mail animated:YES];
[mail release], mail = nil;
} else {
// show message to the use that he can't send an email.
}

MFMailComposeViewController hangs my app

I am trying to add email functionality to my app. I can get the MFMailComposeViewController to display correctly and pre-populate its subject and body, but for some reason when the user clicks on the "Cancel" or "Send" buttons in the nav bar the app just hangs. I inserted a NSLog() statement into the first line of mailComposeController"didFinishWithResult:error and it doesn't even print that line out to the console.
Does anybody have an idea what would cause the MFMailComposeViewController to hang like that?
Here is my code from the header:
#import "ManagedObjectEditor.h"
#import <MessageUI/MessageUI.h>
#interface MyManagedObjectEditor : ManagedObjectEditor
<MFMailComposeViewControllerDelegate, UIImagePickerControllerDelegate,
UINavigationControllerDelegate> {
}
- (IBAction)emailObject;
#end
from the implementation file:
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init];
mailComposer.delegate = self;
[mailComposer setSubject:NSLocalizedString(#"An email from me",
#"An email from me")];
[mailComposer setMessageBody:emailString
isHTML:YES];
[self presentModalViewController:mailComposer animated:YES];
[mailComposer release];
}
[error release];
[emailString release];
and here is the code from the callback:
#pragma mark -
#pragma mark Mail Compose Delegate Methods
- (void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError *)error {
NSLog(#"in didFinishWithResult:");
switch (result) {
case MFMailComposeResultCancelled:
NSLog(#"cancelled");
break;
case MFMailComposeResultSaved:
NSLog(#"saved");
break;
case MFMailComposeResultSent:
NSLog(#"sent");
break;
case MFMailComposeResultFailed: {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Error sending email!",#"Error sending email!")
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:NSLocalizedString(#"Bummer",#"Bummer")
otherButtonTitles:nil];
[alert show];
[alert release];
break;
}
default:
break;
}
[self dismissModalViewControllerAnimated:YES];
}
Thanks!
I got bit by this too, you need to set the mailComposeDelegate, not the delegate.