AppleMailAppleScript技能Skill apple-mail

全面指导使用 AppleScript 自动化 Apple Mail 操作,包括阅读电子邮件、发送消息和管理邮箱。

自动化脚本 2 次安装 12 次浏览 更新于 3/2/2026

Apple Mail AppleScript 技能

这个技能提供了使用 AppleScript 自动化 Apple Mail 操作的全面指导,包括阅读电子邮件、发送消息和管理邮箱。

核心原则

  1. 通过账户对象访问邮箱 - 不要尝试直接在账户上访问 inbox
  2. 迭代邮箱以找到正确的一个 - 邮箱名称可能不同(INBOX, Inbox, 等)
  3. 使用账户名称匹配 - 匹配账户名称而不是电子邮件地址属性
  4. 优雅地处理错误 - AppleScript 错误可能很隐晦,使用试错法尝试不同的方法

常见查询模式

1. 列出所有邮件账户

始终首先列出账户,以验证账户存在并获取正确的名称:

osascript <<'EOF'
tell application "Mail"
    set accountNames to {}
    repeat with acc in accounts
        set end of accountNames to (name of acc)
    end repeat
    return accountNames as string
end tell
EOF

示例输出:

MonzoiCloudbrunofdcampos@gmail.commmbcfields@gmail.comcampos.bruno.fd@gmail.com

2. 从账户读取最后 N 封电子邮件

正确的模式 用于从特定账户访问电子邮件:

osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    set allMailboxes to every mailbox of targetAccount

    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" or name of mbox is "Inbox" then
            set inboxMsgs to messages of mbox
            set msgCount to count of inboxMsgs
            set numToFetch to 5
            if msgCount < 5 then set numToFetch to msgCount

            set output to ""
            repeat with i from 1 to numToFetch
                set msg to item i of inboxMsgs
                set output to output & "Email #" & i & return
                set output to output & "Subject: " & subject of msg & return
                set output to output & "From: " & sender of msg & return
                set output to output & "Date: " & (date received of msg as string) & return
                set output to output & return & "---" & return & return
            end repeat

            return output
        end if
    end repeat

    return "Inbox not found"
end tell
EOF

从试错中学到的关键课程:

  • 错误: inbox of targetAccount (不起作用,会导致错误 -1728)
  • 错误: address of acc (address 属性不可靠)
  • 正确: every mailbox of targetAccount 然后迭代以找到 “INBOX” 或 “Inbox”

3. 阅读电子邮件内容

获取特定电子邮件的全部正文内容:

osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    set allMailboxes to every mailbox of targetAccount

    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" or name of mbox is "Inbox" then
            set msg to item 1 of messages of mbox
            set emailContent to content of msg
            return emailContent
        end if
    end repeat
end tell
EOF

4. 发送电子邮件

创建并发送新电子邮件:

osascript <<'EOF'
tell application "Mail"
    set newMessage to make new outgoing message with properties {subject:"Your Subject", content:"Your email body here", visible:true}
    tell newMessage
        make new to recipient at end of to recipients with properties {address:"recipient@example.com"}
        send
    end tell
end tell
EOF

选项:

  • visible:true - 在发送前显示撰写窗口(适合审核)
  • visible:false - 在后台静默发送

5. 回复电子邮件

回复现有电子邮件(保留线程):

osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    set allMailboxes to every mailbox of targetAccount

    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" or name of mbox is "Inbox" then
            -- 根据发件人找到要回复的消息
            set foundMessages to (messages of mbox whose sender contains "sender@example.com")
            set originalMsg to item 1 of foundMessages

            -- 创建回复
            set theReply to reply originalMsg
            tell theReply
                set content to "Your reply message here"
                send
            end tell

            return "Reply sent successfully"
        end if
    end repeat
end tell
EOF

