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.

Jesse.H
quelle

Antworten:

240

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

let email = "[email protected]"
if let url = URL(string: "mailto:\(email)") {
  if #available(iOS 10.0, *) {
    UIApplication.shared.open(url)
  } else {
    UIApplication.shared.openURL(url)
  }    
}
Stephen Groom
quelle
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 = "[email protected]"
            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>
WebMajstr
quelle
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 = ["[email protected]"]
    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)
    }

    }
Steve Rosenberg
quelle
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(["[email protected]"])
    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)
}
Ved Rauniyar
quelle
16

Swift 2, mit Verfügbarkeitsprüfung :

import MessageUI

if MFMailComposeViewController.canSendMail() {
    let mail = MFMailComposeViewController()
    mail.mailComposeDelegate = self
    mail.setToRecipients(["[email protected]"])
    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)
}
Ixx
quelle
16

Für Swift 4.2+ und iOS 9+

let appURL = URL(string: "mailto:[email protected]")!

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

Ersetzen Sie [email protected] durch Ihre gewünschte E-Mail-Adresse.

Mehdico
quelle
15

So sieht es für Swift 4 aus:

import MessageUI

if MFMailComposeViewController.canSendMail() {
    let mail = MFMailComposeViewController()
    mail.mailComposeDelegate = self
    mail.setToRecipients(["[email protected]"])
    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)
    }
Yuval
quelle
12

Aktualisierte Antwort von Stephen Groom für Swift 3

let email = "[email protected]"
let url = URL(string: "mailto:\(email)")
UIApplication.shared.openURL(url!)
Ben W.
quelle
10

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

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

Das hat bei mir ganz gut geklappt :)

Nii Mantse
quelle
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(["[email protected]"])
        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)
}
Maria Ortega
quelle
4

Sie sollten versuchen, mit dem integrierten Mail-Composer zu senden. Wenn dies fehlschlägt, versuchen Sie es mit share:

func contactUs() {

    let email = "[email protected]" // 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)
            }
        }
    }
}
lenooh
quelle
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 = ["[email protected]"]
   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.

Nishal Solanki
quelle
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(["[email protected]"]) // 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)
    }
Shiv Prakash
quelle
0

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

let email = "[email protected]"
if let url = NSURL(string: "mailto:\(email)") {
   UIApplication.sharedApplication().openURL(url)
}
Paul Lehn
quelle
0

Für Swift 4.2 und höher

let supportEmail = "[email protected]"
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.

iHarshil
quelle
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