Mail.app: Download linked files from selected messages


-- script: Download Linked files from Mail selected messages
-- select the message(s) in Mail.app, run this script
-- the files will be downloaded to "Mail downloads" folder on the Desktop
-- written: by me, right now
-- making this script Mail rule makes sense & is easy, but I don't like Mail rules


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
property theExtension : "ico" -- indicate HERE what type linked files you want download
property currentDownloadFolder : missing value
property theName : missing value -- preserved for name of each subfolder
property fileName : missing value -- preserved for name of each downloaded file
property mailDownloadsFolder : missing value

set mailDownloadsFolder to "" & (path to desktop folder) & "Mail downloads:"
tell application "Finder" to if not (exists folder mailDownloadsFolder) then make new folder at desktop with properties {name:"Mail downloads"}

tell application "Mail"
	repeat with eachMessage in (get selection)
		tell eachMessage to set {theName, theSource} to {subject, source}
		set currentDownloadFolder to mailDownloadsFolder & theName & ":"
		my makeNewSubFolder()
		repeat with icoLink in (my findURLsIn(theSource, theExtension))
			set fileName to my getBaseName(icoLink)
			set n to my checkUniqueFileNumber()
			my download(icoLink, fileName & "_" & n & " ." & theExtension)
		end repeat
	end repeat
end tell


-----------------------------------------------------------------  HANDLERS  ---------------------------------------------------------------

on checkUniqueFileNumber()
	set n to 1
	repeat
		try
			alias (currentDownloadFolder & fileName & "_" & n & " .ico")
			set n to n + 1
		on error
			return n
		end try
	end repeat
	return n
end checkUniqueFileNumber

on getBaseName(posixPath)
	set {ATID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "/"}
	if (posixPath ends with "/") then
		set basename to text item -2 of posixPath
	else
		set basename to text item -1 of posixPath
	end if
	if (basename contains ".") then
		set AppleScript's text item delimiters to "."
		set basename to text 1 thru text item -2 of basename
	end if
	set AppleScript's text item delimiters to ATID
	return basename
end getBaseName

on download(icoLink, fileName)
	do shell script "curl -L -o " & quoted form of ((POSIX path of currentDownloadFolder) & fileName) & space & icoLink
end download

on findURLsIn(theString, theExtension)
	set theString to current application's NSString's stringWithString:theString
	set theDD to current application's NSDataDetector's dataDetectorWithTypes:(current application's NSTextCheckingTypeLink) |error|:(missing value)
	set theURLs to theDD's matchesInString:theString options:0 range:{0, theString's |length|()}
	set thePred to current application's NSPredicate's predicateWithFormat:("SELF BEGINSWITH 'http' AND SELF ENDSWITH " & quoted form of theExtension)
	set newArray to (theURLs's valueForKeyPath:"URL.absoluteString")'s filteredArrayUsingPredicate:thePred
	return newArray as list
end findURLsIn

on makeNewSubFolder()
	tell application "Finder" to if not (exists folder currentDownloadFolder) then make new folder at folder mailDownloadsFolder with properties {name:theName}
end makeNewSubFolder