Hi!
I have already shown how to do it HERE. With minor changes, the script will be like this:
set theSMS to "Hi, have new PDF !"
set theAliasPdf to choose file of type {"com.adobe.pdf"}
tell application "System Events" to set thePdf to (POSIX path of theAliasPdf)
tell application "Messages"
activate
set theService to first service whose service type = iMessage
set theBuddy to buddy "1234 123 123" of theService
end tell
tell application "System Events" to tell application process "Messages"
click menu item "New Message" of menu 1 of menu bar item "File" of menu bar 1
click text field "To:" of scroll area 3 of splitter group 1 of window "Messages"
keystroke (full name of theBuddy) & return
click text area 1 of scroll area 4 of splitter group 1 of window "Messages"
keystroke theSMS
set the clipboard to thePdf
click menu item "Paste" of menu 1 of menu bar item "Edit" of menu bar 1
delay 1
keystroke return
end tell
KniazidisR’s script depends on controlling the Messages app GUI, which is certainly not the first method you should be rushing to use if there are other methods available. Messages app on macOS has an AppleScript dictionary, so—in theory—supplies commands to do what you need in the most appropriate fashion.
A lot of Message’s AppleScript functionality has decayed through neglect, but the send command still works well in High Sierra, and can be used to send a PDF file to an existing iMessage recipient. You’d be much better off doing it that way.
Yes, this command sends. Only text (SMS) or only file, but not together in 1 message… With UI Scripting they are sended together, in 1 message.
Sending only PDF, or only SMS:
--set theSMS to "Hi, have new PDF !"
set theAliasPdf to choose file of type {"com.adobe.pdf"}
tell application "System Events" to set thePdf to (POSIX path of theAliasPdf)
tell application "Messages"
activate
set theService to first service whose service type = iMessage
set theBuddy to buddy "1234 123 123" of theService
send file thePdf to theBuddy -- or, send theSMS to theBuddy
end tell
Note: Perhaps, exists a solution to this problem without scripting UI, but I still do not see it. And as I understand it, it is not there at all. Now, if iMessages understood HTML… then you could build the needed message and send it. I tried it already - iMessage recognizes HTML text as plain text… We should try XML now.
Text content and file attachments in an iMessage are sent separately, anyway, so I don’t see an issue here. Regardless, it seems to me that the priority is getting the file transmitted. We can be most helpful by solving as much of the problem as we can (which doesn’t necessarily have to be all of it) using the most reliable methods first; then, should the OP request specific additions/tweaks that need less conventional methods to achieve them, they can be offered later as a fall-back option that the user understands may give unpredictable results or an intrusive user experience.
Yes, but it’s not an either/or situation. You can have the script do both, one after the other. I’d suggest sending the text content first, then the file. This script you’ve provided is by far a much more pleasant experience to the user, much less likely to encounter problems that aren’t created by Apple themselves, and gives the OP a good example of something he can learn from
I’d personally get rid of the activate command. You don’t need it; it just brings Messages to the foreground when we don’t really want it to. If you ever do need to open an application explicitly without bringing it to the foreground, you can use the launch command to have the window appear but not take focus; or the run to have the application open but remain hidden. In most cases, including with Messages, the run (or some equivalent) gets called implicitly by entering the tell block, so you don’t need to call any of these yourself here.
As a minor note, you don’t need System Events to get the posix path. If, for some reason, you did want to get the posix path, you can do that without calling out to any application:
set theAliasPdf to the POSIX path of (choose file of type {"com.adobe.pdf"})
But you don’t need the posix path only to then go create a file object reference. You can simply use the alias reference in the Messages tell block:
As for the POSIX path command, I partially agree with you. System Events can be omitted, but Standard Add-ons use System Events to execute this command. Therefore, I have taken the habit of accessing the Posix path property of the System Events application, and not the Standard Addition’s command POSIX Path. There is one reason - why intermediaries, if you can do without them? Logically it should be faster.
The send command of the Messages application does not send aliases and generates an error. You can check it yourself.
I presume you mean Standard Additions, and that’s not so. You can test it yourself:
use framework "Foundation"
use framework "AppKit"
use scripting additions
tell application "System Events" to quit
delay 0.5 -- in case
-- don't ask Finder for process, because it will pass it to System Events
set theNames to (current application's NSWorkspace's sharedWorkspace()'s runningApplications()'s valueForKey:"localizedName") as list
set x to POSIX path of (choose file)
set newNames to (current application's NSWorkspace's sharedWorkspace()'s runningApplications()'s valueForKey:"localizedName") as list
return {theNames contains "System Events", newNames contains "System Events"}
Well, Shane, thanks for the clarification. Now there is only one thing left: to check what is faster - accessing System Events or accessing Standard Additions. It’s all so vague with Apple … I don’t know how to check it out. Bad habits are the most difficult to treat.
Although POSIX path is defined in Standard Additions, I’m not convinced it’s not implemented in AppleScript itself, and just defined in additions for convenience. At any rate, the speed comparison is a no-brainer: avoiding System Events avoids the overhead of sending an Apple event, so it’s always likely to be much faster. And that’s ignoring the fact that System Events keeps going to sleep, so you might have to launch it to use it.
Well, thanks for the clearing. So the correct code will be like this:
--set theSMS to "Hi, have new PDF !"
set theAliasPdf to choose file of type {"com.adobe.pdf"}
set thePdf to POSIX path of theAliasPdf
tell application "Messages"
set theService to first service whose service type = iMessage
set theBuddy to buddy "1234 123 123" of theService
send file thePdf to theBuddy -- or, send theSMS to theBuddy
end tell