I'm trying to write an AppleScript for use with Mail (on Snow Leopard) to save image attachments of messages to a folder. The main part of the AppleScript is:
property ImageExtensionList : {"jpg", "jpeg"}
property PicturesFolder : path to pictures folder as text
property SaveFolderName : "Fetched"
property SaveFolder : PicturesFolder & SaveFolderName
tell application "Mail"
set theMessages to the selection
repeat with theMessage in theMessages
repeat with theAttachment in every mail attachment of theMessage
set attachmentFileName to theAttachment's name
if isImageFileName(attachmentFileName) then
set attachmentPathName to SaveFolder & attachmentFileName
save theAttachment in getNonexistantFile(attachmentPathName)
end if
end repeat
end repeat
end tell
on isImageFileName(theFileName)
set dot to offset of "." in theFileName
if dot > 0 then
set theExtension to text (dot + 1) thru -1 of theFileName
return theExtension is in ImageExtensionList
end if
return false
end isImageFileName
When run, I get the error:
error "Mail got an error: Can’t continue isImageFileName." number -1708
where error -1708 is:
Event wasnt handled by an Apple event handler.
However, if I copy/paste the isImageFileName() into another script like:
property ImageExtensionList : {"jpg", "jpeg"}
on isImageFileName(theFileName)
set dot to offset of "." in theFileName
if dot > 0 then
set theExtension to text (dot + 1) thru -1 of theFileName
return theExtension is in ImageExtensionList
end if
return false
end isImageFileName
if isImageFileName("foo.jpg") then
return true
else
return false
end if
it works fine. Why does Mail complain about this?
It may be a quirk, but it has an explanation. If you're in a tell application "whatever" block, all calls are made in the namespace of that application's dictionary, not your script's dictionary. Because of that, you have to explicity tell AppleScript to look back into your script for the name. Saying my is like saying tell me, instructing the script where to look for the function.
Try "my isImageFileName". It's not Mail, just a quirk of AppleScript.
Related
According to GTD and "inbox zero" I also wanted a corresponding "sent mailbox zero" by applying a rule in Apple Mail. (Why? Please, see the end of this question.)
Now, here is a simple Applescript solution: sortOut. How could it be more efficient?
The workflow is simply this
Loop through all sent messages that was a reply to some other message.
Get the message id of the message the sent message was a reply to.
Locate the mailbox for this (prior) message.
Any suggestions how to solve step 3 more efficiently will be appreciated, e.g. locating a mailbox directly based on message id, without having to use the message: protocol and then open the message and preferably not to code something like ... (in every mailbox) whose message id is mID which turns out to be rather slow.
tell application "Mail"
set i to 0
set mb1 to sent mailbox
repeat with m in ((messages of mb1) whose all headers contains "In-Reply-To")
set mID to content of header "In-Reply-To" of m
set cmd to "open 'message:" & mID & "'"
try
do shell script cmd
delay 1
set s to the selection
set m2 to item 1 of s
set mb2 to mailbox of m2
set mailbox of m to mb2
close front window
set i to i + 1
end try
end repeat
if i ≠ 1 then
set s to "s"
else
set s to ""
end if
set myMsg to (i & " message" & s & " moved successfully") as rich text
display notification myMsg with title "SortOut" subtitle "Sorting complete"
end tell
Some earlier discussions elsewhere indicate that some people may even wonder why I want this. My reason is simply that I like to have have all threads and conversations, concerning every project and deadline, collected together based on context.
When a project is finished I archive it as a completed entity for easy reference if I need to go back or follow up some things (e.g. when planning a yearly event, “Remember what I replied to this question last year?” That also means that all those conversations will have the same label in gmail.
So, instead of having almost 15000 sent emails in one mailbox, I now have them sorted into context based mailboxes—and the mailbox for sent messages is empty!
BTW, the Alfred workflow Mail Actions by Pedro Lobo is simply amazing for filing mail. My script sortOut does the rest ;-)
Sorry, Pedro, I didn't have enough reputation to post a link to your brilliant work.
I just updated the code but still could not locate the mailbox corresponding to a message id from the In-Reply-To header using Applescript (without the message:protocol).
tell application "Mail"
set i to 0
set mb1 to sent mailbox
repeat with m in ((messages of mb1) whose all headers contains "In-Reply-To")
set mID to content of header "In-Reply-To" of m
set cmd to "open 'message:" & mID & "'"
try
do shell script cmd
delay 1
set s to the selection
set m2 to last item of s
set mb2 to mailbox of m2
if name of mb2 does not contain "INBOX" then
set mailbox of m to mb2
close front window
set i to i + 1
end if
end try
end repeat
if i ≠ 1 then
set s to "s"
else
set s to ""
end if
set myMsg to (i & " message" & s & " moved successfully") as rich text
display notification myMsg with title "SortOut" subtitle "Sorting complete"
mb2
end tell
I've installed OS x 10.10.1
Now this script doesn't work:
tell application "Mail"
set theSelectedMessages to selection
set this_message to item 1 of the theSelectedMessages
tell this_message
set these_attachments to every mail attachment
repeat with z from 1 to the count of these_attachments
set this_attachment to item z of these_attachments
set this_name to the name of this_attachment as text
.........and so on
I get the message : error in the apple event Routine. The error comes in this line: "set these_attachments to every mail attachment"
In 10.9 the script worked.
WoWo
woide#wwp-service.de
G'day from the land of Oz
Your code, slightly modified, works. I think your use of 'selection' might be faulty, but haven't test it. Try 'selected mailbox'.
Regards
Brian Christmas
tell application "Mail"
set theSelectedMessages to messages of mailbox "* items to shift"
set this_message to item 1 of the theSelectedMessages
tell this_message
set these_attachments to every mail attachment
set AttachmentNames to {}
repeat with z from 1 to the count of these_attachments
set this_attachment to item z of these_attachments
set this_name to the name of this_attachment as rich text
set end of AttachmentNames to this_name as rich text
end repeat
end tell
end tell
AttachmentNames & return & z
--> {"2014-11-10 233839Z.zip", "2014-11-10 233839Z.zip", "(20141110233839Z 2).pdf", "2014-11-10 233839Z", "
", 4}
I am working on applescript and the following does not work :
I've put the file in the script folder, created a rule which find messages but the script does never happen.
I tried to flag, change the background color to no avail. The rule "test" exists.
What is wrong here?
Code :
using terms from application "Mail"
-- on perform mail action with messages selectedMessages
set today to current date
set deleteDate to today - (7 * days)
on perform mail action with messages selectedMessages for rule test
tell application "Mail"
repeat with eachMessage in selectedMessages
-- repeat with a from 1 to 5
--- Process the current message
-- set background color of eachMessage to white
-- if date received of eachMessage in selectedMessages is after deleteDate then
set background color of eachMessage to white
set flagged status to false
-- end if
-- display dialog theText
end repeat
end tell
end perform mail action with messages
end using terms from
I'm trying to trigger an error on purpose and then continue my script.
Error number -2700
triggers an "Unkown Error" error but it also ends the script with the returning value of -2700 instead of 0.
Also, I don't want the script to end after the error but to continue when you press the "OK" button.
The reason I want to do this is so that I won't have to make an Error dialog in every language myself.
Help?
(The comments mess up my code, that's why I post a new answer)
"For each language" sounds strange. Normally, you programme in a particular language and you'd write an error handling routine. In AppleScript this would be
try
-- your script here
on error errMsg number errNum
errorHandler(errMsg,errNum)
end try
on errorHandler (errMsg,errNum)
display dialog errMsg & " (" & errNum & ")."
end errorHandler
Try:
try
1 / 0
on error errMsg number errNum
tell me
activate
display alert errMsg & return & return & errNum buttons "OK"
end tell
end try
beep 3
tho is my first post - glad to have found this community :)
I'm afraid I have limited applescript knowledge but I discovered a script that will create a new message with recipients based on senders of emails in a particular mailbox.
This is almost what I need...
What I really need is a script that will create a new message with recipients based on senders of all selected emails.
I am actually astonished that this is not an option in more mail clients. It's not an option in Mail, nor Mailmate, nor Entourage.
The code I am working with is...
tell application "Mail"
set theSenderList to {}
set theMailboxes to the selected mailboxes of message viewer 0
repeat with aMailbox in theMailboxes
repeat with aMessage in messages of aMailbox
set end of theSenderList to sender of aMessage
end repeat
end repeat
set newMessage to make new outgoing message with properties {visible:true, subject:"Answers to ", content:"Here is the solution to "}
repeat with aSender in theSenderList
tell newMessage
make new bcc recipient at end of bcc recipients with properties {address:aSender}
end tell
end repeat
end tell
To access the selected messages, you can simply use selected messages instead of selected mailboxes. Once you've made this change, the loop over the selected mailboxes no longer applies. Instead, keep just the inner loop over messages.
...
set theMessages to the selected messages of message viewer 0
repeat with aMessage in theMessages
set end of theSenderList to sender of aMessage
end repeat
...
To find this sort of thing yourself:
open the AppleScript editor,
open the library window (Window → Library, or ⇧⌘L)
add the application to the library (click the plus symbol in the library window),
open the scripting dictionary for the application (double click the application in the library window)
Select the Mail suite, then the message viewer class in the browser.
You can also open a scripting dictionary via File → Open Dictionary..., or with ⇧⌘O.
In the properties for the message viewer, you'll see both "selected messages" and "selected mailbox".
The dictionary viewer uses a number of icons in the browser to indicate the type for a term
Suite: an "S" in an orange square.
Class: a "C" in a purple square.
Command: a "C" in a blue circle.
Element: an "E" in an orange square.
Property: a "P" in a purple square.
See Also
Where to find what commands/properties are available for AppleScript in Microsoft Outlook 2011?