关键点:

  • 使用 reply originalMsg 创建一个线程回复(不是 make new outgoing message
  • reply 命令自动设置收件人和主题为 “Re:”
  • 不要使用 with opening window false 参数,会导致语法错误
  • 在发送前设置回复的内容

回复与新邮件:

  • 错误: 创建新消息给同一收件人(打破线程)
set newMessage to make new outgoing message with properties {subject:"Re: Subject"}
  • 正确: 使用回复命令在原始消息上(保持线程)
set theReply to reply originalMsg

6. 按主题搜索电子邮件

查找匹配特定主题关键词的电子邮件:

osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    set allMailboxes to every mailbox of targetAccount

    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" or name of mbox is "Inbox" then
            set foundMessages to (messages of mbox whose subject contains "keyword")
            set output to ""

            repeat with msg in foundMessages
                set output to output & "Subject: " & subject of msg & return
                set output to output & "From: " & sender of msg & return
                set output to output & "Date: " & (date received of msg as string) & return
                set output to output & "---" & return
            end repeat

            return output
        end if
    end repeat
end tell
EOF

7. 按发件人搜索电子邮件

查找来自特定发件人的所有电子邮件:

osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    set allMailboxes to every mailbox of targetAccount

    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" or name of mbox is "Inbox" then
            set foundMessages to (messages of mbox whose sender contains "sender@example.com")

            set output to "Found " & (count of foundMessages) & " messages" & return & return
            repeat with msg in foundMessages
                set output to output & subject of msg & return
            end repeat

            return output
        end if
    end repeat
end tell
EOF

8. 获取电子邮件元数据而不加载内容

获取主题、发件人和日期而不加载完整内容(更快):

osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    set allMailboxes to every mailbox of targetAccount

    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" or name of mbox is "Inbox" then
            set recentMsgs to items 1 thru 10 of messages of mbox
            set output to ""

            repeat with msg in recentMsgs
                set output to output & subject of msg & " | " & sender of msg & return
            end repeat

            return output
        end if
    end repeat
end tell
EOF

9. 检查未读消息计数

计算收件箱中的未读消息数:

osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    set allMailboxes to every mailbox of targetAccount

    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" or name of mbox is "Inbox" then
            set unreadCount to count of (messages of mbox whose read status is false)
            return "Unread messages: " & unreadCount
        end if
    end repeat
end tell
EOF

10. 将电子邮件移动到邮箱

将消息移动到不同的邮箱:

osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    set allMailboxes to every mailbox of targetAccount

    -- 找到源邮箱
    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" then
            set theMessage to item 1 of messages of mbox

            -- 找到目标邮箱
            repeat with destBox in allMailboxes
                if name of destBox is "Archive" then
                    move theMessage to destBox
                    return "Message moved to Archive"
                end if
            end repeat
        end if
    end repeat
end tell
EOF

11. 按标准删除电子邮件

删除匹配特定标准的电子邮件:

osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    set allMailboxes to every mailbox of targetAccount

    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" then
            set messagesToDelete to (messages of mbox whose subject contains "spam")

            repeat with msg in messagesToDelete
                delete msg
            end repeat

            return "Deleted " & (count of messagesToDelete) & " messages"
        end if
    end repeat
end tell
EOF

常见邮箱名称

不同的电子邮件提供商使用不同的邮箱名称:

Gmail 账户

  • INBOX - 主收件箱
  • [Gmail]/All Mail - 所有邮件存档
  • [Gmail]/Sent Mail - 发送的消息
  • [Gmail]/Trash - 删除的项目
  • [Gmail]/Drafts - 草稿消息
  • [Gmail]/Spam - 垃圾邮件文件夹

iCloud 账户

  • Inbox - 主收件箱(注意大小写)
  • Sent Messages - 发送的邮件
  • Trash - 删除的项目
  • Drafts - 草稿消息

其他提供商

  • 可能使用 Sent Items, Deleted Items 等。
  • 总是迭代通过邮箱并检查名称

电子邮件消息属性

您可以访问的常见消息对象属性:

subject of msg              -- 电子邮件主题行
sender of msg              -- 发件人电子邮件地址
date received of msg       -- 电子邮件接收日期
date sent of msg          -- 电子邮件发送日期
content of msg            -- 完整电子邮件正文(可能很慢)
read status of msg        -- 布尔值:如果已读为 true,未读为 false
flagged status of msg     -- 布尔值:如果标记/星标为 true
message id of msg         -- 唯一消息标识符
to recipients of msg      -- 收件人对象列表
cc recipients of msg      -- CC 收件人对象列表
all headers of msg        -- 原始电子邮件头
message size of msg       -- 大小,以字节为单位

错误处理

常见错误和解决方案

错误:“无法获取账户的收件箱”

-- ❌ 错误:尝试直接访问收件箱
tell application "Mail"
    set targetAccount to account "email@example.com"
    set inboxMsgs to messages of inbox of targetAccount  -- 这会失败!
end tell

-- ✅ 正确:迭代邮箱
tell application "Mail"
    set targetAccount to account "email@example.com"
    set allMailboxes to every mailbox of targetAccount
    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" or name of mbox is "Inbox" then
            set inboxMsgs to messages of mbox
        end if
    end repeat
end tell

错误:“无法获取账户的地址”

-- ❌ 错误:address 属性不可靠
if address of acc contains "email@example.com" then

-- ✅ 正确:使用 name 属性代替
if name of acc contains "email@example.com" then

错误:“无法获取每个账户的项目 1”

-- ❌ 错误:不要在批量操作中尝试访问属性
repeat with acc in accounts
    if address of acc contains "..." then  -- 这会失败!

-- ✅ 正确:单独获取属性
repeat with acc in accounts
    set accName to name of acc
    if accName contains "..." then

错误:消息未找到或邮箱不存在

-- 解决方案:首先检查存在性
set allMailboxes to every mailbox of targetAccount
if (count of allMailboxes) = 0 then
    return "No mailboxes found for this account"
end if

最佳实践

  1. 始终首先列出账户 当调试时:

    osascript -e 'tell application "Mail" to name of every account'
    
  2. 在访问前检查邮箱名称

    set mailboxNames to name of every mailbox of targetAccount
    
  3. 在 bash 中使用 heredoc 语法 进行多行 AppleScript:

    osascript <<'EOF'
    tell application "Mail"
        -- 您的脚本在这里
    end tell
    EOF
    
  4. 处理邮箱名称的大小写敏感性

    if name of mbox is "INBOX" or name of mbox is "Inbox" then
    
  5. 限制消息检索 以避免减速:

    set recentMsgs to items 1 thru 10 of messages of mbox
    
  6. 在迭代前检查消息计数

    set msgCount to count of messages of mbox
    if msgCount < numToFetch then set numToFetch to msgCount
    
  7. 及早使用 return 当您找到所需内容时:

    repeat with mbox in allMailboxes
        if name of mbox is "INBOX" then
            -- 处理并返回
            return result
        end if
    end repeat
    

性能提示

  1. 不要不必要地加载内容 - 获取 content of msg 很慢
  2. 限制一次脚本处理的消息数量
  3. 使用过滤器whose 子句)在处理前缩小结果范围
  4. 如果执行多个操作,缓存邮箱引用

