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...

Sort Apple Mail with GPT (Download)
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
Data Privacy | Imprint