Copy Mac Mail Message Contents To Clipboard?

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

In order to answer your question, please post your macro.
See

Sorry — I thought the previous response would’ve been attached to my query.
Below is the script that I attempted to add the time received to, with faulty results…

Tom <https://forum.keyboardmaestro.com/users/tom> 

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

Get the list of all the recipients
Copy the list as formatted text to a variable
Integrate the variable into your header element
Here is a heavily commented form of the complete script, 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

It doesn’t matter how you name the variable. The important things is to set it.

You can do it in an analogous way as the theDate variable is set in line 20 of the script:

set theDate to date string of (get date received of theMsg)

So, add this:

set theTime to time string of (get date received of theMsg)

And then —the same as with the date— add the theTime variable to the theHeader variable, which will produce the output (line 52, marked with “# Compose the header” in the script).

For example, to add the time at the end:

set theHeader to "From: " & theSender & linefeed & "To: " & toRecipients & linefeed & "CC: " & ccRecipients & linefeed & "BCC: " & bccRecipients & linefeed & "Subject: " & theSubject & linefeed & "Date received: " & theDate & linefeed & "Time received: " & theTime

This will produce a header like this (example):

From: xxx xxx xxx.xxx@xxx.xxx
To: bbedit@googlegroups.com
CC:
BCC:
Subject: Manipulating buffer in window with AppleScript?
Date received: Wednesday, 12. April 2017
Time received: 00:38:45‌


Or, if you prefer to have date and time in one line:

set theHeader to "From: " & theSender & linefeed & "To: " & toRecipients & linefeed & "CC: " & ccRecipients & linefeed & "BCC: " & bccRecipients & linefeed & "Subject: " & theSubject & linefeed & "Received: " & theDate & "; " & theTime

which will produce this:

From: xxx xxx xxx.xxx@xxx.xxx
To: bbedit@googlegroups.com
CC:
BCC:
Subject: Manipulating buffer in window with AppleScript?
Received: Wednesday, 12. April 2017; 00:38:45

Probably you have these problems because you are posting from your mail client. If you have access to a web browser, it’s better to communicate with the forum via web browser.

The mail notifications are fine to get notified about new posts/topics, but not so much to post or to respond to posts. As you see, via mail the format gets messed up (quoted text, code blocks, inline code, etc.) and apparently you don’t have much control over your post.

Besides that you won’t see when a post has been updated or edited, I think.

Hmm…

I tried to introduce the changes to the script (below), and apparently something is amiss.

I was also wondering if there's a way to not put "CC" or "BCC" if those fields are empty in the received e-mail.

Next…I'll be wanting a script that writes a reply!

Thank you for your expertise!

Paul

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)
   # 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 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 & "  Time: " & theTime
   
   
   # 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

The script as you have quoted it stops halfway at ~line 56, that is, the last part of the script is missing. Of course, it won’t work like this.

Please use the whole script code, as posted in the earlier post, and add your changes. When copying from the post make sure to copy the whole script code, from line 1 to the last line.

Well, I (or somebody else) could modify the script to not show any “CC” or “BCC” if there aren’t any. But the question is: is it useful to provide you with pre-made solutions?

Your “Next…I'll be wanting a script that writes a reply!” tells me that you have further ambitions with the script. So, I really think it would be worth that you learn at least some AppleScript basics, which will allow you to build/modify the script yourself. It’s not necessary that your script works flawlessly. In case of any problems, post here.

Read the scripting dictionary of the Mail app and try to learn enough about AS to build a script that “in theory should work”. Then post the questions about the missing details here. Or, even when you come across a problem already in the building process, you can ask here.

But, asking for complete, working scripts, without understanding the basics, is something I won’t deliver to. I don’t have the time for this, and – as already mentioned – I doubt that it is a good way.

####Edit:

Sorry, if this sounded harsh, but indeed I’m a bit angry disappointed. I’ve written the script for you (I’m not using it, nor was I using a similar script before). I even added very explicit comments, to facilitate your understanding of how it works. And you don’t even pay attention when copy/pasting the script code, posting incomplete code here, and asking why it doesn’t work!?

Sorry, this was harsh again. I’m calming down now…:wink:

Hello Tom,

I always draft and proof in a WP application, then copy and paste into either e-mail, web response, etcetera. So, naturally, I was alarmed when you wrote that only part of my novice AS revisions made it to my forum entry.

If I were you, I too would be angry/disappointed if somebody kept hitting my favor bank with carelessly composed queries (which, as you know, happens all the time).

[Irony is, I just attempted to edit the post to make sure my entire script was included (which, it turns out, would fail regardless, per the correct code in your response), and it didn’t take either.]

I agree: nobody learns anything by being spoon-fed answers. Certainly this is not my method in dealing with clients or students, and I apologize if I come across as some lazy ingrate.

When I wrote ‘Next…I’ll be wanting a script that writes a reply!’ it was intended to be facetious, playing on the very I-Don’t-Want-To-Learn; Just-Give-Me-The-Answer attitude that irks me (and you as well, so it would seem).

