Automator: Select only one file out of many files in a folder. Script needed

applescriptautomatorfilefolderstext;

I have a folder with different 100 rtf-text-files in a folder.

I would like to have Automator to take the content of one text-file and send out it out via mail once a day to the same mailing-addresses – without sending the same text twice.

Because I am a newbie and don’t find a way to filter out only one rtf file with Automator’s predefined actions, I think I have to create a script.

What I’ve got so far:

New Application:

  1. Find Finder-Item: I chose the folder with the files. Condition: File extension is rtf —> now I’ve got all (3 test-)rtf’s as result.

(*)

  1. Open Finder-Item: Open with default application
  2. Get Contents of TextEdit Document
  3. New Mail Message

What this workflow does: It opens all rtf-files in TextEdit. Then a new Mail-Window opens and displays the content of the last opened textfile. Of cause it does’t send it.

I think I have to include a step/script where the (*) is, so Automator has a specific rtf-file to pass to the next steps.
Can you please help me to find this step or show me how to create a script? Or maybe you know another solution?

enter image description here

Best Answer

When wanting to randomly choose from a group of files, to send the contents thereof as an email, while ensuring the content from each file is used only once, requires maintaining a list of filenames from which the content has already been sent. There are quite a few different ways this list can be created, accessed and maintained.

Staying away from Automator and using AppleScript for the entire process, the easiest would be as an AppleScript property variable, however an AppleScript property variable gets reset if the script is recompiled in Script Editor and or saved again after it's been originally saved.

This is not necessarily a problem, if once the script has been properly configured to meet the needs and is functioning properly during testing, it is then saved as an application and not modified or saved again after the initial run of it having been saved as an application. If that might be an issue, then the list will need to be saved as a disk file. (Personally, I'd choose to use the disk file.)

Saving the list of filenames from which the content has already been emailed as a disk file can also be done in a number of ways. You essentially need to pick one of the possible ways and code it accordingly.

The following AppleScript code examples, shows two ways to accomplish the overall task. The first, using an AppleScript property variable and the second using a disk file, to maintain the list.

  • Note: In one of my comments, I asked "Do the files have to be Rich Text or can they be Plain Text?", and the reason for this is, as Plain Text the file would not need to be opened in the GUI to retrieve the contents, where as with Rich Text it would need to be opened in .e.g. TextEdit to retrieve the contents. Not having to do it through the GUI is faster and visually less obtrusive. Also, if this is done in Automator using the Get Contents of TextEdit Document action, it retrieves the contents as plain text anyway. So, it is actually advantageous to use Plain Text files over Rich Text to begin with. These examples are coded to use Rich Text and TextEdit, with a modification shown afterwards if using Plain Text.

In the first example AppleScript code, there are some variables which you'll need to set:

  • thisFolder - The location of the folder containing the 100 files.
  • theRecipientName - The Name of the Email Recipient.
  • theRecipientAddress - The Email Address of the Email Recipient.
  • theSubject - The Subject of the Email Message.

In the second example AppleScript code, in addition to the variables shown above:

  • theAlreadySentListFilename - The location and name of the file containing the filenames from which the content has already been sent.

The remainder of the script is coded in a manner (tokenized) to work with these variables and others set within the script. Also, the tell application "Mail" block of code is coded to send the message automatically, however it has been commented out, until testing is done and or if not wanting to automatically send. Uncomment accordingly.

To use this script, in Script Editor, create a new document and save it as an application in /Applications, naming it as, e.g. 100 Messages to Send.app.

Next, copy and paste the example AppleScript code below into the 100 Messages to Send.app in Script Editor and hit the Compile button on the Toolbar.

Modify the variables, mentioned earlier above.

Save the app and test from within Script Editor.

Once done with testing, hit the Compile button on the Toolbar to reset the theAlreadySentList AppleScript property variable to an empty list, then save and close the 100 Messages to Send.app so as not to reset the theAlreadySentList AppleScript property variable once production mode begins.

First example AppleScript code:

--  ### Folder Path Variable

--  # Set the location of the folder containing the 100 files.
--  # NOTE: All 100 files must be in the same individual folder.

set thisFolder to (path to documents folder as text) & "100 Messages to Send"

--  ### Mail Variables

set theRecipientName to "John Doe"
set theRecipientAddress to "johndoe@domain.com"
set theSubject to "Hello World"
--  # Leave the following as 'missing value'.
set theMessageContent to missing value


--  ##### DO NOT modify below this line unless necessary. #####


--  ### Some Other Variables

--  # The property variable  'theAlreadySentList',  is a list of 
--  # filenames from which the messages have already been sent.
--  # The value of this property is maintained so long as
--  # this script is not save again or recompiled after it
--  # has been originally saved for the first time.

property theAlreadySentList : {}
global thisFile

--  ### Handler

on chooseRandomFileFrom(thisFolder)
    tell application "Finder"
        set thisFile to some file of container thisFolder
    end tell
    return thisFile
end chooseRandomFileFrom

--  # Get the count of entries in the 'theAlreadySentList' list.
--  # This is used to display a message and break the 'repeat' loop
--  # once all 100 messages have been sent.

set theCount to (count of theAlreadySentList) as integer

--  # Choose a file at random.

set thisFileName to name of chooseRandomFileFrom(thisFolder)

--  # Evaluate the sent status of 'thisFileName' and respond accordingly.

repeat -- 200 times -- # Uncomment if you want a failsafe out of the 'repeat' loop.
    if theCount is equal to 100 then
        display dialog "All 100 messages have already been sent!" buttons {"OK"} default button 1
        exit repeat
    else if thisFileName is in theAlreadySentList then
        --  # Choose another file at random.
        set thisFileName to name of chooseRandomFileFrom(thisFolder)
    else
        --  # This file has not been used yet, process accordingly.
        set end of theAlreadySentList to thisFileName
        tell application "TextEdit"
            open thisFile
            activate
            delay 1 --# Adjust as necessary. Time must be given for the file to open before proceeding.
            set theMessageContent to text of front document
            close front document
        end tell
        tell application "Mail"
            activate
            set theMessage to make new outgoing message with properties {visible:true, subject:theSubject, content:theMessageContent}
            tell theMessage
                make new to recipient at end of to recipients with properties {name:theRecipientName, address:theRecipientAddress}
            end tell
            -- delay 1 --# Adjust as necessary. Uncomment to use this command.
            -- send theMessage --# Uncomment to use this command.
        end tell
        exit repeat
    end if
end repeat

In this second example AppleScript code, a disk file is used to store the list of filenames from which the content has already been sent as an email message.

To use this script, in Script Editor, create a new document and save it as an application in /Applications, naming it as, e.g. 100 Messages to Send.app. This is done so you can add a plain text file to the application bundle to use for the list of filenames already sent. (I prefer to keep related support files within the application bundle.)

Having saved the document as an application, now open the application bundle (in Finder, right-click Show Package Contents) to Contents/Resources/ and create the, e.g. Sent Messages Filename List.txt file as an empty file, and then close the application bundle.

Next, copy and paste the example AppleScript code below into the e.g. 100 Messages to Send.app in Script Editor and hit the Compile button on the Toolbar.

Modify the variables, as mentioned earlier above.

Save the app and test from within Script Editor.

Once done with testing, clear the entries from the Sent Messages Filename List.txt, so it's an empty file when running the app for the first time in production mode.


Second example AppleScript code:

--  ### Folder Path Variable

--  # Set the location of the folder containing the 100 files.
--  # NOTE: All 100 files must be in the same individual folder.

set thisFolder to (path to documents folder as text) & "100 Messages to Send"

--  ### Mail Variables

set theRecipientName to "John Doe"
set theRecipientAddress to "johndoe@domain.com"
set theSubject to "Hello World"
--  # Leave the following as 'missing value'.
set theMessageContent to missing value

--  ### Sent Messages Filename List Location Variable

--  # Set the location and name of the file containing the 
--  # filenames from which the content has already been sent.

set myPath to POSIX path of (path to me as string)
set theAlreadySentListFilename to myPath & "Contents/Resources/Sent Messages Filename List.txt"


--  ##### DO NOT modify below this line unless necessary. #####


--  ### Some Other Variables

global thisFile
global theAlreadySentList
set theAlreadySentList to {}

--  ### Handlers

on buildListFromDiskFile(thisDiskFile)
    set thisContent to do shell script "cat " & quoted form of thisDiskFile
    repeat with thisParagraph in paragraphs of text in thisContent
        set end of theAlreadySentList to (thisParagraph as text)
    end repeat
end buildListFromDiskFile

on chooseRandomFileFrom(thisFolder)
    tell application "Finder"
        set thisFile to some file of container thisFolder
    end tell
    return thisFile
end chooseRandomFileFrom

--  # Load data from disk file for: 'theAlreadySentList'

buildListFromDiskFile(theAlreadySentListFilename)

--  # Get the count of entries in the 'theAlreadySentList' list.
--  # Used to display a message once all 100 messages have been sent.

set theCount to (count of theAlreadySentList) as integer

--  # Choose a file at random.

set thisFileName to name of chooseRandomFileFrom(thisFolder)

--  # Evaluate the sent status of 'thisFileName' and respond accordingly.

repeat -- 200 times -- # Uncomment if you want a failsafe out of the 'repeat' loop.
    if theCount is equal to 100 then
        display dialog "All 100 messages have already been sent!" buttons {"OK"} default button 1
        exit repeat
    else if thisFileName is in theAlreadySentList then
        --  # Choose another file.
        set thisFileName to name of chooseRandomFileFrom(thisFolder)
    else
        --  # This file has not been used yet, process accordingly.
        --  #
        --  # Add the filename to the list.
        do shell script "echo " & thisFileName & " >> " & quoted form of theAlreadySentListFilename
        --  # Get the content of the Rich Text file.
        tell application "TextEdit"
            open thisFile
            activate
            delay 1 --# Adjust as necessary. Time must be given for the file to open before proceeding.
            set theMessageContent to text of front document
            close front document
        end tell
        --  # Create the Mail Message (and Send it).
        tell application "Mail"
            activate
            set theMessage to make new outgoing message with properties {visible:true, subject:theSubject, content:theMessageContent}
            tell theMessage
                make new to recipient at end of to recipients with properties {name:theRecipientName, address:theRecipientAddress}
            end tell
            -- delay 1 --# Adjust as necessary. Uncomment to use this command.
            -- send theMessage --   # Uncomment to use this command.
        end tell
        exit repeat
    end if
end repeat

NOTE: If you are going to use Plain Text files instead of the Rich Text files, then the entire tell application "TextEdit" block of code can be replaced with the following two lines of code:

set thisFile to POSIX path of (thisFolder & ":" & thisFileName)
set theMessageContent to do shell script "cat " & quoted form of thisFile

You can also change the comment above it, -- # Get the content of the Rich Text file., swapping Rich with Plain.