Send email with attachment using Javascript for Automation
Asked Answered
R

2

6

I would like use Javascript for Automation in OS X Yosemite to create a new email message in Mail.app and attach a file to the email. This is my code:

Mail = Application('com.apple.Mail')
message = Mail.OutgoingMessage().make()
message.visible = true
message.toRecipients.push(Mail.Recipient({ address: "[email protected]" }))
message.subject = "Test subject"
message.content = "Lorem ipsum dolor sit"

It works fine until this point. I see a new message window with the recipient, subject, and body text correctly filled in. But I can’t figure out how to add a file attachment to the message. The scripting dictionary for Mail.app indicates that the contents property (an instance of RichText) can contain attachments, but I don’t know how to add one.

I tried this but I get an error:

// This doesn't work.
attachment = Mail.Attachment({ fileName: "/Users/myname/Desktop/test.pdf" })
message.content.attachments = [ attachment ]
// Error: Can't convert types.

I found several examples on the web how to do this in AppleScript, for example this one:

tell application "Mail"
    ...
    set theAttachmentFile to "Macintosh HD:Users:moligaloo:Downloads:attachment.pdf"
    set msg to make new outgoing message with properties {subject: theSubject, content: theContent, visible:true}

    tell msg to make new attachment with properties {file name:theAttachmentFile as alias}
end tell

But I can’t figure out how to convert this to Javascript.

Radioactivate answered 2/1, 2015 at 17:57 Comment(0)
A
7

I figured out a way to do this through trial and error, you need to use message.attachments.push(attachment) instead of attachments = [...]

Mail = Application('com.apple.Mail')
message = Mail.OutgoingMessage().make()
message.visible = true
message.toRecipients.push(Mail.Recipient({ address: "[email protected]" }))
message.subject = "Testing JXA"
message.content = "Foo bar baz"

attachment = Mail.Attachment({ fileName: "/Users/myname/Desktop/test.pdf" })
message.attachments.push(attachment)
Aiken answered 2/1, 2015 at 18:18 Comment(5)
Yup, it's one of several idiotic obfuscations in JXA. The correct syntax should be Mail.make({new:k.outgoingMessage, at:message.attachments, withProperties:{visible:true,subject:"Test",content:"Foo"}}), because that's how Apple events actually work; i.e. RPC + simple relational queries. But the AS team insists on lying to users of languages such as JavaScript and Objective-C, so you have to wade through this faux-OOP crap that pretends (badly) that you're manipulating a local Array object instead of describing a one-to-many relationship in the remote process's object graph. #HeadDeskRandi
Yeah, it should just match the underlying concepts, they are not hard to understand.Aiken
Yup. I've been banging my head against a wall trying to tell the AppleScript/JXA developers this. Apple event IPC is actually very easy and logical to understand once you realize it's not OOP. What's really frustrating is that if JXA did match the underlying concepts, it'd be trivially easy to provide users with an automatic translation tool (c.f. ASTranslate) that converts AppleScript commands to the equivalent JavaScript syntax, at which point 90% of "How do I convert this AppleScript to <language>" questions effectively answer themselves.Randi
BTW, I sent the AS/JXA team a a nearly complete JavaScript OSA reference implementation. Its Apple event support derives from the old appscript bridge which, unlike JXA, went through many thousands of hours of relentless tyre-kicking and real-world use with hundreds of scriptable apps by hundreds of personal and professional users, not least myself. Buggy and unpolished, but worth a look if you're curious as to how JXA could/should work. Maybe if enough JS users get mad at JXA they can have a mass pile on to force Apple to redo it right.Randi
@Randi What is k in your code sample (first commend above) and why at:message.attachements, why at? This makes it sound as if a new mail shall be created as an attachment.Werby
C
7

Building on the answer above by @tlehman, I found that his solution worked very well, except for one thing: The attachments were NOT successful. No errors, no messages, the attachment just was not made to the message. The solution is to use the Path() method.

Here is his solution + the Path() method, which is needed if there are any spaces in the path:

Mail = Application('com.apple.Mail')
message = Mail.OutgoingMessage().make()
message.visible = true
message.toRecipients.push(Mail.Recipient({ address: "[email protected]" }))
message.subject = "Testing JXA"
message.content = "Foo bar baz"

attachment = Mail.Attachment({ fileName: Path("/Users/myname/Desktop/if the file has spaces in it test.pdf") })
message.attachments.push(attachment)
Confirmatory answered 24/8, 2018 at 20:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.