I don't use Mail.app and haven't much experience implementing Mail actions, so am not in the position to test your script. However, reading through it, there are places in it of potential concern that I would wish to look to first when debugging.
How large is your "News" mailbox ?
There are two features in your script that threaten it to hang or timeout:
1. set EveryMessage to every message of TargetInbox
If that mailbox has thousands or even hundreds of emails in it, retrieving every message
as a list of individually referenced message
objects (which is what this statement is doing) could take some time. It's almost always way more efficient and less intensive on processor and memory usage to store a reference to
the every message
object (collection):
set EveryMessage to a reference to every message of the TargetInbox
It has another beneficial feature that I'll address later.
2. Potentially demanding nested repeat
loops
Nested loops are a necessary evil sometimes, but the query about the mailbox size is, again, a source of anxiety for me, especially since its called upon in at the heart of the nest where the bulk of the operations are done. This means that, for each new message that triggers the script, every single message in the mailbox has to be checked and compared to the trigger message.
These are two branches of one issue, really, because if your mailbox only has 5 messages in it, none of this is particularly bothersome. Otherwise, you're first getting AppleScript to retrieve every message in the mailbox and store them in a variable; then cycling through this potentially heavy load and comparing each item to another.
If you had no choice but to use a repeat
loop whilst knowing that it would have to iterate through a lot of list items (once you exceed about 500 of anything, AppleScript can begin to buckle) it can help, once again, to pass AppleScript a reference to the list of items instead of the actual list. Passing any reference through a script object (which is what a reference to
essentially does), is much, much faster than making AppleScript access an object by other means. Here's an excellent explanation and demonstration of these principles.
Simple changes and error corrections
After addressing the heavy issue above, which could turn out to be of little relevance to your particular case, here are one or two de facto elements that are easily changed to either improve the efficiency of the script, or prevent it throwing an error:
1. Placement of variable declarations
set eachSender to the sender of eachMessage
This line is currently declared inside the inner repeat
loop, which also happens to be the the meatier of the two, in general hypothetical terms. However, what this is doing is setting the value of the variable eachSender
to the same value for as many messages you have in your mailbox. That's a lot of wasted operations for AppleScript (a total of the number of these_messages
multplied by the number of EveryMessage
).
Instead, move it to here:
repeat with eachMessage in these_messages
set eachSender to the sender of eachMessage # ...now it's here
repeat with this_message in EveryMessage
# It was here...
.
.
.
end repeat
end repeat
Now AppleScript only has to set the variable once for eachMessage
in these_message
. That's an efficiency improvement of polynomial time down to linear time!
2. set messageDate to date received of EveryMessage
Initially, I thought you were trying to access the EveryMessage
object as a reference to the collection I spoke of earlier, and simply didn't realise you couldn't do that in the way you declared EveryMessage
.
But, I now realise it was most likely just your hands typing faster than your thoughts, and introducing an irksome typo. EveryMessage
here ought to bethis_message
, i.e.:
set messageDate to date received of this_message
This leads me quite nicely onto my final point, which I hinted at earlier, regarding the other benefit of declaring a variable to an object collection as a reference.
Had you done this:
set EveryMessage to a reference to every message of the TargetInbox
then this:
set messageDate to date received of EveryMessage
would be a perfectly valid piece of AppleScript, which allows you to access the property of every single item in a list IFF done so through a reference to that list before any sort of dereferencing has taken place. Once it's dereferenced, list is evaluated into individual object references, and it will no longer give you the means to enumerate through its properties in that manner.
What you get if done correctly is list containing the values of the date received
property of every message of the TargetInbox
, all through a single line of AppleScript.
Currently, as this wasn't how you implemented it, the declaration for set messageDate
will definitely throw an error.
This explains why none of the deletions are occurring, because your script will never successfully reach that part. However, the error would occur immediately, so my feeling is the script isn't even reaching that line either, not even once. Therefore, the problem must originate from a point in the script before it ever successfully enters the inner repeat
loop. And you already know my hunch about that.
Now for a potential solution
I'm sorry that I can't actually test my script to verify that this will definitely work first time without any tweaks, so tell me how you get on with this:
using terms from application "Mail"
on perform mail action with messages these_messages
tell application "Mail"
set everyMessage to a reference to messages in mailbox "News" of account "iCloud"
repeat with eachMessage in these_messages
delete (everyMessage where ¬
the date received is not the (current date) ¬
and its sender is the sender of eachMessage)
end repeat
end tell
end perform mail action with messages
end using terms from
As you can see, I've done away completely with the inner most repeat
loop thanks to the use of the a reference to
operator. As I declared everyMessage
in that manner, I am (hopefully) able to enumerate the properties of all the items the list contains in one go, which should be approximately infinity times faster than having to check the property for each item individually.
display dialog "Hi"
, which is like the JavaScript equivalent of alert("Hi"), in the repeats to check if they are reappearing correctly. Then you switch out Hi with a variable that you use (such asthis_message
) so you can make sure that the variable is correct.display dialog
as a kind ofconsole.log
for debugging. Will give it a try.