How to Copy Outlook (2011/2016) Message to Clipboard

Hi Tom,

I'm trying to morph this to work with Microsoft Outlook 2016. I didn't get very far before I ran into a hiccup. For some reason it doesn't like the syntax and throws an error at line " set toRecipients to toAddresses as rich text" with Expected class name but found identifier. Any thoughts? Also, in the very intro to the code you mention "use scripting additions" - can you advise what you mean?

Thanks!
Cheryl

@tom's script was written for Apple Mail which is very different from MS Outlook (2011 and 2016). So it's not surprising the script quickly failed.

I've been playing with a script for Outlook 2011, and it works, but I'm not happy with how the results look when I paste into another app, although TextEdit is OK. I'm working on another option to put encoded HTML on the clipboard as well, and hope that looks better.

But if you want the best results, I've found just create a PDF from Outlook when you go to print the message. This provides all the data, and looks great.

Until I have something better, good luck.

Yes, as @JMichaelTX has said, the script is for Apple’s Mail program. Outlook’s AppleScript dictionary might be similar to the one of Apple Mail up to a certain degree, but there are certainly terms that differ.

You can look up Outlook’s dictionary by doing this:

  1. Open the Script Editor program (/Applications/Utilities/Script Editor.app)
  2. In the File menu of Script Editor go to Open Dictionary
  3. Select Outlook from the list

Now you can see the contents of Outlook’s dictionary. If it’s not too different you may be able to adapt the script. I don’t have Outlook installed on any computer, so I can’t help you here.

Also, in the very intro to the code you mention "use scripting additions" - can you advise what you mean?

This is not a mention, this is part of the code. It allows the script to use external libraries (“scripting additions”).

Thanks so much...I am using the Microsoft dictionary but it is failing when it hits anything that says "as rich text". Is this a variable term by application or is this standard Applescript terminology? It would seem standard but it throws an error of "Expected class name but found identifier."

I tried to do some legwork and research this error but the must be fairly common as I'm not finding this exact situation.

Appreciate your help and, once adjusted, will post the code back to this site for others to use.

thanks

Have you tried it with as text or without anything? Or maybe with something special that Outlook’s dictionary is offering?

IIRC, the reason for the as rich text in my script was not to get styled text, it is rather due to some weird behavior of Apple’s Text Suite. See this problem here and Shane Stanley’s explanation in the follow-up(s).

If Outlook doesn’t use Apple’s Text Suite, then you shouldn’t have that problem.

Yes, this is very pesky.

The workaround is to use as unicode text.

as string usually works as well but is deprecated.

-Chris

I have converted @Tom's Apple Mail script to work with Outlook 2011.
I don't have Outlook 2016, but I would expect it to be similar -- same script might even work -- but no guarantees. :wink:

Notes

  • This is a work-in-progress. It is not complete. However, it is functionallly complete.
  • At this point is is provided to serve as an example of how to extract data
    from an Outlook 2011 message.
  • This is mostly a conversion of the Apple Mail Script by @Tom to work with Outlook 2011.
  • I am not satisfied with the output format, but it does contain all relavent data in the Message.
  • If you don't like my choice of fonts, change them in the script.
  • Since Outlook 2011 stores the message body a HTML or plain text, the final output
    will be generated as HTML, then converted to RTF using ASObjC. Both RTF and Plain text are put on the Clipboard.
  • As written it does Require
    • Satimage.osax
      (Free D/L & info at Smile companion osax )
    • This can be easily converted to using the KM Engine Search and Replace RegEx command, but that is left as an exercise, if so desired, for the reader. :wink:
  • I have also included the simple script block to create a new Evernote Note from the HTML.

Please feel free to post any comments, issues, and/or suggestions concerning this script.


Example Output as Pasted into TextEdit

(paste into other apps can vary considerably)

AppleScript to Put Outlook 2011 Message on Clipboard

property ptyScriptName : "Copy MS Outlook Contents To Clipboard?"
property ptyScriptVer : "2.1" --  Cleanup to Publish
property ptyScriptDate : "2018-05-29"
property ptyScriptAuthor : "JMichaelTX"

