Copy Mac Mail Message Contents To Clipboard?

Hello Keyboard Maestro Maestros,

Alas the simple Command-C/COPY to copy a messages entire contents (including headers) to the clipboard has vanished in Mac Mail, Yosemite forward.

I have a very clumsy sequence that opens/forwards, selects all, copies, then pastes to TextEdit, but was wondering (praying?) if anyone has come up with a more elegant method of performing this obvious task?

Many thanks,

Keyboard Maestro Newbie

Basically this AppleScript does what you want:

tell application "Mail"
  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
  set theContent to the content of theMsg as rich text
  set theHeaders to all headers of theMsg
  set the clipboard to theHeaders & theContent
end tell

It takes the content and the headers from the first selected message.
To run the script with KM paste it to an Execute AppleScript action.

I’m not an experienced Mail scripter though, so it’s likely that there is a better or more elegant solution.

3 Likes

Hey Paul,

Any special reason you’re pasting into TextEdit?

-Chris

Hello Chris,

Don’t kick me, but I use word, and I keep running compilations of received e-mail.

Using a TextEdit document as an interim holding bin for some reason gets rid of a lot of extra spaces, returns and other gibberish that would happen if I paste directly into the Word documents.

(The same thing happens in reverse, by the way – try simply pasting from Word into Mac Mail and you’ll get quadruple spaces and other formatting BS. TextEdit seems to purge the incompatibilities…)

I am not saying this is an efficient way to work, but it does the trick.

Regs,

Paul

Hey Paul,

I wouldn't. I use Microsoft products myself when they are useful. :wink:

Are you trying to paste styled-text or just the text content of a message?

And what version of Word are you using?

-Chris

Hey Paul,

If you don’t care about styled-text then you can greatly improve the efficiency of your process by doing something like this with AppleScript:

--------------------------------------------------------------------------------
# Auth: Christopher Stone (and @Tom)
# dCre: 2016/11/04 22:37
# dMod: 2016/11/04 22:43 
# Appl: Mail, Microsoft Word
# Task: Append text of selected message to end of front Word document.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Mail, @Microsoft_Word, @Append, @Text, @Selected, @Message, @End, @Front, @Document
--------------------------------------------------------------------------------

# Mail code by @Tom.
tell application "Mail"
   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
   set theContent to the content of theMsg
   set theHeaders to all headers of theMsg
end tell

set theText to (theHeaders & theContent)

tell application "Microsoft Word"
   insert text theText at end of text object of active document
end tell

--------------------------------------------------------------------------------

Of course that can be significantly customized.

-Chris

Hello Chris,

Well, I’m overwhelmed as AppleScript is far beyond my brain capacity, but if I can grasp ever-so-slightly, it looks like your (and Tom’s) script is indeed far more efficient.

Mind you, there are a ton of similar QuicKeys/Keyboard Maestro sequences I’ve written as the copying of text from Word to Mail creates similar artifacts.

I’ve learned that if I want to carry over formatting and hyperlinks from a Word doc to Mac Mail, I need to do a “hard” copy/paste to TextEdit, then another hard copy/paste from said TextEdit document into Mail.

I assure you, you’d be dazzled by the dance between apps and windows my clumsy “scripts” cause.

I don’t know when I’ll have an opportunity to implement your script, but I thank you for helping to show me a more efficient way of my getting from A to B.

Best,

Paul

PS - Oh: Office 2011, riddled with updates and patches to do things like remember the window sizes and positions…

Hey Paul,

Yes. That's why I asked you if you wanted to paste styled-text.

Unfortunately using AppleScript you cannot acquire the style-information of an email message in Mail.app without jumping through a lot of hoops.

Probably not, since I've been doing similar things for 30+ years, but I get the idea.

I'm still using Office 2011 as well – I'm not at all happy with Office 365.

-Chris

Hello Chris,

I don’t mind jumping through hoops, so long as the machine is doing the jumping!

Office 365 defines “dog”. I had to work on promoting it, and it’s very challenging to get “excited” about something you find so incredibly flawed.

I’m not very fond of many of these cloud-based applications, and it’s particularly crippling on the media side of things, Adobe being incredibly adept at extortion.

Sigh…

PPS

Well, the script indeed works, but it copies over EVERYTHING (ala all the header gibberish).

