0

I have created a script which takes some user input from me (prompts with basic dialogs), then generates a standalone script that sends me a text message and an email, which I can then schedule as a calendar alert to trigger at a desired date/time.

Everything works fine, until there is an apostrophe/single quote in the user input. For example if my email body is:

Here's my email

the script will fail to run, with:

sh: -c: line 0: unexpected EOF while looking for matching `"'
sh: -c: line 1: syntax error: unexpected end of file

Here's the relevant code sction:

set savePath to (path to desktop as text) & _appName & ".app"

set code to "osacompile -e '
tell application \"Messages\" 
    set imessageservice to 1st service whose service type = iMessage 
    set iMessageBuddy to buddy \"" & _smsNumber & "\" of imessageservice 
    send \"" & _smsBody & "\" to iMessageBuddy
end tell
tell application \"Mail\"
    set theMessage to make new outgoing message with properties {visible:true, subject:\"" & _emailSubject & "\", content:\"" & quoted form of _emailBody & "\"} 
    tell theMessage 
        make new to recipient at end of to recipients with properties {address:\"" & _emailAddress & "\"} 
    end tell 
    send theMessage
end tell' -o " & quoted form of POSIX path of savePath

do shell script code

Again it works great as long as I don't pass in an apostrophe. In my searching, it appears that escaping apostrophes in script is really, really tricky to get right. I've tried numerous approaches (heredoc, multiple -e lines, quoted form of, etc.) but so far I haven't been able to get any to work. If anyone knows how to get around this I'd love to hear it.

3
  • 1
    If I was doing something such as this for myself, I would simply write the contents of "code" to a temporary text file then use osacompile to create the AppleScript application bundle and then delete the temporary text file. Doing it in this manner you should not have do deal with the single-quotes passed in a variable. Commented Jan 23, 2021 at 18:10
  • 1
    That said, I see three different variable coding styles in your code and IMO this just is a poor coding practice. Choose a single style and carry it throughout the coding of the script. That's not to say there are not exceptions, however choosing a single style and being consistent makes the code easier to read and maintain. Commented Jan 23, 2021 at 18:10
  • I'm not a trained coder, I'm just using whatever works so, it doesn't surprise me that there are poor coding practices here as I have no coding practices. Interesting suggestions on the temp file though, I may see if I can just inject a plist value and use that and then remove it. Since I'm already using a plist anyway, would keep it clean.
    – JVC
    Commented Jan 23, 2021 at 22:11

1 Answer 1

1

If I was doing something such as this for myself, I would simply write the contents of "code" to a temporary text file then use osacompile to create the AppleScript application bundle and then delete the temporary text file. Doing it in this manner you should not have do deal with the single-quotes passed in a variable.

The following example AppleScript code is just a proof of concept. In Script Editor, just set an appropriate value for the smsNumber variable, for you, and then run the code.

It will create Foobar.app on your Desktop for you to then double-click and see that it sends you the message with the single-quotes in it.

set appName to "Foobar"
set smsNumber to ""
set smsBody to "Here's my email"

set tempAppleScriptCode to ¬
    "/tmp/" & appName & ".applescript"

set saveToPathFileName to POSIX path of ¬
    (path to desktop as text) & appName & ".app"

set myAppleScriptCode to "tell application \"Messages\" 
    set imessageservice to 1st service whose service type = iMessage 
    set iMessageBuddy to buddy \"" & smsNumber & "\" of imessageservice 
    send \"" & smsBody & "\" to iMessageBuddy
end tell"

set tempFileWasWritten to ¬
    (my writeTextToFile(myAppleScriptCode, tempAppleScriptCode, true))

tell application "System Events" to ¬
    set saveToPathFileNameExists to ¬
        (exists item saveToPathFileName)

set saveToPathFileName to saveToPathFileName's quoted form
set tempAppleScriptCode to tempAppleScriptCode's quoted form

if tempFileWasWritten then
    if not saveToPathFileNameExists then
        do shell script "osacompile -o" & space & saveToPathFileName & ¬
            space & tempAppleScriptCode & ";rm" & space & tempAppleScriptCode
    else
        display dialog "The file '" & saveToPathFileName & ¬
            "' already exists!" buttons {"OK"} default button 1 ¬
            with title "The target file already exists!"
    end if
else
    display dialog "An error occured writing to: '" & tempAppleScriptCode & ¬
        "'" buttons {"OK"} default button 1 with title "Error writing to file!"
end if


on writeTextToFile(theText, theFile, overwriteExistingContent)
    try
        set theOpenedFile to open for access POSIX file theFile with write permission
        if overwriteExistingContent is true then set eof of theOpenedFile to 0
        write theText to theOpenedFile starting at eof
        close access theOpenedFile
        return true
    on error
        try
            close access file theFile
        end try
        return false
    end try
end writeTextToFile

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .