So öffnen Sie die Mail-App von Swift aus


118

Ich arbeite an einer einfachen schnellen App, in der der Benutzer eine E-Mail-Adresse eingibt und eine Taste drückt, die die E-Mail-App mit der eingegebenen Adresse in der Adressleiste öffnet. Ich weiß, wie man das in Objective-C macht, aber ich habe Probleme, es in Swift zum Laufen zu bringen.

Antworten:


240

Sie können einfache mailto: -Links in iOS verwenden, um die Mail-App zu öffnen.

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)
  }    
}

77
Vielleicht lohnt es sich hinzuzufügen, dass dies nicht im Simulator funktioniert, sondern nur auf dem Gerät ... Siehe stackoverflow.com/questions/26052815/…
Pieter

4
Jetzt müssen Sie "!" in der zweiten Zeile für die NSURL NSURL (Zeichenfolge: "mailto: (email)")!
Anthonyqz

4
Warum heißt es, dass dies nur auf iOS 10 oder neuer verfügbar ist, wenn die Antwort eindeutig 3 Jahre alt ist
Pete

1
Beispiel für Swift 4 / iOS 10+: UIApplication.shared.open (URL, Optionen: [:], Vervollständigungshandler: Null) Das Übergeben eines leeren Wörterbuchs für Optionen führt zum gleichen Ergebnis wie das Aufrufen von openURL.
Luca Ventura

Danke ... Es hilft sehr :) :)
Anjali jariwala

57

Während andere Antworten alle richtig sind, können Sie nie wissen, ob auf dem iPhone / iPad, auf dem Ihre Anwendung ausgeführt wird, die Mail-App von Apple installiert ist oder nicht, da sie vom Benutzer gelöscht werden kann.

Es ist besser, mehrere E-Mail-Clients zu unterstützen. Der folgende Code behandelt das Senden von E-Mails auf elegantere Weise. Der Ablauf des Codes ist:

  • Wenn die Mail-App installiert ist, öffnen Sie den Mail-Composer, der mit den bereitgestellten Daten gefüllt ist
  • Versuchen Sie andernfalls, die Google Mail-App, dann Outlook, dann Yahoo Mail und dann Spark in dieser Reihenfolge zu öffnen
  • Wenn keiner dieser Clients installiert ist, wird auf den Standard zurückgegriffen mailto:.., der den Benutzer auffordert, die Mail-App von Apple zu installieren.

Code ist in Swift 5 geschrieben :

    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: .urlHostAllowed)!
            let bodyEncoded = body.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!

            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)
        }
    }

Bitte beachten Sie, dass ich den Textkörper für die Outlook-App absichtlich verpasst habe, da er nicht analysiert werden kann.

Sie müssen der Info.plistDatei außerdem folgenden Code hinzufügen , der die verwendeten URl-Abfrageschemata auf die Whitelist setzt.

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

4
Gut gemacht. Dies ist die vollständigste Antwort und kann problemlos für andere E-Mail-Client-Apps erweitert werden. IMHO, ich denke nicht, dass es Ende 2019 akzeptabel ist, der Person nur "Entschuldigung, Sie haben kein Glück" zu sagen, wenn sie nicht die Standard-Apple Mail-App verwendet, wie die meisten anderen Lösungen vorschlagen. Dies behebt diesen Mangel.
wildcat12

Funktioniert diese Methode mit HTML? Ich kann es nicht richtig anzeigen lassen.
Matthew Bradshaw

@MatthewBradshaw Sie können HTML für den Standard-Mail-Composer unterstützen, indem Sie isHTMLden obigen Code auf true setzen. Für andere Clients scheint dies nicht möglich zu sein. Weitere Informationen finden
WebMajstr

1
Danke, das ist großartig. Ich habe es leicht modifiziert, damit der Benutzer den Client seiner Wahl auswählen kann (ich filtere sie im Voraus mit canOpenUrl). Übrigens funktioniert der Text für Microsoft Outlook einwandfrei :-)
Filip

Das ist brilliant! Hat jemand dies für SwiftUI getan?
Averett

55

