Extract text and attachments from corrupt messages in Apple Mail

This week I got an eMail message containing important PDF files, but somehow Apple Mail was not able to display the whole thing including the attachments:

What to do? I really needed the attached PDF documents… First I tried to access the attachments with AppleScript (get mail attachments of item 1 of (selection as list)), but got an error message in return: AppleEvent handler failed.

Then - being an AppleScript & Python nut - I found an excellent script by Matthew Cowles that extracts attachments from eMail messages. And so I created an AppleScript that writes the raw source of a selected eMail message in Apple Mail to a temporary file and then processes this temporary file with a Python script similar to Matthew’s to save the extracted attachments to a chosen folder.

It worked like a charm on my Mac! I successfully extracted the attachments and the text. And if you ever encounter the same problem of a corrupted eMail message in Apple Mail, then I invite you to download the script and test it:

MIMEX - Extract text and attachments from corrupt messages in Apple Mail (ca. 133 KB)

I used the script successfully on Mac OS X 10.5.5, but I guess it also runs without problems on Mac OS X 10.4.

Important: Opening and saving the below script code in Script Editor won’t result in a usable AppleScript! That is because the AppleScript internally relies on a Python script, which is located inside its Script bundle. Therefor please download the complete script here.


property mytitle : "mimex"

on run
	try
		-- getting the selected eMail message in Apple Mail
		tell application "Mail"
			set selmsgs to selection as list
		end tell
		if selmsgs is {} then
			set errmsg to "You did not select a message in Apple Mail."
			error errmsg
			return
		else if length of selmsgs is greater than 1 then
			set errmsg to "You selected more than one message in Apple Mail."
			error errmsg
			return
		end if
		-- we are interested in the raw source of the eMail message to process it with Python...
		tell application "Mail"
			set msg to item 1 of selmsgs
			set msgcont to source of msg
		end tell
		-- saving the eMail message source in a temporary file
		set tmpfilepath to my gettmpfilepath("txt")
		try
			set tmpfile to open for access tmpfilepath with write permission
			write msgcont to tmpfile
			close access tmpfile
		on error
			close access tmpfile
			set errmsg to "Writing the source of the eMail message to a temporary file failed."
			error errmsg
			return
		end try
		-- where should the extracted attachments be saved?
		set destfolderpath to my getdestfolderpath()
		if destfolderpath is missing value then
			return
		end if
		-- processing the saved eMail message source with a Python tool which
		-- (hopefully) extracts the attachments to the chosen folder path
		set pyscriptpath to (path to me as Unicode text) & "Contents:Resources:mimex.py"
		-- set pyscriptpath to (path to desktop as Unicode text) & "mimex.py"
		set command to "/usr/bin/python " & quoted form of POSIX path of pyscriptpath & " " & quoted form of (POSIX path of tmpfilepath) & " " & quoted form of POSIX path of destfolderpath
		set output to do shell script command
		-- removing the temporary file
		set command to "rm " & quoted form of POSIX path of tmpfilepath
		do shell script command
		if output is not "" then
			error output
		end if
	on error errmsg number errnum
		tell me
			activate
			display dialog "Sorry, an error occured:" & return & return & errmsg & return & "(" & errnum & ")" buttons {"OK"} default button 1 with icon stop giving up after 30 with title mytitle
		end tell
	end try
end run

-- I return a file path to a not yet existing temporary file
on gettmpfilepath(suffix)
	set tmpfolderpath to (path to temporary items folder from user domain) as Unicode text
	repeat
		set randnum to random number from 10000 to 99999
		set tmpfilepath to tmpfolderpath & randnum & "." & suffix
		try
			set tmpfilealias to tmpfilepath as alias
		on error
			exit repeat
		end try
	end repeat
	return tmpfilepath
end gettmpfilepath

-- I am asking the user to specify a destination folder to save the attachements
-- If the user cancels, I return «missing value»
on getdestfolderpath()
	try
		set destfolderpath to choose folder with prompt "Please choose a folder to save the attachments:" without invisibles, multiple selections allowed and showing package contents
	on error
		return missing value
	end try
	return destfolderpath as Unicode text
end getdestfolderpath