Applescript in Mojave

I can’t get an AppleScript that used to create an email message from my Xojo app to work after updating to Mojave. Apparently this is a known problem. Has anyone come across a fix for this? I have tried adding Mail to Full Disk Access in System Preferences but this didn’t help.

You might check that your app is listed in the Automation section of Security and Privacy and has Mail.app checked.

You need to ask from within your app if the app is allowed to do an AppleScript against Mail. The only way to do this properly that I know about is with the MBS plugin:

[code]'get permissions for new app
dim target as NSAppleEventDescriptorMBS = NSAppleEventDescriptorMBS.descriptorWithBundleIdentifier(BundleID)

// we ask for all apple events
PermissionsForApp = NSAppleScriptMBS.DeterminePermissionToAutomateTarget(target, “", "”, true)
PermissionsDictionary.Value(BundleID) = PermissionsForApp[/code]

There’s other possibilities apart from Apple Script.

  1. Use “ShowURL” and “MailTo:” to create a new e-mail in the users e-mail client.
  2. Use the SMTP socket and send it yourself.

I’m partial to the ShowURL("mailto:") method because it will open the user’s selected email client and doesn’t require special permissions.

Using AppleScript you have to pick the email client, which maybe the user doesn’t agree with you.

You could use NSSharingService for macOS.

NSSharingService should respect this, too. It has the benefit of being able to add attachments.

[code] Dim sRecipients() As String = Array(“email1@domain1.com”, “email2@domain2.com”)

Dim sSubject As String = “Hi there!”
Dim sBody As String = “I’m going to send you an email.” + EndOfLine + “But I don’t have anything to say…”

Dim oAttachments() As FolderItem
oAttachments.Append(oFolderItemToAttach1)
oAttachments.Append(oFolderItemToAttach2)

#If TargetMacOS And Target64Bit Then
//Compose E-Mail using NSSharingService
Const NSSharingServiceNameComposeEmail = “com.apple.share.Mail.compose”

Declare Function NSClassFromString Lib "Cocoa" (className As CFStringRef) As Ptr
Declare Function sharingServiceNamed Lib "Cocoa" selector "sharingServiceNamed:" ( NSSharingServiceClass As Ptr, serviceName As CFStringRef ) As Ptr

Declare Sub setRecipients Lib "Cocoa" selector "setRecipients:" (NSSharingServiceInstance As Ptr, obj As Ptr)
Declare Sub setSubject Lib "Cocoa" selector "setSubject:" (NSSharingServiceInstance As Ptr, subject As CFStringRef)
Declare Sub performWithItems Lib "Cocoa" selector "performWithItems:" (NSSharingServiceInstance As Ptr, obj As Ptr)

'NSSharingService instance
Dim ptrNSSharingServiceClass As Ptr = NSClassFromString("NSSharingService")
Dim ptrNSSharingServiceComposeEmail As Ptr = sharingServiceNamed(ptrNSSharingServiceClass, NSSharingServiceNameComposeEmail)


//Declares for NSMutableArray
Declare Function alloc Lib "Cocoa" Selector "alloc" (NSClass As Ptr) As Ptr
Declare Function init Lib "Cocoa" Selector "init" (NSClass As Ptr) As Ptr
Declare Sub addObject_String Lib "Cocoa" Selector "addObject:"(NSMutableArrayClass As Ptr, anObject As CFStringRef)
Declare Sub addObject_Ptr Lib "Cocoa" Selector "addObject:"(NSMutableArrayClass As Ptr, anObject As Ptr)

Static ptrMutableArrayClass As Ptr = NSClassFromString("NSMutableArray")

'Build Recipients Array
Dim ptrRecipients As Ptr = init(alloc(ptrMutableArrayClass))
For Each sRecipient As String In sRecipients
  addObject_String(ptrRecipients, sRecipient)
Next

'Build Items Array
Dim ptrItems As Ptr = init(alloc(ptrMutableArrayClass))
addObject_String(ptrItems, sBody)

'add Attachments to Items Array
Declare Function fileURLWithPath Lib "Foundation" selector "fileURLWithPath:" ( ptrNSURLClass As Ptr, path As CFStringRef ) As Ptr
for each oAttachFolderItem As FolderItem in oAttachments
  if (oAttachFolderItem = nil) or (oAttachFolderItem.Exists = false) then continue
  
  Dim ptrNSURLClass As Ptr = NSClassFromString("NSURL")
  Dim ptrAttachment As Ptr = fileURLWithPath(ptrNSURLClass, oAttachFolderItem.NativePath)
  
  addObject_Ptr(ptrItems, ptrAttachment)
next

'set Subject, Recipient
setSubject(ptrNSSharingServiceComposeEmail, sSubject)
setRecipients(ptrNSSharingServiceComposeEmail, ptrRecipients)

'Compose E-Mail with Items
performWithItems(ptrNSSharingServiceComposeEmail, ptrItems)

#EndIf[/code]

Add an AppleScript entry in the plist file ?

This will still pop up the Permission Request Dialog, which a user could (accidentally) deny. So it may be they don’t get the functionality.

So for a simple Task such as composing an email, you’re better off doing it in some other way.

ShowURL("mailto:") works well, but has a limit of content length.

NSSharingService has the additional benefit that you can add attachments.
And - for both: no Permissions required.

The App should show a message informing the user what the following permission is needed/used for, before the system asks for permission.

Do your users always read these? :wink:
But you’re right - even though I prefer not having these MessageBoxes and Permission Popups if there is a way without it.
And for that very reason I’ve provided a code snipplet with one more way to compose an email without that permission request.
And composing an email without AppleScript has been the OP’s intent.

Thanks everyone. I’m going to give Jürg O’s suggestion a try. Thanks for posting the code, Jürg O!

I ran into the AppleScript issue and dragged a special plist file into the Xojo project. This brings up a dialog box the first time you run it asking for permission.

Search for the sample file from December 16 - title " Applescript in Xojo 2018 r4." If you’re using your program for personal use, then this may suffice as a simple answer requiring no other changes - at least it did for me.

Jürg Otter 's code works perfectly! Thank you!