iOS端使用Swift调用Outlook发送带附件邮件的实现方法
实现说明
你当前使用的ms-outlook://compose URL Scheme仅支持to、cc、bcc、subject、body 5个基础查询参数,微软未开放该Scheme的附件传递能力,无法通过拼接URL的方式直接添加附件。
目前唯一稳定合规的实现方式是通过iOS系统级UIActivityViewController分享面板调起Outlook,系统会自动将附件、邮件基础信息传递给Outlook完成预填充。
具体实现步骤(Swift)
- 前置配置:在项目Info.plist中添加Outlook URL Scheme白名单,否则无法检测Outlook安装状态
- 将待发送附件写入App本地临时目录,获取可被系统读取的文件URL
- 自定义
UIActivityItemSource对象封装收件人、主题、正文等基础邮件信息 - 初始化
UIActivityViewController,将邮件信息对象、附件文件URL作为分享项传入 - 过滤不需要的分享渠道,适配iPad端弹出样式后调起面板
核心代码示例
Info.plist白名单配置:
<key>LSApplicationQueriesSchemes</key> <array> <string>ms-outlook</string> </array>
Swift业务代码:
import UIKit func sendEmailViaOutlookWithAttachment( to: [String], subject: String, body: String, attachmentData: Data, attachmentFileName: String, from viewController: UIViewController ) { // 提前判断Outlook是否安装 guard let outlookUrl = URL(string: "ms-outlook://"), UIApplication.shared.canOpenURL(outlookUrl) else { print("未安装Outlook客户端") return } // 1. 将附件写入临时目录,生成系统可读取的文件URL let tempPath = NSTemporaryDirectory() let attachmentPath = (tempPath as NSString).appendingPathComponent(attachmentFileName) let attachmentUrl = URL(fileURLWithPath: attachmentPath) do { try attachmentData.write(to: attachmentUrl) } catch { print("附件写入临时目录失败: \(error.localizedDescription)") return } // 2. 构造邮件基础信息对象 let emailContent = OutlookEmailItem( toRecipients: to, subject: subject, body: body ) // 3. 初始化分享控制器 let activityVC = UIActivityViewController( activityItems: [emailContent, attachmentUrl], applicationActivities: nil ) // 4. 可选:过滤非必要分享渠道 activityVC.excludedActivityTypes = [ .mail, .message, .airDrop, .copyToPasteboard, .postToSocial ] // 适配iPad弹出样式 if let popover = activityVC.popoverPresentationController { popover.sourceView = viewController.view popover.sourceRect = CGRect(x: viewController.view.bounds.midX, y: viewController.view.bounds.midY, width: 0, height: 0) popover.permittedArrowDirections = [] } viewController.present(activityVC, animated: true) } // 自定义邮件信息传递对象 class OutlookEmailItem: NSObject, UIActivityItemSource { private let toRecipients: [String] private let subject: String private let body: String init(toRecipients: [String], subject: String, body: String) { self.toRecipients = toRecipients self.subject = subject self.body = body super.init() } func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any { return body } func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? { // 仅向Outlook返回正文内容 guard activityType?.rawValue == "com.microsoft.Office.Outlook.compose" else { return nil } return body } func activityViewController(_ activityViewController: UIActivityViewController, subjectForActivityType activityType: UIActivity.ActivityType?) -> String { return subject } @available(iOS 13.0, *) func activityViewController(_ activityViewController: UIActivityViewController, emailToRecipientsForActivityType activityType: UIActivity.ActivityType?) -> [String]? { return toRecipients } }
注意事项
- 出于iOS沙盒安全限制,Outlook无法直接读取你App沙盒内的文件,任何尝试通过URL Scheme传递文件路径的方案都无法生效
- 若需要添加多个附件,只需将所有附件对应的本地文件URL依次加入
activityItems数组即可 - 上述实现为微软官方适配的标准调用方式,不会随Outlook版本升级出现兼容问题
内容的提问来源于stack exchange,提问作者BlessySaini
相关产品推荐
相关产品推荐

