Cara membuka aplikasi email dari Swift


119

Saya sedang mengerjakan aplikasi cepat sederhana di mana pengguna memasukkan alamat email dan menekan tombol yang membuka aplikasi email, dengan alamat yang dimasukkan di bilah alamat. Saya tahu cara melakukan ini di Objective-C, tapi saya kesulitan membuatnya berfungsi di Swift.

Jawaban:


240

Anda dapat menggunakan tautan mailto: sederhana di iOS untuk membuka aplikasi email.

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
Mungkin patut ditambahkan bahwa ini tidak berfungsi di simulator, hanya di perangkat ... Lihat stackoverflow.com/questions/26052815/…
Pieter

4
sekarang Anda perlu menambahkan "!" di baris kedua, untuk NSURL NSURL (string: "mailto: (email)")!
anthonyqz

4
mengapa dikatakan bahwa ini hanya tersedia di iOS 10 atau yang lebih baru ketika jawabannya jelas berusia 3 tahun
pete

1
Contoh Swift 4 / iOS 10+: UIApplication.shared.open (url, options: [:], completeHandler: nil) Meneruskan kamus kosong untuk pilihan menghasilkan hasil yang sama seperti memanggil openURL.
Luca Ventura

Terima kasih ... Ini sangat membantu :) :)
Anjali jariwala

62

Sementara jawaban lain semuanya benar, Anda tidak akan pernah tahu apakah iPhone / iPad yang menjalankan aplikasi Anda telah menginstal aplikasi Mail Apple atau tidak karena dapat dihapus oleh pengguna.

Lebih baik mendukung banyak klien email. Kode berikut menangani pengiriman email dengan cara yang lebih anggun. Alur kodenya adalah:

  • Jika aplikasi Mail diinstal, buka pembuat Mail yang telah diisi sebelumnya dengan data yang disediakan
  • Jika tidak, coba buka aplikasi Gmail, lalu Outlook, lalu Yahoo mail, lalu Spark, dalam urutan ini
  • Jika tidak ada dari klien tersebut yang diinstal, kembali ke default mailto:..yang meminta pengguna untuk menginstal aplikasi Mail Apple.

Kode ditulis di 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: .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)
        }
    }

Harap dicatat bahwa saya sengaja melewatkan isi untuk aplikasi Outlook, karena tidak dapat menguraikannya.

Anda juga harus menambahkan kode berikut ke Info.plistfile yang memasukkan skema kueri URl yang digunakan ke daftar putih.

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

4
Sudah selesai dilakukan dengan baik. Ini adalah jawaban terlengkap dan mudah dikembangkan untuk aplikasi klien email lainnya. IMHO, menurut saya, di akhir tahun 2019 tidak boleh hanya memberi tahu orang tersebut "maaf, Anda kurang beruntung" jika mereka tidak menggunakan aplikasi default Apple Mail, seperti yang disarankan oleh sebagian besar solusi lain. Ini memperbaiki kekurangan itu.
kucing liar12

Apakah metode ini berfungsi dengan HTML? Saya tidak bisa menampilkannya dengan benar.
Matthew Bradshaw

@MatthewBradshaw Anda dapat mendukung HTML untuk pembuat email default dengan menyetel isHTMLkode di atas ke true. Untuk klien lain, tampaknya tidak mungkin, untuk bacaan lebih lanjut lihat stackoverflow.com/questions/5620324/mailto-link-with-html-body
WebMajstr

1
Terima kasih, wajan ini bagus. Saya memodifikasinya sedikit agar pengguna memilih klien preferensi mereka (saya memfilternya terlebih dahulu dengan canOpenUrl). Btw body untuk Microsoft Outlook berfungsi dengan baik :-)
Filip

Ini luar biasa! Apakah ada yang melakukan ini untuk SwiftUI?
Averett

55

Saya tidak yakin apakah Anda ingin beralih ke aplikasi email itu sendiri atau hanya membuka dan mengirim email. Untuk opsi terakhir yang ditautkan ke tombol 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)
    }

    }

1
Saya mengalami masalah di mana fungsi delegasi mailComposeController tidak dipanggil.
AustinT

3
Tambahkan "impor MessageUI" ke impor Anda dan pastikan untuk menambahkan opsi "MFMailComposeViewControllerDelegate" ke deklarasi kelas Anda seperti: class myClass: UIViewController, MFMailComposeViewControllerDelegate {
Jalakoo

MFMailComposeViewController () mengembalikan nol untuk saya
ilan

2
Juga mengalami masalah: 'NSInvalidArgumentException', reason: 'Application tried to present a nil modal view controller on target. Aplikasi mogok di beberapa perangkat (iPhone 5, iPhone 6 dan iPad Mini)
Spacemonkey

23

Di Swift 3 Anda memastikan untuk menambah import MessageUIdan kebutuhan sesuai dengan MFMailComposeViewControllerDelegateprotokol.

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

Protokol:

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

17

Untuk Swift 4.2+ dan 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)
}

Ganti TEST@EXAMPLE.COM dengan alamat email yang Anda inginkan.


16

Swift 2, dengan pemeriksaan ketersediaan :

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

15

Berikut tampilannya untuk 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)
    }

12

Jawaban terbaru dari Stephen Groom untuk Swift 3

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

10

Berikut ini pembaruan untuk Swift 4 jika Anda hanya ingin membuka klien email melalui URL:

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

Ini bekerja dengan baik untuk saya :)


9

Ini adalah solusi langsung dari 3 langkah di Swift.

import MessageUI

Tambahkan untuk menyesuaikan Delegasi

MFMailComposeViewControllerDelegate

Dan buat saja metode Anda:

    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

Anda harus mencoba mengirim dengan pembuat email built-in, dan jika gagal, coba dengan 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)
            }
        }
    }
}

error: "Aplikasi ini tidak diizinkan untuk meminta skema mailto"
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)
}

Perhatikan bahwa tidak semua pengguna mengonfigurasi perangkatnya untuk mengirim email, itulah sebabnya kami perlu memeriksa hasil canSendMail () sebelum mencoba mengirim. Perhatikan juga bahwa Anda perlu menangkap callback didFinishWith untuk menutup jendela email.


1

Di pengontrol tampilan dari mana Anda ingin aplikasi email Anda terbuka di keran.

  • Di bagian atas file lakukan, impor MessageUI .
  • Letakkan fungsi ini di dalam Controller Anda.

    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)
     }
  • Perluas Pengontrol Tampilan Anda dan sesuaikan dengan MFMailComposeViewControllerDelegate .

  • Gunakan metode ini dan tangani kegagalan pengiriman email Anda.

    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

Bagi kita yang masih tertinggal di Swift 2.3 berikut adalah jawaban Gordon dalam sintaks kita:

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

0

Untuk Swift 4.2 dan yang lebih baru

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

Beri pengguna untuk memilih banyak opsi email (seperti iCloud, google, yahoo, Outlook.com - jika tidak ada email yang dikonfigurasi sebelumnya di teleponnya) untuk mengirim email.


1
Dalam kasus saya, dengan iOS 13, saat memanggil UIApplication.shared.open, OS akan selalu menampilkan dialog yang menawarkan untuk menginstal Mail.app (oh, dan canOpenURL untuk "mailto" juga selalu benar), bahkan jika ada yang lain aplikasi email. Jadi ini pasti tidak berhasil.
NeverwinterMoon
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.