Script for speaking a summary of incoming email

I wrote this about a year ago, and have found it very useful. So I thought I’d post it here.

The script simply looks up the Address Book contact info for emails as they arrive. Then it creates a summary paragraph and speaks it. Any emails from addresses not in Address Book are announced summarily as “Unknown Sender”.

Example: “2 emails just arrived from Alice Smith, and 1 from Joe Thomas, and 3 from unknown senders.”

I welcome any suggestions and comments - as this was my first AppleScript !!!

To install the script:

  • Place the .scpt file somewhere in your documents.
  • In Mail.app, open the Mail->Preferences menu, and go to the Rules section. Add a new rule to apply to all incoming messages and choose “Run AppleScript” as the action to perform.
(* the entry point function that Mail.app will call when a message is received *)
on perform_mail_action(info)
	tell application "Mail"
		set selectedMessages to |SelectedMessages| of info
		set theRule to |Rule| of info
	end tell
	my speak_message_summary(selectedMessages, " just arrived ", "")
	
end perform_mail_action

(* a function we can call anytime to summarize the contents of Mail.app's inbox *)
on summarize_inbox()
	
	tell application "Mail"
		set selectedMessages to (messages of inbox)
	end tell
	my speak_message_summary(selectedMessages, " in inbox ", "")
	
end summarize_inbox




(* a function to speak a summary of a list of Mail objects *)
on speak_message_summary(selectedMessages, actionDescription, introduction)
	
	set summaryString to my summarize_messages(selectedMessages, actionDescription)
	
	say introduction
	say summaryString
	
end speak_message_summary


(* a function that summarizes a list of Mail message objects as a string paragraph *)
(*       the actionDescription is the verb used when speaking                     *)
on summarize_messages(selectedMessages, actionDescription)
	
	(* a list of strings to return at the end of processing *)
	set summaryText to ""
	
	(* build up a list of unique emails  *)
	tell application "Mail"
		set messageCount to count of selectedMessages
		
		set emailList to {}
		set emailCountList to {}
		repeat with thisMessage in selectedMessages
			set senderEmail to (extract address from sender of thisMessage)
			if emailList does not contain senderEmail then
				set the end of emailList to senderEmail
				set the end of emailCountList to 1
			else
				set emailPos to my list_position(senderEmail, emailList)
				set currentCount to item emailPos of emailCountList
				set currentCount to currentCount + 1
				set item emailPos of emailCountList to currentCount
			end if
		end repeat
	end tell
	
	(*  search the address book  *)
	set matchingNames to {}
	set matchingNameCounts to {}
	set unknownEmails to {}
	set unknownCount to 0
	
	tell application "Address Book"
		repeat with i from 1 to count of emailList
			set eachEmail to item i of emailList
			ignoring case
				set matchingContacts to (people whose value of emails contains eachEmail)
			end ignoring
			if (count of matchingContacts) is 0 then
				set the end of unknownEmails to eachEmail
				set unknownCount to unknownCount + (item i of emailCountList)
			else
				set thisContact to first item in matchingContacts
				set the end of matchingNames to (first name of thisContact) & " " & (last name of thisContact)
				set the end of matchingNameCounts to (item i of emailCountList)
			end if
		end repeat
	end tell
	
	
	(*   write summary paragraph with the contact info and message counts  *)
	if (count of matchingNames) > 0 then
		repeat with i from 1 to the count of matchingNames
			set announceCount to item i of matchingNameCounts
			set pluralize to my pluralizeS(announceCount)
			if i is 1 then
				set summaryText to (summaryText & (announceCount as text) & "  email" & pluralize & actionDescription & " from " & (item i of matchingNames))
			else
				set summaryText to (summaryText & ", and " & (announceCount as text) & " from " & (item i of matchingNames))
			end if
		end repeat
		
		if (unknownCount > 0) then
			set pluralize to my pluralizeS(unknownCount)
			set summaryText to (summaryText & ", and " & (unknownCount as text) & " from unknown sender" & pluralize)
		end if
	else
		set pluralize to my pluralizeS(unknownCount)
		set summaryText to (summaryText & (unknownCount as text) & " email" & pluralize & actionDescription & " from unknown sender" & pluralize)
	end if
	
	return summaryText
	
end summarize_messages

(* an overly simplistic function to return plural word suffix based on the object count *)
on pluralizeS(thisCount)
	if thisCount > 1 then
		return "s"
	else
		return " "
	end if
end pluralizeS

(* basic function for searching and returning an item's position in a list *)
on list_position(thisItem, thisList)
	repeat with i from 1 to the count of thisList
		if item i of thisList is thisItem then return i
	end repeat
	return 0
end list_position