Ich bin mir nicht sicher, ob Sie zur Mail-App selbst wechseln oder einfach eine E-Mail öffnen und senden möchten. Für die letztere Option, die mit einer Schaltfläche IBAction verknüpft ist:

    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)
    }

    }

1
Ich habe Probleme, bei denen die Delegierungsfunktion mailComposeController nicht aufgerufen wird.
AustinT

3
Fügen Sie "import MessageUI" zu Ihren Importen hinzu und stellen Sie sicher, dass Sie die Option "MFMailComposeViewControllerDelegate" zu Ihrer Klassendeklaration hinzufügen, wie: class myClass: UIViewController, MFMailComposeViewControllerDelegate {
Jalakoo

MFMailComposeViewController () gibt null für mich zurück
ilan

2
Auch mit Problemen : 'NSInvalidArgumentException', reason: 'Application tried to present a nil modal view controller on target. App stürzt in einigen Geräten (iPhone 5, iPhone 6 und iPad Mini) ab
Spacemonkey

23

In Swift 3 stellen Sie sicher, dass import MessageUIdas MFMailComposeViewControllerDelegateProtokoll hinzugefügt wird und dass es dem Protokoll entspricht.

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
  }
}

Protokoll:

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

16

Swift 2, mit Verfügbarkeitsprüfung :

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)
}

16

Für Swift 4.2+ und 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)
}

Ersetzen Sie TEST@EXAMPLE.COM durch Ihre gewünschte E-Mail-Adresse.


15

So sieht es für Swift 4 aus:

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)
    }

12

Aktualisierte Antwort von Stephen Groom für Swift 3

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

10

Hier ist ein Update für Swift 4, wenn Sie den Mail-Client einfach über Folgendes öffnen möchten URL:

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

Das hat bei mir ganz gut geklappt :)


9

Dies ist eine einfache Lösung von 3 Schritten in Swift.

import MessageUI

Hinzufügen, um den Delegaten anzupassen

MFMailComposeViewControllerDelegate

Und erstellen Sie einfach Ihre Methode:

    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)
}

4

Sie sollten versuchen, mit dem integrierten Mail-Composer zu senden. Wenn dies fehlschlägt, versuchen Sie es mit 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)
            }
        }
    }
}

Fehler: "Diese App darf nicht nach Schema mailto abfragen"
Khushal iOS

3
@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)
}

Beachten Sie, dass nicht alle Benutzer ihr Gerät für das Senden von E-Mails konfiguriert haben. Aus diesem Grund müssen wir das Ergebnis von canSendMail () überprüfen, bevor wir versuchen, E-Mails zu senden. Beachten Sie auch, dass Sie den Rückruf von didFinishWith abfangen müssen, um das E-Mail-Fenster zu schließen.


1

In der Ansichtssteuerung, von der aus Ihre E-Mail-App geöffnet werden soll.

  • Importieren Sie oben in der Datei MessageUI .
  • Fügen Sie diese Funktion in Ihren Controller ein.

    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)
     }
  • Erweitern Sie Ihren View Controller und passen Sie sich dem MFMailComposeViewControllerDelegate an .

  • Setzen Sie diese Methode ein und behandeln Sie den Fehler, indem Sie Ihre Mails senden.

    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)
    }

0

Für diejenigen von uns, die bei Swift 2.3 immer noch zurückbleiben, ist hier Gordons Antwort in unserer Syntax:

let email = "foo@bar.com"
if let url = NSURL(string: "mailto:\(email)") {
   UIApplication.sharedApplication().openURL(url)
}

0

Für Swift 4.2 und höher

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

Geben Sie dem Benutzer die Möglichkeit, viele E-Mail-Optionen (wie iCloud, Google, Yahoo, Outlook.com - wenn auf seinem Telefon keine E-Mail vorkonfiguriert ist) auszuwählen, um E-Mails zu senden.


1
In meinem Fall zeigte das Betriebssystem unter iOS 13 beim Aufrufen von UIApplication.shared.open immer ein Dialogfeld an, in dem Mail.app installiert werden kann (oh, und canOpenURL für "mailto" ist auch immer wahr), selbst wenn es andere gibt Mail-Apps. Das klappt also definitiv nicht.
NeverwinterMoon
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.