如何从 Swift 打开邮件应用程序

我工作在一个简单的快速应用程序,其中用户输入一个电子邮件地址,并按下一个按钮,打开邮件应用程序,与输入的地址在地址栏。我知道在 Objective-C 怎么做但是在斯威夫特就不行了。

145564 次浏览

我不知道你是想切换到邮件应用程序本身或只是打开和发送电子邮件。对于链接到按钮 IBAction 的后一个选项:

    import UIKit
import MessageUI


class ViewController: UIViewController, MFMailComposeViewControllerDelegate {


@IBAction func launchEmail(sender: AnyObject) {


var emailTitle = "Feedback"
var messageBody = "Feature request or bug report?"
var toRecipents = ["friend@stackoverflow.com"]
var mc: MFMailComposeViewController = MFMailComposeViewController()
mc.mailComposeDelegate = self
mc.setSubject(emailTitle)
mc.setMessageBody(messageBody, isHTML: false)
mc.setToRecipients(toRecipents)


self.presentViewController(mc, animated: true, completion: nil)
}


func mailComposeController(controller:MFMailComposeViewController, didFinishWithResult result:MFMailComposeResult, error:NSError) {
switch result {
case MFMailComposeResultCancelled:
print("Mail cancelled")
case MFMailComposeResultSaved:
print("Mail saved")
case MFMailComposeResultSent:
print("Mail sent")
case MFMailComposeResultFailed:
print("Mail sent failure: \(error?.localizedDescription)")
default:
break
}
self.dismissViewControllerAnimated(true, completion: nil)
}


}

您可以使用简单的 mailto: 链接在 iOS 中打开邮件应用程序。

let email = "foo@bar.com"
if let url = URL(string: "mailto:\(email)") {
if #available(iOS 10.0, *) {
UIApplication.shared.open(url)
} else {
UIApplication.shared.openURL(url)
}
}

Swift 2,带 可用性检查:

import MessageUI


if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(["test@test.test"])
mail.setSubject("Bla")
mail.setMessageBody("<b>Blabla</b>", isHTML: true)
presentViewController(mail, animated: true, completion: nil)
} else {
print("Cannot send mail")
// give feedback to the user
}




// MARK: - MFMailComposeViewControllerDelegate


func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
switch result.rawValue {
case MFMailComposeResultCancelled.rawValue:
print("Cancelled")
case MFMailComposeResultSaved.rawValue:
print("Saved")
case MFMailComposeResultSent.rawValue:
print("Sent")
case MFMailComposeResultFailed.rawValue:
print("Error: \(error?.localizedDescription)")
default:
break
}
controller.dismissViewControllerAnimated(true, completion: nil)
}

这是一个直接的解决方案的3个步骤在迅捷。

import MessageUI

添加以符合委托

MFMailComposeViewControllerDelegate

然后创建你的方法:

    func sendEmail() {
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(["support@mail.com"])
mail.setSubject("Support App")
mail.setMessageBody("<p>Send us your issue!</p>", isHTML: true)
presentViewController(mail, animated: true, completion: nil)
} else {
// show failure alert
}
}


func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
controller.dismissViewControllerAnimated(true, completion: nil)
}

斯蒂芬 · 格鲁姆为斯威夫特3更新的答案

let email = "email@email.com"
let url = URL(string: "mailto:\(email)")
UIApplication.shared.openURL(url!)

在 Swift 3中,确保添加 import MessageUI并且需要遵守 MFMailComposeViewControllerDelegate协议。

func sendEmail() {
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(["ved.ios@yopmail.com"])
mail.setMessageBody("<p>You're so awesome!</p>", isHTML: true)


present(mail, animated: true)
} else {
// show failure alert
}
}

议定书:

func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true)
}

对于那些仍然落后于 Swift 2.3的人,以下是 Gordon 在我们的语法中给出的答案:

let email = "foo@bar.com"
if let url = NSURL(string: "mailto:\(email)") {
UIApplication.sharedApplication().openURL(url)
}
@IBAction func launchEmail(sender: AnyObject) {
if if MFMailComposeViewController.canSendMail() {
var emailTitle = "Feedback"
var messageBody = "Feature request or bug report?"
var toRecipents = ["friend@stackoverflow.com"]
var mc: MFMailComposeViewController = MFMailComposeViewController()
mc.mailComposeDelegate = self
mc.setSubject(emailTitle)
mc.setMessageBody(messageBody, isHTML: false)
mc.setToRecipients(toRecipents)


self.present(mc, animated: true, completion: nil)
} else {
// show failure alert
}
}


func mailComposeController(controller:MFMailComposeViewController, didFinishWithResult result:MFMailComposeResult, error:NSError) {
switch result {
case .cancelled:
print("Mail cancelled")
case .saved:
print("Mail saved")
case .sent:
print("Mail sent")
case .failed:
print("Mail sent failure: \(error?.localizedDescription)")
default:
break
}
self.dismiss(animated: true, completion: nil)
}

请注意,并非所有用户都将其设备配置为发送电子邮件,这就是为什么我们需要在尝试发送之前检查 canSendMail ()的结果。还需要注意的是,您需要捕获 did FinishWith 回调以便解除邮件窗口。

以下是 Swift 4的外观:

import MessageUI


if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(["test@test.test"])
mail.setSubject("Bla")
mail.setMessageBody("<b>Blabla</b>", isHTML: true)
present(mail, animated: true, completion: nil)
} else {
print("Cannot send mail")
// give feedback to the user
}


func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
switch result.rawValue {
case MFMailComposeResult.cancelled.rawValue:
print("Cancelled")
case MFMailComposeResult.saved.rawValue:
print("Saved")
case MFMailComposeResult.sent.rawValue:
print("Sent")
case MFMailComposeResult.failed.rawValue:
print("Error: \(String(describing: error?.localizedDescription))")
default:
break
}
controller.dismiss(animated: true, completion: nil)
}

