Mail attachments from Mail automate download to folder

Any chance your path is simply incorrect? Perhaps something case sensitive?

What happens if you try different paths inside and outside of your user account’s folder structure?

I also tried the version with no luck:

use scripting additions

using terms from application "Mail"
	on perform mail action with messages messageList in mailboxes mbox for rule aRule
		
		--	Save on DesktopPath 	
		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
		
	end perform mail action with messages
end using terms from

Also tried path’s that are in and out of iCloud.

Try putting some logging to file in and check the flow, the path, and add in some on error processing to cover any explicit errors that may not be surfacing when run automatically in Mail.

I thought I had fixed it, but I also only get it to work when it’s applied. The rule is running as I can get it to Change color or Mark it read but the AppleScript doesn’t run. I will continue to look at it. But as it works when applied, can’t figure why it’s not ran automatically.

Please try the the below. It has worked on a few test emails from other accounts. Changed the perform mail action line removing the mailbox and instead of using selection, instead is calling the messageList variable set in the before mentioned line.

-- Tested on macOS 10.14.5

use scripting additions

using terms from application "Mail"
    on perform mail action with messages messageList for rule aRule
	    set destinationPath to (POSIX file "/Users/user_name/Action/") as string
	    tell application "Mail"
		    repeat with aMessage in messageList
			    repeat with anAttachment in mail attachments of aMessage
				    set attachmentName to name of anAttachment
				    save anAttachment in file (destinationPath & attachmentName)
			    end repeat
		    end repeat
	    end tell
	
    end perform mail action with messages
end using terms from
2 Likes

I can confirm, the last version of code I posted appears to be working. The email I created this to process had it’s PDF downloaded and file actioned appropriately through the mail rule automatically.

Thanks! Script is working fine for me as long I don’t want to move the mail into another folder with the same rule.

Does anyone have a solution for it?
First run apple script and then move it to another folder out of the inbox.

That would be awesome!

A word of warning. I have found that Mail.app’s AppleScript support is highly flakey, especially when it comes to saving attachments reliably. This problem has existed for years and never been fixed by Apple, and for that reason my workflow for saving emails is NOT based on using AppleScript to save the attachments.

