1
votes

I have a message in Mail's Drafts folder. I would like to duplicate it (preserving its attachment), add a TO address, then send it (the duplication).

I'm not able to reference the duplicate.

tell application "Mail"

  set theTemplate to the (first message of drafts mailbox)

  set theDuplicate to (duplicate theTemplate to drafts mailbox)

  // error: The variable theDuplicate is not defined.
  display dialog ((subject of theDuplicate) as rich text)

  tell theDuplicate

    -- add the recipient
    make new to recipient at end of to recipients with properties {name:("Foo Bar"), address:("[email protected]")}

    -- send message
    send

  end tell

end tell

Mail's Dictionary entry on duplicate suggests that what I'm trying to do is supported:

duplicate v : Copy an object.

duplicate specifier : The object(s) to copy.

[to location specifier] : The location for the new copy or copies.

[with properties record] : Properties to set in the new copy or copies right away.

What am I not understanding?

1

1 Answers

3
votes

There's one aspect you're missing: the duplicate command does not return the duplicate it creates - you can tell by the absence of → <type> in the dictionary.

Thus you need to obtain a reference to the duplicate using a separate commnand, after duplication.

Sadly, AppleScript isn't done being difficult yet:

drafts mailbox appears to be an abstraction over the various specific draft mailboxes associated with specific email accounts defined.

Targeting the abstract drafts mailbox works fine for accessing extant drafts, but when copying to a draft mailbox it seems that a specific drafts mailbox must be targeted.

You can determine the actual, specific drafts mailbox that your draft is stored in by examining what is reported when you click Events in AppleScript Editor after executing the set theTemplate to the (first message of drafts mailbox) command: it will show you a reference to the specific mailbox that the draft resides in, e.g., in the case of a Gmail account:

message id 153525 of mailbox "Drafts (Gmail)"

If you don't want to hard-code a specific reference, you loop over mailboxes of drafts mailbox to find the one specific child mailbox that holds the draft of interest.

Only when targeting a specific drafts mailbox does the duplicate command actually work (at least visibly - it's conceivable that copying to the abstract mailbox works and Mail.app works, but merely doesn't show - however, the fact that the count of messages in drafts mailbox does not change suggests otherwise).

But the fun doesn't stop there: you cannot set recipient properties on a draft message and send it directly: you have to convert it to an outgoing message first, yet there is no direct way to perform this conversion (that I know of). As a workaround, the code below uses the redirect command, which, however, has side-effects - see the comments.

tell application "Mail"

    # Find the _specific_ drafts mailbox that contains the
    # template draft message.
    set theTemplate to missing value
    try
        repeat with mboxDrafts in mailboxes of drafts mailbox
            if (count of messages of mboxDrafts) > 0 then
                set theTemplate to get first message of mboxDrafts
                exit repeat
            end if
        end repeat
    end try
    if theTemplate is missing value then error "No drafts found"

    set countBefore to count of messages of mboxDrafts

    # Duplicate the original, creating a clone in the same mailbox.
    duplicate theTemplate to mboxDrafts

    if (count of messages of mboxDrafts) ≤ countBefore then
        error "Failed to duplicate template draft message."
    end if

    # Obtain a reference to the duplicate.
    set theDuplicate to last message of mboxDrafts


    # Transform the draft message into an *outgoing message* using the `redirect`
    # command, so as to be able to assign recipients and to send (sadly, converting
    # with `as outgoing message` doesn't work).
    # !! Using `redirect` has side effects: the sender shows up as 'Resent-From` (too)
    # !! and the recipient(s) as 'Resent-To'.
    # !! Using `reply` works too, but _quotes_ the existing contents of the message.
    # !! I have yet to find a side-effect free way of converting a draft
    # !! message to an outgoing message 
    set theDuplicateAsOutgoing to redirect theDuplicate without opening window

    tell theDuplicateAsOutgoing

        # Add the recipient.
        make new to recipient at end of to recipients with properties {name:("Foo Bar"), address:("[email protected]")}

        # Send message.
        send

    end tell

end tell