How to open mail app from Swift

前端 未结 15 1347
被撕碎了的回忆
被撕碎了的回忆 2020-11-30 20:18

Im working on a simple swift app where the user inputs an email address and presses a button which opens the mail app, with the entered address in the address bar. I know ho

15条回答
  •  天涯浪人
    2020-11-30 20:39

    While other answers are all correct, you can never know if the iPhone/iPad that is running your application has the Apple's Mail app installed or not as it can be deleted by the user.

    It is better to support multiple email clients. Following code handles the email sending in a more graceful way. The flow of the code is:

    • If Mail app is installed, open Mail's composer pre-filled with provided data
    • Otherwise, try opening the Gmail app, then Outlook, then Yahoo mail, then Spark, in this order
    • If none of those clients are installed, fallback to default mailto:.. that prompts the user to install Apple's Mail app.

    Code is written in Swift 5:

        import MessageUI
        import UIKit
    
        class SendEmailViewController: UIViewController, MFMailComposeViewControllerDelegate {
            
            @IBAction func sendEmail(_ sender: UIButton) {
                // Modify following variables with your text / recipient
                let recipientEmail = "test@email.com"
                let subject = "Multi client email support"
                let body = "This code supports sending email via multiple different email apps on iOS! :)"
                
                // Show default mail composer
                if MFMailComposeViewController.canSendMail() {
                    let mail = MFMailComposeViewController()
                    mail.mailComposeDelegate = self
                    mail.setToRecipients([recipientEmail])
                    mail.setSubject(subject)
                    mail.setMessageBody(body, isHTML: false)
                    
                    present(mail, animated: true)
                
                // Show third party email composer if default Mail app is not present
                } else if let emailUrl = createEmailUrl(to: recipientEmail, subject: subject, body: body) {
                    UIApplication.shared.open(emailUrl)
                }
            }
            
            private func createEmailUrl(to: String, subject: String, body: String) -> URL? {
                let subjectEncoded = subject.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
                let bodyEncoded = body.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
                
                let gmailUrl = URL(string: "googlegmail://co?to=\(to)&subject=\(subjectEncoded)&body=\(bodyEncoded)")
                let outlookUrl = URL(string: "ms-outlook://compose?to=\(to)&subject=\(subjectEncoded)")
                let yahooMail = URL(string: "ymail://mail/compose?to=\(to)&subject=\(subjectEncoded)&body=\(bodyEncoded)")
                let sparkUrl = URL(string: "readdle-spark://compose?recipient=\(to)&subject=\(subjectEncoded)&body=\(bodyEncoded)")
                let defaultUrl = URL(string: "mailto:\(to)?subject=\(subjectEncoded)&body=\(bodyEncoded)")
                
                if let gmailUrl = gmailUrl, UIApplication.shared.canOpenURL(gmailUrl) {
                    return gmailUrl
                } else if let outlookUrl = outlookUrl, UIApplication.shared.canOpenURL(outlookUrl) {
                    return outlookUrl
                } else if let yahooMail = yahooMail, UIApplication.shared.canOpenURL(yahooMail) {
                    return yahooMail
                } else if let sparkUrl = sparkUrl, UIApplication.shared.canOpenURL(sparkUrl) {
                    return sparkUrl
                }
                
                return defaultUrl
            }
            
            func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
                controller.dismiss(animated: true)
            }
        }
    

    Please note that I intentionally missed out the body for the Outlook app, as it is not able to parse it.

    You also have to add following code to Info.plist file that whitelists the URl query schemes that are used.

    LSApplicationQueriesSchemes
    
        googlegmail
        ms-outlook
        readdle-spark
        ymail
    
    

提交回复
热议问题