Routine to Save email as PDF saves each file as many times as number

I had written a routine to save email messages to folders I choose as PDF’s. I have been trying to extend the functionality so I can selected multiple messages in Mail . The problem I have is that each file is saved as many times as there are selected messages so if I selected 2 it saves each message twice if 3 then three times and so on. Icannot figure out where the loop is in my script.

 =--Built to Determine if email message(S) has been sent or received.
--To provide File name base on Subject and Sender using initials if sender more than one word
global destinationFolder, Subject_, cycles
set Init to {}
set cycles to 0
set destinationFolder to ""
tell application "Mail"
	activate "Mail" --ensure app to front
	set allMsg to selection
	if (count of allMsg) = 0 then --must have at least 1 email selected
		display dialog "No Messages Selected"
		repeat with i from 1 to count of allMsg --cycles through each message
			delay 0.05
			set themsg to item i of allMsg
			set Subject_ to subject of item 1 of themsg
			if (offset of "RE:" in Subject_) as integer > 0 then set Subject_ to characters 4 through -1 of Subject_ as string --Strips out Re: when subject not changed in email
			set Sender_ to sender of item 1 of themsg
			--Determine if email in or out
			if (offset of "" in Sender_) as integer > 0 ¬
				or (offset of "" in Sender_) as integer > 0 ¬
				or (offset of "" in Sender_) as integer > 0 ¬
				or (offset of "" in Sender_) as integer > 0 ¬
				or (offset of "" in Sender_) as integer > 0 then
				set Sender_ to "" --Sender is me
				set Recipient_ to name of first recipient of item 1 of themsg
				set Subject_ to Subject_ & " to " & Recipient_
				set Status to "Outward"
			else --must be inward email
				set Sender_ to extract name from Sender_
				if (offset of "@" in Sender_) as integer > 0 then --test if name has been extracted if not switches to 1st part email address
					set brkpos to offset of "@" in Sender_
					set Sender_ to characters 1 through (brkpos - 1) of Sender_
				else if (count of words in Sender_) > 1 then
					repeat with i from 1 to count of words in Sender_
						set Init to Init & first character of word i of Sender_
					end repeat
					set Sender_ to Init
					--display dialog Init as string
				end if
				set Subject_ to Subject_ & " From " & Sender_
				set Status to "Inward"
				set Recipient_ to ""
			end if
			set theMsgCount to count every mail attachment of themsg --counts attachments if any
			set Subject_ to text returned of (display dialog Status & "  email  from " & return & Sender_ & return ¬
				& "Proposed file name is in the box " & return & ¬
				"Select OK or  start typing to erase and change " & return & ¬
				"and then Select OK" buttons {"OK", "Change"} default button "OK" default answer (Subject_))
			set Subject_ to my FixFileName(Subject_) --Calls handler to strip bad characters

			--Get folder to save email in and if multipole messages check if it needs to be changed
				if (count of characters of POSIX path of destinationFolder) > 0 then --Cannot count characters in path returned so have to switch to POSIX path and cannot get POSIX Path of a null string hence try to catch the error
					if button returned of (display dialog ("Folder Currently selected " & POSIX path of destinationFolder as string) ¬
						& return buttons {"OK", "Change"} default button 1) = "Change" then
						set destinationFolder to choose folder
					end if
				end if
			on error
				display dialog "Path not yet selected"
				set destinationFolder to (choose folder)
			end try
			set Subject_ to my getEmptyPath((destinationFolder as string), Subject_) --Calls handler to check if file exists in destinationFolder
			my FileasPDF() --Calls handler to process the save part of routine
		end repeat
	end if
end tell

on FixFileName(Subject_) --Deletes characters that cannot be used in file names
	--display dialog "Check Filename for duplicates"
	--display dialog "Fixed str " & str
	set fixed_string to {}
	set bad_char to {":", "/"}
	repeat with c from 1 to (count every character in Subject_)
		if bad_char contains (character c of Subject_) then
			set end of fixed_string to " "
			set end of fixed_string to (character c of Subject_)
		end if
	end repeat
	fixed_string as string
	set Subject_ to fixed_string
end FixFileName

-- See if a file with the passed name exists
-- If so, add an integer to the name, and check again
-- Keep checking until an unused name is found
-- Parameters:	path of container as text
--			       file name, no extension
-- This is only intended to save mail messages as PDF's so that extension is added in the handler
-- Returns:		updated file name

on getEmptyPath(destinationFolder, Subject_)
	--display dialog "in Path"
	set filePath to destinationFolder & Subject_
	set Ext to ".PDF" --only checking for file type PDf as that is how the message is being saved
	tell application "Finder"
		if exists file (filePath & Ext) then
			set x to 1 -- start counting
				set cFilePath to filePath & " " & x & Ext
				if exists file cFilePath then -- found empty spot?
					set x to x + 1 -- no, keep counting
				else -- yes, leave
					exit repeat
				end if
			end repeat
			return Subject_ & " " & x -- this name is safe to use
			return Subject_ -- use original name
		end if
	end tell
	set cycles to cycles + 1
	display dialog cycles
end getEmptyPath
on FileasPDF()
	tell application "System Events"
		tell process "Mail"
			keystroke "p" using command down
			repeat until exists sheet 1 of window 1
				delay 0.2
			end repeat
			tell sheet 1 of window 1
				click menu button "PDF"
				repeat until exists menu 1 of menu button "PDF"
					delay 0.02
				end repeat
				click menu item "Save as PDF." of menu 1 of menu button "PDF"
			end tell
			repeat until exists window "Save"
				delay 0.2
			end repeat
			tell window "Save"
				keystroke "g" using {command down, shift down}
				repeat until exists sheet 1
					delay 0.2
				end repeat
				tell sheet 1
					--Subject_Added Peter to test how to pass file name
					set value of text field 1 to POSIX path of destinationFolder & "/" & Subject_
					click button "Go"
				end tell
				repeat while exists sheet 1
					delay 0.2
				end repeat
				--display dialog "Save " & x1
				click button "Save"
			end tell
		end tell
	end tell
end FileasPDF

The problem isn’t with your code… per se. The problem is how Mail works. If I have 2 messages selected in Mail, and I try to print them, then both messages are printed (same with “save as pdf”). So Mail prints everything you have selected.

Basically for your code to work only one message can be selected at a time when you try to “save as pdf” and the selected message must be the one you are trying to save. So you will have to have the ability to adjust the selection in Mail. The main problem with this is the selection property of Mail is read-only so there’s no native applescript way to change the selection. You will have to use gui scripting for this which will be very difficult.

Your other options would be to 1) change the logic of your script so this issue doesn’t matter or 2) live with it and just manually delete the extra pdf files at the end of your script.

Good luck. :smiley:


Thanks for your response, I had printed the results for a one and two selection and other than 2 cycles for 2 selections the realists are identical. Guess I will have to revisit the logic or try GUi and that will be difficult. Anyway thanks again