An Intelligrit Labs Project
A command-line interface for controlling macOS Mail.app. Provides complete scriptable access to accounts, mailboxes, messages, and attachments.
- List and manage Mail.app accounts
- Browse and manage mailboxes
- List, read, search, and manage messages
- Archive, move, delete, flag, and mark messages
- Send emails
- Manage attachments
- Fully scriptable - perfect for automation and building GUIs
go install github.com/intelligrit/mail-app-cli@latestgit clone https://github.com/intelligrit/mail-app-cli.git
cd mail-app-cli
go build -o mail-app-cliList all Mail.app accounts:
mail-app-cli accounts listShow details for a specific account:
mail-app-cli accounts show "Gmail"List all mailboxes:
mail-app-cli mailboxes listList mailboxes for a specific account:
mail-app-cli mailboxes list --account "Gmail"List messages in a mailbox:
mail-app-cli messages list --account "Gmail" --mailbox "INBOX"List with filters:
# Show only unread messages
mail-app-cli messages list -a "Gmail" -m "INBOX" --unread
# Show only flagged messages
mail-app-cli messages list -a "Gmail" -m "INBOX" --flagged
# Show messages since a specific date
mail-app-cli messages list -a "Gmail" -m "INBOX" --since "2025-12-01"
# Show messages since a specific date and time
mail-app-cli messages list -a "Gmail" -m "INBOX" --since "2025-12-14 09:00:00"
# Combine filters
mail-app-cli messages list -a "Gmail" -m "INBOX" --unread --since "2025-12-01" --limit 10Show full message details:
mail-app-cli messages show <message-id> -a "Gmail" -m "INBOX"Mark message as read/unread:
# Mark as read
mail-app-cli messages mark <message-id> -a "Gmail" -m "INBOX" --read
# Mark as unread
mail-app-cli messages mark <message-id> -a "Gmail" -m "INBOX" --read=falseFlag/unflag a message:
# Flag a message
mail-app-cli messages flag <message-id> -a "Gmail" -m "INBOX" --flagged
# Unflag a message
mail-app-cli messages flag <message-id> -a "Gmail" -m "INBOX" --flagged=falseArchive a message:
mail-app-cli messages archive <message-id> -a "Exchange" -m "Inbox"Gmail limitation: archiving is refused for Gmail accounts. Mail.app offers no safe scriptable archive for Gmail — scripted moves out of INBOX silently revert on the next sync, and the only workaround that sticks (bouncing the message through Trash) can permanently delete mail. Archive Gmail messages in Mail.app or Gmail itself, or use
messages deleteto send them to Trash.
Move a message to another mailbox:
mail-app-cli messages move <message-id> "Archive" -a "Gmail" -m "INBOX"Delete a message:
mail-app-cli messages delete <message-id> -a "Gmail" -m "INBOX"Send a message:
mail-app-cli send \
--account "Gmail" \
--to user@example.com \
--subject "Hello" \
--body "Message content here"Send to multiple recipients:
mail-app-cli send \
-a "Gmail" \
-t user1@example.com \
-t user2@example.com \
-c cc@example.com \
-s "Multi-recipient message" \
--body "Content"Search for messages across all mailboxes:
mail-app-cli search "important meeting"Search with limit:
mail-app-cli search "project update" --limit 20List attachments in a message:
mail-app-cli attachments list <message-id> -a "Gmail" -m "INBOX"Save an attachment:
mail-app-cli attachments save <message-id> "document.pdf" -a "Gmail" -m "INBOX"Save to a specific path:
mail-app-cli attachments save <message-id> "document.pdf" -a "Gmail" -m "INBOX" -o ~/Downloads/document.pdfAll commands output JSON format for easy parsing and scripting. The output is formatted with 2-space indentation for human readability while remaining machine-parseable.
For even prettier output, pipe through jq:
mail-app-cli accounts list | jqmail-app-cli accounts list | jq '.[] | select(.emailAddress | endswith("@gmail.com"))'mail-app-cli accounts list | jq '.[] | select(.enabled==true) | .name'mail-app-cli mailboxes list | jq '[.[].unreadCount] | add'mail-app-cli mailboxes list | jq '.[] | select(.unreadCount > 0) | {account, name, unread: .unreadCount}'mail-app-cli messages list -a "Gmail" -m "INBOX" | jq '.[].subject'mail-app-cli messages list -a "Gmail" -m "INBOX" | jq '.[] | select(.read==false and (.sender | contains("boss@company.com")))'mail-app-cli search "important" | jq -r '.[] | [.account, .mailbox, .subject, .sender] | @csv'mail-app-cli search "project" | jq 'group_by(.account) | map({account: .[0].account, count: length})'mail-app-cli attachments list <message-id> -a "Gmail" -m "INBOX" | jq '.[].name'mail-app-cli attachments list <message-id> -a "Gmail" -m "INBOX" | jq '.[] | select(.fileSize > 1048576)'#!/bin/bash
unread=$(mail-app-cli messages list -a "Gmail" -m "INBOX" --unread | jq 'length')
if [ $unread -gt 0 ]; then
echo "You have $unread unread messages"
fi#!/bin/bash
mail-app-cli messages list -a "Exchange" -m "Inbox" | jq -r '.[] | select(.read==true) | .id' | while read -r msg_id; do
mail-app-cli messages archive "$msg_id" -a "Exchange" -m "Inbox"
done#!/bin/bash
echo "Today's Unread Email Summary"
echo "============================"
mail-app-cli mailboxes list | jq -r '.[] | select(.unreadCount > 0) | "\(.account)/\(.name): \(.unreadCount) unread"'#!/bin/bash
SENDER="colleague@company.com"
ACCOUNT="Gmail"
MAILBOX="INBOX"
# Find all messages from sender
mail-app-cli messages list -a "$ACCOUNT" -m "$MAILBOX" | jq -r ".[] | select(.sender | contains(\"$SENDER\")) | .id" | while read -r msg_id; do
# Get attachments for each message
mail-app-cli attachments list "$msg_id" -a "$ACCOUNT" -m "$MAILBOX" | jq -r '.[].name' | while read -r att_name; do
echo "Saving: $att_name from message $msg_id"
mail-app-cli attachments save "$msg_id" "$att_name" -a "$ACCOUNT" -m "$MAILBOX" -o "~/Downloads/$att_name"
done
donemail-app-cli/
├── cmd/ # Cobra command definitions
│ ├── root.go
│ ├── accounts.go
│ ├── mailboxes.go
│ ├── messages.go
│ ├── send.go
│ ├── search.go
│ └── attachments.go
├── pkg/
│ └── mail/ # Mail.app AppleScript/JXA client
│ └── client.go
└── main.go
The CLI uses AppleScript and JavaScript for Automation (JXA) to interact with Mail.app. This provides:
- Native integration with Mail.app
- Access to all Mail.app features
- No external dependencies or APIs required
- Works with all mail providers configured in Mail.app
- macOS (tested on macOS 12+)
- Mail.app configured with at least one account
- Go 1.21+ (for building from source)
- Go 1.21 or higher
- macOS with Mail.app
go build -o mail-app-cli# Test account listing
./mail-app-cli accounts list
# Test mailbox listing
./mail-app-cli mailboxes list
# Test message listing
./mail-app-cli messages list -a "Your Account" -m "INBOX" --limit 5Future enhancements:
- Rules management
- Smart mailbox operations
- Signatures management
- VIP contacts
- Export/import functionality
- Batch operations
- IMAP folder synchronization
- Message threading support
- Draft management
Contributions are welcome! This project follows standard Go conventions.
- Fork the repository
- Create a feature branch
- Make your changes following Go best practices
- Write tests for new functionality
- Ensure all tests pass
- Commit your changes
- Push to the branch
- Open a Pull Request
mail-app-cli is developed by Intelligrit Labs, the R&D arm of Intelligrit LLC. We build tools for ourselves and release them for everyone. Intelligrit delivers AI-driven IT modernization for federal agencies.
MIT License - see LICENSE file for details
For issues, questions, or contributions, please open an issue on GitHub.
- Built with Cobra CLI framework
- Uses AppleScript and JXA for Mail.app integration