I wonder why Apple decided to get rid of that straightforward “Copy Message Contents” pull-down menu.

Perhaps so they could spend the time writing code for iMessage bubbles in IOS 9…

Well, you said in your OP you wanted to copy the headers:

to copy a messages entire contents (including headers) to the clipboard

If you don’t want the headers than remove the corresponding line from the script:

set theHeaders to all headers of theMsg

and change the line after that to:

set the clipboard to theContent

Indeed I did ask for "headers", albeit incorrectly.

  What I meant was what Mail USED to copy over (Thunderbird still
  does…):

I have no clue what Mail used to copy some years ago, nor do I have Thunderbird installed, but if you want to get only certain parts of the header you can do something like this:

tell application "Mail"
  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
  set theSender to the sender of theMsg
  set toAddresses to {}
  repeat with i in to recipients of theMsg
    set end of toAddresses to address of i
  end repeat
  set saveTID to AppleScript's text item delimiters
  set AppleScript's text item delimiters to {", "}
  set toRecipients to toAddresses as rich text
  set AppleScript's text item delimiters to saveTID
  set theDate to date string of (get date received of theMsg)
  set theSubject to subject of theMsg
  set theHeaders to "From: " & theSender & linefeed & "To: " & toRecipients & linefeed & "Subject: " & theSubject & linefeed & "Date received: " & theDate
  set theContent to the content of theMsg as rich text
  set the clipboard to theHeaders & linefeed & linefeed & theContent
end tell

You can add other elements as needed, for example cc recipients, time, or whatever.

Hey Tom,

I am thrilled to report that your most recent script does exactly what I wanted!

Thank you, sir!

PPS

Hello Tom,

“You can add other elements as needed…”

Hmm…

Owing to my feeble scripting abilities, can anybody kindly let me know what additions I would make to include the CC and BCC fields in this script?

Thank you in advance,

Paul

You can get the cc recipients and the bcc recipients in exactly the same way as the to recipients.

  1. Get the list of all the recipients
  2. Copy the list as formatted text to a variable
  3. Integrate the variable into your header element

Here is a heavily commented form of the script (with cc and bcc), explaining each step:

tell application "Mail"
  
  # 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
  # Subject
  set theSubject to subject of theMsg
  # Date received
  set theDate to date string of (get date received of theMsg)
  
  # Elements containing multiple items (recipients)
  # Normal (“To”) Recipients
  set toAddresses to {}
  repeat with i in to recipients of theMsg
    set end of toAddresses to address of i
  end repeat
  # CC Recipients
  set ccAddresses to {}
  repeat with i in cc recipients of theMsg
    set end of ccAddresses to address of i
  end repeat
  # BCC Recipients
  set bccAddresses to {}
  repeat with i in bcc recipients of theMsg
    set end of bccAddresses to address of i
  end repeat
  
  # 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 rich text
  set ccRecipients to ccAddresses as rich text
  set bccRecipients to bccAddresses as rich text
  # Restore text item delimiters
  set AppleScript's text item delimiters to saveTID
  
  # Compose the header
  set theHeader to "From: " & theSender & linefeed & "To: " & toRecipients & linefeed & "CC: " & ccRecipients & linefeed & "BCC: " & bccRecipients & linefeed & "Subject: " & theSubject & linefeed & "Date received: " & theDate
  
  # Get the content
  set theContent to the content of theMsg as rich text
  
  # Compose complete message (header + content)
  set finalMsg to theHeader & linefeed & linefeed & theContent
  
  # Transfer it to the clipboard
  set the clipboard to finalMsg
  
end tell

Tom,

While it may not amaze you, I wanted to report that I ran the script you provided, and it did exactly what I aspired to.

I am going to put the previous and your new scripts in columns side-by-side to compare. Perhaps I might learn a thing or three…

Thank you,

Paul

Don't do that. I have not only added the new elements, I have also rearranged quite some things for better readability. So, comparing it side-by-side with the old version will probably confuse you.

The comments in the new version should explain most things.

Thank you, Tom.

Indeed the comments are an excellent map.

Hi Tom -

I thought I’d be clever and attempt to introduce time received into the script…and I created a mess.

I assumed the variable is “theTime”.

What am I botching?

Thank you,

Paul