You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS自带Mail应用:如何检测新邮件到来

思路可行性分析

你的实现思路完全可行:

  • 利用sdef导出Mail应用的脚本定义并生成头文件,是ScriptingBridge开发的标准流程,能让你在Swift中类型安全地调用Mail的AppleScript接口
  • ScriptingBridge是Apple官方提供的跨应用脚本交互框架,完全支持对Mail应用的邮件读写操作
现有代码的问题与优化建议

你当前的代码仅能一次性获取收件箱所有邮件,无法实现「检测新邮件」的核心需求,需要补充监听逻辑和新邮件判断机制:

  1. 添加新邮件监听逻辑
    可以通过定时轮询并对比邮件的receivedDate来识别新邮件,也可结合应用激活事件触发检查,示例代码如下:
import Foundation
import Mail
import AppKit

class MailMonitor {
    let mailApplication: MailApplication
    var lastCheckedDate: Date = Date()
    var timer: Timer?

    init() {
        mailApplication = SBApplication(bundleIdentifier: "com.apple.mail") as! MailApplication
        setupTimer()
        setupWorkspaceObserver()
    }

    private func setupTimer() {
        // 每5分钟轮询一次收件箱
        timer = Timer.scheduledTimer(withTimeInterval: 300, repeats: true) { [weak self] _ in
            self?.checkForNewEmails()
        }
    }

    private func setupWorkspaceObserver() {
        // 监听Mail应用激活事件,立即检查新邮件
        NSWorkspace.shared.notificationCenter.addObserver(
            self,
            selector: #selector(checkForNewEmails),
            name: NSWorkspace.didActivateApplicationNotification,
            object: nil
        )
    }

    @objc func checkForNewEmails() {
        guard let inbox = mailApplication.inboxes?.firstObject as? MailMailbox else {
            print("无法获取收件箱")
            return
        }

        guard let messages = inbox.messages?().compactMap({ $0 as? MailMessage }) else {
            print("无法获取邮件列表")
            return
        }

        // 筛选出上次检查之后收到的新邮件
        let newMessages = messages.filter {
            guard let receivedDate = $0.receivedDate else { return false }
            return receivedDate > lastCheckedDate
        }

        if !newMessages.isEmpty {
            print("发现\(newMessages.count)封新邮件:")
            for message in newMessages {
                print("主题:\(message.subject ?? "无主题")")
                print("发件人:\(message.sender ?? "未知发件人")")
                print("收到时间:\(message.receivedDate ?? Date())")
                print("---")
            }
            // 更新上次检查时间
            lastCheckedDate = Date()
        }
    }
}

// 启动监听
let mailMonitor = MailMonitor()
RunLoop.main.run()
  1. 权限注意事项
  • macOS 10.14+需在Info.plist中添加NSAppleEventsUsageDescription权限说明,否则会被系统拦截
  • 若应用为沙盒应用,需开启「Apple Events」权限,并添加对com.apple.mail的应用访问权限
  1. 可选替代方案
    除了ScriptingBridge,也可直接使用NSAppleScript执行AppleScript代码实现相同功能,简单场景下更灵活,但类型安全性不如ScriptingBridge。

内容的提问来源于stack exchange,提问作者Avi Rok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 05:55:00