Swift에서 메일 앱을 여는 방법


119

사용자가 이메일 주소를 입력하고 주소 표시 줄에 입력 된 주소로 메일 앱을 여는 버튼을 누르는 간단한 빠른 앱을 개발 중입니다. Objective-C에서이 작업을 수행하는 방법을 알고 있지만 Swift에서 작동하는 데 문제가 있습니다.

답변:


240

간단한 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)
  }    
}

77
시뮬레이터에서만 작동하지 않고 장치에서만 작동한다는 점을 추가 할 가치가있을 것입니다 ... 참조 stackoverflow.com/questions/26052815/…
Pieter

4
이제 "!"를 추가해야합니다. 두 번째 줄에서 NSURL NSURL (string : "mailto : (email)")!
anthonyqz

4
대답이 분명히 3 년이되었을 때 iOS 10 이상에서만 사용할 수 있다고 말하는 이유
pete

1
Swift 4 / iOS 10+ 예제 : UIApplication.shared.open (url, options : [:], completeHandler : nil) 옵션에 대해 빈 사전을 전달하면 openURL 호출과 동일한 결과가 생성됩니다.
Luca Ventura

감사합니다 ... 그것은 많은 도움이 :)
안 잘리 jariwala

62

다른 답변은 모두 정확하지만 응용 프로그램을 실행하는 iPhone / iPad에 Apple의 Mail 앱이 설치되어 있는지 여부는 사용자가 삭제할 수 있으므로 알 수 없습니다.

여러 이메일 클라이언트를 지원하는 것이 좋습니다. 다음 코드는보다 우아한 방식으로 이메일 전송을 처리합니다. 코드의 흐름은 다음과 같습니다.

  • 메일 앱이 설치된 경우 제공된 데이터로 미리 채워진 메일 작성기를 엽니 다.
  • 그렇지 않으면 Gmail 앱, Outlook, Yahoo 메일, Spark를 순서대로 열어보십시오.
  • 이러한 클라이언트가 설치되어 있지 않으면 mailto:..사용자에게 Apple의 메일 앱을 설치하라는 메시지를 표시하는 기본값으로 대체합니다 .

코드는 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)
        }
    }

Outlook 앱의 본문은 구문 분석 할 수 없기 때문에 의도적으로 누락되었습니다.

또한 Info.plist사용되는 URl 쿼리 체계를 허용 목록 에 추가하는 다음 코드를 파일 에 추가해야합니다 .

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

4
잘 했어. 이것은 가장 완전한 답변이며 다른 이메일 클라이언트 앱으로 쉽게 확장 할 수 있습니다. IMHO, 대부분의 다른 솔루션이 제안하는 것처럼 기본 Apple Mail 앱을 사용하지 않으면 "죄송합니다. 운이 좋지 않습니다."라고 말하는 것이 2019 년 말에 허용되지 않는다고 생각합니다. 이것은 그 결핍을 해결합니다.
wildcat12

이 방법은 HTML에서 작동합니까? 제대로 표시 할 수 없습니다.
Matthew Bradshaw

@MatthewBradshaw isHTML는 위의 코드를 true 로 설정하여 기본 메일 작성기에 HTML을 지원할 수 있습니다 . 다른 클라이언트의 경우 가능하지 않은 것 같습니다. 자세한 내용은 stackoverflow.com/questions/5620324/mailto-link-with-html-body
WebMajstr

1
감사합니다. 사용자가 선호하는 클라이언트를 선택할 수 있도록 약간 수정했습니다 (canOpenUrl로 미리 필터링하고 있음). Microsoft Outlook의 Btw 본문이 잘 작동합니다. :-)
Filip

이것은 훌륭합니다! 누구든지 SwiftUI를 위해 이것을 했습니까?
Averett

55

메일 앱 자체로 전환 할 것인지 아니면 그냥 열어서 이메일을 보낼 것인지 잘 모르겠습니다. 버튼 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
mailComposeController 대리자 함수가 호출되지 않는 문제가 있습니다.
AustinT 2015 년

3
가져 오기에 "import MessageUI"를 추가하고 다음과 같이 클래스 선언에 "MFMailComposeViewControllerDelegate"옵션을 추가해야합니다. class myClass: UIViewController, MFMailComposeViewControllerDelegate {
Jalakoo

MFMailComposeViewController ()는 나를 위해 nil을 반환합니다
ilan

2
또한 문제가 있음 : 'NSInvalidArgumentException', reason: 'Application tried to present a nil modal view controller on target. 일부 장치 (iPhone 5, iPhone 6 및 iPad Mini)에서 앱 충돌
Spacemonkey 2015

23

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

17

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을 원하는 이메일 주소로 바꿉니다.


16

가용성 확인 기능이있는 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)
}

15

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

Swift 3에 대한 Stephen Groom의 답변 업데이트

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

10

다음은 단순히 URL다음을 통해 메일 클라이언트를 열려는 경우 Swift 4에 대한 업데이트입니다 .

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

이것은 나를 위해 완벽하게 잘 작동했습니다. :)


9

이것은 Swift에서 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)
}

4

기본 제공 메일 작성기로 전송을 시도해야하며 실패하면 공유로 시도하십시오.

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

오류 : "이 앱은 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)
}

모든 사용자가 전자 메일을 보내도록 장치를 구성한 것은 아니므로 보내기 전에 canSendMail ()의 결과를 확인해야합니다. 또한 메일 창을 닫으려면 didFinishWith 콜백을 잡아야합니다.


1

탭에서 메일 앱을 열려는 뷰 컨트롤러에서.

  • 파일 맨 위에서 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)
     }
  • 뷰 컨트롤러를 확장하고 MFMailComposeViewControllerDelegate를 준수하십시오 .

  • 이 방법을 넣고 실패를 처리하고 메일을 보냅니다.

    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에서 여전히 뒤처지는 사람들을 위해 구문에서 Gordon의 대답이 있습니다.

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

0

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, google, yahoo, Outlook.com-전화에 미리 구성된 메일이없는 경우)을 선택하도록합니다.


1
필자의 경우 iOS 13에서 UIApplication.shared.open을 호출 할 때 OS는 항상 Mail.app 설치를 제안하는 대화 상자를 표시합니다 (오, "mailto"에 대한 canOpenURL도 항상 true입니다). 메일 앱. 그래서 이것은 확실히 효과가 없습니다.
NeverwinterMoon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.