Reputation: 1356
I need a script to compose a new mail with given script arguments. Here's what I got so far:
#!/usr/bin/env xcrun swift
import Foundation
import AppKit
func printHelpMessage() {
let helpMessage = "Script expects the following arguments: <recepient> <subject>"
print(helpMessage)
}
func composeMail() {
guard let service = NSSharingService(named: .composeEmail) else { return }
service.recipients = [recepient]
service.subject = subject
service.perform(withItems: ["Test Mail Body"])
}
guard CommandLine.argc == 3 else {
printHelpMessage()
exit(0)
}
let recepient = CommandLine.arguments[1]
let subject = CommandLine.arguments[2]
composeMail()
The error message I get is
2020-06-10 12:05:34.938140+0200 ComposeMail[58079:3848327] [default] 0 is not a valid connection ID.
2020-06-10 12:05:34.952445+0200 ComposeMail[58079:3848327] [default] 0 is not a valid connection ID.
2020-06-10 12:05:34.952805+0200 ComposeMail[58079:3848327] [default] 0 is not a valid connection ID.
Could this be System Integrity Protection?
Upvotes: 0
Views: 199
Reputation: 1356
Turns out that when using AppKit
classes, an NSApplication
instance has to be implemented with an AppDelegate
, even though this is a script.
Here's what is working for me now, it's quick and dirty, but might be a starting point:
import AppKit
let app = NSApplication.shared
class AppDelegate: NSObject, NSApplicationDelegate {
var recepient:String?
var subject: String?
var mailBody: String?
var attachment: String?
func applicationDidFinishLaunching(_ notification: Notification) {
guard CommandLine.argc == 5 else {
printHelpMessage()
exit(0)
}
recepient = CommandLine.arguments[1]
subject = CommandLine.arguments[2]
mailBody = CommandLine.arguments[3]
attachment = CommandLine.arguments[4]
composeMail()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
exit(1)
}
}
func composeMail() {
guard let recepient = recepient,
let subject = subject,
let mailBody = mailBody,
let attachment = attachment,
let service = NSSharingService(named: .composeEmail)
else {
exit(2)
}
let attmtUrl = URL(fileURLWithPath: attachment).absoluteURL
service.recipients = [recepient]
service.subject = subject
service.perform(withItems: [mailBody, attmtUrl as URL])
}
func printHelpMessage() {
let helpMessage = "Script expects the following arguments: <recepient> <subject> <mail body> </path/to/attachment>"
print(helpMessage)
}
}
let delegate = AppDelegate()
app.delegate = delegate
app.run()
Thanks @anthosr (see answer below) for pushing me into the right direction!
Disclaimer: please be aware that attaching will not work with MS Outlook – for reasons that are beyond me, the attachment is being ignored. With Apple Mail it works though.
Upvotes: 0
Reputation: 11
I just hit the same issue and traced it back to not having NSApplication initialized.
The NSApplication developer page mentions that this needs to be initialized before using most AppKit classes. I built a simple app, inserted my email code, and it works now. I have not yet figured out how to accomplish this as a pure command-line app though, which is my goal and it looks like yours as well.
Upvotes: 1