繁体   English   中英

使用Mail.app从Cocoa发送HTML Mail

[英]Send HTML Mail from Cocoa with Mail.app

我正试图通过Mail.app从Cocoa应用程序发送html电子邮件。 我想在Mail.app中打开新邮件,包括主题,收件人,并添加带有链接和其他内容的HTML Body。 但找不到这样做的方法。 我已经尝试过Scripting Bridge,但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

这段代码发送电子邮件与html,只有我正在改变 - 发送。 但是我需要在用户做出一些更改之后发送信件。

回顾一下问题 :使用AppleScript创建带有HTML内容以进行交互式编辑的消息不起作用 (从OS X 10.9.2开始):新消息表单提供了一个主体。

这应该被认为是一个错误 ,我鼓励大家在http://bugreport.apple.com上告诉Apple - 警告 :在Mail.sdefMail.app的AppleScript字典中没有定义html content message类属性,所以分配HTML可能不受官方支持。

有一种解决方法 ,但它并不漂亮:

  • 无形地创建消息。
  • 将其保存为草稿
  • 打开草稿消息,此时显示HTML内容。

实现这一目标具有挑战性,因为需要一些变通方法。 但是下面的代码尝试最难:

注意:由于代码使用GUI脚本,因此必须为运行此代码的应用程序启用辅助设备访问 (通过System Preferences > Security & Privacy > Accessibility )(例如, AppleScript Editor或者,如果通过osascriptTerminal.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

目前还不清楚你在寻找什么,但我会尽我所能提供一些帮助。

如果你留下send评论,那么邮件应该已经在Mail.app中打开,等待进一步编辑和发送。

通过添加行save newMessage ,它将保存到草稿文件夹中。 用户可以打开它并随时继续编辑。 如果您想从应用程序中实际发送草稿,请使用:

set sendMessage to first message of drafts mailbox
send sendMessage

祝好运!

我没有看到你需要在发送之前编辑邮件,所以我之前的回答是错误的。 这一次应该是正确的。

基本上

  • 采用预先格式化的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上运行良好

希望有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM