Swift'den posta uygulaması nasıl açılır


119

Kullanıcının bir e-posta adresi girdiği ve adres çubuğuna girilen adresle posta uygulamasını açan bir düğmeye bastığı basit bir hızlı uygulama üzerinde çalışıyorum. Bunu Objective-C'de nasıl yapacağımı biliyorum, ancak Swift'de çalıştırmakta güçlük çekiyorum.

Yanıtlar:


241

Posta uygulamasını açmak için iOS'ta basit mailto: bağlantılarını kullanabilirsiniz.

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
Belki de bunun simülatörde çalışmadığını eklemeye değer, sadece cihazda ... Bkz. Stackoverflow.com/questions/26052815/…
Pieter

4
şimdi eklemeniz gerekiyor "!" ikinci satırda, NSURL NSURL için (dize: "mailto: (email)")!
anthonyqz

4
yanıt açıkça 3 yaşında olduğunda neden bunun yalnızca ios 10 veya daha yeni sürümlerde geçerli olduğunu söylüyor
pete

1
Swift 4 / iOS 10+ örneği: UIApplication.shared.open (url, options: [:], completeHandler: nil) Seçenekler için boş bir sözlüğü geçirmek, openURL'nin yaptığı çağrı ile aynı sonucu verir.
Luca Ventura

Teşekkürler ... Çok yardımcı oluyor :) :)
Anjali jariwala

62

Diğer cevapların hepsi doğru olsa da, uygulamanızı çalıştıran iPhone / iPad'de Apple'ın Mail uygulamasının yüklü olup olmadığını asla bilemezsiniz , çünkü kullanıcı tarafından silinebilir.

Birden çok e-posta istemcisini desteklemek daha iyidir. Aşağıdaki kod, e-posta gönderimini daha zarif bir şekilde ele alır. Kodun akışı:

  • Mail uygulaması yüklüyse, sağlanan verilerle önceden doldurulmuş Mail'in oluşturucusunu açın
  • Aksi takdirde, bu sırayla Gmail uygulamasını, ardından Outlook, ardından Yahoo mail ve ardından Spark'ı açmayı deneyin.
  • Bu istemcilerden hiçbiri yüklü değilse mailto:.., kullanıcının Apple'ın Mail uygulamasını yüklemesini isteyen varsayılana geri dönün .

Kod Swift 5'te yazılmıştır :

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

Lütfen, ayrıştıramadığı için Outlook uygulamasının gövdesini kasıtlı olarak gözden kaçırdığımı unutmayın.

Ayrıca Info.plist, kullanılan URl sorgu şemalarını beyaz listeye alan dosyaya aşağıdaki kodu da eklemeniz gerekir .

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

4
Aferin. Bu en eksiksiz cevaptır ve diğer e-posta istemcisi uygulamaları için kolayca genişletilebilir. IMHO, diğer çözümlerin çoğunun önerdiği gibi, varsayılan Apple Mail uygulamasını kullanmazlarsa, 2019'un sonlarında kişiye sadece "üzgünüm, şansın yok" demenin kabul edilebilir olduğunu sanmıyorum. Bu, bu eksikliği giderir.
wildcat12

Bu yöntem HTML ile çalışıyor mu? Düzgün görüntülenmesini sağlayamıyorum.
Matthew Bradshaw

@MatthewBradshaw isHTML, yukarıdaki kodu true olarak ayarlayarak varsayılan posta oluşturucu için HTML'yi destekleyebilirsiniz . Diğer istemciler için bu mümkün görünmüyor, daha fazla okumak için stackoverflow.com/questions/5620324/mailto-link-with-html-body
WebMajstr

1
Teşekkürler, bu harika. Kullanıcının tercih ettiği istemciyi seçmesine izin vermek için biraz değiştirdim (onları canOpenUrl ile önceden filtreliyorum). Microsoft Outlook için Btw gövdesi iyi çalışıyor :-)
Filip,

Bu harika! Bunu SwiftUI için yapan oldu mu?
Averett

55

Posta uygulamasına geçmek mi yoksa sadece bir e-posta açıp göndermek mi istediğinizden emin değilim. Bir IBAction düğmesiyle bağlantılı ikinci seçenek için:

    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
MailComposeController temsilci işlevi çağrılmadığında sorunlar yaşıyorum.
AustinT

3
İçe aktarmalarınıza "Import MessageUI" ekleyin ve "MFMailComposeViewControllerDelegate" seçeneğini aşağıdaki gibi sınıf bildiriminize eklediğinizden emin olun: class myClass: UIViewController, MFMailComposeViewControllerDelegate {
Jalakoo

MFMailComposeViewController () benim için sıfır döndür
ilan

2
Ayrıca sorunlarınız: 'NSInvalidArgumentException', reason: 'Application tried to present a nil modal view controller on target. Uygulama bazı cihazlarda (iPhone 5, iPhone 6 ve iPad Mini)
çöküyor

23

Swift 3'te protokol eklediğinizden import MessageUIve buna uymanız gerektiğinden emin olursunuz 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
  }
}

Protokol:

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

17

Swift 4.2+ ve iOS 9+ için

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'u istediğiniz e-posta adresiyle değiştirin.


16

Swift 2, uygunluk kontrolü ile:

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

Swift 4 için şöyle görünüyor:

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

Stephen Groom'dan Swift 3 için güncellenmiş yanıt

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

10

E-posta istemcisini bir aracılığıyla açmak istiyorsanız işte Swift 4 için bir güncelleme URL:

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

Bu benim için mükemmel çalıştı :)


9

Bu, Swift'de 3 adımdan oluşan basit bir çözümdür.

import MessageUI

Temsilciye uymak için ekleyin

MFMailComposeViewControllerDelegate

Ve sadece yönteminizi oluşturun:

    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

Yerleşik posta oluşturucuyla göndermeyi denemelisiniz ve bu başarısız olursa, paylaşmayı deneyin:

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

hata: "Bu uygulamanın şema mailto için sorgulama yapmasına izin verilmiyor"
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)
}

Tüm kullanıcıların cihazlarının e-posta göndermek için yapılandırılmadığını unutmayın, bu nedenle göndermeyi denemeden önce canSendMail () sonucunu kontrol etmemiz gerekir. Posta penceresini kapatmak için didFinishWith geri aramasını yakalamanız gerektiğini de unutmayın.


1

Posta uygulamanızın dokunarak açılmasını istediğiniz yerden görünüm denetleyicisinde.

  • Dosyanın en üstünde, MessageUI'yi içe aktarın .
  • Bu işlevi Denetleyicinize yerleştirin.

    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)
     }
  • Görünüm Denetleyicinizi genişletin ve MFMailComposeViewControllerDelegate'e uyun .

  • Bu yöntemi koyun ve e-postalarınızı göndererek başarısızlığı giderin.

    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

Swift 2.3'te hala geride kalan bizler için sözdizimimizde Gordon'un cevabı:

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

0

Swift 4.2 ve üstü için

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

Kullanıcıya e-posta göndermek için birçok posta seçeneği (iCloud, google, yahoo, Outlook.com gibi - telefonunda önceden yapılandırılmış posta yoksa) seçmesini sağlayın.


1
Benim durumumda, iOS 13 ile, UIApplication.shared.open çağrılırken, işletim sistemi her zaman Mail.app yüklemeyi öneren bir iletişim kutusu gösterecektir (oh, "mailto" için canOpenURL de her zaman doğrudur), başkaları olsa bile posta uygulamaları. Yani bu kesinlikle yürümüyor.
NeverwinterMoon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.