Apple Mail AppleScript Skill
This skill provides comprehensive guidance on using AppleScript to automate Apple Mail operations, including reading emails, sending messages, and managing mailboxes.
Core Principles
- Access mailboxes through account objects - Don't try to access
inboxdirectly on accounts - Iterate through mailboxes to find the right one - Mailbox names can vary (INBOX, Inbox, etc.)
- Use account name matching - Match on account name rather than email address property
- Handle errors gracefully - AppleScript errors can be cryptic, use trial and error with different approaches
Common Query Patterns
1. List All Mail Accounts
Always start by listing accounts to verify the account exists and get the correct name:
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
Example output:
MonzoiCloudbrunofdcampos@gmail.commmbcfields@gmail.comcampos.bruno.fd@gmail.com
2. Read Last N Emails from an Account
The correct pattern for accessing emails from a specific account:
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
Key lessons from trial and error:
- ❌ WRONG:
inbox of targetAccount(doesn't work, causes error -1728) - ❌ WRONG:
address of acc(address property doesn't exist reliably) - ✅ CORRECT:
every mailbox of targetAccountthen iterate to find "INBOX" or "Inbox"
3. Read Email Content
Get the full body content of a specific email:
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. Send an Email
Create and send a new email:
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
Options:
visible:true- Shows the compose window before sending (useful for review)visible:false- Sends silently in the background
5. Reply to an Email
Reply to an existing email (preserves threading):
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
-- Find the message to reply to (e.g., by sender)
set foundMessages to (messages of mbox whose sender contains "sender@example.com")
set originalMsg to item 1 of foundMessages
-- Create reply
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
Key points:
- Use
reply originalMsgto create a threaded reply (NOTmake new outgoing message) - The
replycommand automatically sets the recipient and subject with "Re:" - Don't use
with opening window falseparameter, it causes syntax errors - Set the content of the reply before sending
Reply vs New Email:
- ❌ WRONG: Creating new message to same recipient (breaks threading)
set newMessage to make new outgoing message with properties {subject:"Re: Subject"}
- ✅ CORRECT: Using reply command on original message (maintains threading)
set theReply to reply originalMsg
6. Search Emails by Subject
Find emails matching a subject keyword:
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. Search Emails by Sender
Find all emails from a specific sender:
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. Get Email Metadata Without Content
Get subject, sender, and date without loading full content (faster):
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. Check Unread Message Count
Count unread messages in inbox:
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
en