2

We have a working AppleScript that creates an email with an attachment and it works fine in the Script Editor. However, we cannot get the attachment to work in the handler used in our macOS app. Difficult to find doc and figure out the difference between activate and send commands. Thanks for any help you can provide.

Here is the AppleScript

set recipientAddress to "joe@joe.com"
set recipientName to "Joe"
set theSubject to "Estimate"
set theContent to "This is your Estimate. Please call with any questions."
set theAttachment to "/Users/iMac/Library/Containers/com.jzmobile.JZMac/Data/Documents/PDF1"

tell application "Mail"
    set outgoingMessage to make new outgoing message with properties {subject:theSubject, content:theContent, visible:true}
    tell outgoingMessage
        make new to recipient with properties {name:recipientName, address:recipientAddress}
        tell content of outgoingMessage
            make new attachment with properties {file name:theAttachment}
        end tell
    end tell
    activate
end tell

Here is the Handler:

var script: NSAppleScript = { 
        let script = NSAppleScript(source: """

    -- This is our handler definition
    on sendMyEmail(theSubject, theContent, recipientName, recipientAddress, attachment)
        tell application "Mail"

            -- Create an email
            set outgoingMessage to make new outgoing message ¬
            with properties {subject:theSubject, content:theContent, visible:true}

            -- Set the recipient
            tell outgoingMessage
                make new to recipient ¬
                with properties {name:recipientName, address:recipientAddress}
            tell content of outgoingMessage
                make new attachment with properties {file name:attachment}

            #activate
            end tell
               -- Send the message
            send 
            end tell

        end tell
        #activate

    end sendMyEmail
    """  
            )!  
        let success = script.compileAndReturnError(nil)  
        assert(success)  
        return script  
    }() 

@objc func runScript() {

    let parameters = NSAppleEventDescriptor.list()  
    parameters.insert(NSAppleEventDescriptor(string: subject), at: 0)  
    parameters.insert(NSAppleEventDescriptor(string: "Some content of the email"), at: 0)  
    parameters.insert(NSAppleEventDescriptor(string: "John Smith"), at: 0)  
    parameters.insert(NSAppleEventDescriptor(string: "john@email.com"), at: 0)  
    parameters.insert(NSAppleEventDescriptor(string: attachmentFileURL), at: 0)

    let event = NSAppleEventDescriptor(  
        eventClass: AEEventClass(kASAppleScriptSuite),  
        eventID: AEEventID(kASSubroutineEvent),  
        targetDescriptor: nil,  
        returnID: AEReturnID(kAutoGenerateReturnID),  
        transactionID: AETransactionID(kAnyTransactionID)  
    )  

    // this line sets the name of the target handler
    event.setDescriptor(NSAppleEventDescriptor(string: "sendMyEmail"), forKeyword: AEKeyword(keyASSubroutineName))

    // this line adds the parameter list we constructed above  
    event.setDescriptor(parameters, forKeyword: AEKeyword(keyDirectObject))  

    var error: NSDictionary? = nil  
    _ = self.script.executeAppleEvent(event, error: &error) as NSAppleEventDescriptor?  

    print ("runScript",self.script)

}
l'L'l
  • 44,951
  • 10
  • 95
  • 146
John
  • 538
  • 4
  • 18
  • 1
    If the app is sandboxed (which is the default meanwhile) you are not allowed to run scripts with `NSAppleScript`. And if not how do you call the handler? – vadian Sep 03 '19 at 19:32
  • Thanks vadian. I have added the Apple Event handler to the question. It works fine in the sandbox. The email is created but the attachment is missing. What can be easily accomplished in iOS with MFMailComposeViewController is not a trivial task in macOS! – John Sep 03 '19 at 19:50
  • Aren't the parameters in reversed order? You should insert the descriptors at 0, 1, 2, 3, 4. – vadian Sep 03 '19 at 19:55
  • That's Apple Events...I don't get it either, but it works. Seems as long as they are in the right order they get passed into the script correctly. Again, the email is created and displayed correctly, except the attachment is missing. The script works perfectly in the script editor and displays the attachment. – John Sep 03 '19 at 20:07
  • 1
    What is `attachmentFileURL`? Is it indeed an URL? If yes try `attachmentFileURL.path`. And you might get the URL of the Documents folder of the container with the dedicated API of `FileManager` – vadian Sep 03 '19 at 20:11
  • it's the URLString - the path + the file to be attached. The script is looking for a POSIX string and again it works fine in the script editor. – John Sep 03 '19 at 20:20
  • Cocoa Scripting is much more susceptible than Script Editor – vadian Sep 03 '19 at 20:22

1 Answers1

-2

Passing a path string will not work; the sandbox will block it. You must pass a file object (alias/POSIX file).

The sandbox will also restrict your own app’s ability to access arbitrary file system locations.

foo
  • 664
  • 1
  • 4
  • 4
  • First, you need to add an Entitlement to access mail. The script is being sent before the file is retrieved. Mail needs a short time to add the attachment. Add the command delay 1 right before the send command and it works perfectly. Note, there is nothing special about "POSIX" it is simply the /User/iMac/ type format. – John Sep 04 '19 at 11:51