Mail "Can't get selection"

As a complete newbie, working on my first script, I have been looking at various posts to solve this problem and have tried several blocks of code that used different approaches, but still “can’t get selection”, although I have selected either one of two email messages in the Mal Inbox before running the code.

tell application "Mail"
	set theMessage to item 1 of (get selection)
	set attachment_file to first mail attachment of theMessage
	set attachment_name to name of the first mail attachment of theMessage
	save attachment_file in "Users:Daily:Documents:Properties:Birdwood Road:Solar & Battery Power:" & attachment_name
end tell

There must be something fundamental I am missing in trying to use the Script Editor, so please tell me what it is.

Try this:

tell application "Mail"
	set theMessage to item 1 of (get selected messages of message viewer 1)
	if exists mail attachments of theMessage then
		set attachment_file to first mail attachment of theMessage
		set attachment_name to name of the first mail attachment of theMessage
		save attachment_file in "Users:Daily:Documents:Properties:Birdwood Road:Solar & Battery Power:" & attachment_name
	end if
end tell

Thank you, Ionah. Your script gives me the error “can’t get message viewer 1”, with error -1728, which is “The referenced object doesn’t exist. This is a run-time resolution error, such as when attempting to reference a third object when only two objects exist.”

I am unsure why that message viewer, or in my earlier script, that message, doesn’t exist.

@Fredrik71, I used your code and got a Syntax error ‘Expected “,” but found property.’ at compilation. The compiler replaced “as” with “rule type” and wouldn’t compile.

I also don’t understand why you introduced “set theOpenedFile…” when you and I are both trying to save a file into a folder.

@Fredrik71, I misunderstood your code. Now I have used the following, but still get the “can’t get selection” error upon compilation.

set savePath to (“Users:Daily:Documents:Properties:Birdwood Road:Solar & Battery Power:” as string)

tell application “Mail”

set theMessages to selection

if exists mail attachments of theMessages then

set attachment_file to first mail attachment of theMessages

set attachment_name to name of the first mail attachment of theMessages

set theOpenedFile to open for access file (savePath & attachment_name) with write permission

save attachment_file in savePath & attachment_name

close access theOpenedFile

end if

end tell

What’s actually open in Mail when you run the script?
You should have a message viewer open with one mail selected (like the left side of the following screenshot) and not a message window (on the right).

When I run the script, I have exactly what you have asked, @ionah . No message is open, but one is selected.

@Fredrik71, I appreciate the advice, since my programming experience is mostly homegrown. When I first learnt it at Uni in 1964, it was on Fortran 4, and OO wasn’t heard of; I still have a lot of trouble with that:-)

Your code compiles, but when I run it, I get the message “The specified object is a property, not an element.”, referring to “selection” in the (get selection) command.

Which version of macOS are you using? I’m on Monterey and your first script works here.
Have a look at the Mail dictionary: maybe the syntax to get the selected email has changed?

I cannot reproduce the error message.

Either selection is empty and you get an error about “can’t get item 1”, or the error “Can’t make item 1 of selection into type specifier” is thrown if you write item 1 of selection without get and with nothing selected, but I never get “Can’t get selection”.

@ionah, I am using Sonoma (14.1.2). the dictionary says “selection (list of message, r/o) : List of messages that the user has selected”. I have no way of knowing if it has changed since Monterey, but I think I am using it correctly.

@StefanK, thank you; changing my use of selection as follows permits the code to get past that line. However my new error message says “mail attachment of selection of account “internode.on.net” doesn’t understand the “exists” message.” That applies whether I place the “exists” after the “if” of before the “then”. The Apple Documentation (Operators Reference) gives both methods of use.

set savePath to ("Users:Daily:Documents:Properties:Birdwood Road:Solar & Battery Power:" as string)
tell application "Mail"
	tell account "internode.on.net"
		set theMessage to a reference to selection
		if exists mail attachment of theMessage then
			set attachment_file to first mail attachment of theMessage
			set attachment_name to name of the first mail attachment of theMessage
			set theOpenedFile to open for access file (savePath & attachment_name) with write permission
			save attachment_file in savePath & attachment_name
			close access theOpenedFile
		end if
	end tell
end tell

I revised my code to ignore the “if” statements, since I cannot get them to work at the moment. Next I was foundering on “name” in the above code being “a property not an element”, but after changing the code to include “a reference to”, the code below now runs as far as

set savePath to savePath & attachment_name

