Advertisement
rccharles

sort attachments into folders

Mar 1st, 2019
943
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (*
  2.  
  3. Requirements:
  4.     https://discussions.apple.com/thread/8480829
  5.    
  6. Quick hints
  7. 1) Apple hids the User's library folder.  You will want to make it visible.
  8.   http://osxdaily.com/2013/10/28/show-user-library-folder-os-x-mavericks/
  9. 2) Place this Applescript in this folder with name ShortMailDownload.scpt.  You may not use the App extension.
  10.    "/Users/mac/Library/Application Scripts/com.apple.mail"    
  11. 2) The first "on" statement needs to be
  12.    on perform mail action with messages theMessages
  13. 3) Mail > Preferences... > Rules > Add Rule
  14.     "Perform the following actions"   [ buttons should be ]
  15.     "Run AppleScript" "ShortMailDownload"
  16. 4) When saving you may get a warning message that some other app, Mail, has made changes to the script. When ever the script is run, the script changes a global variable which modifies the script.  Ignore and save any way.
  17.  
  18. Limitation: Yosemite, 10.10.5, Mail Version 8.2 (2104) only supports extracting one attachment. No problem in High Sierra, 10.13.6.
  19.  
  20. off topic.  Clicking on menu item:
  21. tell application "System Events" to click menu item "Date" of menu "Sort By" of menu item "Sort By" of menu "View" of menu bar item "View" of menu bar 1 of process "Mail"
  22.  
  23. Based on the example " Sample Rule Action Script.scpt" script in macOS 10.6.8 found in folder
  24. "/Library/Scripts /Library/Scripts/Mail Scripts/Rule Actions"
  25.   Sample Rule Action Script.scpt
  26.  
  27. I think "on perform mail action" needs to be the first "on" routine.
  28.  
  29. -- If run as an ordinary script, instead of directly from the Scripts
  30.     -- menu, it will call the default handler instead.
  31.     on r u n
  32.         tell application "Mail" to set selectedMessages to selection
  33.         tell me to perform mail action with messages (selectedMessages)
  34.     end r u n
  35.     http://hints.macworld.com/article.php?story=20070215145127300
  36.  
  37. There is lots of outdated advice on download attachments found by Google.
  38. https://stackoverflow.com/questions/39882312/how-to-download-an-attachment-from-mail-via-applescript-and-mail-rules
  39.  
  40.  
  41.        Copyright 2018 rccharles  
  42.      
  43.        Permission is hereby granted, free of charge, to any person obtaining a copy  
  44.        of this software and associated documentation files (the "Software"), to deal  
  45.        in the Software without restriction, including without limitation the rights  
  46.        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
  47.        copies of the Software, and to permit persons to whom the Software is  
  48.        furnished to do so, subject to the following conditions:  
  49.        
  50.        The above copyright notice and this permission notice shall be included in all  
  51.        copies or substantial portions of the Software.  
  52.        
  53.        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
  54.        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
  55.        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
  56.        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
  57.        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
  58.        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
  59.        SOFTWARE.  
  60.  
  61. *)
  62. (*  Uncomment when you want to debug this script in the Script Editor. Go into Mail and select a message. Run this script. *)
  63. (*
  64. on run
  65.     tell application "Mail"
  66.         try
  67.             set theSelectedMessages to selection
  68.             log "class of theSelectedMessages is " & class of theSelectedMessages
  69.             log "count of theSelectedMessages is " & (count of theSelectedMessages)
  70.         on error errMsg number n
  71.             display dialog "Silly, you need to select a message in Mail." & return & "on error the errMsg is " & errMsg & " number is " & n giving up after 8
  72.             return
  73.         end try
  74.         -- not used, don't know how to pass to perform ...
  75.         set theRule to {name:"dummyRule"}
  76.        
  77.         tell me to perform mail action with messages theSelectedMessages -- for  theRule
  78.        
  79.     end tell -- app "Mail"
  80. end run
  81. *)
  82. (**)
  83. using terms from application "Mail"
  84.     on perform mail action with messages theMessages --for rule theRule
  85.        
  86.         -- Suggest this code be the first "on" in file, no on r u n & no assumed on r u n either
  87.        
  88.         -- Required by debug routine.  
  89.         global debugRunning
  90.         set debugRunning to ""
  91.        
  92.         -- debug status for displaying messages in this routine.
  93.         set debugSwitch to true
  94.         log "debugSwitch is " & debugSwitch
  95.         -- initialize
  96.         set longWait to 20
  97.        
  98.         (*
  99.           Where to place files
  100.         *)
  101.         -- intermediate folder in Home folder
  102.         -- must be Downloads for later version of macOS
  103.         set intermediateDownloadFolder to "Downloads:"
  104.         -- Folder inside of Downloads folder
  105.         set intermediateSubFolder to "subFolderForMailDownload"
  106.         -- final destination folder in Home folder
  107.         set finalDestination to "Students"
  108.        
  109.         set startMsg to "perform mail with " & getMyName() & " ====== " & ((current date) as string) & " ====== perform mail "
  110.         my debugLog(startMsg)
  111.         --display dialog startMsg giving up after 2
  112.         set intermediateFolder to intermediateDownloadFolder & intermediateSubFolder
  113.         log "intermediateFolder is " & intermediateFolder
  114.        
  115.         if (count of theMessages) = 0 then
  116.             log "odd no messages to process."
  117.             display dialog "Odd, no messages to process." giving up after longWait
  118.             return 1
  119.         end if
  120.        
  121.         -- mail requires download to the Downloads or subfolders of Downloads
  122.         -- for some reason, this gets the path to this app when invoked by mail.
  123.         set pathToHome to (path to home folder) as string
  124.         log ("pathToHome  is " & pathToHome)
  125.         set listOfPathToHome to textToList(pathToHome, ":")
  126.         set pathToHome to item 1 of listOfPathToHome & ":" & item 2 of listOfPathToHome & ":" & item 3 of listOfPathToHome & ":"
  127.         log ("revised pathToHome is " & pathToHome)
  128.        
  129.         -- make intermediate folder
  130.         try
  131.             tell application "Finder"
  132.                 set newfolder to make new folder at (pathToHome & intermediateDownloadFolder) with properties {name:intermediateSubFolder}
  133.                 my debugLog("Created folder " & pathToHome & intermediateDownloadFolder & intermediateSubFolder)
  134.             end tell
  135.         on error errMsg number n
  136.             -- It's ok if the folder already exits [ -48 ]. Put out warning for all other errors.  
  137.             if n is not -48 then
  138.                 set commonError to "on error " & intermediateSubFolder & " the errMsg is " & errMsg & " number is " & n
  139.                 display dialog commonError giving up after longWait
  140.                 my debugLog(commonError)
  141.                 return 2
  142.             end if
  143.         end try
  144.        
  145.         -- make final destination folder
  146.         try
  147.             tell application "Finder"
  148.                 set newfolder to make new folder at pathToHome with properties {name:finalDestination}
  149.                 my debugLog("Created  final destination folder " & pathToHome & finalDestination)
  150.             end tell
  151.         on error errMsg number n
  152.             -- It's ok if the folder already exits [ -48 ]. Put out warning for all other errors.  
  153.             if n is not -48 then
  154.                 set commonError to "on error " & finalDestination & " errMsg is " & errMsg & " number is " & n
  155.                 display dialog commonError giving up after longWait
  156.                 my debugLog(commonError)
  157.                 return 3
  158.             end if
  159.         end try
  160.        
  161.        
  162.         tell application "Mail"
  163.             --activate
  164.             log "was activated"
  165.            
  166.             -- look throught the messages we selected.
  167.             repeat with aMessage in theMessages -- loop through each message
  168.                 log "class of aMessage is " & class of aMessage
  169.                
  170.                 -- get the senders email address
  171.                 set fromMail to aMessage's sender
  172.                 my debugLog("fromMail is " & fromMail)
  173.                
  174.                 -- Create folder for the individual student.
  175.                 -- ---- Set final target folder ---->
  176.                 set pathToStudents to pathToHome & finalDestination & ":"
  177.                 my debugLog("pathToStudents is " & pathToStudents)
  178.                 repeat 1 times -- sinulate continue
  179.                     try
  180.                         tell application "Finder"
  181.                             set newStudent to make new folder at pathToStudents with properties {name:fromMail}
  182.                             my debugLog("Created final destination subfolder " & pathToStudents & fromMail)
  183.                         end tell
  184.                     on error errMsg number n
  185.                         -- It's ok if the folder already exits [-48 ]. Put out warning for all other errors.
  186.                         if n is not -48 then
  187.                             set commonError to "attempting to create " & pathToStudents & fromMail & return & " on error the errMsg is " & errMsg & " number is " & n
  188.                             display dialog commonError giving up after longWait
  189.                             my debugLog(commonError)
  190.                             exit repeat -- look at next message. simulate iterate here.
  191.                         end if
  192.                     end try
  193.                    
  194.                     set pathToTheStudent to pathToStudents & fromMail & ":"
  195.                     my debugLog("pathToTheStudent is " & pathToTheStudent)
  196.                     -- repeat with aFile in aMessage's mail attachments
  197.                     -- set ourList to every mail attachment of aMessage                
  198.                     repeat with aFile in (mail attachments of aMessage)
  199.                         log "save aFile"
  200.                         repeat 1 times -- sinulate continue
  201.                            
  202.                             --if (downloaded of aFile) then -- check if file is already downloaded
  203.                             set attachmentName to name of aFile
  204.                             my debugLog("attachmentName is " & attachmentName)
  205.                             set {fileName, fileExt} to my getNameExt(attachmentName)
  206.                             log "fileName  is " & fileName & " fileExt  is " & fileExt
  207.                             -- ---- Intermediate folder target ---->
  208.                             -- apple changed mail to require the download to be in the downloads folder :-(
  209.                             set pathForDownload to pathToHome & intermediateFolder & ":"
  210.                            
  211.                             set clearCount to 0
  212.                             set destPath to pathForDownload & attachmentName
  213.                             set finalDestPath to pathToStudents & fromMail & ":" & attachmentName
  214.                             log "check for free name. clearCount is " & clearCount & return & " destPath is " & destPath & return & " finalDestPath is " & finalDestPath
  215.                            
  216.                             try
  217.                                 repeat while my fileExists(destPath) or my fileExists(finalDestPath)
  218.                                     if clearCount > 300 then
  219.                                         set commonError to "could not find free name when searching for free name. clearCount is " & clearCount & " clean up intermediate and final foldrs. " & return & destPath & return & finalDestPath
  220.                                         my debugLog(commonError)
  221.                                         -- have to throw an error to get out of this repeat. Could have set a switch I guess.
  222.                                         display dialog commonError giving up after longWait
  223.                                         error "cannot find free file name" number 8110
  224.                                     end if
  225.                                     set clearCount to clearCount + 1
  226.                                     log "clearCount is " & clearCount
  227.                                     set destPath to pathForDownload & fileName & "#" & clearCount & "." & fileExt
  228.                                     set finalDestPath to pathToStudents & fromMail & ":" & fileName & "#" & clearCount & "." & fileExt
  229.                                     my debugLog("searching for free name. clearCount is " & clearCount & return & " destPath is " & destPath & return & " finalDestPath is " & finalDestPath)
  230.                                 end repeat -- while  
  231.                             on error errMsg number n
  232.                                 if n is not 8110 then
  233.                                     set commonError to "attempting to create free filename " & return & " on error the errMsg is " & errMsg & " number is " & n
  234.                                     display dialog commonError giving up after longWait
  235.                                     my debugLog(commonError)
  236.                                    
  237.                                 end if
  238.                                 exit repeat -- look at next message. simulate iterate here.
  239.                             end try
  240.                             my debugLog("found usable name. destPath is " & destPath)
  241.                             save aFile in destPath as native format
  242.                             log "file was saved."
  243.                            
  244.                             -- move it right on to file location.
  245.                             -- debuggin to see if we got the right name
  246.                             my debugLog("Saved to intermediate.  destPath is " & destPath)
  247.                            
  248.                             if my fileExists(destPath) then
  249.                                 tell application "Finder"
  250.                                     try
  251.                                         -- from file filename path to full folder name path :-(.
  252.                                         move destPath to pathToTheStudent
  253.                                         my debugLog("saved to final folder pathToTheStudent is " & pathToTheStudent)
  254.                                     on error msg number n
  255.                                         set outMsg to "Got error message while moving " & destPath & " to " & pathToTheStudent & return & "message is " & msg & return & "number is " & n
  256.                                         my debugLog(outMsg)
  257.                                         display dialog outMsg giving up after longWait
  258.                                         -- might as well try the next attachment
  259.                                         exit repeat -- look at next message. simulate iterate here.                                    
  260.                                     end try
  261.                                 end tell
  262.                             else
  263.                                 -- very bad, folder doesn't exist as expected.
  264.                                 my debugLog("very bad, folder  " & destPath & " doesn't exist as expected.")
  265.                                 exit repeat -- look at next message. simulate iterate here.    
  266.                             end if
  267.                            
  268.                         end repeat -- one time to make like a continue statment
  269.                     end repeat -- next attached file
  270.                 end repeat -- continue
  271.             end repeat -- next message
  272.         end tell --tell app "Mail"
  273.         return 0
  274.     end perform mail action with messages
  275. end using terms from
  276.  
  277.  
  278. (* ======================== Subroutines ======================= *)
  279. -- ------------------------------------------------------  
  280. (*
  281. *)
  282. on appendToFile(fileId, theData)
  283.    
  284.     local theSize, writeWhere
  285.    
  286.     set theSize to (get eof fileId)
  287.     set writeWhere to theSize + 1 as integer
  288.     write theData to fileId starting at writeWhere
  289.    
  290. end appendToFile
  291.  
  292. -- ------------------------------------------------------  
  293. (*
  294.  debug(<string>)
  295.  Write messages to a log file.
  296.  
  297.   -- Need to place these two lines in the calling routine.
  298.     global debugRunning
  299.     set debugRunning to ""
  300.  -- references appendToFile()  
  301.   -- example:
  302.     debug("start program. Reading from " & listOfFiles)
  303.    
  304.    found here: /Users/mac/Documents/BJ\ Prior\ Years/BJ2004/sendmailapp2\ copy
  305.  
  306. *)
  307. on debug(theMessage)
  308.     -- return
  309.     global debugRunning
  310.     local theSize, startupDiskName, pathToLog, fileReference
  311.    
  312.     set pathToLog to (path to home folder as text) & "tryAttachmentsLog.txt"
  313.     -- log "pathToLog is " & pathToLog
  314.     -- display dialog "pathToLog is " & pathToLog giving up after 4
  315.    
  316.     try
  317.         -- Complete the path.
  318.         set pathToLog to pathToLog as text
  319.         set fileReference to (open for access file pathToLog ¬
  320.             with write permission)
  321.        
  322.         if debugRunning = "" then
  323.             set theSize to (get eof fileReference)
  324.             if theSize > 0 then
  325.                 appendToFile(fileReference, " " & return)
  326.             end if
  327.             appendToFile(fileReference, "   --- debug on " & ((current date) as string) & "   --- " & return)
  328.             set debugRunning to "running"
  329.         end if
  330.         -- log "theMessage " & theMessage
  331.         -- display dialog "in debug..." & return & "theMessage " & theMessage giving up after 3
  332.         appendToFile(fileReference, theMessage & return)
  333.        
  334.         close access fileReference
  335.         tell application "Finder"
  336.             set the creator type of the file pathToLog ¬
  337.                 to "R*ch"
  338.         end tell
  339.     on error mes number n
  340.         try
  341.             set commonErr to "error ... " & mes & " error number is " & n
  342.             log commonErr
  343.             close access fileReference
  344.             display dialog commonErr giving up after 4
  345.         end try
  346.        
  347.     end try
  348.     -- log "end of debug"
  349. end debug
  350.  
  351. (*
  352. write log message to script editor log and to our file log
  353. *)
  354. on debugLog(theMessage)
  355.     log "debugLog: " & theMessage
  356.     return debug(theMessage)
  357. end debugLog
  358.  
  359. -- ------------------------------------------------------  
  360. (*
  361.   ideas from:
  362.   https://stackoverflow.com/questions/3469389/applescript-testing-for-file-existence
  363.  
  364.  use the alias way.
  365. *)
  366. on fileExists(theFile) -- (String) as Boolean
  367.     (* "System Events" and "Finder" checking for file existance revealed problems. l*)
  368.     set debugging to false
  369.     if debugging then log "  fileExists: theFile is " & theFile
  370.     try
  371.         set theAlias to theFile as alias
  372.         set theExistance to true
  373.     on error errMsg number n
  374.         if debugging then log "  fileExists: n is " & n
  375.         -- File or folder doesn't exist.
  376.         if n is not -43 then
  377.             set commonError to "on error the errMsg is " & errMsg & " number is " & n
  378.             if debugging then log "  fileExists: " & commonError
  379.             display dialog commonError giving up after 10
  380.             -- cause grief above.
  381.             error "Failure of alias." number -1
  382.         else
  383.             set theExistance to false
  384.         end if
  385.     end try
  386.     if debugging then log "  fileExists: theExistance is " & theExistance
  387.     return theExistance
  388. end fileExists
  389.  
  390. (*
  391.   Philip Regan
  392.   https://stackoverflow.com/questions/3469389/applescript-testing-for-file-existence
  393. *)
  394. (*on fileExists(theFile) -- (String) as Boolean
  395.     tell application "System Events"
  396.         if exists file theFile then
  397.             return true
  398.         else
  399.             return false
  400.         end if
  401.     end tell
  402. end fileExists*)
  403.  
  404. -- ------------------------------------------------------
  405. (*
  406.    Yvan Koenig
  407.    https://macscripter.net/viewtopic.php?id=43133
  408.    with mods for no extension present
  409.    
  410. *)
  411. on getExt(theName)
  412.     if (offset of "." in theName) is greater than 0 then
  413.         set saveTID to AppleScript's text item delimiters
  414.         set AppleScript's text item delimiters to {"."}
  415.         set theExt to last text item of theName
  416.         set AppleScript's text item delimiters to saveTID
  417.         if theExt ends with ":" then set theExt to text 1 thru -2 of theExt
  418.     else
  419.         set theExt to ""
  420.     end if
  421.     return theExt
  422. end getExt
  423.  
  424. -- ------------------------------------------------------
  425. (*
  426.     Input: a file with or without an extension.
  427.     hhas
  428.     https://forums.macrumors.com/threads/applescript-to-get-file-name.927338/
  429.    
  430.     may not work with folders with extensions like apps.
  431.    
  432.     Test cases:
  433.                 set fileName to " "                  
  434.                 set fileExt to my getExt(attachmentName)
  435.                 log "fileName  is " & fileName & " fileExt  is " & fileExt
  436.                 set fileExt to my getExt("testfileNo")
  437.                 log "fileName  is " & fileName & " fileExt  is " & fileExt
  438.                 set fileExt to my getExt("path:to:testfileNo:")
  439.                 log "fileName  is " & fileName & " fileExt  is " & fileExt
  440.                 log ">>>>>>>>>>>>>>>>>>>>>>"
  441.                 set {fileName, fileExt} to my getNameExt(attachmentName)
  442.                 log "fileName  is " & fileName & " fileExt  is " & fileExt
  443.                 set {fileName, fileExt} to my getNameExt("testfileNo")
  444.                 log "fileName  is " & fileName & " fileExt  is " & fileExt
  445.                 set {fileName, fileExt} to my getNameExt("path:to:testfileNo:")
  446.                 log "fileName  is " & fileName & " fileExt  is " & fileExt
  447. *)
  448. on getNameExt(fileName)
  449.     set saveTID to AppleScript's text item delimiters
  450.     set AppleScript's text item delimiters to "."
  451.     if fileName contains "." then
  452.         set {displayName, nameExt} to {text 1 thru text item -2, text item -1} of fileName
  453.     else
  454.         set {displayName, nameExt} to {fileName, ""}
  455.     end if
  456.     set AppleScript's text item delimiters to saveTID
  457.    
  458.     return {displayName, nameExt}
  459. end getNameExt
  460. -- ------------------------------------------------------
  461. (*
  462.     modified to let the extension be.
  463.  
  464.     by mklement0
  465.     https://stackoverflow.com/questions/5770384/how-find-the-file-name-of-an-executing-applescript
  466. *)
  467. on getMyName()
  468.     local myAlias, myName
  469.     tell application "System Events"
  470.         set myAlias to path to me -- alias to the file/bundle of the running script
  471.         set myName to name of myAlias -- filename with extension, if any.
  472.         -- leave extension alone.
  473.     end tell
  474.     return myName
  475. end getMyName
  476.  
  477. -- ------------------------------------------------------
  478. (*
  479.    ls_l is list file with options  
  480.   the format is best for debuging.
  481.  
  482.   example usage:
  483.   set {fileExists, fromUnix} to ls_l(attachmentNamePath, "-l")
  484.   log "attachmentNamePath fileExists is " & fileExists & return & " fromUnix is " & fromUnix
  485.  
  486.   *)
  487. on ls_l(attachmentNamePath, options)
  488.     --log "ls_l"
  489.     --log options
  490.    
  491.     set unixAttachmentNamePath to POSIX path of attachmentNamePath
  492.     --log "unixDesktopPath = " & unixAttachmentNamePath
  493.    
  494.     set quotedUnixAttachmentNamePath to quoted form of unixAttachmentNamePath
  495.     --log "quoted form is " & quotedUnixAttachmentNamePath
  496.     try
  497.         set fromUnix to do shell script "ls " & options & " " & quotedUnixAttachmentNamePath
  498.         set fromUnix to "ls " & options & return & fromUnix
  499.         set fileExists to true
  500.     on error errMsg number n
  501.         set fromUnix to "ls " & options & "  error..." & errMsg & " with number " & n
  502.         set fileExists to false
  503.        
  504.     end try
  505.     return {fileExists, fromUnix}
  506. end ls_l
  507.  
  508. -- ------------------------------------------------------
  509. (*
  510. textToList seems to be what you are trying to do
  511.   thisText is the input string
  512.   delim is what to split on
  513.  
  514.   returns a list of strings.  
  515.  
  516. - textToList was found here:
  517. - http://macscripter.net/viewtopic.php?id=15423
  518.  
  519. *)
  520.  
  521. on textToList(thisText, delim)
  522.     set resultList to {}
  523.     set {tid, my text item delimiters} to {my text item delimiters, delim}
  524.    
  525.     try
  526.         set resultList to every text item of thisText
  527.         set my text item delimiters to tid
  528.     on error
  529.         set my text item delimiters to tid
  530.     end try
  531.     return resultList
  532. end textToList
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement