When will [MFMailComposeViewController canSendMail] return NO - iphone

My iPhone app is using the MFMailComposeViewController class to send an in-app email with an attachment.
The app will only attempt to display the mail composer dialog if the "canSendMail" method of class MFMailComposeViewController returns true (YES). Specifically, if the following method returns YES, it shows the mail composer, otherwise the user is presented with an error alert dialog stating that there are no email accounts set up on the device:
- (BOOL)canDeviceSendEmail
{
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
return mailClass != nil && [mailClass canSendMail];
}
A team of testers have reported that they get this error alert dialog, even when email accounts are set up on the device. The tester used an iPhone 3G with OS 3.1.3. Therefore the MFMailComposeViewController class must have existed, and the "canSendMail" method must have returned NO.
My question is therefore: apart from the case when there are no email accounts set up on the device, in what other circumstances can the "canSendMail" method return NO?
~ Thanks

If at least one email account is enabled on the device, the following call should return YES:
[MFMailComposeViewController canSendMail]
Conversely, if all accounts are disabled/removed, it will return NO.

For +canSendMail to return YES the default account must be set-up for sending emails.
(Internally, +[MFMailComposeViewController canSendMail] calls +[MailAccountProxy defaultMailAccountForDelivery], which finds the first mail account being -isDefaultDeliveryAccount.)

In addition to an email account not being setup on a device, canSendMail also returns NO when an MDM profile is installed and configured to not allow third party apps to send mail. In this case you must use openURL: with a mailto: URL in order to launch Mail.app and optionally fill in the to, cc, bcc, subject, and body field.
mailto: RFC
https://www.rfc-editor.org/rfc/rfc2368

This worked for me.
In Device Go setting->Mail,Contacts,Calendar->Accounts
Here you can see no account is added.Now add account now go back to your app and you can find its returning yes this time and you are able to send E-mail.
Thanks

[MFMailComposeViewController canSendMail] will return NO when you don't have any mail account on device. In this case you can open mail app by the following code:
- (void)openMailApp {
NSString *recipients = #"mailto:?cc=&subject=";
NSString *body = #"&body=";
NSString *email = [NSString stringWithFormat:#"%#%#", recipients, body];
email = [email stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];
}

In case of iOS 10.1, you can enable mail from iCloud first (in Settings). Then sign in to your iCloud account. All the contacts and email should be available in your simulator after those changes.
With the change, I can get true from:
MFMailComposeViewController.canSendMail()
I am using Xcode 8.1 with Swift 3.

Vladimir's answer without deprecated functions:
NSString *recipients = #"mailto:testingEmail#example.com?subject=emailsubject";
NSString *body = #"&body=body:";
NSString *email = [NSString stringWithFormat:#"%#%#", recipients, body];
email = [email stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email] options:#{} completionHandler:^(BOOL success) {
}];

You can't be certain that MFMailComposeViewController must have existed because your method doesn't discriminate between MFMailComposeViewController not existing and [MFMailComposeViewController canSendMail] returning NO.
What iPhone OS you're testing on is not relevant; what version of the iPhone SDK your application links against is what determines whether MFMailComposeViewController will be available at runtime. If you want that class, you need to build with SDK 3.0 or later.

Did you include the Messaging Framework? I had a similar issue once and it was only because I forgot to add the correct framework to the XCode project.

Related

how to open iMessage with some text message?

