Sort Apple Mail with GPT (Download)
Discover how to enhance your email management with a powerful AppleScript that utilizes OpenAI for categorizing your messages! This guide walks you through logging email actions, handling content, and utilizing the OpenAI API to assign flags based on predefined categories—all while ensuring error...

on appendLog(logMessage)
try
set homePath to (do shell script "echo $HOME")
set logFile to homePath & "/Library/Logs/openai-mail-flags.log"
set timeStr to do shell script "date '+%Y-%m-%d %H:%M:%S'"
set logLine to timeStr & " - " & logMessage
do shell script "printf '%s\\n' " & quoted form of logLine & " >> " & quoted form of logFile
on error errStr
display dialog "Logging Error: " & errStr
end try
end appendLog
on truncateToWords(theText, wordLimit)
set wordCount to 0
set truncatedText to ""
set theWords to every word of theText
repeat with i from 1 to count of theWords
if wordCount ≥ wordLimit then
exit repeat
end if
set truncatedText to truncatedText & " " & (item i of theWords)
set wordCount to wordCount + 1
end repeat
if wordCount ≥ wordLimit then
return truncatedText & "..."
else
return truncatedText
end if
end truncateToWords
using terms from application "Mail"
on perform mail action with messages messageList
-- List mapping colors to their flag numbers (color, flag number)
set colorFlags to {{"Red", 0}, {"Orange", 1}, {"Yellow", 2}, {"Green", 3}, {"Blue", 4}, {"Purple", 5}, {"Grey", 6}}
-- List mapping colors to categories (color, category)
set colorCategories to { {"Blue", "Newsletter"}, {"Purple","Invoice"}}
-- Initialize log file
my appendLog("=== Starting new mail processing session ===")
-- Log available categories
set catStr to ""
repeat with i from 1 to count of colorCategories
set colorCat to item i of colorCategories
set theColor to item 1 of colorCat
set theCategory to item 2 of colorCat
set catStr to catStr & theCategory & " (" & theColor & "), "
end repeat
set catStr to catStr & "Other"
my appendLog("Available categories: " & catStr)
tell application "Mail"
try
repeat with theMessage in messageList
set msgContent to ""
try
set msgContent to content of theMessage as text
set msgSubject to subject of theMessage
my appendLog("Processing message: " & msgSubject)
on error
-- Skip this message if content can't be retrieved
my appendLog("Error: Could not retrieve message content")
cycle
end try
-- Check message content before processing
if msgContent is "" then
my appendLog("Error: Empty message content")
cycle
end if
-- Truncate content to 100 words
set truncatedContent to my truncateToWords(msgContent, 100)
my appendLog("Content: " & truncatedContent)
-- Build category options string
set categoryOptions to ""
repeat with i from 1 to count of colorCategories
set colorCat to item i of colorCategories
set theColor to item 1 of colorCat
set theCategory to item 2 of colorCat
set categoryOptions to categoryOptions & theCategory & "|"
end repeat
set categoryOptions to categoryOptions & "Other"
set thePrompt to "Based on this text, respond with exactly one word (" & categoryOptions & "): " & truncatedContent
-- Log the prompt being sent
my appendLog("Prompt sent to OpenAI: " & thePrompt)
-- Escape the prompt for JSON
set escapedPrompt to do shell script "printf %s " & quoted form of thePrompt & " | sed 's/\"/\\\\\"/g'"
-- Prepare OpenAI API request with properly escaped JSON
set jsonData to "{\"model\":\"gpt-4o-mini\",\"messages\":[{\"role\":\"user\",\"content\":\"" & escapedPrompt & "\"}],\"temperature\":0}"
-- Write JSON to a temporary file
set tmpFile to "/tmp/openai_request.json"
do shell script "echo " & quoted form of jsonData & " > " & quoted form of tmpFile
-- Make the API call using the temporary file
set curlCommand to "curl -s https://api.openai.com/v1/chat/completions " & ¬
"-H 'Content-Type: application/json' " & ¬
"-H 'Authorization: Bearer <YOUR API KEY HERE>' " & ¬
"-d @" & tmpFile & " > /tmp/openai_response.json"
try
do shell script curlCommand
set fullResponse to do shell script "cat /tmp/openai_response.json"
my appendLog("Raw response: " & fullResponse)
-- Parse response using Python for reliable JSON handling
set parseCommand to "python3 -c 'import sys,json; response=json.loads(sys.argv[1]); print(response[\"choices\"][0][\"message\"][\"content\"])' " & quoted form of fullResponse
try
set extractedCategory to do shell script parseCommand
my appendLog("OpenAI decided: " & extractedCategory)
-- Find category's color
repeat with i from 1 to count of colorCategories
set colorCat to item i of colorCategories
set theColor to item 1 of colorCat
set theCategory to item 2 of colorCat
if extractedCategory contains theCategory then
-- Find color's flag number
repeat with j from 1 to count of colorFlags
set colorFlag to item j of colorFlags
set flagColor to item 1 of colorFlag
set flagNumber to item 2 of colorFlag
if flagColor is equal to theColor then
set flag index of theMessage to flagNumber
my appendLog("Flag set: " & theCategory & " (" & theColor & ")")
exit repeat
end if
end repeat
exit repeat
end if
end repeat
on error errStr
my appendLog("Parse error: " & errStr)
end try
on error errStr
my appendLog("API Error: " & errStr)
display dialog "API Error: " & errStr
end try
-- Clean up temporary files
do shell script "rm -f /tmp/openai_request.json /tmp/openai_response.json"
end repeat
my appendLog("=== Mail processing session completed ===")
return true
on error errStr
my appendLog("Script Error: " & errStr)
display dialog "Error: " & errStr
return false
end try
end tell
end perform mail action with messages
end using terms from
Comments ()