My approach is to save the entire email message (the raw content) to a file and run a python script that pulls out the attachments and saves them to disk. I name the files using the format YYYY-MMDD_MD5_filename where YYYY-MMDD is the date the mail was sent, MD5 is the MD5 hash of the entire mail content (that makes sure that all saved files are unique to the email message, and filename is the filename for the attachment.

To be able to sort the email messages, from AppleScript I use:
set accountName to the name of the account of the mailbox of theMessage
where theMessage is the selected message in Mail.app.

I tie the entire thing together in a Keyboard Maestro macro (that I will likely post on the MPU forum once I have a bit of time. The workflow is basically:

  1. Use AppleScript to find the current selected message (make sure there is only one) and write the entire message content to a file on the Desktop. Return from the script the accountName found above (or an error code if there is a problem, like more than one message selected).
  2. Check for the error codes and display error messages and quit. Otherwise, save the account name in a KM variable.
  3. Run the python script which takes the raw file and saves the attachments on the desktop, using the filename prefix above as computed. Rename the file containing the raw file using the prefix with _raw appended (I keep that because it is easy to search via grep). Return from the script the filename prefix, the raw file name, and the name of each attachment file.
  4. Use KM user interface scripting to have Mail.app save the email itself to a PDF on the desktop. (I have found no other way to do this.)
  5. Rename the mail pdf using the prefix as above.
  6. Use the account name to assign tags to the files thus created. Based on the account it came from I assign a tag to each file. I also take the mail pdf as “email”, the raw file as “rawemail” and each attachment as “attachment.” If there are attachments I also add a “hasattachment” tag to the mail pdf.
  7. Hazel takes over and (if the file has been on the desktop for at least 1 hour) moves all the files into the correct subfolder of my MailArchive folder using the tag assigned based on the mail account.

I hope this workflow is useful.

I suspect you’ve been using poor scripts. While some features of Mail’s scriptability indeed do not work, the rest (which is most) do, and it’s perfectly suitable for saving attachments in High Sierra. Any experience contrary to this or of a long-standing nature is likely to be from an incorrect implementation. On Mojave, it’s totally possible new problems might have arisen, though I’ve not heard or seen specific reports that would make using AppleScript not be the most sensible and straightforward first-line option to try.

It’s good to know that there is a backup option that you have used yourself and have kindly described how to implement it. It’s probably one that is a “break glass in case of emergency” kind of solution, and one that could probably be simplified somewhat.

@chri.sk

Thanks for the followup . I am not convinced that the script quality is the issue. I should have been a bit clearer: the issue is related to obtaining and saving attachments to mail message via AppleScript. This is a known bug that has been reported for years over multiple OS X and MacOS versions. When I first ran into problems I found numerous other reports and descriptions of this problem, with no fix from Apple. I have found it consistently occurring through Mojave. In fact, the workflow I described started with an AppleScript to save the attachments, but after I find it unreliable (two successive emails, each from the same person, each with a single attached Pages document, for one the script worked, for the other it failed getting the attachment) I switched to the implementation described.

My script is quite straightforward, and uses code similar to that already posted in this discussion, eg setting a variable to “every mail attachment of theMessage”; checking to ensure the resulting list is not empty; repeating through each attachment and saving it to the associated file. I do not think my code was in error, but am open to hearing from you if you have a better way to do this so I can learn.

Insofar as my approach being a workaround, that is true for saving the attachments, but a necessary one. The rest of my approach is quite kludgy, but sadly necessary as my workflow relies on tagging the created files (which is not supported in AppleScript, but is by Keyboard Maestro (and easy enough to do in other languages as well)) and on saving the mail message itself to a PDF.

Unfortunately, I have not found a way to get the mail message to reliably save in PDF format (I had thought to print the message to PDF, but haven’t gotten that to work, although there I suspect I am missing something and if you can help please send me sample code!), and so I have had to do so with UI scripting in KM, which as an approach I don’t like, as that is highly depending on timing issues that can make the script flakey. If I could get the mail message printed to PDF via AppleScript that would be ideal and I can still use KM as the glue between AppleScript, python, file renaming, and file tagging.

When I used Mail.app in High Sierra, I didn’t encounter any problems obtaining attached files from messages residing in the inbox of an IMAP account. Some attachments had and some had not already been locally downloaded/cached on the system, but all were successfully retrieved from the previous 60 days. Locally stored ones were instantly retrieved; remote-only stored ones took appropriate amounts of time to download); all got saved to a specified location. I should add that I didn’t try to execute the script as a Mail rule, and just scheduled it to run using launchd. I notice people have been referring to things not working in the context of a Mail rule script, which is a detail of importance.

As I’ve had such a positive, consistence result in an OS version that’s only 1 (or 2) versions back, it leads me to question (not you, but the internet) the voracity of these reports.

  • In considering how reliable a claim is, such as ”known bug, reported for years”, I would ask (rhetorically) by whom was it reported, and how (if at all) have these reports been verified?

  • The problem with forums is that an assertion gets made, someone else agrees. Then it’s suddenly fact. And, of course, people are much more likely to publicly agree with an evolving consensus than to disagree and seem argumentative or a know-it-all (I’m probably coming across as such).

Importantly, when it gets established that a known bug has been reported well, substantiated but credible parties, etc., then one has to be clear about what the exact nature of the bug is. So far, it hasn’t been stated clearly. I’m not asking you do so, it’s just something to be mindful of when people report these things.

  • If someone states ”Mail’s AppleScript has a bug where it doesn’t let one save attachments” this isn’t a valid description of bug. There’s no indication of under what circumstances the issue arises, and there are many different steps one takes to get to the point where an attachment is (or should be) saved (and each of these steps can be performed in a myriad ways, e.g. how one deals with multiple messages, or multiple attachments in a single message; how one formulates their file reference used to save the attachment; even how one might go about referencing their inbox folder on a particular type of account; and the type of account).
  • Example description of a bug report that is more helpful, believable, and verifiable

    ”Mail’s save command in AppleScript sometimes fails to save an attachment to the file system. Initially noticed when attempting to bulk save all pdf attachments received this year and only half were retrieved but no errors reported (script supplied). Upon testing with a single attachment in a single message, the attachment was saved about 75% of the time (script supplied), and 25% of the time, the command can definitely be seen to get sent to Mail (logs), but no result is returned. The file reference was constructed as seen in the script, by concatenation of HFS path strings. The 25% of attachment(s) that failed to save had these filenames. The other 75% had these filenames.”

  • Example bug description that one might cite on a forum to guide other scripters

    ”AppleScripting Mail (on macOS version xx.x.x) occasionally won’t save an attachment, and this is confirmed as a known bug that arises even when performed on a single file attachment of a single message, when file references are given as plain text HFS style paths.”

None of that tells me what your script actually looked like, and thus it’s not possible for me to suggest what you might have been able to do differently to get the result you hoped for. Without wanting to pigeonhole you into this group, but perhaps something to keep in the back of your mind, whenever someone that is presenting an issue uses terms like straightforward or simple it raises doubt.

  • If you think about it critically, stripping it down to the base statements, what one has said in equivalent terms is: ➀ ”X is a straightforward problem to solve”; and”I was not able to get X to work successfully." The person saying this concludes that ”It is not possible for X to work.” To others, the options are less definitive: the user may be correct and it perhaps isn’t possible for X to work; there may be an erroneous assumption being made (often, that a solution must be simple, or the nature of the problem is straightforward) or assumptions being omitted; or there’s a faulty application of logic, and thus everything else should be disregarded in evaluation.

Saying you used code that’s similar to what’s been posted only enforces the possibility you may have, therefore, been using similarly broken code. The most recent script offering, however, is allegedly successful,

As I don’t have your original script, and I don’t use Mail currently, I can’t offer any specific scripting recommendations. I think my main recommendation would be to try and avoid passing on what you casually read on the internet, and potentially adding to the problem of information being believed because it’s commonly cited. And if you do have a warning for people to head (which clearly is motivated by the wish to help), I think the two choices at your end would be to either validate information, reference your source, and importantly, be specific about the claim; or, somewhat easier, make the claim, but be clear that you don’t have information about the situations in for which the claim is definitely true, and that you remember having difficulties, but you only attempted to do it one particular way, so cannot say for sure there are other ways.

Of course, people doing the reading have the responsibility to examine what they’re reading from you and from me, etc., but that’s not something either of us have any control over.

I do apologise that this some (or much) or this reply comes across as if I might be targeting you, in some fashion, or as if some heinous crime has been committed. I also do consider the possibility that my personal success can’t be deemed proof of anything, as I might (and probably do) have a smaller dataset that would be more likely to return a favourable outcome (fewer emails than others, fewer attachments per email, and only using the script for about 8 months). So, although I sound like I’m adamant you’re wrong, I don’t think that at all.

Nothing is necessary. Problems always have more than one solution.

Oh, by the way…

You can’t append something with a prefix. You either mean to prepend with the prefix (i.e. stick it at the front); or to append with the suffix (i.e., stick it at the end).

If that’s the issue (or an issue), I’d suggest not tagging. For instance, to know how to sort your files according to mail account, you could create a file containing information that can do this.

Though if you condensed your workflow and really evaluated why you’re doing something in a particular way, and whether the restrictions you have imposed on an outcome are necessary, or just desirable, or just not being aware of other options, you might try a way you think you wouldn’t get on with, but end up liking it more as you adapt.

For example, why do you want to save the emails as PDFs?

Also, what’s then one-hour minimum for ?

Sorry, i know I’m asking a lot of questions. Well, let me at least help with one issue should you need it now or in the future:

AppleScript to add and set tags
use framework "Foundation"

property this : a reference to the current application
property NSString : a reference to NSString of this
property NSURL : a reference to NSURL of this

property NSURLTagNamesKey : "NSURLTagNamesKey"

# HANDLERS:
to getTags for filepath as text
        local filepath
  
        tell the __NSURL__(filepath) to getResourceValue:(reference) ¬
                forKey:NSURLTagNamesKey |error|:(missing value)) as list 
