Here is a snippet of code showing how to save email message attachments using the Mail application. The script processes all selected messages and saves each attachment to the Desktop:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
--
-- Save attachments of selected Mail messages to the desktop
--
set desktopPath to (path to desktop)'s POSIX path
tell application "Mail"
repeat with aMessage in (get selection)
repeat with anAttachment in mail attachments of aMessage
set attachmentName to name of anAttachment
save anAttachment in POSIX file (desktopPath & attachmentName)
end repeat
end repeat
end tell
And if you want to return a value (e.g. a list of all the filePaths saved to)
(to enable notification, for example, or composition within some larger process)
then concatMap (combined with list-wrapping of returned filePaths), allows (by concatenation), for a pruned list – with no ‘empties’ where where selected messages turned out to have no attachments.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
--
-- Save attachments of selected Mail messages to the desktop
--
set folderPath to (path to desktop)'s POSIX path
tell application "Mail"
script attachmentsSaved
on |λ|(mailItem)
script fpSaved
on |λ|(x)
set fp to folderPath & (name of x)
save x in POSIX file fp
{fp}
end |λ|
end script
concatMap(fpSaved, get mail attachments of mailItem)
end |λ|
end script
-- Return value: file paths of any saved files
my concatMap(attachmentsSaved, get selection)
--> {"/Users/houthakker/Desktop/labour draft.docx", "/Users/houthakker/Desktop/Socialist_dress_outline.isf"}
end tell
-- GENERIC ------------------------------------------------------------------
-- concatMap :: (a -> [b]) -> [a] -> [b]
on concatMap(f, xs)
set lng to length of xs
set acc to {}
tell mReturn(f)
repeat with i from 1 to lng
set acc to acc & |λ|(item i of xs, i, xs)
end repeat
end tell
return acc
end concatMap
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
Oddly enough, when I run this using POSIX file, Mail throws an error that some objects were not the correct type. It works fine, if I change it to this:
`save anAttachment in file (desktopPath & attachmentName)`
The entire script which works on the selection without using POSIX:
set desktopPath to (path to desktop) as string
tell application "Mail"
set selectedMessages to the selection
repeat with aMessage in selectedMessages
repeat with anAttachment in mail attachments of aMessage
set attachmentName to name of anAttachment
save anAttachment in file (desktopPath & attachmentName)
end repeat
end repeat
end tell
I think the rules have changed a bit. Considering folderPath is a path to a file server folder, the mail account is called “Exchange” and the archive folder is called “Archief”:
using terms from application "Mail"
on perform mail action with messages theDetectedMessages for rule theRule
set folderPath to "Volumes:Public:Scansnap:OA Contracten:test:" as string
tell application "Mail"
set theMessageCount to count of theDetectedMessages
repeat with a from 1 to theMessageCount
set theCurrentMessage to item a of theDetectedMessages
repeat with theAttachment in mail attachments of theCurrentMessage
set theAttachmentName to name of theAttachment
save theAttachment in file (folderPath & theAttachmentName)
end repeat
set read status of theCurrentMessage to true
move theCurrentMessage to (mailbox "Archief" of account "Exchange")
end repeat
end tell
end perform mail action with messages
end using terms from
This script files the enclosures, marks the messages as read, and files them. For some reason, letting mail handle those 2 last things instead of the AppleScript, did not work.