Help! trying to add sender from Mail to Contacts

Okay, I’m a worst case scenario - little knowledge and no fear of tweaking.

Here’s what I’m trying to do:

  1. Based on a selected email(s)
  2. Add the sender to a group(s) in Contacts

I had a script that used to work but somehow gave up the ghost.

So now I tried to cobble together two different scripts and I’ve gotten something that runs without error but does NOTHING! (perfect, right?)

Can anyone tell me either where my errors are in the script attached OR a better way to do this?

Thanks,

Anthony

tell application "Mail" to set theSelection to selection
if theSelection is {} then return beep 2

if length of theSelection = 1 then
	set thePrompt to "Select the group(s) to which to add the sender of the selected message."
else
	set thePrompt to "Select the group(s) to which to add the senders of the selected messages."
end if
tell application "Contacts" to set theList to name of groups
set R to choose from list theList with prompt thePrompt with multiple selections allowed
if R is false then return

tell application "Mail"
	activate
	set theSenders to {}
	repeat with thisMessage in theSelection
		set theSender to extract name from sender of thisMessage
		set nameArray to my split(theSender, " ")
		set theFirstName to item 1 of nameArray
		set theLastName to last item of nameArray
		set theEmail to extract address from sender of thisMessage
		copy theSender to the end of theSenders
	end repeat
end tell

tell application "Contacts"
	activate
	repeat with thisSender in theSenders
		delay 0.1
		set thePersons to (people whose value of emails contains (thisSender as text))
		
		
		if (count thePersons) = 1 then
			repeat with theGroupName in items of R
				add (item 1 of thePersons) to group theGroupName
			end repeat
		else
			repeat with theGroupName in items of R
				repeat with thisPerson in thePersons
					add thisPerson to group theGroupName
					set thePerson to make new person with properties {first name:theFirstName, last name:theLastName}
					make new email at end of emails of thePerson with properties {label:"Work", value:theEmail}
					save
					
				end repeat
			end repeat
		end if
	end repeat
	save
	set selected of group theGroupName to true
	
end tell

on split(theString, theDelimiter)
	set oldDelimiters to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	set theArray to every text item of theString
	set AppleScript's text item delimiters to oldDelimiters
	return theArray
end split

My understanding is that there is an error with the instruction:

set thePersons to (people whose value of first email contains (thisSender as text))

I guess that it’s supposed to be something like:

set thePersons to (people whose value of first email contains (theEmail as text))

Of course it assume that you trace the emails as you trace the senders.

Here is an edited script :

tell application "Mail" to set theSelection to selection
if theSelection is {} then return beep 2

if length of theSelection = 1 then
	set thePrompt to "Select the group(s) to which to add the sender of the selected message."
else
	set thePrompt to "Select the group(s) to which to add the senders of the selected messages."
end if
tell application "Contacts" to set theList to name of groups
set R to choose from list theList with prompt thePrompt with multiple selections allowed
if R is false then return

tell application "Mail"
	activate
	set theSenders to {}
	set theEmails to {} # ADDED
	repeat with thisMessage in theSelection
		set theSender to extract name from sender of thisMessage
		set nameArray to my split(theSender, " ")
		set theFirstName to item 1 of nameArray
		set theLastName to last item of nameArray
		set theEmail to extract address from sender of thisMessage
		copy theSender to the end of theSenders
		copy theEmail to the end of theEmails # ADDED
	end repeat
end tell

tell application "Contacts"
	activate
	
	set indx to 0 # ADDED
	repeat with thisSender in theSenders
		
		delay 0.1
		set indx to indx + 1 # ADDED
		set theEmail to item indx of theEmails # ADDED
		set thePersons to (people whose value of first email contains (theEmail as text)) # MODIFIED
		
		
		if (count thePersons) = 1 then
			repeat with theGroupName in items of R
				add (item 1 of thePersons) to group theGroupName
			end repeat
		else
			repeat with theGroupName in items of R
				repeat with thisPerson in thePersons
					add thisPerson to group theGroupName
					set thePerson to make new person with properties {first name:theFirstName, last name:theLastName}
					try
						make new email at end of emails of thePerson with properties {label:"Work", value:theEmail}
					end try
					save
					
				end repeat
			end repeat
		end if
		
	end repeat
	
	save
	set selected of group theGroupName to true
	
end tell


on split(theString, theDelimiter)
	set oldDelimiters to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	set theArray to every text item of theString
	set AppleScript's text item delimiters to oldDelimiters
	return theArray
end split

CAUTION : I tested only with datas in which there is no people sharing the same email (which means that thePersons contain only one item).

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 2 mars 2019 19:04:36

Here is an extended version.
This one create a new record if there was no existing one matching the mail address.

(*
https://macscripter.net/viewtopic.php?pid=195222#p195222

add sender from Mail to Contacts


2019/03/04 added code for special case where theArray contains a single string
	and enhanced the mode replaceEmail is false

*)


property replaceEmail : false
(*
set it to true to replace the email in a record matching first name, last name but not the email
set it to false to add a new email in a record matching first name, last name but not the email
*)

tell application "Mail" to set theSelection to selection
if theSelection is {} then return beep 2

if length of theSelection = 1 then
	set thePrompt to "Select the group(s) to which to add the sender of the selected message."
