Context
- I'm working on a Mail.app plugin. I would like to disseminate plugin via AppStore.
- I'm interested in exposing a functionality to user enabling user to choose if plugin should apply to all or selected email account.
- My intention is to use AppleScript to get a list of available email accounts and expose the list to the end-user via SwiftUI
Sourcing account information
Apple Script
I'm using the following AppleScript
tell application "Mail"
set accountDict to {}
repeat with acc in accounts
set accName to name of acc
set accEmails to email addresses of acc
set accountDict's end to {accName:accEmails}
end repeat
return accountDict
end tell
The above generates expected results when executed using Script Editor.
Swift Implementation
This is still incomplete but shows the overall plan.
//
// EmailAccounts.swift
import Foundation
enum EmailScriptError: Error {
case scriptExecutionError(String)
}
struct EmailAccounts {
func getAccountNames() -> [String]? {
let appleScriptSource = """
tell application "Mail"
set accountDict to {}
repeat with acc in accounts
set accName to name of acc
set accEmails to email addresses of acc
set accountDict's end to {accName:accEmails}
end repeat
return accountDict
end tell
"""
var error: NSDictionary?
var accountNames: [String] = []
// Create script object, exit if fails
guard let scriptObject = NSAppleScript(source: appleScriptSource) else {
return nil
}
// Execute script and store results, nil on error
let scriptResult = scriptObject.executeAndReturnError(&error)
if error != nil { return nil }
// Iterate over results
for index in 0...scriptResult.numberOfItems {
if let resultEntry = scriptResult.atIndex(index) {
if let resultString = resultEntry.stringValue {
// Process result handling
// accountNames.append(resultString)
}
}
}
return accountNames
}
}
Questions
- Most important one, can I deploy the App on the App Store and use
NSAppleScript
as shown above? - If yes can I use the script in the manner shown above or will I need to store the script in
User > Library > Application Scripts
location and source it from there. This is outlined in the Scripting from a Sandbox article by Craig Hockenberry, which I cannot link due to being hosted within a not-permitted domain. - If yes what entitlements I need to give to the target.
- I understand that I wouldn't be able to use ScriptingBridge, which feels more robust but wouldn't permit me to deploy the app on the AppStore.
- My key objective is to programatically identify mail accounts available to Mail.app, if there is a wiser / easier way of doing that I would be more than receptive.
Let’s tackle you big picture question first and then come back to the details:
can I deploy the App on the App Store and use NSAppleScript as shown above?
Probably not.
I don’t work for App Review, and they’re the only folks who can give you definitive answers about what is or isn’t allowed on the store. However:
-
When you use
NSAppleScript
, the Apple events originate in your process. -
For a sandboxed process to send arbitrary Apple events, it must be signed with the
com.apple.security.temporary-exception.apple-events
temporary exception entitlement. -
My experience is that App Review only approves the use of such entitlement is exceptional circumstances, for example, to work around a sandbox bug on older systems where the bug is fixed on the latest system.
If you want a more definitive answer, you’ll need to talk to App Review directly.
will I need to store the script in User > Library > Application Scripts location and source it from there.
This mechanism is designed to support attachability. See this post for my thoughts on that topic.
And finally a couple of random comments:
which I cannot link
You can, but you have to do it in the clear. See tip 14 in Quinn’s Top Ten DevForums Tips.
I understand that I wouldn't be able to use ScriptingBridge
IME Scripting Bridge is anything but robust. However, it’s irrelevant to this discussion. Scripting Bridge is just a different way to send Apple events, but what matters is the Apple events that get sent and the process that they get sent from. There’s no difference between Scripting Bridge and NSAppleScript
is that respect.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"