Apple Mail - Discard Spam
Summary: Completely deletes the messages in the Spam mailbox.
Requires: SpamSieve, Apple Mail
Install Location: ~/Library/Scripts/Applications/Mail
Last Modified: 2021-08-09
Description
Note that due to a bug in Apple Mail, this script is not able to delete the messages when running on macOS 10.15 or later. However, this script is no longer needed, anyway, if you follow the Switching From the Spam Mailbox to the Junk Mailbox instructions because you can use the Erase Junk Mail command.
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).
To test this script you can run it in Script Editor (a.k.a. AppleScript Editor) and look for any error messages in the Console application. You can also enable debug logging by changing pEnableDebugLogging
from false
to true
.
In rare cases, Mail may leave some spam messages in the trash. You can work around this by setting the pRetryDelay
at the top of the script to 5
instead of 0
.
Installation Instructions · Download in Compiled Format · Download in Text Format
Script
property
pEnableDebugLogging :
false
property
pTrashingDelay : 0
property
pRetryDelay : 0
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 “" &
_spamFolderName & "” 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}
my
debugLog("Found " & (
count
of
_messages) & " messages in mailbox “" &
name
of
_mailbox & "”.")
repeat
with
_message
in
_messages
my
moveMessageToTrash(
_message)
end
repeat
delay
pTrashingDelay
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)
delay
pRetryDelay
set
_failedMessagesIDs
to
my
deleteMessageIDsFromTrash(
_messageIDs)
if
_failedMessagesIDs
is
not
{}
then
my
logToConsole("After retrying, Mail still did not delete the messages: " &
_failedMessagesIDs)
else
my
debugLog("After retrying, Mail did delete the messages: " &
_failedMessagesIDs)
end
if
else
my
debugLog("Mail deleted all the moved messages from the trash")
end
if
end
tell
end
completelyDeleteMessagesFromMailbox
on
moveMessageToTrash(
_message)
tell
application
"Mail"
try
delete
_message
my
debugLog("Moved message to trash: " &
message id
of
_message)
on
error
_error
try
set
_messageID
to
message id
of
_message
on
error
_innerError
my
logToConsole("Mail encountered an error moving unknown message to trash: " &
_error)
my
logToConsole("Message is unknown because of error getting Message-ID: " &
_innerError)
return
-- Give up on this message, but let it continue trying to move other messages to trash.
end
try
try
delete
_message
my
logToConsole("Mail encountered a temporary error moving message " &
_messageID & " to the trash: " &
_error)
on
error
_error
my
logToConsole("Mail could not move the message " &
_messageID & " to the trash because of an error: " &
_error)
end
try
end
try
end
tell
end
moveMessageToTrash
on
deleteMessageIDsFromTrash(
_messageIDs)
tell
application
"Mail"
try
set
_trashedMessages
to
messages
of
trash mailbox
-- Includes contents of child mailboxes.
on
error
_error
number
_errorNumber
if
_errorNumber
is
-1712
then
-- errAETimeout
display dialog
"Mail took too long to respond, probably because there are too many messages in the trash. Please try empting the trash before using Discard Spam again."
end
if
error
_error
number
_errorNumber
end
try
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
my
debugLog("Deleting message from trash: " &
_messageIDToDelete)
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
debugLog(
_message)
if
pEnableDebugLogging
then
my
logToConsole(
_message)
end
debugLog
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