Save mail text and attachments

Hi folks! hope someone can help me out with this as I am scratching my head a bit.

Promblem Summary: I need to save the contents of an email as PLAIN TEXT not RTF to one folder and save the attached image to another folder.

We have a form on our wesbite with a script attached that processes the form data and emails the form data to a specified email address.
The emails will always contain plain text and 1 (jpg usually) image attachment.

Thanks in advance, I’m not much of an applescripter and its a bit beyond me.

Model: iMac (intel)
AppleScript: 2.1.1
Browser: Safari 417.9.3
Operating System: Mac OS X (10.4)

  1. Do you want to select the emails and then manually run the script on them, or do you want to have the Mail.app run the script on every incoming email?
  2. You are using Apple’s Mail.app, right?
  3. To refer to messages that you selected in the Mail window, say
tell app "Mail"
set theSelectedMessages to selection
end tell

  1. To loop through the selected messages one by one, add
repeat with theMessage in theSelectedMessages
(* Put code here to do something with each message in turn*)
end repeat

  1. To refer to the body or text of each message, (in the repeat loop above), code

set theText to content of theMessage

  1. To refer to the attachment of each message, (in the repeat loop above), code

set theAttachment to first item of theMessage's mail attachments -- NOTE: this will crash if there are no attachments.

  1. To save the elements,

set theAttachmentFIleName to "your:path:to:attachment:folder:" & theAttachment's name
save theAttachment in theAttachmentFIleName

Saving the text is a bit trickier - just saving the content doesn’t work, as it is not a file, and “save” works only on documents or windows. So you would have to delete the attachment and then save the message itself.

As an addendum, here is how to write the body of the email to a new file on the Desktop in plain text form:


tell application "Finder" to set ptd to (path to desktop folder) as string
tell application "Mail"
	set theMessages to selection
	repeat with theMessage in theMessages
		set theText to content of theMessage
		set theFile to ptd & "Message Number " & (theMessage's id as string)
		set theFileID to open for access file theFile with write permission
		write theText to theFileID
		close access theFileID
	end repeat
end tell

==> file “Message Number 2776” of folder “Desktop”

  1. I am using apple’s mail.app and I would want it to run automatically not manually. I would setup a conditional rule in Mail.app to run the run the applescript if the correct criteria were met.

OK, so here is what happens in that case: when the Mail.app is told to “Run Applescript” as the action of a Rule, then the named Applescript must have a “on perform mail action” handler. The code in that handler is executed, and the handler is provided with the list of messages that met the Rule, and the name of the Rule, if that is needed. Putting this all together, we get


using terms from application "Mail"
	on perform mail action with messages theMessages
	tell application "Finder" to set ptd to (path to desktop folder) as string -- save textfiles directly on desktop  - this may not be what you want.
		repeat with theMessage in theMessages -- loop through the messages sent by Mail
			set theText to content of theMessage -- retrieve message body
			set theFile to ptd & "Message Number " & (theMessage's id as string) -- change this to include a folder if you want
			set theFileID to open for access file theFile with write permission -- open the new file for writing
			write theText to theFileID -- write the body text of the current email into the new file
			close access theFileID -- close the file
			set theAttachment to first item of theMessage's mail attachments -- this will crash if there are no attachments in the message
			set theAttachmentFileName to "your:path:to:attachment:folder:" & theAttachment's name -- replace quoted text with your desired path
			save theAttachment in theAttachmentFileName -- saves the attachment in the designated folder
		end repeat
	end perform mail action with messages
end using terms from

The only thing left is to customize the file paths to exactly where you want the texts and the attachments to be saved, and also to change the text-file naming convention to whatever you want it to be.

Well, it half worked… here’s the script as I used it

using terms from application "Mail"
	on perform mail action with messages theMessages
		tell application "Finder" to set ptd to "iMac:Users:richardburrow:Desktop:Pad Requests:email:" as string -- save textfiles directly on desktop  - this may not be what you want.
		repeat with theMessage in theMessages -- loop through the messages sent by Mail
			set theText to content of theMessage -- retrieve message body
			set theFile to ptd & "nobody.txt" -- change this to include a folder if you want
			set theFileID to open for access file theFile with write permission -- open the new file for writing
			write theText to theFileID -- write the body text of the current email into the new file
			close access theFileID -- close the file
			set theAttachment to first item of theMessage's mail attachments -- this will crash if there are no attachments in the message
			set theAttachmentFileName to "iMac:Users:richardburrow:Desktop:Pad Requests:attachment:" & theAttachment's name -- replace quoted text with your desired path
			save theAttachment in theAttachmentFileName -- saves the attachment in the designated folder
		end repeat
	end perform mail action with messages
end using terms from

It saved the attachment down correctly but saved the text file down with only the following:

I assume this is something to do with the attachment, what do I need to do to be able to script it to save the text down properly as well?

The way it is coded, it will save each message body as the exact same file. That’s why I had the message number added to the filename in my example. You’ll have to include a way for each file to have a different name, and the easiest I could think of without having to code a “make unique filename” subroutine was to just use the message number.

If the message body text file “nobody.txt” has only a comma, I bet that is what was in the message. If you had the rule set, maybe another message came in while you were working, and it overwrote the first one, since both had the same destination (nobody.txt).

Try with some more messages - you can’t include “Display Dialog” in a Mail handler, it will crash Mail.app, but what you can do is add this code block to the top of the file and that will allow you to test it without having to actually send yourself mail. Place this code just after the “using terms from” line.


(* select some message(s) in Mail before running this*)
tell app "Mail"
set theSelectedMessages to selection
perform mail action with messages theSelectedMessages
end tell

I removed your messageID code as I actually want the script to overwrite the same file each time.

No other messages came in I am sure of that. You mentioned

I wondered if the fact that the email has an attachement this might cause the

in the resulting text file.

I can’t seem to find a way to delete an attachment from a message. I get a script evaluation error.

Nonetheless, I did test my “write contents to file” code and it works just fine for me. What I am thinking is that perhaps the “write” command needs to have the previous file removed before it can write again. That’s all I can think of now.

Try adding a "tell app “Finder” to delete file “blah:blah:” before the open for access etc.

The next step is to remove the handler aspect of it and then just go select a message in Mail and run it - that way you can use Display Dialog to see what the “content” is. Really, the only changes you have to make are removing the “on perform…” and “end perform…” statements and adding

tell app "Mail"
set selectedMessages to selection
set theMessage to item 1 of selectedMessages
(* do stuff with theMessage here - add in the code from the other script*)
end tell

Hi again Jonny

Your first script (quoted below) worked beautifully it wrote the email contents to a file perfectly. I am pretty sure that becuase the mail has an attachment that is causing the problem.

tell application "Finder" to set ptd to (path to desktop folder) as string
tell application "Mail"
   set theMessages to selection
   repeat with theMessage in theMessages
       set theText to content of theMessage
       set theFile to ptd & "Message Number " & (theMessage's id as string)
       set theFileID to open for access file theFile with write permission
       write theText to theFileID
       close access theFileID
   end repeat
end tell

You mentioned that you think the write commands needs to have the previous file removed before it can write again. I tried deleting the existing file and then ran the script again.
It still produced a text file with just ˇ¸Ë‡¸ in it. Maybe the problem needs to be approached from a different angle. Perhaps I could set the conditional rule in Mail.app to apply two
scripts to the incomming mail. One to save just the text contents of the mail and another to save the attachment down. Do you think this would work.

I know the above code works for just saving down the text of the email. Could you provide me with a script that would just save down the attachment of the email. Forgive me, I’m a real newbie.

Scratch that, it didn’t work. It just won’t save the text of an email properly if there is an attachment on the email.

I am getting a little desperate here, but is it possible to come at this from another angle again. Would it be possible to copy the contents of the mail to clipboard and then save the contents of the clipboard to a text file?

Yes, but it would require opening a new file in TextEdit, pasting, saving … nothing too difficult though.

We need to debug this - can you run it manually on one selected message in Mail and put a command “display dialog theText” somewhere in there just after it sets theText to the contents of the message, but before it tries to write to the file? Note that this will not work from a Mail rule - you have to code “perform mail action with selection” as I wrote in an earlier message.

Try this for the clipboard stuff:

set the clipboard to theMessage’s content – stick that line in there somewhere after “theMessage” is defined. Then go to Finder and choose “show clipboard”. If you get that far and it looks like the text that you want, we can do the TextEdit thing.

I put

in the script and ran via the mail rule and then viewed the contents of the clipboard and it said clipboard contents unknown. I tried to paste the contents of the clipboard into a new textedit document and nothing. Grr this is soo frustrating.

There has got to be a way to save the contents of the message as well as the attachment, it seams such a basic thing…

I’m working on it. I have to get a mutual fund thing done tonight but I think I can figure out your script too.

You are such a star! :smiley:

OK I just tested this on a message with a body text and an attachment and it works.

Note that there must be a folder on the desktop named “Attachments”.

Don’t edit any of it, just run it after selecting a message in Mail that has exactly one attachment. Delete the previous text file on the desktop and again, make a new folder named “Attachments” on the Desktop.

using terms from application "Mail"
	on perform mail action with messages theMessages
		tell application "Finder" to set ptd to (path to desktop folder) as string
		tell application "Finder" to set pathToAttachments to (path to desktop folder as string) & "Attachments:"
		tell application "Mail"
			repeat with theMessage in theMessages
				set theText to content of theMessage
				if theMessage's mail attachments is not {} then
					repeat with theAttachment in theMessage's mail attachments
						set theFileName to pathToAttachments & (theMessage's id as string) & space & theAttachment's name
						try
							save theAttachment in theFileName
						on error errnum
						end try
					end repeat
				end if
				set theFile to ptd & "Message Number " & (theMessage's id as string)
				set theFileID to open for access file theFile with write permission
				write theText to theFileID
				close access theFileID
			end repeat
		end tell
	end perform mail action with messages
end using terms from


tell application "Mail"
	set myMessages to selection
	tell me to perform mail action with messages myMessages
end tell



Now if it works from just running it in Script Editor, it should run as a Mail rule, as that is what we are simulating here with the last four lines.

I ran the following code

using terms from application "Mail"
	on perform mail action with messages theMessages
		tell application "Finder" to set ptd to (path to desktop folder) as string
		tell application "Finder" to set pathToAttachments to "iMac:Users:richardburrow:Desktop:" & "Attachments:"
		tell application "Mail"
			repeat with theMessage in theMessages
				set theText to content of theMessage
				if theMessage's mail attachments is not {} then
					repeat with theAttachment in theMessage's mail attachments
						set theFileName to pathToAttachments & (theMessage's id as string) & space & theAttachment's name
						try
							save theAttachment in theFileName
						on error errnum
						end try
					end repeat
				end if
				set theFile to ptd & "Message Number " & (theMessage's id as string)
				set theFileID to open for access file theFile with write permission
				write theText to theFileID
				close access theFileID
			end repeat
		end tell
	end perform mail action with messages
end using terms from


tell application "Mail"
	set myMessages to selection
	tell me to perform mail action with messages myMessages
end tell

and got a text file on the desktop called “Message Number 5474” I also got a file called “5474 Photo 50.jpg” in the attachments folder.
The text file still only had ˇ¸Ë‡¸ in it I selected the exact same message in mail that I sent you.

I just checked my script and it worked perfectly for me on a message with text and an attached zip file - so the nature of your message must be the problem.

Let me check your message in Script Debugger - … OK, the Content is blank when I check the properties of the message you sent in Script Debugger. It isn’t considering the two lines above the image as “Content”. Is it possible that these lines are formatted strangely, or maybe are part of the image???

I will send you a message with an attachment and content and you will see that it works.

You are right, I have just figured out what half the problem is. I forgot I used a template in conjunction the the php form processing script to format the resulting form content email. The email is an html email the data is actully in a table. I will change the template to take the data out of the table and just place it on new lines instead.

The email that you sent me with the attachment worked perfectly, so it has got to be because of the way the email was formatted. I will let you know how I get on.

:D:D:D THANK YOU SOO MUCH FOR ALL YOUR HELP! :D:D:D

Yup - I just examined the Mail window with UI Browser and that ain’t text - it’s 11 groups of a web area of a split area, each having its own text.

It will work if you make it plain text.