This is how I open iMessage in my ipad app
NSString *stringURL = #"sms:";
NSURL *url = [NSURL URLWithString:stringURL];
[[UIApplication sharedApplication] openURL:url];
But what I want is open iMessage with some message i have text filed and i want to send its test to i message the way we do in mail like
[mailViewController setMessageBody:textView.text isHTML:NO];
is there anything in iMessage by which I can open iMessage with test filed Message
thanks in advance
Very late response, but this was the first result I saw when trying to solve this problem and I wanted to provide my solution.
My reason for wishing to open the iMessage app and not use MFMessageComposeViewController was because MFMessageComposeViewController does not support iMessage apps. My goal was to prompt the user to open my iMessage app and the only way to do that is to open the iMessage app.
This can be done as follows (in Swift 2):
let phoneNumber = "9765432100"
let bodyText = "Hello World"
guard let messageURL = NSURL(string: "sms:\(phoneNumber)&body=\(bodyText)") else { return }
if UIApplication.sharedApplication().canOpenURL(messageURL) {
UIApplication.sharedApplication().openURL(messageURL)
}
Some things to keep in mind:
1) You must add sms: to LSApplicationQueriesSchemes in your Info.plist
2) You can not open group messages in this manner.
3) Phone numbers must be formatted as follows: 9765432100. No spaces or extra characters, just the number
You can not open iMessage with any URL. Messages.app will detect if the number has iMessage support and sent the message via iMessage.
When calling sms: URI you are just opening any app that will handle it, on a iPhone/iPad this will be the message app. The is the given number has an iMessage account the sms will be send via the iMessage network. If no account is found on the iPad you can not send the message.
if you wan the user to send an SMS message from within your app you should use MFMessageComposeViewController.
Like:
// Fist check if we can send messages
if ([MFMessageComposeViewController canSendText] {
MFMessageComposeViewController *composer = [MFMessageComposeViewController new];
composer.body = #"Your message goes here";
// Then present the composer in a UIPopoverController.
}

Open mail client of iPhone programmatically

In my application, if the user gave their gmail account then i am required to open the mail client with the gmail login credentials which comes when we select gmail option of mail programmatically but if that account is already stored in mail then i am required to redirect the user directly to their account. Can anybody pliz give me a glimpse of how i can achieve this programmatically.
You won't get that much control over the Mail app as all apps on the iPhone are sandboxed to prevent them from messing with Apple applications.
The only thing you can do (if you want to open the mail client to send an email), is something like this:
/* create mail subject */
NSString *subject = [NSString stringWithFormat:#"Subject"];
/* define email address */
NSString *mail = [NSString stringWithFormat:#"test#test.com"];
/* define allowed character set */
NSCharacterSet *set = [NSCharacterSet URLHostAllowedCharacterSet];
/* create the URL */
NSURL *url = [[NSURL alloc] initWithString:[NSString stringWithFormat:#"mailto:?to=%#&subject=%#",
[mail stringByAddingPercentEncodingWithAllowedCharacters:set],
[subject stringByAddingPercentEncodingWithAllowedCharacters:set]]];
/* load the URL */
[[UIApplication sharedApplication] openURL:url];
/* release the URL. If you are using ARC, remove this line. */
[url release];
Swift version of Léon Rodenburg's answer:
// define email address
let address = "test#test.com"
// create mail subject
let subject = "Subject"
// create the URL
let url = NSURL(string: "mailto:?to=\(address)&subject=\(subject)".stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!)
// load the URL
UIApplication.sharedApplication().openURL(url!)
Swift:
if let url = NSURL(string: "mailto://\(email)") {
UIApplication.sharedApplication().openURL(url)
}
I would suggest a much more improved answer.
The Slack.com mobile app does this, it detects common email clients listed on the device and shows a popup picker of 'which' email client you would like to open.
So to implement:
Google around to find the top 10 email clients (eg Mail, Google Inbox, OutLook, AirMail etc).
Get a list of installed apps on the phone either by searching all apps (but I am told you can now only find if an app is explicitly installed, so you will need detect the app).
Show a popup list if more than 1 email app is detected, requesting them 'which' app to open eg. Mail, Inbox.
This is the best solution I have seen working to date.

iPhone MFMailComposeViewController

I have to send an email in one of the application,i have implement MFMailComposeViewController and everything is working fine, mail can be send and received also.
However my main issue is that, is it possible to send mail without opening the Sheet of MFMailComposeViewController ?
Means in my application I have to pass on url into suject field and have to type the recepients name in textfield, so is it that we cannot open the sheet of messagecontroller window and send the mail from the uibarbutton integration?
plz let me know that
If you dont want to use MFMailComposer, you may use following code.You have to handle you textfield's mail id's through string manipulation and append it in mString before body.you may use UItextview for body.
NSString *mString = #"mailto:foo#example.com?cc=bar#example.com&subject=Greetings%20from%20Cupertino!&body=Wish%20you%20were%20here!";
NSString *url = [NSString stringWithString:mString];
[[UIApplication sharedApplication] openURL: [NSURL URLWithString: url]];
To prevent spam from using the user mailbox, application cannot send mail automatically. THe user will have to press "Send" themselves. This way, they know what e-mail is going out.
If you want your app to automatically send mail, you will have to setup your own SMTP client/server.

sending sms and email through program automatically

I have read that In App SMS is finally supported in iPhone OS 4...look at
here
I want to know that if it is also possible to send emails automatically without user's intraction if yes then how?.I mean while our application is running.
No, that's not possible with the official iPhone SDK.
You have to use MFMailComposeViewController or [[UIApplication sharedApplication] openURL: #"sms:12345678"]; or send a text.
Here is the code for Email
NSString *recipients=[NSString stringWithFormat:#"mailto:ABC#gmail.com?cc=bcd#gmail.com&subject=Hi"];
NSString *body=[NSString stringWithFormat:#"&body=How r u "];
NSString *email=[NSString stringWithFormat:#"%#%#",recipients,body];
email=[email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];

Sending an image in a faceless email

I am trying to send a faceless email (sending an email without showing the interface), using the code below.
I also want to attach an image to this email.
Is this possible?
- (void) sendEmailTo:(NSString *)toStr withSubject:(NSString *)subjectStr withBody:(NSString *)bodyStr
{
NSString *emailString=[[NSString alloc] initWithFormat:#"mailto:?to=%#&subject=%#&body=%#",
[toStr stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],
[subjectStr stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],
[bodyStr stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:emailString]];
[emailString release];
}
You are unable to send faceless emails using the built-in emailer.
However you should be able to roll your own emailer using parts from email frameworks like for instance Pantomime