(*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
RETURNS:	Sets Clipboard to Entire Outlook Msg, including Header

METHOD:
  • This is a work-in-progress.  It is not complete.  However, it is functionallly complete.
  • At this point is is provided to serve as an example of how to extract data
  from an Outlook 2011 message.
  • This is mostly a conversion of the Apple Mail Script by @Tom to work with Outlook 2011.
  • I am not satisfied with the output format, but it does contain all relavent data in the Message.
  • Since Outlook 2011 stores the message body a HTML or plain text, the final output
  will be generated as HTML, then converted to RTF using ASObjC.  Both RTF and Plain text are put on the Clipboard.

REQUIRED:
  1.	macOS 10.11.6+
  2.	Mac Applications
  • MS Outlook 2011
  
  3.	EXTERNAL OSAX Additions/LIBRARIES/FUNCTIONS
  • Satimage.osax
  (Free D/L & info at http://tinyurl.com/Satimage-Osax-DL )
  
TAGS:	@Lang.AS @SW.OL @CAT.Messages @CAT.Clipboard @Auth.JMichaelTX

REF:  The following were used in some way in the writing of this script.

  1.	2017-04-14, Tom, Keyboard Maestro Discourse
  Copy Mac Mail Message Contents To Clipboard?
  https://forum.keyboardmaestro.com/t/copy-mac-mail-message-contents-to-clipboard/5400/31
  
  2.	2018-05-28, ShaneStanley, Late Night Software Ltd.
  How Do I Set Clipboard (Pasteboard) to Both Rich Text (RTF) and Plain Text?
  http://forum.latenightsw.com/t/how-do-i-set-clipboard-pasteboard-to-both-rich-text-rtf-and-plain-text/1189/5?u=jmichaeltx


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*)
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

--- classes, constants, and enums used by the ASObjC Handler htmlToRTFCB() ---
property NSUTF8StringEncoding : a reference to 4
property NSString : a reference to current application's NSString
property NSRTFTextDocumentType : a reference to current application's NSRTFTextDocumentType
property NSPasteboardTypeRTF : a reference to current application's NSPasteboardTypeRTF
property NSPasteboardTypeString : a reference to current application's NSPasteboardTypeString
property NSDictionary : a reference to current application's NSDictionary
property NSAttributedString : a reference to current application's NSAttributedString
property |NSURL| : a reference to current application's |NSURL|


property LF : linefeed
property BRLF : "<BR>" & linefeed


tell application "Microsoft Outlook"
  # Get the first selected message
  set selMsg to the selection
  try
  set theMsg to first item of selMsg
  on error
  display alert "Probably No Message Selected!"
  error number -128
  end try
  
  # Get the desired header elements
  
  # Elements containing only one item
  # Sender
  set theSender to the sender of theMsg
  set theSender to my convertEmailToStr(theSender)
  # Subject
  set theSubject to subject of theMsg
  # Date received
  set theDate to date string of (get time received of theMsg)
  # Time received
  set theTime to time string of (get time received of theMsg)
  
  # Elements containing multiple items (recipients)
  # Normal (“To”) Recipients
  set toAddresses to {}
  repeat with i in to recipients of theMsg
  set oEMail to email address of i
  set end of toAddresses to my convertEmailToStr(oEMail)
  end repeat
  
  
  # CC Recipients
  set ccAddresses to {}
  repeat with i in cc recipients of theMsg
  set oEMail to email address of i
  set end of ccAddresses to my convertEmailToStr(oEMail)
  end repeat
  # BCC Recipients
  set bccAddresses to {}
  repeat with i in bcc recipients of theMsg
  set oEMail to email address of i
  set end of bccAddresses to my convertEmailToStr(oEMail)
  end repeat
  
  if (has html of theMsg) then
  set msgBodyHtml to content of theMsg -- is already HTML for Outlook
  else
  set msgBodyHtml to my convertToHtml(theSubject, content of theMsg)
  end if
  
  
end tell -- Outlook

-----------------------------------
--	FORMAT HTML OUTPUT --
----------------------------------

# Format the recipients 
# Save current text item delimiters
set saveTID to AppleScript's text item delimiters
# Set the desired delimiters for the representation, e.g. {", "}, {"; "}, {" – "}, {" | "}
set AppleScript's text item delimiters to {", "}
# Format the recipients lists as delimited text
set toRecipients to toAddresses as text
set ccRecipients to ccAddresses as text
set bccRecipients to bccAddresses as text
# Restore text item delimiters
set AppleScript's text item delimiters to saveTID

# CC and BCC are optional. So let’s precompose the variables to display these two strings, in function of if there are any CC/BCC recipients
if ccRecipients is not "" then
  set ccRecipientsDisplay to "CC: " & ccRecipients & linefeed
else
  set ccRecipientsDisplay to ""
end if
if bccRecipients is not "" then
  set bccRecipientsDisplay to "BCC: " & bccRecipients & linefeed
else
  set bccRecipientsDisplay to ""
end if

# Compose the header
set TRTD to "<tr><td>" & LF
set TDTR to "</td></tr>" & LF

set headerHtml to "<table width=\"100%\" style=\"font-family: verdana; font-size: 16px;\">" & my addrow({"<B>Subject:</B>", theSubject}) & my addrow({"<B>Received:</B>", theDate & "  " & theTime}) & my addrow({"<B>From:</B>", theSender}) & my addrow({"<B>To:</B>", toRecipients & BRLF & ¬
  ccRecipientsDisplay & bccRecipientsDisplay}) & ¬
  "</table>"

--- Put Header in HTML Table ---

set headerHtml to "
<div><BR>
<table width=\"100%\"><tr>
<td style=\"border-bottom: 1px solid black; border-top: 1px solid black; font-family: verdana; font-size: 16px;\">
" & headerHtml & " 
</td>
</tr>
</table><BR>
</div>
"

--- Insert Header AFTER Content <body> Tag ---

set regexFind to "(<body.+)"
set regexReplace to "\\1" & linefeed & headerHtml & linefeed
set finalMsg to change regexFind into regexReplace in msgBodyHtml syntax "PERL" with regexp

--- CONVERT HTML to RTF, and PUT ON CLIPBOARD ---

my htmlToRTFCB(finalMsg)

------------------------------------------
--	OPTIONAL:  Create Note in Evernote --		#JMTX ADD
------------------------------------------
-- This produces better result than a Paste of the clipboard in a new note
-- Remove comment block to use
(*
tell application "Evernote"
  set oNote to create note with html finalMsg title theSubject
end tell
*)

--~~~~~~~~~~~~~~~~~~~~~~~~~ END OF MAIN SCRIPT ~~~~~~~~~~~~~~~~~~~~~~

on htmlToRTFCB(pHtmlStr)
  (*
REF:  

  1.	2018-05-28, ShaneStanley, Late Night Software Ltd.
  How Do I Set Clipboard (Pasteboard) to Both Rich Text (RTF) and Plain Text?
  http://forum.latenightsw.com/t/how-do-i-set-clipboard-pasteboard-to-both-rich-text-rtf-and-plain-text/1189/5
*)
  
  -- convert to data
  set htmlString to NSString's stringWithString:pHtmlStr
  set htmlData to htmlString's dataUsingEncoding:NSUTF8StringEncoding
  -- make attributed string
  set attString to NSAttributedString's alloc()'s initWithHTML:htmlData documentAttributes:(missing value)
  -- need it in RTF data form for clipboard
  set rtfData to attString's RTFFromRange:{0, attString's |length|()} documentAttributes:{DocumentType:NSRTFTextDocumentType}
  set pb to current application's NSPasteboard's generalPasteboard() -- get pasteboard
  pb's clearContents()
  -- set both types for the first object on the clipboard
  pb's setData:rtfData forType:NSPasteboardTypeRTF
  
