How To Send E-mail In App

YongJunCha·2022년 1월 5일
0
post-thumbnail

Why We Use This?

  • 생각보다 앱에서 이메일을 보내야 하는 일이 있을 수 있다.
  • 우선 이 기능을 사용하려면 iPhone 네이티브 앱에 자신의 메일을 연동해놔야 한다.
  • 하지만 iOS유저의 경우 메일을 연동 해놓는 사람들이 그렇게 까지 많지 않아서
  • 진짜 어쩔 수 없는 상황이 아니라면 메일은 서버사이드에서 해결하는 것이 좋지 않을까 생각한다.

Reference

Import

import MessageUI

MessageUI를 먼저 임포트를 해준다.

Protocol

class MailViewController : UIViewController, MFMailComposeViewControllerDelegate

우선은 상기의 코드에서 볼 수 있듯 메일 기능에 대한 콜백을 받기위해 MFMailComposeViewControllerDelegate을 준수해준다.

Code

if !MFMailComposeViewController.canSendMail() {
    print("Mail services are not available")
    return
}

상기의 코드는 이 디바이스가 메일이 연동이 되어있는지 안 되어있는지 판단해주는 펑션이다.
네이티브 메일 앱에 연동이 안 되어있으면 이 앱은 사용할 수 없는데 바로 여기서 필터링 해주는 것이다.

let composeVC = MFMailComposeViewController()
composeVC.mailComposeDelegate = self
 
// Configure the fields of the interface.
composeVC.setToRecipients(["address@example.com"])
composeVC.setSubject("Hello!")
composeVC.setMessageBody("Hello from California!", isHTML: false)
 
// Present the view controller modally.
self.present(composeVC, animated: true, completion: nil)

연동이 되어있는 곳에 메일의 내용을 작성해준다.
받는 사람의 경우 배열로 되어있어서 여러명에게 메일을 작성할 수 있고,
제목과 메세지 내용을 작성할 수 있다.

그렇다면 파일 첨부도 가능할까 생각할 수 있다.

let attachmentData = try Data(contentsOf: fileURL)
                mailComposer.addAttachmentData(attachmentData, mimeType: "txt", fileName: "Youtube_Keyword_data")

데이터의 URL을 지정해준뒤 상기의 코드를 작성해주면 쉽게 첨부할 수 있다.
그렇다면 이제는 메세지 기능의 콜백은 어디서 받는 방법이다.

Apple docs : MFMailComposeViewControllerDelegate
Apple docs : mailComposeController(_:didFinishWith:error:)
Apple docs : MFMailComposeResult enum
상기의 문서 세개를 조합해보면
어떻게 선언을 해야하는지, 결과로는 어떤 enum 타입이 떨어지는지 자세히 나와있다.

func mailComposeController(controller: MFMailComposeViewController,
                           didFinishWithResult result: MFMailComposeResult, error: NSError?) {
    // Check the result or perform other tasks.
    
    // Dismiss the mail compose view controller.
    controller.dismiss(animated: true, completion: nil)
}

코드는 상기와 같다.
이제 여기서 해줄 일은 result 타입별로 실행시켜줄 일을 나누는 것 뿐이다.
switch 코드만 넣어주면 된다.

    //MARK:- MailcomposerDelegate
    
    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        switch result {
        case .cancelled:
            print("User cancelled")
            break

        case .saved:
            print("Mail is saved by user")
            break

        case .sent:
            print("Mail is sent successfully")
            break

        case .failed:
            print("Sending mail is failed")
            break
        default:
            break
        }

        controller.dismiss(animated: true)

    }

상기의 delegate function에서 메일 기능의 콜백을 받을 수 있다.
전체적인 완성코드는 하기에 첨부하겠다.

//
//  emailViewController.swift
//  FileManagerRealmBackUpTest
//
//  Created by Yong Jun Cha on 2021/12/07.
//

import Foundation
import MessageUI
import UIKit
import Combine

class EmailViewController : UIViewController, MFMailComposeViewControllerDelegate {
    
    var cancellables: [AnyCancellable] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    @IBAction func sendKeywordDataByUsingEmail(_ sender: Any) {
        if MFMailComposeViewController.canSendMail() {
            let mailComposer = MFMailComposeViewController()
            mailComposer.setSubject("경기도 알림톡 유튜브 검색어 백업자료")
            mailComposer.setMessageBody("\(Date())까지의 경기도 알림톡 유튜브 검색자료 백업데이터 입니다. ", isHTML: false)
            mailComposer.setToRecipients(["yongjun.cha@snplab.io"])
            let fileManager = FileManager()
            let documentURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
            let fileURL = documentURL.appendingPathComponent("Youtube_Keyword_data.txt")
            print("URL :: \(documentURL.description)")
            
            
            
            do {
                let attachmentData = try Data(contentsOf: fileURL)
                mailComposer.addAttachmentData(attachmentData, mimeType: "txt", fileName: "Youtube_Keyword_data")
                mailComposer.mailComposeDelegate = self
                self.present(mailComposer, animated: true
                             , completion: nil)
            } catch let error {
                print("We have encountered error \(error.localizedDescription)")
            }
            
        } else {
            print("Email is not configured in settings app or we are not able to send an email")
        }
    }
    
    
    
    //MARK:- MailcomposerDelegate
    
    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        switch result {
        case .cancelled:
            print("User cancelled")
            break

        case .saved:
            print("Mail is saved by user")
            break

        case .sent:
            print("Mail is sent successfully")
            break

        case .failed:
            print("Sending mail is failed")
            break
        default:
            break
        }

        controller.dismiss(animated: true)

    }
}

Review

  • Protocol & Delegate Pattern을 이해하고나니 공식 문서를 보는 것이 훨씬 간편해졌다.
  • 다만 SwiftUI에 적용할 때는 ViewContorller를 사용해야하는 경우도 적지 않고
  • 그렇게 할 때 따로 Injector를 이용해서 넣어줘야하기 때문에 SwiftUI식으로 넣는 방법도
  • CodeLab해봐야겠다는 생각을 했다.

0개의 댓글