Apple Mail - Server Junk Mailbox
Summary: Automatically applies SpamSieve to unread messages in server Junk mailboxes.
Requires: SpamSieve, Apple Mail
Install Location: ~/Library/Application Scripts/com.apple.mail or ~/Library/Scripts/Applications/Mail/
Last Modified: 2021-09-20
Description
This script is for older SpamSieve setups. If you using the Junk mailbox, as described in the “Switching From the Spam Mailbox to the Junk Mailbox” section of the manual, you should use the newer Apple Mail - Rescue Good Message script.
The junk/spam filter on your mail server can cause problems. It is more likely than SpamSieve to mistakenly classify your good messages as spam, yet it rarely catches spam messages that SpamSieve would have missed. Additionally, most people don’t want to deal with two separate spam mailboxes, one for the server junk filter and one for SpamSieve. It’s often best simply to turn off the server junk filter, however some mail servers such as iCloud do not allow this.
This script solves two problems:
- It saves you from mistakes that the server junk filter made by moving any messages that it thinks are good back to the inbox.
- It consolidates the spam messages from all the accounts into a single spam mailbox (the same one where SpamSieve is already putting your spam).
To install:
- Download the script using one of the links below. On macOS 10.8 or later, the script must be saved in the folder /Users/<username>/Library/Application Scripts/com.apple.mail. This is because Mail is sandboxed and only has access to run scripts in that folder. To access the Library folder, click on the Go menu in the Finder while holding down the Option key.
Open the script in AppleScript Editor and enter your account and junk mailbox names in
accountAndServerJunkMailboxNames()
. The account name comes from the Description field in the Accounts tab of Mail’s preferences. For example, if you have one account called Account 1 and want to process its Junk mailbox, you would use:on accountAndServerJunkMailboxNames() return {{"Account 1", {"Junk"}}} end accountAndServerJunkMailboxNames
The mailbox name is normally the same as what you see in Mail. (If you are using the special Junk mailbox, you can get its actual name from the Mailbox Behaviors tab of that account in Mail’s preferences.) You can also get the AppleScript names using the Apple Mail - List Mailboxes script. In rare cases, if you have a Gmail account you may need to enter
[Gmail]/Spam
instead ofSpam
.If you want to process the Junk mailbox of the Personal account and the Junk and Bulk mailboxes of the Work account you would use:
on accountAndServerJunkMailboxNames() return {{"Personal", {"Junk"}}, {"Work", {"Junk", "Bulk"}}} end accountAndServerJunkMailboxNames
By default, SpamSieve consolidates the spam in a mailbox called Spam under On My Mac. This configuration is specified using:
on mainSpamMailboxInfo() return {"", "Spam"} end mainSpamMailboxInfo
You can also specify a particular mailbox in one of your accounts. For example, if you had created a SpamSieveSpam mailbox in the Personal account you could specify that using:
on mainSpamMailboxInfo() return {"Personal", "SpamSieveSpam"} end mainSpamMailboxInfo
- Go to Mail’s Preferences window and create a new rule at the top of the list (above the SpamSieve rule) called Server Junk Mailbox SpamSieve.
- The rule conditions should say Every Message.
- The rule actions should say Run AppleScript […]Apple Mail - Server Junk Mailbox.scpt. First, choose Run AppleScript from the pop-up menu; then select the Apple Mail - Server Junk Mailbox.scpt file (using either the pop-up menu or the Choose… button).
To specify that each account’s spam should be collected in a separate mailbox, set pPerAccountSpamMailboxes
to true
.
Now, whenever you receive a new message in the inbox, SpamSieve will look in all the server junk mailboxes that you specified and check the unread messages. Any that are spam will be moved to the Spam mailbox. Any that are good will be moved to the inbox.
Normally, the script will run when Mail receives a new message in the inbox and applies the “Server Junk Mailbox SpamSieve” rule. You can also set up the script as a standalone application. This has less overhead than running the script from within Mail, and it allows the script to run on a more predictable schedule. To do this, use Script Editor to export the script as an application (with the Stay Open option checked) and then launch the application. You can set in the “idle” handler how often it should run.
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
.
Installation Instructions · Download in Compiled Format · Download in Text Format
Script
property
pMarkSpamMessagesRead :
false
property
pMarkGoodMessagesRead :
false
property
pChangeJunkStatus :
true
property
pColorSpamMessages :
true
property
pFlagSpamMessages :
false
property
pMoveBlueMessagesToTrash :
false
property
pMoveGrayMessagesToTrash :
false
property
pMovePurpleMessagesToTrash :
false
property
pMoveRedMessagesToTrash :
false
property
pMoveOrangeMessagesToTrash :
false
property
pMoveYellowMessagesToTrash :
false
property
pPerAccountSpamMailboxes :
false
property
pOnlyMarkSpamAsRead :
false
property
pEnableDebugLogging :
false
on
accountAndServerJunkMailboxNames()
return
{{"Account 1", {"Junk"}}}
end
accountAndServerJunkMailboxNames
on
mainSpamMailboxInfo()
return
{"", "Spam"}
end
mainSpamMailboxInfo
-- Do not modify below this line.
on
run
-- This is executed when you run the script directly.
my
filterServerJunkMailboxes()
end
run
on
idle
-- This is executed periodically when the script is run as a stay-open application.
try
my
filterServerJunkMailboxes()
on
error
_error
my
logToConsole("Error re-checking server junk mailboxes: " &
_error)
end
try
return
60 * 5
-- Run again in 5 minutes.
end
idle
using terms from
application
"Mail"
on
perform mail action with messages
_messages
-- This is executed when Mail runs the rule.
my
filterServerJunkMailboxes()
end
perform mail action with messages
end
using terms from
on
filterServerJunkMailboxes()
if
application
"Mail"
is not
running
then
return
try
tell
application
"Mail"
to
get
version
on
error
_error
number
_errorNumber
if
_errorNumber
is
-1743
then
-- errAEEventNotPermitted
set
_alertMessage
to
"You can give “Apple Mail - Server Junk Mailbox” access to control Mail and SpamSieve from System Preferences > Security & Privacy > Privacy > Automation. For more information, please see:
https://c-command.com/spamsieve/help/security-privacy-acce"
display alert
_error
message
_alertMessage
end
if
end
try
tell
application
"Mail"
try
repeat
with
_pair
in
my
accountAndServerJunkMailboxNames()
set
{
_accountName,
_mailboxNames}
to
_pair
set
_account
to
account
_accountName
repeat
with
_mailboxName
in
_mailboxNames
try
my
filterAccountMailboxNamed(
_account,
_mailboxName)
on
error
_error
number
_errorNumber
my
logToConsole("Error " &
_errorNumber & " filtering mailbox “" &
_mailboxName & "” of account “" &
_accountName & "”: " &
_error)
end
try
end
repeat
end
repeat
on
error
_error
my
logToConsole("Error filtering junk mailboxes: " &
_error)
end
try
end
tell
end
filterServerJunkMailboxes
on
filterAccountMailboxNamed(
_account,
_mailboxName)
tell
application
"Mail"
set
_mailbox
to
_account's
mailbox
_mailboxName
my
debugLog(
my
makeLogMessage("Start checking mailbox",
_mailbox, ""))
set
_total
to
count
of
messages
of
_mailbox
my
debugLog(
my
makeLogMessage("Total messages in mailbox",
_mailbox,
_total))
my
debugLog(
my
makeLogMessage("Getting unread, non-deleted messages in mailbox",
_mailbox, ""))
with
timeout
of
3 * 60
seconds
set
_messages
to
messages
of
_mailbox
whose
read status
is
false
and
deleted status
is
false
end
timeout
my
debugLog(
my
makeLogMessage("Messages to process in mailbox",
_mailbox,
count
of
_messages))
set
_spamMailbox
to
my
spamMailboxForAccount(
_account)
set
_inbox
to
my
inboxFromAccount(
_account)
repeat
with
_message
in
_messages
if
not
my
processMessageIfSpam(
_message,
_spamMailbox)
then
if
pMarkGoodMessagesRead
then
set
_message's
read status
to
true
my
moveMessage(
_message,
_inbox)
end
if
end
repeat
my
debugLog(
my
makeLogMessage("Finished checking mailbox",
_mailbox, ""))
end
tell
end
filterAccountMailboxNamed
on
processMessageIfSpam(
_message,
_spamMailbox)
set
_source
to
my
sourceFromMessage(
_message)
tell
application
"SpamSieve"
set
_score
to
score
message
_source
end
tell
tell
application
"Mail"
my
debugLog("Spam score of message is " &
_score & ": " &
_message's
subject)
set
_isSpam
to
_score ≥ 50
if
pChangeJunkStatus
then
set
_message's
junk mail status
to
_isSpam
end
if
if
_isSpam
and
(
pMarkSpamMessagesRead
or
pOnlyMarkSpamAsRead)
then
set
_message's
read status
to
true
end
if
if
not
pOnlyMarkSpamAsRead
then
set
_moveToTrash
to
my
colorMessageAndDecideIfShouldMoveToTrash(
_message,
_score)
if
_moveToTrash
then
delete
_message
else
if
_isSpam
then
my
moveMessage(
_message,
_spamMailbox)
end
if
end
if
return
_isSpam
end
tell
end
processMessageIfSpam
on
colorMessageAndDecideIfShouldMoveToTrash(
_message,
_score)
tell
application
"Mail"
set
_table
to
{¬
{99,
blue
,
pMoveBlueMessagesToTrash, 6}, ¬
{95,
gray
,
pMoveGrayMessagesToTrash, 5}, ¬
{88,
purple
,
pMovePurpleMessagesToTrash, 4}, ¬
{81,
red
,
pMoveRedMessagesToTrash, 3}, ¬
{75,
orange
,
pMoveOrangeMessagesToTrash, 2}, ¬
{50,
yellow
,
pMoveYellowMessagesToTrash, 1}, ¬
{0,
none
,
false
, -1}}
-- Flag colors chosen so that messages sort by spamminess: gray, purple, blue, green, yellow, orange, none
repeat
with
_row
in
_table
set
{
_threshold,
_color,
_moveToTrash,
_flagColor}
to
_row
if
_score ≥
_threshold
then
if
pColorSpamMessages
then
set
_message's
background color
to
_color
end
if
if
pFlagSpamMessages
then
set
_message's
flag index
to
_flagColor
end
if
return
_moveToTrash
end
if
end
repeat
end
tell
end
colorMessageAndDecideIfShouldMoveToTrash
on
spamMailboxForAccount(
_account)
if
pPerAccountSpamMailboxes
then
tell
application
"Mail"
set
{
_accountName,
_mailboxName}
to
my
mainSpamMailboxInfo()
try
return
mailbox
_mailboxName
of
_account
on
error
_error
my
logToConsole("Error getting per-account spam mailbox: " &
_mailboxName)
end
try
end
tell
end
if
return
my
mainSpamMailbox()
end
spamMailboxForAccount
on
mainSpamMailbox()
set
{
_accountName,
_mailboxName}
to
my
mainSpamMailboxInfo()
tell
application
"Mail"
if
_accountName
is
""
then
return
mailbox
_mailboxName
else
return
mailbox
_mailboxName
of
account
_accountName
end
if
end
tell
end
mainSpamMailbox
on
inboxFromAccount(
_account)
tell
application
"Mail"
set
_names
to
{"INBOX", "Inbox", "innboks", "Posteingang", "Boite de reception"}
repeat
with
_name
in
_names
try
set
_mailbox
to
mailbox
_name
of
_account
return
_mailbox
end
try
end
repeat
return
inbox
end
tell
end
inboxFromAccount
-- Logging
on
debugLog(
_message)
if
pEnableDebugLogging
then
my
logToConsole(
_message)
end
debugLog
on
logToConsole(
_message)
set
_logMessage
to
"SpamSieve [Apple Mail Server Junk Mailbox MJTLog] " &
_message
do shell script
"/usr/bin/logger -s " &
_logMessage's
quoted form
end
logToConsole
on
makeLogMessage(
_action,
_mailbox,
_detail)
return
_action & " " &
my
describeMailbox(
_mailbox) & ": " &
_detail
end
makeLogMessage
on
describeMailbox(
_mailbox)
tell
application
"Mail"
set
_mailboxName
to
_mailbox's
name
try
set
_accountName
to
name
of
_mailbox's
account
on
error
set
_accountName
to
"On My Mac"
end
try
return
"“" &
_accountName & "” / “" &
_mailboxName & "”"
end
tell
end
describeMailbox
-- Logging Helpers
on
sourceFromMessage(
_message)
tell
application
"Mail"
my
debugLog(
my
makeLogMessage("Getting source of message in",
_message's
mailbox
,
_message's
subject))
return
_message's
source
end
tell
end
sourceFromMessage
on
moveMessage(
_message,
_mailbox)
tell
application
"Mail"
my
debugLog(
my
makeLogMessage("Moving message to",
_mailbox,
_message's
subject))
set
_message's
mailbox
to
_mailbox
end
tell
end
moveMessage