如果你只是想通过 URL打开邮件客户端,这里有一个 Swift 4的更新:

let email = "foo@bar.com"
if let url = URL(string: "mailto:\(email)") {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}

这对我来说完全没问题:)

适用于 Swift 4.2 + 和 iOS 9 +

let appURL = URL(string: "mailto:test@example.com")!


if #available(iOS 10.0, *) {
UIApplication.shared.open(appURL, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(appURL)
}

将 test@example.com 替换为您想要的电子邮件地址。

还可以在 To、 Cc 和 Bcc 字段中包含 主题字段、 信息多个收件人:

mailto:foo@example.com?cc=bar@example.com&subject=Greetings%20from%20Cupertino!&body=Wish%20you%20were%20here!

您应该尝试使用内置邮件编写器发送邮件,如果失败,请尝试使用 share:

func contactUs() {


let email = "info@example.com" // insert your email here
let subject = "your subject goes here"
let bodyText = "your body text goes here"


// https://developer.apple.com/documentation/messageui/mfmailcomposeviewcontroller
if MFMailComposeViewController.canSendMail() {


let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self as? MFMailComposeViewControllerDelegate


mailComposerVC.setToRecipients([email])
mailComposerVC.setSubject(subject)
mailComposerVC.setMessageBody(bodyText, isHTML: false)


self.present(mailComposerVC, animated: true, completion: nil)


} else {
print("Device not configured to send emails, trying with share ...")


let coded = "mailto:\(email)?subject=\(subject)&body=\(bodyText)".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
if let emailURL = URL(string: coded!) {
if #available(iOS 10.0, *) {
if UIApplication.shared.canOpenURL(emailURL) {
UIApplication.shared.open(emailURL, options: [:], completionHandler: { (result) in
if !result {
print("Unable to send email.")
}
})
}
}
else {
UIApplication.shared.openURL(emailURL as URL)
}
}
}
}

而其他答案都是正确的,你永远不会知道运行你的应用程序的 iPhone/iPad 是否安装了苹果的邮件应用程序或不,因为它可以被用户删除。

最好支持多个电子邮件客户端。以下代码以更优雅的方式处理电子邮件发送。代码的流程是:

  • 如果安装了 Mail 应用程序,打开预先填充了所提供数据的 Mail 编写器
  • 否则,试着按这个顺序打开 Gmail 应用程序,然后是 Outlook,然后是雅虎邮箱,然后是 Spark
  • 如果这些客户端都没有安装,回退到默认 mailto:..,提示用户安装 Apple 的 Mail 应用程序。

代码是用 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)&body=\(bodyEncoded)")
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)
}
}

您还必须向 Info.plist文件添加以下代码,以列出所使用的 URL 查询方案。

<key>LSApplicationQueriesSchemes</key>
<array>
<string>googlegmail</string>
<string>ms-outlook</string>
<string>readdle-spark</string>
<string>ymail</string>
</array>

适用于 Swift 4.2及以上版本

let supportEmail = "abc@xyz.com"
if let emailURL = URL(string: "mailto:\(supportEmail)"), UIApplication.shared.canOpenURL(emailURL)
{
UIApplication.shared.open(emailURL, options: [:], completionHandler: nil)
}

让用户选择许多邮件选项(如 iCloud、谷歌、雅虎、 Outlook.com ——如果手机中没有预先配置邮件的话)来发送电子邮件。

在视图控制器中,您希望从哪里打开您的邮件应用程序的水龙头。

  • 在文件的顶部执行 导入 MessageUI
  • 将此函数放入控制器中。

    func showMailComposer(){
    
    
    guard MFMailComposeViewController.canSendMail() else {
    return
    }
    let composer = MFMailComposeViewController()
    composer.mailComposeDelegate = self
    composer.setToRecipients(["abc@gmail.com"]) // email id of the recipient
    composer.setSubject("testing!!!")
    composer.setMessageBody("this is a test mail.", isHTML: false)
    present(composer, animated: true, completion: nil)
    }
    
  • Extend your View Controller and conform to the MFMailComposeViewControllerDelegate.

  • Put this method and handle the failure, sending of your mails.

    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
    if let _ = error {
    controller.dismiss(animated: true, completion: nil)
    return
    }
    controller.dismiss(animated: true, completion: nil)
    }
    

在我的情况下,我只是试图打开邮件应用程序,而没有创建一个电子邮件草稿。

如果有人碰巧发现了这个问题,并且实际上正在尝试做同样的事情,这里我使用的代码是:

private var openMailAppButton: some View {
Button {
if let emailUrl = mailAppUrl() {
UIApplication.shared.open(emailUrl)
}
} label: {
Text("OPEN MAIL APP")
}
}


private func mailAppUrl() -> URL? {
let gmailUrl = URL(string: "googlegmail://")
let outlookUrl = URL(string: "ms-outlook://")
let yahooMail = URL(string: "ymail://")
let sparkUrl = URL(string: "readdle-spark://")
let defaultUrl = URL(string: "message://")
        

if let defaultUrl = defaultUrl, UIApplication.shared.canOpenURL(defaultUrl) {
return defaultUrl
} else 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
}

我创建了一个 Swift 软件包来处理这个问题,并且还实现了一个检查,如果他们有多个电子邮件客户端。

Https://github.com/joe-scotto/emaillink

Func mailComposController (_ controller: MFMailComposViewController, 结果: MFMailComposResult,Error: Swift. Error?){

    controller.dismiss(animated: true, completion: nil)
}