安全和隐私考虑

  1. 邮件访问需要权限 - macOS 在首次使用时会提示访问权限
  2. 小心自动化 - 首先使用 visible:true 测试发送脚本
  3. 尊重用户隐私 - 不要记录敏感电子邮件内容
  4. 使用特定搜索 - 尽可能避免处理整个邮箱

快速参考命令

# 列出所有账户
osascript -e 'tell application "Mail" to name of every account'

# 获取账户的收件箱消息计数
osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    repeat with mbox in mailboxes of targetAccount
        if name of mbox is "INBOX" or name of mbox is "Inbox" then
            return count of messages of mbox
        end if
    end repeat
end tell
EOF

# 获取未读计数
osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    repeat with mbox in mailboxes of targetAccount
        if name of mbox is "INBOX" then
            return count of (messages of mbox whose read status is false)
        end if
    end repeat
end tell
EOF

# 列出账户的所有邮箱名称
osascript <<'EOF'
tell application "Mail"
    set targetAccount to account "email@example.com"
    set mailboxNames to name of every mailbox of targetAccount
    return mailboxNames as string
end tell
EOF

何时使用此技能

当您需要:

  • 从 Apple Mail 读取电子邮件
  • 发送自动化电子邮件
  • 回复电子邮件(保持线程上下文)
  • 搜索特定电子邮件
  • 以编程方式管理邮箱
  • 计算未读消息
  • 根据标准移动或删除电子邮件
  • 提取电子邮件元数据
  • 自动化电子邮件工作流

与其他工作流程的集成

当处理电子邮件自动化时:

  1. 电子邮件通知 - 在特定事件发生时发送警报
  2. 数据提取 - 解析电子邮件以获取特定信息
  3. 电子邮件过滤 - 根据规则自动归档或删除电子邮件
  4. 报告 - 生成电子邮件活动摘要
  5. 备份 - 导出电子邮件数据以进行归档

从试错中学到的经验(试错)

开发此技能的关键见解:

  1. 不要直接使用 inbox of account - 总是迭代邮箱
  2. 账户属性不同 - 使用 name 而不是 address
  3. 邮箱名称因提供商而异 - 检查 “INBOX” 和 “Inbox”
  4. 错误 -1728 通常意味着属性不存在 - 尝试不同的属性
  5. 批量操作 every X 可能会失败 - 单独获取属性
  6. 使用 items 1 thru N 进行安全的列表切片,带有边界检查
  7. 使用 reply 命令,而不是新消息 - 要维护线程,请使用 reply originalMsg 而不是创建新的外发消息
  8. 不要使用 with opening window 参数 - reply 命令不支持 with opening window false 参数,会导致语法错误

记住:AppleScript 错误消息通常很隐晦。当调试时,将脚本简化为最必要的,然后逐渐增加复杂性。