before giving me that same error message about the item “attachment_name”. It didn’t complain when I set that name in the previous line, so there is nothing wrong with the name, just with how I am trying to use it. Can anyone point out my folly here?

set savePath to ("Users:Daily:Documents:Properties:Birdwood Road:Solar & Battery Power:" as string)
tell application "Mail"
	tell account "internode.on.net"
		set theMessage to a reference to selection
		--		if (attachment of theMessage) exists then
		set attachment_file to a reference to first mail attachment of theMessage
		set attachment_name to a reference to name of the first mail attachment of theMessage
		set savePath to savePath & attachment_name
		save attachment_file in file savePath
		--		end if
	end tell
end tell

Did you solve your problem? I don’t check MacScripter every day. I have a script to save attachments at Save attachments with AppleScript for Mail .

I’m using an old version of Mail but this works for me. You may have to check Mail’s dictionary to confirm that the items used below have not changed. I would suggest closing all of Mail’s windows except for the message viewer, in which you have selected a single message with an attachment. You may have to do something to allow you to save files and perhaps someone can assist with that as it’s not required with my OS version.

Before getting started, to keep things simple, specify a destination folder on the desktop, which is where any attachments will be saved. Create a folder with the name ‘repository’ on the desktop and put this at the top of the script.

-- this will refer to a folder named 'repository' that is on the desktop
set savePath to ((path to desktop) as text) & "repository:"
--> "MacHD:Users:username:Desktop:repository:"

To clear up something important… Mail has ‘selected messages’, which is a property of ‘message viewer’, so begin by getting the message viewer. We don’t have to specify an account here because the selection inherently determines the account and mailbox. Run a script containing only the command below and it should return a result that looks like the last line and provides a way to specify the viewer, which we will then use to get the selected messages.

tell application "Mail"
	message viewer 1
end tell
--> message viewer id 1 of application "Mail"

We could probably continue to work with the above but now that we know the message viewer ID, I’d rather be more explicit and use the following:

tell application "Mail"
	message viewer id 1
end tell
--> message viewer id 1 of application "Mail"

Next, we get the ‘selected messages’ of our viewer, and this returns a list of the selected messages — which at this time is a single message. We assign this list to a variable (sm).

set sm to selected messages of message viewer id 1
--> {message id 4901 of mailbox "INBOX" of account id "EF608919-4803-5043-FCAF-34021926ABBA" of application "Mail"}

Then, we cycle through the list of selected messages and save any attachments to the specified folder. Since a message may have multiple attachments, we are working with a list even when there is but a single attachment, so we will cycle through that list as well.

set sm to selected messages of message viewer id 1
repeat with eachMessage in sm
	mail attachment of eachMessage
end repeat
--> {mail attachment id "2" of message id 4901 of mailbox "INBOX" of account id "EF608919-4803-5043-FCAF-34021926ABBA" of application "Mail"}

By the way, if there was a second message selected that did not have an attachment, the results might look something like this below… a nested list where one of the contained lists was empty.

set allAttach to {}
repeat with eachMessage in sm
	set end of allAttach to mail attachment of eachMessage
end repeat
allAttach
--> {{}, {mail attachment id "2" of message id 4901 of mailbox "INBOX" of account id "EF608919-4803-5043-FCAF-34021926ABBA" of application "Mail"}}

And finally, to put it all together:

set savePath to ((path to desktop) as text) & "repository:"
tell application "Mail"
	set sm to selected messages of message viewer id 1 
	
	repeat with eachMsg in sm
		repeat with eachAttach in (mail attachments of eachMsg)
		--> item 1 of every mail attachment of item 1 of {message id 4901 of mailbox "INBOX" of account id "EF608919-4803-5043-FCAF-34021926ABBA" of application "Mail"}

			set nom to name of eachAttach
			--> "Winter 2024.pdf"
			save contents of eachAttach in file (savePath & nom as string)
			--> save item 1 of every mail attachment of message id 4901 of mailbox "INBOX" of account id "EF608919-4803-5043-FCAF-34021926ABBA" in file "MacHD:Users:username:Desktop:repository: Winter 2024.pdf"

		end repeat
	end repeat
end tell

NB If multiple attachments have the same filename, there will be a conflict when saving them

Assuming this works for you, select a couple of messages and try again.

Thank you to all correspondents, @ionah, @Fredrik71, @StefanK, @bwill & @Mockman. Once I copied @Fredrik71 's code into my script editor, I realised that he was correct, my code was not the same as his, and that solved my problem. I am currently working on building that code into a more powerful script that runs a previously written VB Excel macro.