else
	set thePrompt to "Select the group(s) to which to add the senders of the selected messages."
end if
tell application "Contacts" to set theList to name of groups
set R to choose from list theList with prompt thePrompt with multiple selections allowed
if R is false then return

tell application "Mail"
	activate
	set theSenders to {}
	set theEmails to {} # ADDED
	set theFirstNames to {} # ADDED
	set theLastNames to {} # ADDED
	repeat with thisMessage in theSelection
		set theSender to extract name from sender of thisMessage
		set theEmail to extract address from sender of thisMessage
		copy theSender to the end of theSenders
		copy theEmail to the end of theEmails # ADDED
		set nameArray to my split(theSender, " ")
		if (count nameArray) > 1 then # ADDED
			copy item 1 of nameArray to the end of theFirstNames # ADDED
		else # ADDED
			copy "" to the end of theFirstNames # ADDED
		end if # ADDED
		copy item -1 of nameArray to the end of theLastNames # ADDED
	end repeat
end tell

tell application "Contacts"
	activate
	
	set indx to 0 # ADDED
	repeat with thisSender in theSenders
		
		delay 0.1
		set indx to indx + 1 # ADDED
		set the_MailAddress to item indx of theEmails # ADDED
		set the_FirstName to item indx of theFirstNames # ADDED
		set the_LastName to item indx of theLastNames # ADDED
		set thePersons to (people whose value of first email contains (the_MailAddress as text)) # MODIFIED
		
		if (count thePersons) = 0 then
			# must create a card
			(* try to grab an existing record *)
			try
				if the_FirstName = "" then # ADDED
					set the_Person to get (1st person whose (last name is the_LastName)) # ADDED
				else # ADDED
					set the_Person to get (1st person whose (first name is the_FirstName) and (last name is the_LastName))
				end if # ADDED
				the_Person (* Generates an error if there is no such a person *)
				(*
We are here if there is already a record for such first and last name. Edit its mail address.
On est là s'il existe déjà une fiche pour ce couple nom + prénom. On édite l'adresse mail *)
				tell the_Person
					if the_MailAddress is not missing value then
						if replaceEmail then
							try (* 1 *)
								set value of (get email 1) to the_MailAddress
							on error
								(* 
We are here if there was no email data in the record, create it 
On est là si la fiche ne contenait pas d’adresse mail, on en insère une *)
								try (* 2 *)
									make new email at the end of emails with properties {value:the_MailAddress, label:"Work"}
								end try (* 2 *)
							end try (* 1 *)
						else
							(*
There is already at least an email, check if the new one is already stored # ADDED
*)
							set theEmails to (get every email) # ADDED
							set isAvailable to false # ADDED
							repeat with anEmail in theEmails # ADDED
								if (get value of anEmail) = the_MailAddress then # ADDED
									set isAvailable to true # ADDED
									exit repeat # ADDED
								end if # ADDED
							end repeat # ADDED
							
							try (* 3 *)
								if not isAvailable then make new email at the end of emails with properties {value:the_MailAddress, label:"Work"} # EDITED
							end try (* 3 *)
						end if
						
					end if -- the_MailAddress
				end tell -- the_Person
				
			on error
				(* 
We are here if there was no such a record. Create a new one.
On est là si ce couple nom + prénom n’existait pas dans ce groupe, on crée une fiche *)
				
				
				try (* 1 *)
					# Cette formule semble préférable à la création d'un prénom contenant une chaîne vide
					# On laisse ainsi le même état que lors d'une création manuelle.
					if the_FirstName is "" then
						set the_Person to (make new person with properties {last name:the_LastName, company:true})
					else
						set the_Person to (make new person with properties {first name:the_FirstName, last name:the_LastName, company:true})
					end if
				end try (* 1 *)
				tell the_Person
					try (* 1 *)
						make new email at the end of emails with properties {value:the_MailAddress, label:"Work"}
					end try (* 1 *)
				end tell -- the_Person
			end try
			repeat with theGroupName in items of R
				add the_Person to group theGroupName (*  inserts the person in the group(s). *)
			end repeat
			
		else if (count thePersons) = 1 then
			repeat with theGroupName in items of R
				add (item 1 of thePersons) to group theGroupName
			end repeat
		else
			repeat with theGroupName in items of R
				repeat with thisPerson in thePersons
					add thisPerson to group theGroupName
					set thePerson to make new person with properties {first name:the_FirstName, last name:the_LastName} # EDITED
					try
						make new email at end of emails of thePerson with properties {label:"Work", value:the_MailAddress} # EDITED
					end try
					save
					
				end repeat
			end repeat
		end if
		
	end repeat
	
	save
	set selected of group theGroupName to true
	
end tell


on split(theString, theDelimiter)
	set oldDelimiters to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	set theArray to every text item of theString
	set AppleScript's text item delimiters to oldDelimiters
	return theArray
end split

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) dimanche 3 mars 2019 14:02:59

Edited to add the option : replaceEmail

Edited : added code for special case where theArray contains a single string
and enhanced the mode replaceEmail is false

Merci beaucoup! C’est parfait!

Thanks for the feedback.
I added some enhancements above.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 4 mars 2019 17:41:52