I’ll keep hacking away at my imperfect script, the irony being that in pre-Yosemite versions of Mac Mail, you could simply copy and paste a message.

Thank you for your help and forbearance.

PPS

As said, I’m always happy to help you find errors in your script. So:

I proposed you to add this line:

set theTime to time string of (get date received of theMsg)

Now have quick look at your code and I’m sure you’ll spot the error :wink:

You are right, I could have spotted that error already in the first version of your post. But since I saw that a part of the script was completely missing I didn’t bother trying to find any errors.

As a side note, the “tell application” (line 1) and the “end tell” (last line) are an obligatory part of the script code. So, when posting you shouldn’t exclude these lines from the code block formatting. Sure, it’s just a formal thing, but chances are good that other users who are going to copy the code block will end up with an incomplete script.

Here a short explanation of your error, or ‘how to find out how to get the Received Time‘:

When I said that the name of a variable doesn’t matter, I literally meant ‘variable’. The date received is not a variable, it’s a property of message and it is part of Mail’s scripting dictionary.

You cannot simply change the names of these things. (Well, you can, but this would mean working by trial and error.) To see the scripting dictionary of an app, do the following:

  1. Launch Script Editor (/Applications/Utilities/Script Editor.app)
  2. Go to File > Open Dictionary…
  3. Choose the Mail app from the list.
  4. In the toolbar of the now open window make sure that “AppleScript” is selected as language.
  • You now see the AppleScript dictionary of Mail
  1. Go through the dictionary and look for the thing of interest, or use the search field.
  • To stay with the example: If you type “received” into the search field you will only get one hit: “date received”. This tells us that a property “time received” doesn’t exist in Mail’s dictionary.

That means that we cannot change date received to “time received”, because Mail can not understand that. (It’s not part of its dictionary.)

OK, fine. But how to get the Time?

Common sense tells us that it is very unlikely that there would be no way to get the Received Time. And, since date received seems to be the only thing related to “received”, we should suspect now that the Time is somehow part of that date received property.

Since we already had a working script line with date received, things are easy here:

The date was obtained with date string of (get date received of theMsg). The “of” tells us that date string must be a part of date received, and since “date” is a specifier of “string” we can assume that there must be other strings besides the date string.[1]

Unfortunately Script Editor’s dictionary viewer gives us no hint here[2], but in this case a trial and error approach seems promising: Voilà, time string of (get date received of theMsg) will work as expected.

I hope this helps a bit for future adventures :thinking:


[1] One of the cases where the human-language-like syntax of AppleScript is beneficial…

[2] This is because time string is a property of the date class which is part of the AppleScript types suite. I have found no way to display this in Script Editor’s dictionary viewer. One more case where Script Debugger makes life easier: if you type “time” in Script Debugger’s dictionary viewer’s search field you get “time string” as hit #2.

OK, here is a new version with an optional display of the CC and BCC Recipients:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

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)
  # Time received
  set theTime to time 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
  
  # 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 theHeader to "From: " & theSender & linefeed & "To: " & toRecipients & linefeed & ccRecipientsDisplay & bccRecipientsDisplay & "Subject: " & theSubject & linefeed & "Date received: " & theDate & "  Time: " & theTime
  
  
  # 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

The changes are…

  • the new block at lines 56 to 65, and
  • a changed header composition (line 68).

See the comment at line 55.

What I have done:

  • I introduced a new variable ccRecipientsDisplay.
  • If there are any CC Recipients than this variable is set to the CC Recipients (as saved in the ccRecipients variable) plus the formatting elements for the display (the “CC:” and a following linefeed).
  • If there aren’t any CC Recipients than the variable is set to an empty string.
  • The composed header (line 68) now uses the precomposed ccRecipientsDisplay variable, so that there will be displayed nothing if there isn’t any CC.

The same for the BCC Recipients (bccRecipientsDisplay).

1 Like

As luck would have it, I finally got around to posting a macro here that may cover your needs. I saw your post subsequently :slight_smile:

9 posts were split to a new topic: How to Copy Outlook (2011/2016) Message to Clipboard

Yes, you guys (e.g. @charliez1030) should really post new questions in new threads.

If you have found a thread that is related or otherwise close to your subject, then just link it in the intro, for example:

I wish to do this and that and I’ve seen the thread [link here to the thread]. Based on that idea, how can I implement/adapt that for my [your case here].

This has several advantages:

  • Different subjects/topics are kept apart. For example, as you have learned now, scripting Outlook is different from scripting Apple Mail.

  • “Hijacking” another thread results in misleading thread titles (like here: the thread title is “Copy Mac Mail Message”, but the thread now also covers Outlook.)

    • Therad titles that correspond to the content make it much more easier to browse the forum.
  • The Discourse forum software allows to mark an answer as “Solution” (green checkmark). But this works once per thread. So, looking at the present thread it is impossible to set a solution mark, since the tread covers two different topics/questions and answers. (And, only the OP can set the checkmark, anyway.)

    • Here, for example, @JMichaelTX’s script really deserves a “Solution” checkmark, but you can’t set it, because you are not the original poster of the thread.

Thanks for that. Good idea!