8

Mail.app を介して Cocoa アプリから HTML メールを送信しようとしています。Mail.app で新しいメッセージを開き、件名、受信者を含め、リンクやその他のコンテンツを含む HTML 本文を追加したいと考えています。しかし、これを行う方法が見つかりません。スクリプト ブリッジは既に試しましたが、MailOutgoingMessage クラスにはコンテンツ タイプがなく、プレーンテキストでコンテンツを追加できます。

次のようなAppleScriptを試しました:

set htmlContent to read "/Path/index.html"
set recipientList to {"mail@mail.com"}

tell application "Mail"
    set newMessage to make new outgoing message with properties {subject:"qwerty", visible:true}
    tell newMessage
        make new to recipient at end of to recipients with properties {address:"mail@s.com"}
            set html content to htmlContent
        --send
    end tell
end tell

--send を send に変更した場合にのみ、このコードは html で電子メールを送信します。しかし、ユーザーがいくつかの変更を加えた後、後で手紙を送信する必要があります。

4

3 に答える 3

7

問題を要約すると: AppleScript を使用して対話型編集用の HTML コンテンツを含むメッセージを作成することはできません(OS X 10.9.2 以降): 新しいメッセージ フォームはの本文で表示されます。

これはバグと見なされるべきであり、Apple にhttp://bugreport.apple.comで知らせることをお勧めします-注意: html content messageclass プロパティはの AppleScript 辞書で定義されていないため、HTML の割り当ては公式にサポートされていない可能性がありますMail.sdefMail.app

回避策がありますが、きれいではありません:

  • 目に見えないメッセージを作成します。
  • 下書きとして保存します。
  • 下書きメッセージを開くと、HTML コンテンツ表示されます。

いくつかの回避策が必要なため、これを確実に実装することは困難です。ただし、次のコードは最善を尽くします。

注: コードは GUI スクリプトを使用するため、このコードを実行するアプリケーション (または、 を介して実行する場合) に対して、補助デバイスへのアクセスを( を介して)有効にする必要がありますSystem Preferences > Security & Privacy > AccessibilityAppleScript EditorosascriptTerminal.app

# Example values; use `read someFile` to read HTML from a file.
set htmlContent to "<html><body><h1>Hello,</h1><p>world.</p></body></html>"
set recipientList to {"person1@example.com", "person2@example.com"}
set msgSubject to "qwerty"

tell application "Mail"

    # Create the message *invisibly*, and assign subject text
    # as well as the HTML content.
    set newMessage to make new outgoing message with properties ¬
        {visible:false, subject:msgSubject, html content:htmlContent}

    # Add recipients.
    # !! Given the workaround below, this is currently pointless.
    tell newMessage
        repeat with toRcpt in recipientList
            make new to recipient at end of to recipients with properties {address:toRcpt}
        end repeat
    end tell

    # Save the current number of drafts messages.
    set draftCountBefore to count messages of drafts mailbox

    # !! Save the new message as a *draft* - this is necessary
    # for the HTML content to actually appear in the message
    # body when we open the message interactively later.
    save newMessage

    # !! Sadly, it takes a little while for the new message
    # !! to appear in the drafts mailbox, so we must WAIT.
    set newMessageAsDraft to missing value
    repeat with i from 1 to 30 # give up after n * 0.1 secs.
        set draftCountNow to (count messages of drafts mailbox)
        if draftCountNow > draftCountBefore then
            set newMessageAsDraft to message 1 of drafts mailbox
            exit repeat
        end if
        delay 0.1 # sleep a little
    end repeat

    # Abort, if the draft never appeared.
    if newMessageAsDraft is missing value then error "New message failed to appear in the drafts mailbox within the timeout period."

    # Open the new message as a *draft* message - this ensures that 
    # the HTML content is displayed and editable in the message body.
    # !! The ONLY solution I found is to use `redirect`, which, unfortunately,
    # !! *wipes out the recipients*.
    # !! It does, however, ensure that the draft is deleted once the message is sent.
    redirect newMessageAsDraft with opening window

    # Activate Mail.app and thus the draft message's window.
    activate

    # !! Since the recipients have been wiped out, we need to
    # !! add them again - unfortunately, the only way we can do that is to
    # !! *GUI scripting* - simulating invocation of a menu command or
    # !! sending keystrokes.
    tell application "System Events"

        # We must make sure that the target window is active before
        # we can perform GUI scripting on it.
        set newMessageWindow to missing value
        repeat with i from 1 to 30 # give up after n * 0.1 secs.
            tell (first window of (first process whose frontmost is true) whose subrole is not "AXFloatingWindow")
                if name is msgSubject then
                    set newMessageWindow to it
                    exit repeat
                end if
            end tell
            delay 0.1 # sleep a little
        end repeat
        if newMessageWindow is missing value then error "New message failed to become the active window within the timeout period."

        # Turn the list of recipients into comma-delimited *string* for pasting into the To field.
        set {orgTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {","}}
        set recipientListString to (recipientList as text)
        set AppleScript's text item delimiters to orgTIDs

        # Save the current clipboard content.
        set prevClipboardContents to the clipboard

        # Cursor is in the  "To:" field, so use GUI scripting to send the Edit > Paste command now.
        # NOTE: Access for assistive devices must be enabled via System Preferences > Security & Privacy > Accessibility.
        set the clipboard to recipientListString
        my pasteFromClipboard("")

        # Restore the previous clipboard content.
        # !! We mustn't do this instantly, as our temporary content may not have
        # !! finished pasting yet. It would be non-trivial to determine
        # !! when pasting has finished (examining `count of to recipients` doesn't work), 
        # !! so we take our chances with a fixed, small delay.
        delay 0.1
        set the clipboard to prevClipboardContents

        # Place the cursor in the message *body*.
        # !! This works as of Mail.app on OS X 10.9.2, but may break in the future.
        try
            tell newMessageWindow
                tell UI element 1 of scroll area 1
                    set value of attribute "AXFocused" to true
                end tell
            end tell
        end try

    end tell

