-- define globals
global completeMailboxList
global emailClient
global emailerAttachmentsFolderName
global fileURLtoAttachmentsFolder
global importFolderName
global logFile
global logInterval
global pathToHome
global pathToMail
global pathToMailboxes
global warming



-- define variables
set completeMailboxList to {}
set AppleScript's text item delimiters to ""
set warming to 0
tell application "Finder" to set pathToHome to (home as string)
set logInterval to 10



-- localization
set emailerAttachmentsFolderName to "Downloads"



-- set some defaults based on client name
set emailClient to "Claris eMailer"
set importFolderName to "eMailer-Import"



try
	-- determine the version of Mac OS that is running
	try
		get path to extensions
		activate
		display dialog "This script will only run on Mac OS X." buttons {"Quit"} default button 1
		return
	on error
		set pathToMail to pathToHome & ":Library:Mail:"
		set pathToMailboxes to pathToMail & "Mailboxes:"
	end try
	
	
	
	-- main routine
	tell application "Claris Emailer"
		my WaitUntilReady()
		set savedFetchingStatus to get «class pScE»
		set «class pScE» to false
		set topLevelfolderList to every «class cFld»
		repeat with eachFolder in topLevelfolderList
			set completeMailboxList to my traverseEmailerFolders(eachFolder)
		end repeat
		set userMailboxList to my selectMailboxesToImport()
		if (userMailboxList is not equal to {}) then
			my createImportFolder()
			my createAttachmentsFolder()
			
			tell application "TextEdit"
				activate
				close every document saving ask
				make new document at the beginning of documents
				set the name of window 1 to importFolderName
				set text of document 1 to ¬
					"--- " & my displayTime() & ": Starting import from " & emailClient & " ---" & return & return & "Preparing mailboxes..." & return & return & ¬
					return & "--- Import in progress ---" & return
			end tell
			
			repeat with eachMailbox in userMailboxList
				set mailboxIsFolder to 0
				set mailboxHasMessages to 0
				set pathToEmailerMailbox to my findPositionOfEmailerMailboxInHierarchy(eachMailbox)
				try
					if (every «class cFld» of eachMailbox) is not equal to {} then
						set mailboxIsFolder to 1
					end if
				end try
				try
					if (number of every «class msg » in eachMailbox) is greater than 0 then
						set mailboxHasMessages to 1
					end if
				end try
				if (name of eachMailbox is equal to "Logs") then
					set mailboxHasMessages to 0
				end if
				set mboxFile to my createMailboxInImportFolder(eachMailbox, mailboxIsFolder, mailboxHasMessages, pathToEmailerMailbox)
				if (mailboxHasMessages is equal to 1) then
					my processEmailerMailbox(eachMailbox, mboxFile)
				end if
			end repeat
			my writeToLog("", 3)
			my writeToLog("", 4)
			my writeToLog("--- " & my displayTime() & ": Import finished! ---", 6)
			set «class pScE» to savedFetchingStatus
		end if
	end tell
	activate
	display dialog "Importing done! If Mail is already running, you need to quit and relaunch Mail." buttons {"OK"} default button 1
on error errText
	activate
	display dialog errText buttons {"Quit"} default button 1
end try
set AppleScript's text item delimiters to ""



-- routines
on createAttachmentsFolder()
	tell application "Finder"
		set pathToEmailerAttachments to {}
		set AppleScript's text item delimiters to ":"
		set pathToEmailer to path to application "Claris Emailer" as string
		set numberOfItemsInPath to ((length of text items in pathToEmailer) - 1)
		repeat with counter from 1 to numberOfItemsInPath
			set pathToEmailerAttachments to pathToEmailerAttachments & text item counter of pathToEmailer & ":"
		end repeat
		set AppleScript's text item delimiters to ""
		set pathToEmailerAttachments to (pathToEmailerAttachments as string) & emailerAttachmentsFolderName & ":"
		set attachmentFolder to pathToMail & "Attachments:"
		if (alias attachmentFolder exists) then
		else
			make new folder at pathToMail with properties {name:"Attachments"}
		end if
		set emailerAttachmentsFolderContents to every item of alias pathToEmailerAttachments
		repeat with eachItem in emailerAttachmentsFolderContents
			try
				duplicate (eachItem) to alias attachmentFolder
			end try
		end repeat
		set startupDiskName to startup disk as string
		set homeDirectory to home as string
		set AppleScript's text item delimiters to ":"
		set pathToAttachmentsFolder to pathToMail & "Attachments:"
		if first text item of pathToAttachmentsFolder is equal to startupDiskName then
			set tempPath to text items 2 thru -1 of pathToAttachmentsFolder
		else
			set tempPath to "Volumes/" & every text item of pathToAttachmentsFolder
		end if
		set tempURL to every text item of tempPath
		set AppleScript's text item delimiters to "/"
		set tempFileURL to "file:///" & every text item of tempURL
		set AppleScript's text item delimiters to " "
		set URLtextItems to every text item of tempFileURL
		set AppleScript's text item delimiters to "%20"
		set fileURLtoAttachmentsFolder to every text item of URLtextItems
		set AppleScript's text item delimiters to ""
	end tell
end createAttachmentsFolder



on createImportFolder()
	tell application "Finder"
		if (alias pathToMail exists) then
		else
			make new folder at alias (pathToHome & ":Library:") with properties {name:"Mail"}
		end if
		if (alias pathToMailboxes exists) then
		else
			make new folder at alias (pathToMail) with properties {name:"Mailboxes"}
		end if
	end tell
	set safeImportFolderName to my makeUniqueName(importFolderName, pathToMailboxes)
	set importFolderName to safeImportFolderName
	tell application "Finder"
		make new folder at alias pathToMailboxes with properties {name:importFolderName}
		set pathToImportFolder to (pathToMailboxes & importFolderName)
	end tell
end createImportFolder



on createMailboxInImportFolder(eachMailbox, mailboxIsFolder, mailboxHasMessages, pathToEmailerMailbox)
	tell application "Finder"
		set nameOfEachMailbox to name of eachMailbox
		set pathToNewFolder to pathToMailboxes & importFolderName & ":" & pathToEmailerMailbox
		if (mailboxIsFolder is equal to 1) then
			make new folder at alias pathToNewFolder with properties {name:nameOfEachMailbox}
			if (mailboxHasMessages is equal to 1) then
				set mboxName to " " & name of eachMailbox & ".temporary"
			end if
			set createLocation to pathToNewFolder & nameOfEachMailbox & ":"
		else
			set mboxName to name of eachMailbox & ".temporary"
			set createLocation to pathToNewFolder
		end if
		if (mailboxHasMessages is equal to 1) then
			try
				set existsLocation to alias createLocation
			on error
				set createLocation to pathToMailboxes & importFolderName & ":"
			end try
			set safeMboxName to my makeUniqueName(mboxName, createLocation)
			set mboxName to safeMboxName
			make new folder at alias createLocation with properties {name:mboxName}
			set tempMboxFile to createLocation & mboxName & ":mboxTemp"
			set mboxFile to createLocation & mboxName & ":mbox"
			set mboxCreateLocation to createLocation & mboxName & ":"
			make new file at alias (mboxCreateLocation) with properties {name:"mbox"}
		end if
	end tell
	try
		return mboxFile
	on error
		return {}
	end try
end createMailboxInImportFolder



on displayTime()
	set currentDate to current date
	get time string of currentDate
	return the result
end displayTime



on findEmailerAttachments(currentMessage, messageContent, fileCount)
	tell application "Finder"
		set messageContent to (messageContent & return & return & "This message has " & fileCount as string) & " attachment(s):" & return
		repeat with eachFile from 1 to fileCount
			try
				set AppleScript's text item delimiters to ":"
				tell application "Claris Emailer" to set attachmentPath to name of file eachFile of currentMessage
				set tempAttachmentName to last text item of attachmentPath
				set AppleScript's text item delimiters to " "
				set tempBlob to every text item of tempAttachmentName
				log (tempBlob)
				set AppleScript's text item delimiters to "%20"
				set attachmentName to every text item of tempBlob as string
				log (attachmentName)
				set AppleScript's text item delimiters to ""
				if (attachmentName is equal to "") then
					set messageContent to messageContent & "   << Attachment not found >> " & return
				else
					set messageContent to messageContent & "   << " & fileURLtoAttachmentsFolder & attachmentName & " >>" & return
				end if
			on error
				set messageContent to messageContent & "   << filename unknown >>" & return
			end try
		end repeat
		set messageContent to messageContent & return
		set messageContent to messageContent & "Shortcut to Attachments folder:" & return
		set messageContent to messageContent & "   << " & fileURLtoAttachmentsFolder & " >>"
	end tell
	return messageContent
end findEmailerAttachments



on findPositionOfEmailerMailboxInHierarchy(eachMailbox)
	tell application "Claris Emailer"
		set pathToEmailerMailbox to ""
		set parentMailboxes to {}
		set success to 0
		set currentMailbox to name of eachMailbox
		set currentParent to (name of parent of eachMailbox)
		set currentParentID to eachMailbox
		repeat until success is equal to 1
			if (currentParent is equal to "Claris Emailer") then
				set success to 1
			else
				set parentMailboxes to parentMailboxes & currentParent as list
				set currentParentID to (parent of currentParentID)
				set currentParent to (name of parent of currentParentID)
			end if
		end repeat
	end tell
	set lengthOfPathToMailbox to length of parentMailboxes
	if (lengthOfPathToMailbox is greater than 0) then
		set reversedList to reverse of parentMailboxes
		repeat with counter from 1 to lengthOfPathToMailbox
			set pathToEmailerMailbox to pathToEmailerMailbox & item counter of reversedList & ":"
		end repeat
	end if
	return pathToEmailerMailbox
end findPositionOfEmailerMailboxInHierarchy



on makeUniqueName(proposedFile, proposedLocation)
	tell application "Finder"
		set mboxExtension to 0
		set dotPosition to (offset of ".mbox" in proposedFile) as number
		if (dotPosition is not equal to 0) then
			set mboxExtension to 1
			set namePrefix to ((characters 1 thru (dotPosition - 1) of proposedFile) as string)
		end if
		set success to 0
		set counter to 1
		set proposedName to proposedFile
		repeat until success is equal to 1
			set allNames to {}
			try
				set allNames to allNames & name of every file of alias proposedLocation
			end try
			try
				set allNames to allNames & name of every folder of alias proposedLocation
			end try
			if allNames contains proposedName then
				if (mboxExtension is equal to 1) then
					set proposedName to (namePrefix & " " & counter as string) & ".mbox"
				else
					set proposedName to proposedFile & " " & counter as string
				end if
				set counter to counter + 1
			else
				set success to 1
				return proposedName
			end if
		end repeat
	end tell
end makeUniqueName



on processEmailerMailbox(eachMailbox, mboxFile)
	tell application "Claris Emailer"
		tell application "Finder" to set theOriginalMbox to (open for access file mboxFile with write permission)
		my startingNewMailbox(name of eachMailbox)
		set messageCounter to 1
		try
			repeat
				set processedHeaders to ""
				set currentMessage to «class msg » messageCounter of eachMailbox
				set fileCount to (number of files of currentMessage)
				try
					set senderRecord to «class sndr» of currentMessage
					set addressEntry to «class addr» of senderRecord
				on error
					set addressEntry to "???@???"
				end try
				try
					set currentHeaders to «class pIHd» of currentMessage
				on error
					set currentHeaders to «class pMHd» of currentMessage
				end try
				set AppleScript's text item delimiters to return
				set currentHeadersAsTextItems to every text item of currentHeaders
				set AppleScript's text item delimiters to ""
				repeat with eachItem in currentHeadersAsTextItems
					set multipart to "No"
					try
						if (eachItem begins with "Content-type: multi") then
							set multipart to "Yes"
						end if
					end try
					if (multipart is equal to "No") then
						set processedHeaders to processedHeaders & eachItem & return
					end if
				end repeat
				if class of currentMessage is «class inm » then
					try
						set messageContent to "From " & addressEntry & " " & «class tims» of currentMessage & return ¬
							& processedHeaders & return & «class ctnt» of currentMessage
					on error
						set messageContent to "From " & addressEntry & " " & «class tims» of currentMessage & return ¬
							& processedHeaders & return ¬
							& "<< Message was too large and was not imported from Claris eMailer >>" & return
					end try
					if (messageCounter mod logInterval is equal to 0) then
						my writeToLog(("Importing message " & messageCounter as string) & ": " & «class subj» of currentMessage, 4)
					end if
				else if class of currentMessage is «class outm» then
					try
						set messageContent to "From " & addressEntry & " " & «class tims» of currentMessage & return ¬
							& processedHeaders & "From: Me" & return & return & «class ctnt» of currentMessage
					on error
						set messageContent to "From " & addressEntry & " " & «class tims» of currentMessage & return ¬
							& processedHeaders & "From: Me" & return & return & "<< Message was too large and was not imported from Claris eMailer >>" & return
					end try
					if (messageCounter mod logInterval is equal to 0) then
						my writeToLog(("Message " & messageCounter as string), 4)
					end if
				end if
				if (fileCount is greater than 0) then
					set messageContent to my findEmailerAttachments(currentMessage, messageContent, fileCount)
				end if
				set hasFromSpace to offset of (return & "From ") in messageContent
				set AppleScript's text item delimiters to return
				if (hasFromSpace is not equal to 0) then
					try
						set intervalCounter to 1
						repeat
							set subContent to text item intervalCounter of messageContent
							if (subContent starts with "From " and intervalCounter is greater than 1) then
								set subContent to ">" & subContent
							end if
							set AppleScript's text item delimiters to ASCII character 10
							tell application "Finder" to write (subContent as string) & (ASCII character 10) to theOriginalMbox starting at eof
							set AppleScript's text item delimiters to return
							set intervalCounter to intervalCounter + 1
						end repeat
					end try
				else
					try
						set intervalCounter to 0
						repeat
							set startCounter to (intervalCounter * 100) + 1
							set endCounter to (intervalCounter * 100) + 100
							try
								set subContent to text items startCounter thru endCounter of messageContent
							on error
								set subContent to text items startCounter thru -1 of messageContent
							end try
							if (subContent starts with "From " and intervalCounter is greater than 0) then
								set subContent to ">" & subContent
							end if
							set AppleScript's text item delimiters to ASCII character 10
							tell application "Finder" to write (subContent as string) & (ASCII character 10) to theOriginalMbox starting at eof
							set AppleScript's text item delimiters to return
							set intervalCounter to intervalCounter + 1
						end repeat
					end try
				end if
				set messageCounter to messageCounter + 1
			end repeat
		end try
		try
			tell application "Finder" to close access theOriginalMbox
		end try
	end tell
	set AppleScript's text item delimiters to ""
	tell application "Finder"
		set temporaryFolder to (container of alias mboxFile)
		set temporaryFolderName to name of temporaryFolder
		set temporaryOffset to (offset of ".temporary" in temporaryFolderName)
		set newFolderName to ((characters 1 thru (temporaryOffset - 1) of temporaryFolderName) as string) & ".mbox"
		set name of temporaryFolder to newFolderName
	end tell
end processEmailerMailbox



on selectMailboxesToImport()
	set completeMailboxNames to {}
	set userMailboxList to {}
	repeat with eachItem in completeMailboxList
		set completeMailboxNames to completeMailboxNames & {name of eachItem}
	end repeat
	with timeout of 600 seconds
		activate
		set theResult to display dialog ¬
			"You can choose to either import all mailboxes from " & emailClient & " or choose a subset of mailboxes to import." buttons {"Import all mailboxes", "Choose mailboxes to import"} default button 2
		if (theResult is equal to false) then
			set warming to 1
			return
		else
			set chosenPath to button returned of theResult
		end if
	end timeout
	if (chosenPath is equal to "Import all mailboxes") then
		set userMailboxList to completeMailboxList
	else
		with timeout of 600 seconds
			activate
			set selectionList to choose from list (completeMailboxNames) ¬
				with prompt "Select which folder(s) you would like to import. Select multiple items by holding down the command key." with multiple selections allowed
			if (selectionList is equal to false) then
				set warming to 1
			end if
		end timeout
		if (warming is equal to 0) then
			try
				set userMailboxList to {}
				set namesCounter to 1
				set mailboxesCounter to 1
				try
					repeat
						set name1 to item namesCounter of selectionList
						set name2 to name of item mailboxesCounter of completeMailboxList
						if (name1 is equal to name2) then
							set userMailboxList to userMailboxList & {item mailboxesCounter of completeMailboxList}
							set namesCounter to namesCounter + 1
							set mailboxesCounter to mailboxesCounter + 1
						else
							set mailboxesCounter to mailboxesCounter + 1
						end if
					end repeat
				end try
			on error
				return {}
			end try
		end if
	end if
	return userMailboxList
end selectMailboxesToImport



on startingNewMailbox(savedMboxName)
	my writeToLog("", 4)
	set displayString to "Importing '" & savedMboxName & "'"
	my writeToLog(displayString, 3)
end startingNewMailbox



on traverseEmailerFolders(currentFolder)
	tell application "Claris Emailer"
		set completeMailboxList to completeMailboxList & (currentFolder as list)
		set subFolders to every «class cFld» of currentFolder
		repeat with eachFolder in subFolders
			my traverseEmailerFolders(eachFolder)
		end repeat
	end tell
	return completeMailboxList
end traverseEmailerFolders



on WaitUntilReady()
	with timeout of 5 seconds
		repeat
			try
				tell application "Claris Emailer" to get version
				return
			end try
		end repeat
	end timeout
end WaitUntilReady



on writeToLog(passedString, paragraphNumber)
	tell application "TextEdit"
		set paragraph paragraphNumber of text of document 1 to passedString & return
	end tell
end writeToLog