apple-mail
Comprehensive guide for accessing and automating Apple Mail using AppleScript, including reading emails, sending messages, and managing mailboxes.
What this skill does
# 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
1. **Access mailboxes through account objects** - Don't try to access `inbox` directly on accounts
2. **Iterate through mailboxes to find the right one** - Mailbox names can vary (INBOX, Inbox, etc.)
3. **Use account name matching** - Match on account name rather than email address property
4. **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:
```applescript
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:**
```
[email protected]@[email protected]
```
### 2. Read Last N Emails from an Account
The **correct pattern** for accessing emails from a specific account:
```applescript
osascript <<'EOF'
tell application "Mail"
set targetAccount to account "[email protected]"
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 targetAccount` then iterate to find "INBOX" or "Inbox"
### 3. Read Email Content
Get the full body content of a specific email:
```applescript
osascript <<'EOF'
tell application "Mail"
set targetAccount to account "[email protected]"
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:
```applescript
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:"[email protected]"}
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):
```applescript
osascript <<'EOF'
tell application "Mail"
set targetAccount to account "[email protected]"
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 "[email protected]")
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 originalMsg` to create a threaded reply (NOT `make new outgoing message`)
- The `reply` command automatically sets the recipient and subject with "Re:"
- Don't use `with opening window false` parameter, 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)
```applescript
set newMessage to make new outgoing message with properties {subject:"Re: Subject"}
```
- ✅ **CORRECT:** Using reply command on original message (maintains threading)
```applescript
set theReply to reply originalMsg
```
### 6. Search Emails by Subject
Find emails matching a subject keyword:
```applescript
osascript <<'EOF'
tell application "Mail"
set targetAccount to account "[email protected]"
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:
```applescript
osascript <<'EOF'
tell application "Mail"
set targetAccount to account "[email protected]"
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 "[email protected]")
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):
```applescript
osascript <<'EOF'
tell application "Mail"
set targetAccount to account "[email protected]"
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:
```applescript
osascript <<'EOF'
tell application "Mail"
set targetAccount to account "[email protected]"
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
eRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.