5
votes

I'm having some hard time trying to send an email from my app. I tried this code from iCodeBlog (http://icodeblog.com/2009/11/18/iphone-coding-tutorial-in-application-emailing/)

-(void)sendEmail:(id)sender
{
    MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init];
    mail.mailComposeDelegate = self;
    if ([MFMailComposeViewController canSendMail]) {
            //Setting up the Subject, recipients, and message body.
        [mail setToRecipients:[NSArray arrayWithObjects:@"[email protected]",nil]];
        [mail setSubject:@"Subject of Email"];
        [mail setMessageBody:@"Message of email" isHTML:NO];
            //Present the mail view controller
        [self presentModalViewController:mail animated:YES];
    }
        //release the mail
    [mail release];
}
    //This is one of the delegate methods that handles success or failure
    //and dismisses the mail
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
    [self dismissModalViewControllerAnimated:YES];
    if (result == MFMailComposeResultFailed) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Message Failed!" message:@"Your email has failed to send" delegate:self cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
}

It says it send the email and no error occurs but I never get the email in my inbox. I tried sending them to different email accounts and tried sending them from different accounts as well, no error occurs but I never get the email. Any ideas?

If it's important, I get this message on the Debugger Console when I start typing the To: email

DA|Could not open the lock file at /tmp/DAAccountsLoading.lock. We'll load the accounts anyway, but bad things may happen

===== EDIT ======

I just realized that all those emails were sent to my Outbox on Mail.app. Aren't they sent automatically when I click send? If not, then what can I do to make them be sent when the user presses the Send button on MFMailComposeView? Or perhaps call the Mail.app and make those emails be sent.

4

4 Answers

6
votes

Use this code this will definitely work:

    -(IBAction)send{

        [self callMailComposer];
    }

    -(void)callMailComposer{

        Class mailClass = (NSClassFromString(@"MFMailComposeViewController"));
        if (mailClass != nil)
        {
        // We must always check whether the current device is configured for sending emails
            if ([mailClass canSendMail])
                [self displayComposerSheet];
            else
                [self launchMailAppOnDevice];
        }

        else
        {
            [self launchMailAppOnDevice];
        }
    }


    #pragma mark -
    #pragma mark Compose Mail
    #pragma mark 

    // Displays an email composition interface inside the application. Populates all the Mail fields. 
    -(void)displayComposerSheet{

        MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];


        picker.mailComposeDelegate = self;
        NSString *tosubject =@"";
        [picker setSubject:tosubject];


        // Set up recipients
        [picker setCcRecipients:nil];   
        [picker setBccRecipients:nil];

        [picker setToRecipients:nil];



        [picker setMessageBody:strNewsLink isHTML:NO];

        [self presentModalViewController:picker animated:YES];

        if(picker) [picker release];
        if(picker) picker=nil;

    }


    // 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
{    
  NSString* alertMessage;
  // message.hidden = NO;
  // Notifies users about errors associated with the interface
  switch (result)
  {
    case MFMailComposeResultCancelled:
      alertMessage = @"Email composition cancelled";
      break;
    case MFMailComposeResultSaved:
      alertMessage = @"Your e-mail has been saved successfully";

      break;
    case MFMailComposeResultSent:
      alertMessage = @"Your email has been sent successfully";

      break;
    case MFMailComposeResultFailed:
      alertMessage = @"Failed to send email";

      break;
    default:
      alertMessage = @"Email Not Sent";

      break;
  }

  UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"My app name" 
                                                      message:alertMessage
                                                     delegate:nil
                                            cancelButtonTitle:@"OK"
                                            otherButtonTitles:nil];
  [alertView show];
  [self dismissModalViewControllerAnimated:YES];
}


    #pragma mark 
    #pragma mark Workaround
    #pragma mark
    // Launches the Mail application on the device.

        -(void)launchMailAppOnDevice{

        NSString *recipients = @"mailto:?cc=&subject=";
        NSString *body = @"&body=";
        NSString *email = [NSString stringWithFormat:@"%@%@", recipients, body];
        email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];

    }
1
votes

digging up an old thread here... maybe I can save future frustrations when dealing with MFMAilComposerViewController that does not send emails.

my app would send emails on 4 of my 5 test devices and I could not understand what the difference was on the 5th. The problem was an incorrectly setup Gmail account. The MFMailComposerViewController error trap method never returned any errors, it just did not send the email. The problem was an incorrect email address or email password. I discovered this by asking the device user for his email logon info and then an error alert appeared when I tried to logon to his Gmail account. The assumption, yes, my bad, was that canSendMail would check for a valid email account...

0
votes

Btw i hope you are testing this functionality in device as if you try to run this code in Simulator,it will show e-mail sent successfully,but the e-mail is never sent.

Thanks

0
votes

Swift 4 version

    let myController:MFMailComposeViewController = MFMailComposeViewController()
    if MFMailComposeViewController.canSendMail() {
        myController.mailComposeDelegate = self
        myController.setToRecipients(["[email protected]"])
        self.present(myController, animated: true, completion: nil)
    }