Skip to content

Email Notifications

Email Notifications via Apple Mail

Set up real-time email notifications: when the agent’s iCloud email receives a message from a known contact, Apple Mail triggers an AppleScript that notifies the OpenClaw agent.

Overview

Known contact sends email

Apple Mail.app

(Mail Rule fires)

NotifyAgent.applescript

openclaw system event --mode now

--text 'New email from...'

Immediate heartbeat triggered

Agent fetches + authenticates email

Two mechanisms trigger email processing:

  1. Real-time notifications — A Mail.app rule fires an AppleScript that enqueues a system event and triggers an immediate heartbeat (openclaw system event --mode now). The event text includes the RFC 2822 Message-ID so the agent can fetch and authenticate the email.
  2. Periodic heartbeat checks — The agent’s heartbeat routine checks the inbox 2-3x/day for anything the rule didn’t catch

Prerequisites

  • macOS with Apple Mail configured for the agent’s iCloud email
  • OpenClaw installed and running
  • The main agent has exec access (needed to process emails)

Setup Steps

1. Configure Apple Mail

  1. Open Mail.app on the agent Mac
  2. Add the agent’s iCloud account if not already set up
  3. Verify mail is syncing (send a test email)

2. Create the Notification Script

Create NotifyAgent.applescript:

-- Triggered by Mail.app rule when sender is in Contacts
-- Uses RFC 2822 Message-ID (compatible with mail-cli and apple-pim plugin)
using terms from application "Mail"
on perform mail action with messages theMessages for rule theRule
set logFile to (POSIX path of (path to home folder)) & "Library/Logs/lobster-mail-notify.log"
repeat with theMessage in theMessages
set theId to message id of theMessage
-- Strip angle brackets, validate safe characters, log attempt
-- (see full source in openclaw-agents/lobster/scripts/NotifyLobster.applescript)
set theCommand to "export PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin; openclaw system event --mode now --text 'New email from known contact. Message-ID: " & theId & "' >> " & quoted form of logFile & " 2>&1 &"
do shell script theCommand
end repeat
end perform mail action with messages
end using terms from

Security notes:

  • The RFC 2822 Message-ID is passed (not sender or subject), preventing command injection from crafted email headers
  • The ID is validated to contain only safe characters ([a-zA-Z0-9@._-+]) before shell interpolation
  • The agent retrieves email details safely through mail-cli or the apple-pim plugin using this ID
  • PATH export is required because Mail.app’s sandbox only has /usr/bin:/bin
  • Background execution (&) prevents the Mail rule from blocking
  • All notification attempts are logged to ~/Library/Logs/lobster-mail-notify.log for debugging

3. Compile and Deploy

Terminal window
osacompile -o ~/Library/Application\ Scripts/com.apple.mail/NotifyAgent.scpt \
/path/to/NotifyAgent.applescript

4. Create the Mail Rule

  1. Mail.app > Settings > Rules > Add Rule
  2. Description: “Notify Agent (known contacts)”
  3. If: Sender is in my Contacts
  4. Action: Run AppleScript > NotifyAgent.scpt

5. Verify

Send a test email from a contact in the agent Mac’s address book:

Terminal window
openclaw logs --follow

You should see the agent receive: New email from known contact. Message-ID: [email protected]

Also check the log file for notification attempts:

Terminal window
tail -f ~/Library/Logs/lobster-mail-notify.log

How It Works

The AppleScript

The script is intentionally minimal for security:

  • RFC 2822 Message-ID is passed — not sender or subject, preventing command injection from crafted email headers. The ID is validated to contain only safe characters before shell interpolation.
  • PATH export is required — Mail.app is sandboxed and do shell script only has /usr/bin:/bin:/usr/sbin:/sbin in PATH
  • Debug logging — all notification attempts are logged to ~/Library/Logs/lobster-mail-notify.log with timestamps
  • Background execution — the & prevents the Mail rule from blocking

Heartbeat Checks

The agent’s HEARTBEAT.md should include an inbox check task:

- [ ] Check inbox (2-3x/day): review unread emails, flag important ones for owner

This covers emails from unknown senders or cases where the Mail rule didn’t fire (e.g., Mail.app was not running).

Email Processing Workflow

Once notified, the agent follows a zero-inbox approach:

  1. Authenticate — Apple PIM mail tool with auth_check action (blocking, must pass before acting). See Email Authentication.
  2. Read the email — mail-read <id> or Apple PIM mail tool with get action
  3. Mark readmail-mark-read <id> or Apple PIM mail tool with update action
  4. Archive when processed — mail-archive <id> or Apple PIM mail tool with move action
  5. Delete if not needed — Apple PIM mail tool with delete action

Goal: empty inbox at all times. Process immediately, archive when done. Flag important items for the owner via iMessage.

Troubleshooting

AppleScript not firing

  • Verify the rule is enabled in Mail -> Settings -> Rules
  • Check that the sender is in Contacts on the agent Mac (not just on iCloud — Contacts must be synced)
  • Test the script manually: osascript ~/Library/Application\ Scripts/com.apple.mail/NotifyAgent.scpt

”env: node: No such file or directory”

  • Mail.app’s sandbox gives do shell script a minimal PATH (/usr/bin:/bin:/usr/sbin:/sbin)
  • The script must explicitly export PATH to include /opt/homebrew/bin where node lives

”Permission denied” from AppleScript

  • Mail.app needs Automation permission to run scripts
  • System Settings -> Privacy & Security -> Automation -> Mail -> allow

Agent doesn’t respond

  • Verify OpenClaw is running: openclaw status
  • Check that the main agent has auth configured
  • Check logs: openclaw logs --follow

Re-deploying after script changes

After editing the AppleScript source, recompile:

Terminal window
osacompile -o ~/Library/Application\ Scripts/com.apple.mail/NotifyAgent.scpt \
/path/to/NotifyAgent.applescript

No need to recreate the Mail rule — it references the compiled .scpt by path.