end getTags

to setTags for fs as list to tags as list : {}
        local fs, tags

        script filepaths
                property list : fs
                property errors : {}
        end script
        
        repeat with f in the list of filepaths
                set fURL to __NSURL__(f)
                tell (fURL's setResourceValues:{NSURLTagNamesKey:tags} ¬
                        |error|:(reference)) to if [it] = false then ¬
                        set the end of the errors in the filepaths to ¬
                        {file:fURL as alias, description:the last item}
        end repeat
        
        tell the errors in filepaths to if {} ≠ it then return it
        true
end setTags

# PRIVATE HANDLERS:
to __NSURL__(filepath as text)
        local filepath

        NSURL's fileURLWithPath:((NSString's ¬
                stringWithString:filepath)'s ¬
                stringByStandardizingPath())
end __NSURL__

There are two handlers, a getter and a setter. To get the list of tags for a single file:

getTags for "~/Desktop/some.file.ext"

which will return a list of text items representing the name of each tag attached to the file.

To set the tags for one or more files:

# One file:
setTags for "~/Desktop/some file.text" to {"Red", "foo", …}
# One or multiple files:
setTags for {"~/Applications/TextEdit.app", ¬
    "/Users/CK/", "~/Documents/a pdf file.pdf"} ¬
    to {"A tag", "Green", …}

