Apple Mail - Discard Spam

Summary: Completely deletes the messages in the Spam mailbox.
Requires: SpamSieve, Apple Mail
Install Location: ~/Library/Scripts/Applications/Mail

Description

Running this script from the Scripts menu will completely delete all the messages in the Spam mailbox under “On My Mac” (rather than putting them in the trash, which is what happens when you press the Delete key).

Download in Compiled Format · Download in Text Format

Script

on run {}
    
tell application "Mail"
        
my completelyDeleteMessagesFromMailbox(my spamMailbox())
    
end tell
end run

on spamMailbox()
    
set _keys to {"AppleMailTrainSpamName", "AppleMailLocalSpamMailbox"}
    
set _defaultValues to {"Spam", true}
    
set {_spamFolderName, _isLocal} to my lookupDefaults(_keys, _defaultValues)
    
tell application "Mail"
        
if _isLocal then return mailbox _spamFolderName
        
set _accounts to accounts
        
repeat with _account in accounts
            
try
                
return mailbox _spamFolderName of _account
            
end try
        
end repeat
        
error "No spam mailbox named “" & _spamMailboxName & "” found."
    
end tell
end spamMailbox

on completelyDeleteMessagesFromMailbox(_mailbox)
    
tell application "Mail"
        
-- "message id" (from the Message-ID header) is not actually unique, but "id" changes when the message is moved.
        
-- Possibly a race condition here, but AppleScript sometimes fails (and is always much slower) if we try to get the "message id" from a list of messages.
        
set {_messages, _messageIDs} to {messages of _mailbox, message id of messages of _mailbox}
        
repeat with _message in _messages
            
delete _message
        
end repeat
        
set _failedMessagesIDs to my deleteMessageIDsFromTrash(_messageIDs)
        
if _failedMessagesIDs is not {} then
            
set AppleScript's text item delimiters to ", "
            
my logToConsole("Mail did not delete the messages: " & _failedMessagesIDs)
            
            
set _failedMessagesIDs to my deleteMessageIDsFromTrash(_messageIDs)
            
if _failedMessagesIDs is not {} then
                
my logToConsole("After retrying, Mail still did not delete the messages: " & _failedMessagesIDs)
            
end if
        
end if
    
end tell
end completelyDeleteMessagesFromMailbox

on deleteMessageIDsFromTrash(_messageIDs)
    
tell application "Mail"
        
set _trashedMessages to messages of trash mailbox -- Includes contents of child mailboxes.
        
set _deletedMessageIDs to {}
        
repeat with _trashedMessage in _trashedMessages
            
try
                
-- Coercion prevents building up a list of references that can make the script fail.
                
set _messageIDToDelete to (message id of _trashedMessage) as Unicode text
                
if _messageIDToDelete is in _messageIDs then
                    
delete _trashedMessage
                    
copy _messageIDToDelete to end of _deletedMessageIDs
                
end if
            
on error _error
                
my logToConsole("Error deleting message from trash: " & _error)
                
-- Sometimes Mail reports an error getting "_trashedMessage's message id", saying it can't find the message.
            
end try
        
end repeat
        
set _failedMessageIDs to {}
        
repeat with _messageID in _messageIDs
            
try
                
if _messageID is not in _deletedMessageIDs then
                    
-- Coercion prevents building up a list of references that can make the script fail.
                    
set _messageID to _messageID as Unicode text
                    
copy _messageID to end of _failedMessageIDs
                
end if
            
on error _error
                
my logToConsole("Error finding failed messages: " & _error)
            
end try
        
end repeat
        
return _failedMessageIDs
    
end tell
end deleteMessageIDsFromTrash

on logToConsole(_message)
    
set _logMessage to "SpamSieve [Discard Spam Script] " & _message
    
do shell script "/usr/bin/logger -s " & _logMessage's quoted form
end logToConsole

on lookupDefaults(_keys, _defaultValues)
    
tell application "SpamSieve"
        
try
            
set _result to {}
            
repeat with _i from 1 to count of _keys
                
set _key to item _i of _keys
                
set _defaultValue to item _i of _defaultValues
                
set _value to lookup single key _key default value _defaultValue
                
copy _value to end of _result
            
end repeat
            
return _result
        
on error -- SpamSieve 2.9.15 and earlier
            
return lookup keys _keys default values _defaultValues
        
end try
    
end tell
end lookupDefaults

Last Modified: 2014-11-06

Running the Script

You can use Script Editor (a.k.a. AppleScript Editor or AppleScript Utility) to enable Mac OS X’s built-in Script menu. Download the compiled script file and install it in the Install Location recommended above, creating any necessary folders. To run the script, just select it from the menu. FastScripts provides a similar menu that supports keyboard shortcuts and other features.