end tell

(*
 Pastes form the clipboard into the active window of the specified application (process) using GUI scripting
 rather than keyboard shortcuts so as to avoid conflicts with keyboard shortcuts used to invoke this handler.
 Specify "" or `missing value` to paste into the currently active (frontmost) application.
 The target process may be specified by either name or as a process object.

 CAVEAT: While this subroutine IS portable across *UI languages*, it does make an assumption that will hopefully hold for 
 all applications: that the "Edit" menu is the *4th* menu from the left (Apple menu, app menu, File, Edit).

 Examples:
     my pasteFromClipboard("") # paste into frontmost app
     my pasteFromClipboard("TextEdit")
*)
on pasteFromClipboard(targetProcess)
    tell application "System Events"
        if targetProcess is missing value or targetProcess = "" then
            set targetProcess to first process whose frontmost is true
        else
            if class of targetProcess is text then
                set targetProcess to process targetProcess
            end if
            -- Activate the application (make it frontmost), otherwise pasting will not work.
            set frontmost of targetProcess to true
        end if
        tell menu 1 of menu bar item 4 of menu bar 1 of targetProcess
            -- Find the menu item whose keyboard shortcut is Cmd-V
            set miPaste to first menu item whose value of attribute "AXMenuItemCmdChar" is "V" and value of attribute "AXMenuItemCmdModifiers" is 0
            click miPaste
        end tell
    end tell
end pasteFromClipboard
于 2014-04-15T22:10:47.810 に答える
1

送信前にメッセージを編集する必要があるとは思わなかったので、以前の回答は間違っていました。今回は正しいはずです。

それは基本的に

  • フォーマット済みの RTF ファイルを受け取り、
  • レンダリングしてクリップボードに入れ、
  • 新しいメッセージを作成し、
  • フィールドに入力し、
  • フォーカスをメッセージ本文に移動し、
  • フォーマットされたクリップボードを貼り付けます

コードは次のとおりです。

set textSubject to "HTML Test"
set toAddress to "john.doe@gmail.com"
set toName to "John Doe"

tell application "Mail"
    do shell script "cat ~/Documents/RTF\\ File.rtf | textutil -stdin -stdout -convert rtf | pbcopy"

    set refMessage to make new outgoing message with properties {name:toName, address:toAddress, subject:textSubject, visible:true}
    tell refMessage
        make new to recipient at end of to recipients with properties {name:toName, address:toAddress}
    end tell
end tell

tell application "System Events"
    tell application process "Mail"
        set frontmost to true
        set value of attribute "AXFocused" of scroll area 4 of window textSubject to true
    end tell
    keystroke "v" using {command down}
end tell

繰り返しますが、これはSnow Leopardでうまくいきました

それが役に立ったことを願っています。

于 2014-04-14T20:18:15.920 に答える