Sending Email with Image Attachments in Swift
Sending content from an iOS application to external sources like email is a common requirement. This quick post summarizes the steps to implement this feature. Aa an added twist, the project used for this technique post includes capturing an image from one of the app's UIViews.
Demonstration of iOS App Sending Email using Swift
Sending Email from within an app
The crux of the technique is using the iOS provided MFMailComposeViewController. This handy class has a perfectly descriptive name.
To use this component, make sure to include the following import at the top of the file where it's referenced:
import MessageUI
Once the namespace is imported, create and configure a Compose ViewController by setting the properties of the email.
@IBAction func sendEmailTapped(_ sender: UIButton) {
if let addr = emailAddress.text, !addr.isEmpty,
let jpegData = designView.asJpeg,
MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.setToRecipients(["\(addr)"])
mail.setSubject("Design attached")
mail.setMessageBody("Body goes here", isHTML: true)
mail.mailComposeDelegate = self
mail.addAttachmentData(jpegData,
mimeType: "image/jpeg",
fileName: "mydesign.jpeg")
present(mail, animated: true)
}
else {
print("Email cannot be sent")
}
}
Code Snippet that Sends an Email from Swift Code
Once the inputs for the email are set, call the present() function to call up the iOS mail sheet (you can see it in the demo after the "email" button is tapped in the app.
In this sample app, an attachment is included with the email. Almost any type of data can be attached--just make sure to set the correct MIME type for the Data, so the sending and receiving e-mail client applications will know how to present a preview to the user, and decide what actions can be taken with the attachment once it's received. In this demo, the attachment is a JPEG image file.
mail.addAttachmentData(jpegData,
mimeType: "image/jpeg",
fileName: "mydesign.jpeg")
A caveat to using the Compose ViewController is that the device must be able to send email. Typically this just means the user has configured at least one e-mail account, but make sure to trap the error and provide a useful error to a user. This example only uses the print() statement to send output to the debug log--but you should use an Alert() or other user-visible error report.
Note the delegate assignment in the above code snippet:
mail.mailComposeDelegate = self
Implement the MFMailComposeViewControllerDelegate to get feedback from iOS whether the email send operation succeeded or not. This delegate method is a good place to provide feedback to the user.
Errors are provided in an error implementing the Error protocol, so be helpful to users and provide them feedback and a way to recover.
extension ViewController:
MFMailComposeViewControllerDelegate {
func mailComposeController(_ controller:
MFMailComposeViewController,
didFinishWith result: MFMailComposeResult,
error: Error?) {
if let _ = error {
self.dismiss(animated: true, completion: nil)
}
switch result {
case .cancelled:
print("Cancelled")
break
case .sent:
print("Mail sent successfully")
break
case .failed:
print("Sending mail failed")
break
default:
break
}
controller.dismiss(animated: true, completion: nil)
}
}
Code Snippet of MFMailComposeViewControllerDelegate
extension ViewController: MFMailComposeViewControllerDelegate {
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
if let _ = error {
self.dismiss(animated: true, completion: nil)
}
switch result {
case .cancelled:
print("Cancelled")
break
case .sent:
print("Mail sent successfully")
break
case .failed:
print("Sending mail failed")
break
default:
break
}
controller.dismiss(animated: true, completion: nil)
}
}
Related Posts
The demo video above actually illustrates two other techniques, covered in related posts:
Related Post: Drawing with Core Graphics using Swift
Related Post: Capture a UIView as a a JPEG image using Swift
Full Project Source Code
The source for this project is available in my GitHub repository: