I am using the MessageUI framework to send an email but I never receive that email when sent.
I am importing #import <MessageUI/MessageUI.h>
and then I have the following code
- (void)emailFile
{
if(![MFMailComposeViewController canSendMail]) {
UIAlertView *cantSend = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Device not configured to send email" delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[cantSend show];
[cantSend release];
} else {
MFMailComposeViewController *mailView = [[[MFMailComposeViewController alloc] init] autorelease];
mailView.mailComposeDelegate = self;
[mailView setToRecipients:[NSArray arrayWithObject:#"matthew.inman#cdl.co.uk"]];
[mailView setSubject:#"Test"];
[mailView setMessageBody:#"This is a text message" isHTML:NO];
[self presentModalViewController:mailView animated:YES];
}
}
and
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
if(error) {
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Mail Error" message:[error localizedDescription] delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[errorView show];
[errorView release];
} else {
switch (result) {
case MFMailComposeResultSent:
NSLog(#"Sent Mail");
break;
case MFMailComposeResultSaved:
NSLog(#"Mail Saved");
break;
case MFMailComposeResultCancelled:
NSLog(#"Mail Cancelled");
break;
case MFMailComposeResultFailed:
NSLog(#"Mail Failed");
break;
default:
break;
}
}
[controller dismissModalViewControllerAnimated:YES];
}
I get the message "Sent Mail" in the console but I like I said I never receive the email that I am sending.
I have gone through the apple documentation and can't find anything that helps can anyone else help me please. I'm I doing something wrong?
Make sure you are testing on a device, email will not be sent via the simulator.
Related
In my email composer I would like for the result of 'cancelbuttonclicked' to close the MFMailComposerViewController. Can I implement within the switch statement or do those need to be separate methods. Also, I would like for the send button to send the message before dismissing.
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
switch (result) {
case MFMailComposeResultSent:{
UIAlertView *messageSent = [[UIAlertView alloc] initWithTitle:#"Message Sent" message:#"Your message has been sent" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[messageSent show];
break;
}
case MFMailComposeResultSaved:{
UIAlertView *messageComposeResultSaved = [[UIAlertView alloc] initWithTitle:#"Message Saved" message:#"Your message has been saved" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[messageComposeResultSaved show];
break;
}
case MFMailComposeResultCancelled:{
UIAlertView *messageComposeResultCancelled = [[UIAlertView alloc] initWithTitle:#"Message Cancelled" message:#"Your message has been cancelled" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[messageComposeResultCancelled show];
break;}
case MFMailComposeResultFailed:{
UIAlertView *messageFailed = [[UIAlertView alloc]initWithTitle:#"Message Failed" message:#"Your message could not be sent" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[messageFailed show];
break;
}
}
}
Your code should work fine. There are no limitations on using UIAlertView inside a switch. However, to make it a bit less messy, I'd suggest rewriting it like this:
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
NSString *alertTitle = nil;
NSString *alertMessage = nil;
switch (result) {
case MFMailComposeResultSent:{
alertTitle = #"Message Sent";
alertMessage = #"Your message has been sent";
break;
}
case MFMailComposeResultSaved:{
alertTitle = #"Message Saved";
alertMessage = #"Your message has been saved";
break;
}
case MFMailComposeResultCancelled:{
alertTitle = #"Message Cancelled";
alertMessage = #"Your message has been cancelled";
break;}
case MFMailComposeResultFailed:{
alertTitle = #"Message Failed";
alertMessage = #"Your message could not be sent";
break;
}
}
[[[UIAlertView alloc] initWithTitle:alertTitle
message:alertMessage
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
}
It lets you avoid multiple initWithTitle....
But there is another concern: UIAlertView is deprecated is iOS 8. You should use UIAlertController instead. This answer has an example of UIAlertController usage.
I am using ObjectiveC and I want to send an email to a list of email addresses that I have in a sqlite database. The email array hold the addresses that I want to send the mail to.
I show you my code
- (void)sendEmailButtonClicked: (id)sender {
// Email Subject
NSString *emailTitle = #"Test Email";
// Email Content
NSString *messageBody = #"iOS programming is so fun!";
// To address
NSArray *toRecipents = [NSArray arrayWithObject:emailArray];
NSLog(#"What are the emais %#",toRecipents);
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setToRecipients:toRecipents];
[mc setMessageBody:messageBody isHTML:NO];
// Present mail view controller on screen
[self presentViewController:mc animated:YES completion:NULL];
}
- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
switch (result)
{
case MFMailComposeResultCancelled:
NSLog(#"Mail cancelled");
break;
case MFMailComposeResultSaved:
NSLog(#"Mail saved");
break;
case MFMailComposeResultSent:
NSLog(#"Mail sent");
break;
case MFMailComposeResultFailed:
NSLog(#"Mail sent failure: %#", [error localizedDescription]);
break;
default:
break;
}
// Close the Mail Interface
[self dismissViewControllerAnimated:YES completion:NULL];
}
I obtain this error: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM mf_isLegalCommentedEmailAddress]: unrecognized selector sent to instance 0x78e5e180'
Anyone can help me please? Thank you so much!
First of all it should be:
NSArray *toRecipents = [NSArray arrayWithArray:emailArray];
But why not just do:
[mc setToRecipients:emailArray];
Assuming email array is a valid array object as we can't see from your code where/how you create it.
EDIT
You likely can't send an email from the simulator if there isn't an email account setup. Check for this with the following:
if ([MFMailComposeViewController canSendMail]) {
//Do your email stuff
}
else {
//Present an error etc ...
}
There's an issue with your array. This code works fine when sending to multiple recipients:
//Email
-(void)mailButton {
NSArray *emailArray = #[#"me#gmail.com", #"you#gmail.com", #"him#gmail.com", #"her#gmail.com", #"everyone#gmail.com"];
if ([MFMailComposeViewController canSendMail]) {
NSString *subject = #"Subject";
NSString *messageBody = [NSString stringWithFormat:#"Message Body"];
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:subject];
[mc setMessageBody:messageBody isHTML:NO];
[mc setToRecipients:emailArray];
[self presentViewController:mc animated:YES completion:NULL];
}
else {
UIAlertView *emailError = [[UIAlertView alloc] initWithTitle:#"Email Unavailable"
message:#"Sorry, were unable to find an email account on your device.\nPlease setup an account in your devices settings and try again."
delegate:self
cancelButtonTitle:#"Close"
otherButtonTitles:nil];
[emailError show];
}
}
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
switch (result) {
case MFMailComposeResultCancelled:
break;
case MFMailComposeResultSaved:
break;
case MFMailComposeResultSent:
break;
case MFMailComposeResultFailed:
break;
default:
break;
}
[self dismissViewControllerAnimated:YES completion:NULL];
}
toRecipents should be an array, which contains only one email address.
As below,
toRecipents = #[#"foo#example.com"];
If, you want to send email some people, you should use setCcRecipients method.
After sending SMS from my phone(it's working properly) in my project using the MFMessageComposeViewController I can't get back to the app or press cancel. Instead I'm stuck in Apple SMS interface and I can't do anything else then to restart the app. Do I miss something in didFinishWithResult or could it be something else? Thanks
- (IBAction)sendSMS:(id)sender {
MFMessageComposeViewController *controller =
[[[MFMessageComposeViewController alloc] init] autorelease];
if([MFMessageComposeViewController canSendText])
{
NSString *str= #"Hi";
controller.body = str;
controller.recipients = [NSArray arrayWithObjects:
#"", nil];
controller.delegate = self;
[self dismissViewControllerAnimated:YES
completion:nil];
[self presentViewController:controller animated:YES completion:nil];
}
}
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult) result
{
switch (result) {
case MessageComposeResultCancelled:
break;
case MessageComposeResultFailed:
{
UIAlertView *warningAlert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Failed to send SMS!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[warningAlert show];
break;
}
case MessageComposeResultSent:
break;
default:
break;
}
[self dismissViewControllerAnimated:YES completion:nil];
}
Here is my .m code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *emailCell = [tableView cellForRowAtIndexPath:indexPath];
if ([emailCell.textLabel.text isEqualToString:#"Contact Developer"]) {
NSLog(#"Email button pressed...");
if([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:#"A Message from MobileTuts+"];
NSArray *toRecipients = [NSArray arrayWithObjects:#"fisrtMail#example.com", #"secondMail#example.com", nil];
[mailer setToRecipients:toRecipients];
NSString *emailBody = #"Have you seen the MobileTuts+ web site?";
[mailer setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:mailer animated:YES];
[mailer release];
- (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];
}
}
else {
UIAlertView *emailAlert = [[UIAlertView alloc] initWithTitle:#"Error!"
message:#"Please make sure you have an email address configured in your Mail app."
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[emailAlert show];
[emailAlert release];
}
}
}
I have imported everything correctly in .h and .m, but the email won't close... I have tried as suggested on Stack Overflow to fiddle with the mailer.mailComposeDelegate = self; but I am still getting an undeclared identifier error. How do I fix this? Thanks.
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
Move this function out of the tableview delegate method. You should learn some basics. You cannot have a method within another method. If you need then you can call the method by [self callingFunctionName];
In you case,
if ([emailCell.textLabel.text isEqualToString:#"Contact Developer"]) {
NSLog(#"Email button pressed...");
[self sendEmail];
}
-(void)sendEmail{
if([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:#"A Message from MobileTuts+"];
NSArray *toRecipients = [NSArray arrayWithObjects:#"fisrtMail#example.com", #"secondMail#example.com", nil];
[mailer setToRecipients:toRecipients];
NSString *emailBody = #"Have you seen the MobileTuts+ web site?";
[mailer setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:mailer animated:YES];
[mailer release];
}
}
This will open the mail composer. When you send, cancel or save the mail, the delegate function
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
will automatically be called.
I'm implementMFMailComposeViewController in my demp app. However, for some reasons, my app crashes after I touch to add texts in the email text field. But sending WITHOUT adding any text works fine.
My Xcode is not showing too much. Here is what I'm getting:
I'm setting an initial text already in the email text field. Maybe the issue is here? request any code and I'll be happy to include it.
UPDATE:
Here 2 methods where the first method openMail fires up when touching the UIButton
- (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];
}
if ([MFMailComposeViewController canSendMail])
{
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:#"Feedback from Demo App user"];
NSArray *toRecipients = [NSArray arrayWithObjects:#"myEMAIL#hotmail.com", #"myEMAIL2#gmail.com", nil];
[mailer setToRecipients:toRecipients];
NSString *emailBody = #"Happy to hear your feedback!";
[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];
}
}
- (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];
}
Probably you're using ARC, and you're not have strong pointer to your MFMailComposeViewControllerand after display, ARC is releasing it.
use
#property (nonatomic,stron) MFMailComposeViewController *mail;
and when you're initialize MFMailComposeViewController:
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
self.mail = mailer;
Do you still have this line in your code:
[mailer release];
If so that is the problem. If not, then PLEASE update our code sample so its exactly what you are using now.