I'm attempting to modify an applescript that fires a growl notification when there is a new message in Outlook. The original script is here.
In my if statement, I am trying to say that if the folder is either Deleted Items, Junk E-mail or Sent Items, don't fire the notification.
Here is the statement:
if folder of theMsg is "Junk E-mail" or "Deleted Items" or "Sent Items" then
set notify to false
else
set notify to true
end if
It appear that applescript does not like the multiple is/or items I've added. Is there a way to include the multiple criteria, or do I need to write a nested if/then?
The correct way to chain if conditions in AppleScript is to repeat the full conditional:
if folder of theMsg is "A" or folder of theMsg is "B" or folder of theMsg is "C" then
– there is no implicit repetition of the left hand argument. A more elegant way to do this is to compare your left hand argument to a list of items:
if folder of theMsg is in {"A", "B", "C"} then
which has the same effect (note this relies on the implicit coercion of text to list, which, depending on your tell context, may fail. In that case, explicitly coerce your left, i.e. (folder of theMsg as list)).
When including multiple criteria in your conditional statements, you must rewrite the entire conditional. This can be extremely tedious at times, but that's just the way AppleScript works. Your expression would become the following:
if folder of theMsg is "Junk E-mail" or folder of theMsg is "Deleted Items" or folder of theMsg is "Sent Items" then
set notify to false
else
set notify to true
end if
There is a workaround, though. You can initialize all of your criteria into a list and see if your list contains a match:
set the criteria to {"A","B","C"}
if something is in the criteria then do_something()
Having come accross this post by Googling "applescript if multiple conditions" and didn't came accross the code snippet I was expecting here is what's I've done (just for informative purposes) :
You could also recursively scan multiple conditions. The following example is :
— Looking if the sender e-mail address contains (Arg 1.1) something (Arg 2.1.1 and 2.1.2) to immediately stop the script and "notify" => true (Arg 3.1).
— Looking if the folder/mailbox (Arg 1.2) starts with "2012" (Arg 2.2.1) but is not folder 2012-A B or C (Arg 2.2.2) if it doesn't start with 2012 or is contained in one of the 3 folders stop and do nothing => false (Arg 3.2).
if _mc({"\"" & theSender & " \" contains", "\"" & (name of theFolder) & "\""}, {{"\"#me.com\"", "\"Tim\""}, {"starts with \"2012\"", "is not in {\"2012-A\", \"2012-B\", \"2012-C\"}"}}, {true, false}) then
return "NOTIFY "
else
return "DO NOTHING "
end if
-- multiple conditions comparaison via a shell script
on _mc(_args, _crits, _r)
set i to 0
repeat with _arg in _args
set i to i + 1
repeat with _crit in (item i of _crits)
if (item i of _r) as text is equal to (do shell script "osascript -e '" & (_arg & " " & _crit) & "'") then
return (item i of _r)
end if
end repeat
end repeat
return not (item i of _r)
end _mc
https://developer.apple.com/library/mac/#documentation/AppleScript/Conceptual/AppleScriptLangGuide/conceptual/ASLR_about_handlers.html#//apple_ref/doc/uid/TP40000983-CH206-SW3
Try:
repeat with theMsg in theMessages
set theFolder to name of theMsg's folder
if theFolder is "Junk E-mail" or theFolder is "Deleted Items" or theFolder is "Sent Items" then
set notify to false
else
set notify to true
end if
end repeat
Although the other two answers solve the multiple criteria correctly, they won't work unless you specify name of theMsg's folder or you will get
mail folder id 203 of application "Microsoft Outlook"
Related
I am brand new to Applescript. I would like a script that would list the artist and the number of songs in that artist's folder. I would like to do it just for artists whose names starts with A. When I am ready, I would then get the list for artist whose names starts with B, and so on. I did find this post: "What's the fastest way in iOS to retrieve the number of songs for a specific artist?" Maybe that script would work but I don't know how to modify this line "if (artistName != nil)" to get what I want. Also, I don't know where the information is stored so I can retreive it "// store the new count
[artists setObject:[NSNumber numberWithInt:numSongs] forKey:artistName]; Oh, and I am not using iOS I will be using osx. Perhaps I could modify this script that I found. It gets the number of albums by artist.
MPMediaQuery *albumQuery = [MPMediaQuery albumsQuery];
NSArray *albumCollection = [albumQuery collections];
NSCountedSet *artistAlbumCounter = [NSCountedSet set];
[albumCollection enumerateObjectsUsingBlock:^(MPMediaItemCollection *album, NSUInteger idx, BOOL *stop) {
NSString *artistName = [[album representativeItem] valueForProperty:MPMediaItemPropertyArtist];
[artistAlbumCounter addObject:artistName];
}];
NSLog(#"Artist Album Counted Set: %#", artistAlbumCounter);
I appreciate any help that you can offer. Thanks!
It makes no sense to look at iOS code and ObjectiveC at that in order to figure out what you should do with Applescript! In any case, here is what you want.
tell application "iTunes"
# Get playlist currently selected
set myPlayList to view of window 1
set s to (every track in myPlayList whose artist begins with "g")
repeat with t in s
log name of t
end repeat
log (count of s)
end tell
This one uses the selected playlist (or, if that fails for some reason, the whole library) and goes from A to Z. Replace the log parts with your code. To see how it works make sure in Script-Editor it shows the Log and for a better view select the Messages tab. Only file tracks are handled.
tell application "iTunes"
try
set selectedPlayList to view of window 1
on error
beep
set selectedPlayList to (container of browser window 1) -- whole library (I think)
end try
end tell
set totalItems to 0
repeat with i from (id of "A") to (id of "Z")
set thisLetter to (character id i)
log "-----------------------------------------------------------"
tell application "iTunes"
try
set currentItems to (file tracks in selectedPlayList whose artist begins with thisLetter)
set countItems to number of items in currentItems
set totalItems to totalItems + countItems
set s to "s"
if countItems = 1 then set s to ""
log (countItems as text) & " item" & s & " for artists starting with the letter " & quoted form of thisLetter
log "-----------------------------------------------------------"
repeat with i from 1 to countItems
set thisItem to item i of currentItems
tell thisItem -- this is like "tell file track x". Shortens the code because we can use "artist" instead of "artist of thisItem"
log (i as text) & ". " & quoted form of (get artist) & " | " & quoted form of (get name) & " [ " & time & " ] "
end tell
end repeat
on error the error_message number the error_number
beep
display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
return
end try
end tell
end repeat
log "-----------------------------------------------------------"
log "Items: " & totalItems as text
Ive been playing with applescript for about 2 weeks now, but I have hit a problem
Im trying to create an applescript that reads all the names of the folders on our server.
Then displays them in a drop down menu so that I can select the client.
The problem I have is that it is displaying the result as one selection option as a big sentence and is not separating each client, so they can be selected individually.
so far I have:
set theFolder to alias "server:"
tell application "Finder"
set theText to name of theFolder & return
set k to 0
repeat with thisSubfolder in (get folders of theFolder)
set k to k + 1
set theText to theText & name of thisSubfolder & return
end repeat
end tell
set l to {theText}
set l2 to ""
repeat with i in l
set l2 to l2 & quoted form of i & " "
end repeat
do shell script "/Applications/CocoaDialog.app/Contents/MacOS/CocoaDialog \\
standard-dropdown --title Title --text Text --items " & l2
set {button, answer} to paragraphs of result
if button is 1 then
return item {answer + 1} of l
end if
Many thanks
D
When you do this:
set l to {theText}
You're just creating a list of one item (your string), which means you end up with this:
{"theFolder
folder1
folder2
folder3
"}
You're then repeating in that "list," trying to add spaces between the items. But, you don't have a list really. You have a one item list, with return-delimited strings.
The best way to get a list of folder names would be to get them from System Events. Notice that in this case, you have to create a list with the name of the first folder as the only item. Otherwise, the & operation will join everything together as a string, instead of creating a list.
tell application "System Events"
set l to (name of theFolder as list) & name of folders of theFolder
end tell
There are also some syntactical issues that will hurt you later:
1 != "1"
CocoaDialog returns a string, with the button number: "1". You are using if button is 1. For equality, it should be if button is "1".
Parentheses are used for grouping, not brackets
If button is "1", you are returning item {answer + 1} of l. I blame Applescript for letting this work when it shouldn't. You're actually creating a list with a number, which then gets coerced by Applescript for the list index. Here are all the steps, assuming answer is 0:
item {answer + 1} of l gets turned into
item {1} of {folder1, folder2, folder3}
Applescript coerces to item 1 of {folder1, folder2, folder3}
Value returned: folder1
Here is a fully updated version of your script:
set theFolder to alias "server:"
tell application "System Events"
set l to {name of theFolder} & name of folders of theFolder
end tell
set args to ""
repeat with i from 1 to (count l)
set args to args & quoted form of item i of l
if i < (count l) then
set args to args & " "
end if
end repeat
do shell script "/Applications/CocoaDialog.app/Contents/MacOS/CocoaDialog \\
standard-dropdown --title Title --text Text --items " & args
set {button, answer} to paragraphs of result
if button is "1" then
return item (answer + 1) of l
end if
Change the line:
set l to {theText}
to:
set l to paragraphs of theText
and you should be good to go.
trying to send several mails with specific attachments for each address. every address has its own subfolder for attachments. the "grab attachments part" does not work and I am not sure if the handler is set up right: should I pass the subfolder to mail inside the handler or keep it as I have it. This is my first long script so please don't be too harsh ;-)
I'm thinking that i get closer to the working solution, I still don't get it to function. here is my script so far:
` with timeout of 600 seconds
-- Liste: Alle Empfänger
tell application "Contacts"
set emailList to {}
set testPersons to every person of group "Test"
repeat with thisTestPerson in testPersons
set end of emailList to (value of email of thisTestPerson) as string
end repeat
end tell
-- Liste fuer die Übergabe alphabetisch sortieren
set the_list to emailList
set otid to AppleScript's text item delimiters
set AppleScript's text item delimiters to {ASCII character 10} -- always a linefeed
set list_string to (the_list as string)
set new_string to do shell script "echo " & quoted form of list_string & " | sort -f"
set new_list to (paragraphs of new_string)
set AppleScript's text item delimiters to otid
-- Liste: Alle Subfolder
tell application "Finder"
set mainfolder to choose folder "select a folder"
set folderList to {}
set myFolders to every folder of mainfolder
repeat with attachFolder from 1 to (count of myFolders)
set end of folderList to attachFolder as string
end repeat
end tell
-- Sicherheits-Check
set count1 to count of myFolders
set count2 to count of new_list
if count1 is not equal to count2 then
display dialog "Houston, we have a problem:" & return & "Die beiden Listen sind nicht gleich lang..." buttons {"ok"} with icon 2
return
end if
end timeout
--handler processfolder(myFiles)
on processfolder(myFiles)
tell application "Mail"
activate
set theAddress to (item i of emailList)
set theMex to (make new outgoing message at end of outgoing messages with properties {visible:true, subject:"Subjectheader", content:"email body"})
tell content of theMex
make new attachment with properties {file name:FileList} at after last paragraph
end tell
tell theMex
make new to recipient at end of to recipients with properties {address:theAddress}
end tell
send theMex
end tell
end processfolder
-- grab attachments and send mail
tell application "Finder"
repeat with myFolder from 1 to (count of folderList)
set FileList to {}
set myFiles to entire contents of myFolder
repeat with thisFile in myFiles
set end of FileList to thisFile as string
end repeat
my processfolder(myFiles)
end repeat
end tell
display dialog (count1 as string) & " Nachrichten verschickt."
end`
i believe the handler should work alright. Matching the subfolder list with the address list still seems to be a problem, I am not sure if my repeat loop "grab attachment und send mail" does the trick. It is a tricky use of repeat loops and I am still struggling with it. any quick thoughts about what I am still doing wrong?
thanks for being helpful! i really appreciate this!
marco
You must pass the variables as parameters in the handler :
1- (item i of emailList) : i and emailList is not defined in the handler.
2- {file name:FileList} : FileList is not defined in the handler, file name must be a path of type alias or string, not a list of path.
set myFiles to entire contents of myFolder : the myfolder variable is an integer, entire contents will contains the folders and files, if the folder doesn't contains subfolders, entire contents is useless, use files of xFolder.
The rest is okay, but contains unnecessary lines.
Here is the script:
with timeout of 600 seconds
-- Liste: Alle Empfänger
tell application "Contacts"
set emailList to value of email 1 of every person of group "Test"
end tell
-- Liste fuer die Übergabe alphabetisch sortieren
set otid to AppleScript's text item delimiters
set AppleScript's text item delimiters to {linefeed}
do shell script "echo " & (quoted form of (emailList as string)) & " | sort -f"
set emailList to (paragraphs of the result)
set AppleScript's text item delimiters to otid
-- Liste: Alle Subfolder
activate
set mainfolder to choose folder "select a folder"
tell application "Finder" to set folderList to folders of mainfolder
-- Sicherheits-Check
set count1 to count folderList
if count1 is not equal to (count emailList) then
display dialog "Houston, we have a problem:" & return & "Die beiden Listen sind nicht gleich lang..." buttons {"ok"} cancel button "ok" with icon 2
end if
end timeout
-- grab attachments and send mail
repeat with i from 1 to count1
try
tell application "Finder" to set myFiles to (files of entire contents of (item i of folderList)) as alias list
my processfolder(myFiles, item i of emailList)
end try -- no error on empty folder
end repeat
display dialog (count1 as string) & " Nachrichten verschickt."
on processfolder(tFiles, theAddress)
tell application "Mail"
activate
tell (make new outgoing message at end of outgoing messages with properties {visible:true, subject:"Subjectheader", content:("email body" & linefeed & " ")})
make new to recipient at end of to recipients with properties {address:theAddress}
tell content to repeat with tFile in tFiles
make new attachment with properties {file name:tFile} at after last paragraph
make new character with data linefeed at after last paragraph
end repeat
send
end tell
end tell
end processfolder
it is done! Thanks to you and one or two other pros I now have a beautiful bulk mailing script routine using automator, a bash line and (mainly) applescript. I use it for job applications but you can use it for any case where you want individualised bulk emailing with Mail, MS Word and any given list of contacts in Excel (or Address Book for that matter). For the sake of being complete I will add all necessary steps. with any given list of x names, email addresses, personal addresses you can generate x subfolders, containing x personalized letters and not-personalized documents (thanks, Jack! adding the docs works perfectly). once you start the last script and select the folder you can watch mail sending them all out, addressing the person by name and attaching the right personalized letter! It corrects for foreign name spelling that is rendered differently in the email address. It works best for email addresses using the last name before the "#" and can now ignore the first name if it is set in front of the last name (i.e. firstname.lastname#company.com). Thank you all very much for the assistance! this was great team effort.
I shall post it as soon as I am home, should I post it up here and in the other related question or is there a sharing forum?
I want to get the recipients ("to" fields, etc) of a draft on my draft's folder of Mail.app, by using AppleScript. Can't seem to find the correct syntax to that.
Thanks.
Here's code to do it, in Scripting Bridge (Cocoa):
for (MailRecipient *recp in message.recipients) {
MailToRecipient *theRecipient = [[[mail classForScriptingClass:#"to recipient"] alloc] initWithProperties:[NSDictionary dictionaryWithObjectsAndKeys:recp.address, #"address", nil]];
}
Actually it is possible with pure AppleScript unlike the Cocoa solution proposed earlier. Here's a snippet of the code used to get the input values of the "TO" recipients field.
tell application "Mail"
set draftMessages to every message in drafts mailbox
set draftMessagesID to {}
# go through each draft message
repeat with draftMessage in draftMessages
set draftMessageID to id of draftMessage as string
copy draftMessageID to the end of draftMessagesID
end repeat
# go through the list of draft message ids and process the most recent item
if (count of the draftMessagesID) is greater than 1 then
set sortedDraftMessagesID to the reverse of my sortAlphabetically(the draftMessagesID)
# get only the first item, as this is the most recent
set lastDraftMessageID to first item of sortedDraftMessagesID as integer
# get the most recent draft message
set draftMessage to first message of drafts mailbox whose id is lastDraftMessageID
set toAddresees to {}
repeat with toRecipient in (get to recipients of draftMessage)
set toName to name of toRecipient
set toAddress to address of toRecipient
set toFinal to my composeNameAndAddress(toName, toAddress)
copy toFinal to end of toAddresees
end repeat
# now you have the input values of the TO field
log toAddresees
end if
end tell
#handler to compose name and address when one is missing
on composeNameAndAddress(name, address)
if name is missing value then
return address
else
return name & space & "<" & address & ">"
end if
end composeNameAndAddress
#handler to sort a list alphabetically
on sortAlphabetically(theList)
set the indexList to {}
set the sortedList to {}
repeat (the number of items in theList) times
set the lowItem to ""
repeat with i from 1 to (number of items in theList)
if i is not in the indexList then
set thisItem to item i of theList as string
if the lowItem is "" then
set the lowItem to thisItem
set the lowItemIndex to i
else if thisItem comes before the lowItem then
set the lowItem to thisItem
set the lowItemIndex to i
end if
end if
end repeat
set the end of sortedList to the lowItem
set the end of the indexList to the lowItemIndex
end repeat
return the sortedList
end sortAlphabetically
You mentioned that you needed a specific draft, for this script I've assumed that you can (for instance) obtain the latest draft by taking the draft message with the highest ID. This is what the above script does using the reverse command with a generic simple sort handler.
The drafts mailbox is contained by the message viewer. Since the messages have not been sent yet, you cannot get its "to recipients". However, you can get the message source that contains the list of recipients. The trick is to then extract the recipients from this text.
tell application "Mail"
set the_messages to every message in drafts mailbox
repeat with this_message in the_messages
set message_content to the source of this_message
log message_content
end repeat
end tell
I've created the following AppleScript for deleting all the selected tracks:
property okflag : false
-- check if iTunes is running
tell application "Finder"
if (get name of every process) contains "iTunes" then set okflag to true
end tell
if okflag then
tell application "iTunes"
if selection is not {} then
repeat with this_track in selection
try
try
set cla to class of this_track
set floc to (get location of this_track)
delete this_track
on error error_message number error_number
display alert error_message message ("Error number: ") & error_number & "."
end try
if cla is file track then
my delete_the_file(floc)
end if
end try
end repeat
end if
end tell
end if
to delete_the_file(floc)
try
-- tell application "Finder" to delete floc
do shell script "mv " & quoted form of POSIX path of (floc as string) & " " & quoted form of POSIX path of (path to trash as string)
on error
display dialog "Track deleted, but could not be moved to trash" buttons {"Hmm"} default button 1 with icon 1
end try
end delete_the_file
It works fine when I select a single item, but when I select more than one I get: "Can't get location of item 2 of selection" (error number -1728). I believe this is because by deleting a track, the script's index into the selection is corrupted.
I thought I'd try making my own list of tracks to be deleted first:
tell application "iTunes"
if selection is not {} then
set to_delete to {}
repeat with this_track in selection
try
set cla to class of this_track
set floc to (get location of this_track)
if cla is file track then
set pair to {this_track, floc}
set to_delete to to_delete & pair
end if
end try
end repeat
repeat with pair in to_delete
set the_track to item 1 of pair
set floc to item 2 of pair
delete the_track
my delete_the_file(floc)
end repeat
end if
end tell
But then I get 'Can't get item 1 of item 1 of selection of application "iTunes".' I think the problem is "this_track" is not an object of class Track, but an item of a selection. How do I get the actual track object from the selection item?
If you don't see the solution, I'll welcome tips on debugging or any other suggestions.
The variable this_track is a reference to an object specifier. You have to use the contents property to get the enclosed object specifier. The same is true for accessing the variable pair in the second loop. See the class reference section on the class reference in the AppleScript language guide.
Another problem exists in the way the list to_delete is being built. The statement set to_delete to to_delete & pair will not produce a list of pairs but a flat list. See the class reference section on the class list in the AppleScript language guide.
Here's a version of your second script, where these bugs have been removed:
tell application "iTunes"
if selection is not {} then
set to_delete to {}
repeat with this_track in selection
try
set cla to class of this_track
set floc to (get location of this_track)
if cla is file track then
set pair to {contents of this_track, floc}
copy pair to end of to_delete
end if
end try
end repeat
repeat with pair in to_delete
set the_track to item 1 of contents of pair
set floc to item 2 of contents of pair
delete the_track
my delete_the_file(floc)
end repeat
end if
end tell