The result returned is true upon success, or a list of the files that didn’t have their tags set together with a general reason. To clear tags for some files:

setTags for {filepath1, …,  filepathN}

@chri.sk:

Quite a lot for me to respond to! Thank you for taking so much time to address this topic and provide food for thought. I have a number of things to respond to:

  1. Thank you for your disclaimer at the end of your posting. I take no offense; rather, I would prefer that if I am wrong that be pointed out and a correction provided. I’m glad to enter into a dialog in which I can learn.

  2. In terms of the “bug” in mail’s applescripting, I unfortunately cannot provide specifics as to the why. I don’t think I could possibly do that without more information as to the internals of the program. What I and many others have observed is that retrieving attachments from a mail message in AppleScript is not consistently functional, and this has occurred for me personally over multiple OS X and MacOS versions and different computers. For some time I thought it might relate to whether the attachment had already been downloaded or not, but I have experienced the same errors even when the attachment has clearly been downloaded (and is present on-disk on the computer I am testing). Others have reported the same behavior with enough frequency for me to believe this is a true bug, but one that is sufficiently intermittent that it is certainly feasible that any one individual may not have run into it.

For example, my implementation for saving emails (which I tested about 2 weeks ago) was in fact entirely done in AppleScript and appeared to work just fine in my first few days of testing, but then began to fail on some but not all messages. The behavior is flakey enough that I decided not to rely on this approach.

You are quite correct that one should not always believe what one reads, on the internet or elsewhere, unless properly vetted. I can only say that I have worked on the same issue off and on for some time without success or finding anyone else with a successful solution and decided that, short of someone pointing out an error in my code (I can rewrite and post here if you would like to have a look and perhaps straighten me out if I have made a mistake), I should not rely on it.

  1. In terms of a given approach being necessary, you have caught me in hyperbole. Of occurs it was only “necessary” in the sense of being an expedient approach. Of course I could accomplish things in many different ways; I could for example tag files from the shell, python, Swift, etc. By necessary I really meant “necessary to do this outside of AppleScript” and Keyboard Maestro is highly expedient in this particular situation.

  2. Thank you for providing the sample code in AppleScript for file tagging. I should be thinking more about using AS’s support for importing MacOS frameworks. I have not done this to any great extent in part because I have not found good documentation on this area, and if you have any pointers I would appreciate that. I will look through your code as soon as I can so I can understand the technique!

  3. Your idea of creating a file with the necessary information to guide filing the documents is a good one. I preferred tagging for two reasons: 1) It is very easy to have Hazel act on those files subsequently, and I do like to use Hazel for these types of things, and 2) I wanted the files tagged not just for sorting but for subsequent Spotlight searching. Since I wanted the tags to be persistent anyway, having a separate mechanism for sorting wasn’t needed.

  4. In terms of the 1 hour delay, I did that just so that when I do save a mail message and attachments, I may only want to work with them for a period of time and NOT save them permanent. The 1 hour delay has them stick around on the Desktop and eventually wind up in the “right place” later on. My system is a bit more complex overall, because a lot of things happen on my MacbookAir to move files which then sync back to my desktop and are then moved further into their final locations on that system. The system works quite well for me although it may not meet someone else’s needs.

  5. The saving as a PDF is also something that I have been playing around with a bit. My idea is that for emails that I feel I need to save, I wanted to have a format that was easy to read/display and/or print, hence the PDF output from Mail.app. I also wanted the attachments saved to separate files as well. I wanted to save the entire raw email with the idea that I would search the raw text perhaps with grep, although I am just settling this system up and I may learn with use that this is unnecessary. I found that the way mail formats the message when exporting to PDF works well for me and so while I didn’t like UI scripting for this purpose and found no way to automate this via scripting, I didn’t want to invest the time in programmatically creating a PDF from the mail message content. If you have an implementation for that that you might share I would be very interested in the help.

The tags are, as noted, useful for me in both filing and searching - or at least I hope they will be, again I have only just put this together and may find I need to modify it once I see how it works for me in operation.

  1. Finally, the whole “prefix” thing! I decided to save every file related to a given email starting with the email date and MD5 hash. This ensures unique filenames and sorting by date and mails are easy to find by date since I usually know approximately when I received an email I want to review. I called that date-md5 part the filename “prefix.” The raw message I called “raw”, so I append “raw” to the prefix - OR, if we are being semantically pure, I prefix the the filename “raw” with my prefix! I also prefix the attachment filenames and the pdf filename with that same prefix. I am just glad I did not add an appendix!
