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.