end htmlToRTFCB

on convertEmailToStr(poEmail)
  tell application "Microsoft Outlook"
  set emailStr to (name of poEmail & " &lt;" & address of poEmail & "&gt;")
  end tell
  return emailStr
end convertEmailToStr


on addrow(pColList)
  set rowHtml to "<tr>"
  repeat with oCol in pColList
  set rowHtml to rowHtml & "<td>" & (contents of oCol) & "</td>"
  end repeat
  set rowHtml to rowHtml & "</tr>" & LF
  return rowHtml
end addrow


on convertToHtml(pTitleStr, pBodyStr)
  
  set regexFind to "((\\r\\n)|\\n|\\r)"
  set regexReplace to "<BR>\\n"
  set pBodyStr to change regexFind into regexReplace in pBodyStr syntax "PERL" with regexp
  
  set htmlStr to "
<!DOCTYPE html>
<html>
<head>
  <title>" & pTitleStr & "</title>
</head>
<body style=\"font-family: verdana; font-size: 14px;\">
<div>
" & pBodyStr & " 
</div>
</body>
</html>
"
  
  return htmlStr
end convertToHtml
1 Like

This is fantastic! Thanks @JMichaelTX and @Tom at keyboard maestro! This is way more than I could accomplish in my infantile stage of learning Applescript. I'm workin on applying these concepts to capturing event details and will post it back here for all.

Cheers and thanks!

That's great! Unless it's a minor variation of this script, please post in a new topic.

If you are going to be doing much scripting:
You may want to try Script Debugger 7.
SD7 now comes with a 20-day free trial, and then will gracefully downgrade to SD7 Lite (which is still much better than Script Editor).

1 Like