Scary side effect for my ought-to-be harmless script

Hi all,

I need some fresh eyeballs to look at my simple little script. Basically, our sales staff traditionally had to copy and paste all the details of an email into our web-based sales software manually, just copy-and-pasting from Mail to Firefox. So I whipped up a little script to automate the process. The user opens the Communication pop-up in Firefox, then selects the email in question in mail, and then runs my script from the Script menu, which copy-and-pastes everything for them. It has been working fine 99.9% of the time. However, I’ve now had two instances where people have called me up saying that the script has deleted all messages from their inbox. Sure enough when I check, all there inbox messages are found in the trash. The first time I was willing to suspect user error, but the second case was pretty much identical to the first.

The part that has me confused is that my script doesn’t do anything that would edit the inbox, it simply reads details from messages as far as I can tell. Can anyone tell me what the following script does that might cause this issue? Or is it just a conicidence? (I know that the script may not be written as efficiently as possible, and I’m always open to streamlining suggestions, but what I really want to know if if I’ve written things such that I’m indeed running the risk of fouling up people’s inboxes.


on run
	my copyToCompass()
end run

on copyToCompass()
	tell application "Mail"
		if (count of selected messages of front message viewer) is 0 then
			display alert "Sorry, but if you don't select a message then I don't know which one you want to import."
			error number -128
		else
			if (count of selected messages of front message viewer) > 1 then
				display alert "Sorry, but you've got more than one message selected, which one am I suppsed to work with?"
				error number -128
			end if
		end if
		
		set thisMessage to selected messages of front message viewer
		
		tell item 1 of thisMessage
			set recdDateInfo to date received
			set dateYear to year of recdDateInfo
			copy recdDateInfo to b
			set b's month to January
			set dateMonth to 1 + (recdDateInfo - b + 1314864) div 2629728
			set dateMonth to text -2 through -1 of ("0" & dateMonth)
			set dateDate to day of recdDateInfo
			set dateDate to text -2 through -1 of ("0" & dateDate)
			set dateHour to hours of recdDateInfo
			set dateMinute to minutes of recdDateInfo
			set dateSeconds to seconds of recdDateInfo
			
			set recdDate to (dateYear & "-" & dateMonth & "-" & dateDate) as string
			set recdTime to (text -2 through -1 of ("0" & dateHour)) & ":" & (text -2 through -1 of ("0" & dateMinute)) & ":" & (text -2 through -1 of ("0" & dateSeconds))
			
			set recdSender to sender
			set recdSubject to subject
			set recdBody to content as string
			
		end tell
	end tell
	
	tell application "Firefox"
		activate
		try
			copy (the clipboard) to clipTemp
		end try
		set the clipboard to (recdBody as string)
	end tell
	
	tell application "System Events"
		tell process "firefox-bin"
			
			set commWindow to windows whose (value of attribute "AXTitle" is "IncomingCommunicationPopup")
			
			if (count of commWindow) > 1 then
				tell application "Mail"
					activate
					display alert "Sorry, I'm confused.  You have more than one Incoming Communication winow open, I'm not sure with which to work."
					error number -128
				end tell
				
			else if ((count of commWindow) = 0) then
				tell application "Mail"
					activate
					display alert "Sorry, I can't find an Incoming Communication popup window.  I don't know how to handle that.....yet."
					error number -128
				end tell
				
			end if
			
			set commWindow to item 1 of commWindow
			if (value of attribute "AXMain" of commWindow) is false then
				set value of attribute "AXMain" of commWindow to true
			end if
			keystroke "a" using command down
			keystroke (ASCII character 8)
			keystroke recdDate
			keystroke tab
			keystroke recdTime
			keystroke tab
			keystroke recdSender
			keystroke tab
			keystroke recdSubject
			keystroke tab
			keystroke "v" using command down
			
		end tell
	end tell
	
	tell application "Finder"
		delay 1
		try
			set the clipboard to (clipTemp)
		end try
	end tell
end copyToCompass


It seems to me that somehow, Mail is being made active between your activation of Firefox and the keystroke commands. If you send to Mail the first two keystrokes you meant for Firefox (Command-A and Control-H (ASCII character 8)), Mail will send all the messages in the current message viewer to the trash (assuming a message viewer is the active window in Mail).

I know that many people have written that tell app “System Events” to tell proces “foo” to keystoke “blah” will direct the “blah” keystrokes to the foo application, but I have never found that to be the case. In my experience (limited to Mac OS X 10.4, Tiger), System Event’s keystoke command always sends the its keystrokes to the active (frontmost) application. Nigel Garvey has made the same observation. As he implies, this could very well be different in Leopard.

My advice would be to move the activate app “Firefox” to right before the keystroke commands. Maybe it is just that the user is clicking back to Mail while the script saves the clipboard and checks for the right number of popup windows.

Perhaps giving the user a warning about what is going to happen would help them: display alert “I will now switch to Firefox and paste the information. Do not switch applications until the script is finished!” giving up after 10. Or maybe you could just instruct your users to avoid switching applications or otherwise using the computer while the script script is running.

P.S. You might not even need to keystroke ASCII character 8. Since you have previously done Command-A (Select All), just sending the replacement text should overwrite the previous contents (since typing usually overwrites the selection). That way, if you can take out the Control-H and the keystrokes still end up going to Mail for some reason, it probably will not be as destructive (when I typed random stuff into a message viewer, I got lots of beeping (Mail rejecting the keystrokes), Tab still switches focus between the mailbox list and the message list).

Doh! Of course… I can’t believe I missed that. Actually that’s the reason I had the delay in there…I find there’s a bit of a control buffer issue on System Events, so I added the delay to preserve the clipboard contents a bit longer as it was saving and restoring them before my script had a chance to work with them. You’re right though… there’s no need to delete the text after the select-all anyways, so I’ll just remove that. Then if control returns to Mail prematurely, it will at least just not move folks’ message to the trash.

Nice catch!

Thanks,
Bill