Search code examples
iosswiftios14

Does changing the default email app affect MFMailComposeViewController usage?


iOS 14 users can change the default email app. What effect, if any, does this have on MFMailComposeViewController? More specifically, it would be ideal if MFMailComposeViewController "just worked" with whatever the default email client was, for example setting recipients, subject, body, etc.

If that isn't possible, I suppose opening a mailto URL will open whatever the default mail app is. Any way to test this before iOS 14 releases?


Solution

  • iOS 14 and its ability to set a default Mail app did not change anything in regards to MFMailComposeViewController API. It is only capable of displaying Mail's compose sheet, so canSendMail() will still return false when they're not using the Mail app.

    To better support users who choose to use a different email app, you could open a mailto URL. This will open the default email app and bring up their compose sheet. If no email app is installed, it will present a system alert asking the user if they want to restore Mail from the App Store (unless running in the Simulator). This API doc explains how you can create the URL, including how to specify a subject, body, and additional recipients.

    Note that this will leave your app to open the Mail app or other email app. If you'd like to keep users in your app when they're using Mail, you can continue to use MFMailComposeViewController and fall back to mailto when canSendMail() returns false.

    If you would like, you could additionally check if you can open the mailto: URL, and if not, present your own messaging to the user. Note this would require you add mailto to your LSApplicationQueriesSchemes in the Info.plist.

    I found this post to be helpful as well.

    if MFMailComposeViewController.canSendMail() {
        let mail = MFMailComposeViewController()
        mail.mailComposeDelegate = self
        mail.setToRecipients([email])
        mail.setSubject(subject)
        present(mail, animated: true, completion: nil)
    } else {
        if let mailURLString = "mailto:\(email)?subject=\(subject)".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
           let mailURL = URL(string: mailURLString) {
            if UIApplication.shared.canOpenURL(mailURL) { //check not needed, but if desired add mailto to LSApplicationQueriesSchemes in Info.plist
                view.window?.windowScene?.open(mailURL, options: nil, completionHandler: nil)
            } else {
                //maybe they like web apps? 🤷‍♂️ 
                //maybe let them copy the email address to the clipboard or something
            }
        }
    }