1 Like

Thanks for your in-depth response. I would like to attend to one or two brief elements later. For now, I wanted to just add a small disclaimer that I don’t have a working computer currently, so cannot test any scripts. This includes the one I wrote to tag files, which I did on my Android phone as a way to avoid other stuff. If it works first time for either you or anyone else reading, I’ll be gobsmacked (there’ll be an identifier I missed or a cocoa data type i forgot to coerce I imagine). Unless there are specific issues from anyone beforehand, I promise to review the code on my system when I have had it repaired.

First of all thanks for your support!

So does anyone have an how- to to get that topic fixed?

I already tried to use the script for KM from this forum:
https://forum.keyboardmaestro.com/t/save-apple-mail-attachments-to-a-specific-folder/410

But unfortunately don’t get it worked. Seems for me that is pretty close to the solution from nlippman.

So would be great to find a solution here that works for my scenario.

Tagging is a none relevant feature for my case.

As a friendly tip, saying something “doesn’t work” doesn’t help others help you in the best possible way. After all, if the only two possibilities for any outcome were “t works” or “it doesn’t work”, and that’s all that was needed to offer a solution, everyone would most likely include the fix in their original message, with a final paragraph that says “if it doesn’t work, do this, and then it will work 100% of the time.”

Therefore, I’d recommend providing details, particularly a context with a sample data set that includes an input you supplied, the output you expected, and the output that you got. The context refers to things such as the exact parts of the script that didn’t perform as expected (reading the results pane in Script Editor to check AppleScript’s feedback from each command it sent), and including a copy of the script, emphasising parts that did execute correctly, and the part where (and how) it faltered.

It is a bit of work doing this, but, then again, providing help to solve someone’s solution is often a lot, lot more work.

What’s your scenario ?

What you can do to as a starting point that determines whether or not it’s worth proceeding with AppleScript, is to check whether the snippet below successfully returns the names of all attachments you would expect it to:

tell application "Mail" to tell (a reference to every message in the inbox) ¬
	to tell (a reference to its every mail attachment) to return the name

Note this is set to act on every message in the inbox, so if you have 10,000 messages, that’s not advisable, and you short specify a reduced sublist to perform the operation upon:

tell application "Mail" to tell (a reference to messages 1 thru 300 in the inbox) ¬
	to tell (a reference to its every mail attachment) to return the name

That acts on the first 300 messages. Just to clarify, it’s not going to save any attachments, or do anything besides provide a list of file names. It’s a preliminary test that will indicate whether or not AppleScript can and does access the file attachments successfully.

First of all _ thanks for all pre posts :wink: but The last script from Preater_v2 doesn’t work with my at 10.14.6. It just worked once…
Interesting fact to the discussion between Lippmann and Chris.sk the Receipt app does it the same way => write the complete message with all attachments in an new file and parse it afterwards. How they does it I don’t know.
But I tried to get this workflow done for a quite of time and I am tired of that mail.app. I will try it with the python script as well

hi
this script works like a charm on bid sur for downloading attachments to the “Downloads” folder. hope that helps.
set Dest to ((path to home folder) as string) & “Downloads:” – the folder to save attached files

set Dest to ((path to home folder) as string) & “Downloads:” – the folder to save attached files

log "Dest is " & Dest

tell application “Mail”

activate

set ListMessage to selection – take all emails selected

repeat with aMessage in ListMessage – loop through each message

set AList to every mail attachment of aMessage

repeat with aFile in AList --loop through each files attached to an email

if (downloaded of aFile) then – check if file is already downloaded

set Filepath to Dest & (name of aFile)

log "Filepath is " & Filepath

save aFile in Filepath as native format

end if

end repeat – next file

end repeat – next message

end tell

better, since it will set it to whatever folder the user has set as the downloads folder:

set Dest to ((path to downloads folder) as string)
1 Like

thx for the input. you are right.

what do you think about this:

using terms from application “Mail”

on perform mail action with messages theMessages for rule theRule

set downloadsHFSpath to (path to downloads folder) as string

tell application “Mail”

repeat with oneMessage in theMessages

repeat with oneAttachment in (mail attachments of oneMessage)

save oneAttachment in (downloadsHFSpath & name of oneAttachment)

end repeat

end repeat

end tell

end perform mail action with messages

end using terms from