Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

Speak the sender of a mail item Apps
Here's a quick script to speak the name of the person sending you e-mail. I've seen scripts like this for entourage, but never for Apple's Mail.app. To use it, paste it into Script Editor, save, and create a mail rule that acts on every message and add it to the top of your list of mail rules. Set the action to "Run AppleScript" and choose your new script as the target.
on perform_mail_action(info)
  tell application "Mail"
    set theMessages to |SelectedMessages| of info
    repeat with thisMessage in theMessages
    set AppleScript's text item delimiters to {""}
    set thisSender to sender of thisMessage as string
    set quotepos to offset of "\"" in thisSender
      if (quotepos is not 0) then
        set thisSender to (text items (quotepos + 1) through -1) 
          of thisSender as string
        set quotepos to offset of "\"" in thisSender
        if (quotepos is not 0) then
          set thisSender to (text items 1 through (quotepos - 1)) 
            of thisSender as string
        end if
      else
        set atpos to offset of "@" in thisSender
        if (atpos is not 0) then
          set thisSender to (text items 1 through (atpos - 1)) 
            of thisSender as string
        end if
        set brkpos to offset of "<" in thisSender
        if (brkpos is not 0) then
          set thisSender to (text items (brkpos + 1) through -1) 
            of thisSender as string
        end if
      end if
      tell application "Finder" to say "Mail from " & thisSender
    end repeat
  end tell
end perform_mail_action
[robg adds: This worked as described ... see also this hint which explains how to speak the entire contents of messages.]
    •    
  • Currently 3.25 / 5
  • 1
  • 2
  • 3
  • 4
  • 5
  (4 votes cast)
 
[19,309 views]  

Speak the sender of a mail item | 34 comments | Create New Account
Click here to return to the 'Speak the sender of a mail item' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Speak the sender of a mail item
Authored by: Ansel_Witty on Mar 06, '03 10:39:22AM

Seems like it works pretty well, but if the person doesn't put quotes around their name it jsut readys the username of their e-mail address... How can you add that it should read the name even without quotes if there are no quotes? or have it read the whole e-mail address if there is no name at all?

---
"I don't believe in mathematics!" - Albert Einstein



[ Reply to This | # ]
Timing is everything!
Authored by: porkchop_d_clown on Mar 06, '03 10:44:19AM
The no-quotes problem is actually one of the reasons I wrote the updated script. If you want to read the whole name, instead of just up to the @ sign, change the line

set AppleScript's text item delimiters to {"@"}
to read

set AppleScript's text item delimiters to {">"}

---
--
knock knock

[ Reply to This | # ]

Slightly better version...
Authored by: porkchop_d_clown on Mar 06, '03 10:40:32AM
I should remember that I don't write enough applescript to really write a good routine in one pass. This version is shorter and handles various name formats better.

on perform_mail_action(info)
	tell application "Mail"
		set theMessages to |SelectedMessages| of info
		repeat with thisMessage in theMessages
			set AppleScript's text item delimiters to {""}
			set thisSender to sender of thisMessage as string
			set brkpos to offset of "<" in thisSender
			if (brkpos is greater than 1) then
				set thisSender to (text items 1 through (brkpos - 1)) of thisSender as string
				if thisSender contains "\"" then
					set AppleScript's text item delimiters to {"\""}
					set thisSender to text item 2 of thisSender as string
				end if
			else
				if (brkpos is equal to 1) then
					set thisSender to (text items 2 through -1) of thisSender as string
				end if
				set AppleScript's text item delimiters to {"@"}
				set thisSender to text item 1 of thisSender as string
			end if
			tell application "Finder" to say "Mail from " & thisSender
		end repeat
	end tell
end perform_mail_action

---
--
knock knock

[ Reply to This | # ]

Slightly better version...
Authored by: splattertrousers on Mar 06, '03 02:28:11PM

I modified your script to also speak the subject. My script removes "Re:", "Fwd:", etc. from the beginning of the script. I also tried to get it to remove things in brackets or parentheses. The code works when I test it from ScriptEditor, but not when Mail runs it. The only difference is that when I test it from ScriptEditor, I remove all the Mail-specific code, and the outer function. Does anyone have any ideas?

Anyway, here's the script (sorry for the lousy formatting, but when I post as HTML, the > and < signs screw up the output):

on perform_mail_action(info)
tell application "Mail"
set theMessages to |SelectedMessages| of info
repeat with thisMessage in theMessages

set AppleScript's text item delimiters to {""}
set thisSender to sender of thisMessage as string
set brkpos to offset of "<" in thisSender
if (brkpos is greater than 1) then
set thisSender to (text items 1 through (brkpos - 1)) of thisSender as string
if thisSender contains "\"" then
set AppleScript's text item delimiters to {"\""}
set thisSender to text item 2 of thisSender as string
end if
else
if (brkpos is equal to 1) then
set thisSender to (text items 2 through -1) of thisSender as string
end if
set AppleScript's text item delimiters to {"@"}
set thisSender to text item 1 of thisSender as string
end if

set thisSubject to subject of thisMessage as string

-- remove "Re:", "Fwd:", etc.
set AppleScript's text item delimiters to {""}
set colonpos to offset of ":" in thisSubject
if (colonpos < 5) then
set thisSubject to (text items (colonpos + 1) through -1)
of thisSubject as string
end if

-- remove text between [ and ]; and between ( and )
-- I can't get these next two lines to work when calling this from Mail
-- but they work when running from ScriptEditor (though I take this
-- part out of the perform_mail_action subroutine)
--set thisSubject to removeTextBetween(thisSubject, "[", "]")
--set thisSubject to removeTextBetween(thisSubject, "(", ")")

tell application "Finder" to say "Mail from, " & thisSender
& ", regarding, " & thisSubject

end repeat
end tell
end perform_mail_action

-- removes any text between "a" and "b" in "s"; returns the result
-- doesn't handle the case where a...b is nested inside another a...b
-- (because there's no "last offset of" and I didn't feel like writing one
-- (hey, it's the first AppleScript I have written since System 7 days...)
on removeTextBetween(s, a, b)
repeat while ((s contains a) and (s contains b))

set aIndex to offset of a in s
set bIndex to offset of b in s

if ((aIndex > 0) and (bIndex > aIndex)) then

if (aIndex > 1) then
set beforeA to (text items 1 through (aIndex - 1))
of s as string
else
set beforeA to ""
end if

if (bIndex < (length of s)) then
set afterB to (text items (bIndex + 1) through -1)
of s as string
else
set afterB to ""
end if

set s to beforeA & " " & afterB

end if

end repeat

return s
end removeTextBetween



[ Reply to This | # ]
Slightly better version...
Authored by: porkchop_d_clown on Mar 06, '03 04:31:39PM

Use the meta-tags [code] and [/code] when doing HTML formatting and it will correctly handle the script.

---
--
knock knock



[ Reply to This | # ]
Slightly better version...
Authored by: vanstra on Mar 08, '03 02:39:01PM

I've tried this, but it doesn't seems to work. Must I activate the speech in MacOSX ? What rule do I have to add in Mail ?



[ Reply to This | # ]
Speak the sender of a mail item
Authored by: davidcrickett on Mar 06, '03 10:46:38AM

Very nice! :-)

---
davidcrickett



[ Reply to This | # ]
thanks.
Authored by: porkchop_d_clown on Mar 06, '03 10:51:16AM

I found it a big help because I have a couple of machines in the office, and my ibook is usually behind me. When mail comes in, I can decide whether or not I should stop what I'm doing and turn around...


---
--
knock knock



[ Reply to This | # ]
Speak the sender of a mail item
Authored by: falkaholic on Mar 06, '03 01:39:26PM

I swear I looked in rules for a Run AppleScipt command. Now it is there? how new is it?



[ Reply to This | # ]
Speak the sender of a mail item
Authored by: Cerberus on Mar 08, '03 07:17:31AM

Well it isn't in 10.1 so I would say it is NEW.



[ Reply to This | # ]
I needed a small change
Authored by: daveedvdv on Mar 06, '03 02:22:24PM
I'm not accustomed to AppleScript (yet), but I had to change the line
    tell application "Finder" to say ...
to simply
    say ...
Since noone else mentioned it, I suspect I might have something misconfigured somewhere. Oh well, it works now.

[ Reply to This | # ]
I needed a small change
Authored by: porkchop_d_clown on Mar 06, '03 04:35:15PM

Interesting. The only reason I have it that way, is because I saw another script that did it that way. I wonder what the difference is.

---
--
knock knock



[ Reply to This | # ]
tell..
Authored by: Accura on Mar 06, '03 09:08:46PM

The difference will be that with the "tell.." line that finder will speak the text, but with out the system will speak. The dock is a good app to use to do things, if im going to get a dialog to display i tell the dock to do it as it is allways in front of everything

---
"The time has come," the walrus said. "To talk of many things..."



[ Reply to This | # ]
Me Too
Authored by: yoel on Mar 06, '03 09:31:31PM
tell application "Finder" to say "foo"

gives the following error message:

Finder got an error: "foo" doesn't understand the say message.

However,

say "foo"

works as expected. This is on 10.2.4.

[ Reply to This | # ]

But it works fine for me. Hmmm....
Authored by: dcollett on Mar 07, '03 03:08:15AM
I used the original: tell application "Finder" to say "Mail from " & thisSender and it works fine for me (10.2.4). Why would AppleScript perform differently for different users?

[ Reply to This | # ]
But it works fine for me. Hmmm....
Authored by: porkchop_d_clown on Mar 07, '03 10:39:14AM

I don't know, but I realized last night you don't need the "tell application 'Finder'" clause at all. say is in the "standard extensions" library, it's not part of the finder.

---
--
knock knock



[ Reply to This | # ]
Speak the sender of a mail item
Authored by: keana on Mar 06, '03 03:14:05PM

This is cool. I am finding it very useful! I only wish I could write apple scripts. It's on my list of things to learn. Thanks for the very useful and very cool script!



[ Reply to This | # ]
adjusting volume?
Authored by: TTop on Mar 06, '03 04:24:46PM

This is a great script! My only complaint is that the spoken words seem much louder than they should be -- specifically in relation to iTunes, which I already have turned up to about 85% of max. Is there a way to modify the script so that the volume is toned down a bit? I poked around in System Preferences under both Sound and Speech and couldn't seem to find any way to adjust only the Speech items.



[ Reply to This | # ]
adjusting volume?
Authored by: porkchop_d_clown on Mar 06, '03 04:46:10PM

Unfortunately, I don't think you can. Say doesn't take a volume argument.

---
--
knock knock



[ Reply to This | # ]
adjusting volume?
Authored by: hayne on Mar 06, '03 07:25:13PM

You could do:
set volume 3.0
to turn down the volume before speaking the email
and then
set volume 5.8
to turn it back up
The AppleScript "set volume" command can set the volume between 0.0 and 7.0



[ Reply to This | # ]
adjusting volume? -- Yes you can!
Authored by: ghoppe on Mar 09, '03 02:08:35AM

You can adjust the volume by changing this line:

tell application "Finder" to say "Mail from " & thisSender

to

tell application "Finder" to say "[[volm 0.7]] Mail from" & thisSender

Toy with the value 0.7 (0=silence, 1.0=max) until you find a volume you find reasonable. Instead, you could use + or - before the number to raise or lower the volume.

Apple has a list of embedded speech commands on their site.

For example, if you want your mac to speak rapidly you could:

tell application "Finder" to say "[[rate 300]] Mail from" & thisSender



[ Reply to This | # ]
Speak the sender of a mail item
Authored by: matt_j_gray on Mar 06, '03 05:34:18PM

I'd written something similar a while back - the only problem I have with my script and this new one is that Mail doesn't seem to be threaded when it is running its rules. This means when I check my mail in the morning and there are lots of mails that arrive in one hit, Mail reads out all the senders, and I can't do anything else in Mail at the same time.

In other programs (such as Eudora), I think you can keep reading, navigating, etc, in other messages when it is reading out new things. But this script locks Mail up until it is finished.

Any ideas how to make it threaded? Or is that asking way too much of AppleScript? I'm guessing it needs some alteration to the Mail app.



[ Reply to This | # ]
Check the unread count?
Authored by: porkchop_d_clown on Mar 07, '03 02:00:38PM

It seems like the whole applescript interface in mail needs a rework; I've been having lots of issues with things like moving mail inside a script and so on.

My best suggestion at this point would be to add an outer if statement that would cause the rule to do nothing if the number of unread messages was too high.


---
--
knock knock



[ Reply to This | # ]
Changing the voice
Authored by: figz on Mar 06, '03 07:22:41PM
I changed mine to:

tell application "Finder" to say "New message from " & thisSender using "Bruce"

...but you can say "Fred" or "Zarvox" or any of the many other voices in the Speech preference pane that floats your boat!

[ Reply to This | # ]
Here's my take
Authored by: jcstudio on Mar 07, '03 09:35:41AM
Okay, I this may be going over the top. But it's so fun!
on perform_mail_action(info) tell application "Mail" set theMessages to |SelectedMessages| of info repeat with thisMessage in theMessages set AppleScript's text item delimiters to {""} set thisSender to sender of thisMessage as string set thisSubject to subject of thisMessage as string set brkpos to offset of "

[ Reply to This | # ]
Here's my take (again)
Authored by: jcstudio on Mar 07, '03 09:40:26AM

Whoops! I guess I don't understand how to use the <code> tag. Here it is in plain text:

on perform_mail_action(info)
tell application "Mail"
set theMessages to |SelectedMessages| of info
repeat with thisMessage in theMessages
set AppleScript's text item delimiters to {""}
set thisSender to sender of thisMessage as string
set thisSubject to subject of thisMessage as string
set brkpos to offset of "<" in thisSender
if (brkpos is greater than 1) then
set thisSender to (text items 1 through (brkpos - 1)) of thisSender as string
if thisSender contains "\"" then
set AppleScript's text item delimiters to {"\""}
set thisSender to text item 2 of thisSender as string
end if
else
if (brkpos is equal to 1) then
set thisSender to (text items 2 through -1) of thisSender as string
end if
set AppleScript's text item delimiters to {"@"}
set thisSender to text item 1 of thisSender as string
end if
say "You have new Mail from " using "Victoria"
say thisSender using "Bruce"
say "regarding" using "Victoria"
say thisSubject using "Bruce"
end repeat
end tell
end perform_mail_action



[ Reply to This | # ]
Here's my take (again)
Authored by: porkchop_d_clown on Mar 07, '03 10:41:14AM

use [code] and [/code] not <code> and </code> - [code] is an instruction to the discussion software here to preserve line breaks and indenting.

---
--
knock knock



[ Reply to This | # ]
Speak the sender of a mail item
Authored by: matt_j_gray on Mar 09, '03 10:22:01PM

Yep, that is indeed what I do anyway. Oh well, hopefully the next release of Mail will be a bit more threaded.



[ Reply to This | # ]
Enhanced, threaded version
Authored by: Hugin777 on Mar 25, '04 08:51:58AM
Advantages:
  1. Get the big picture - if you get three mails from the same sender, John, it will simply say "New mail: three from John". If you get a lot of mail it will just say e.g. "New mail: from 6 different senders !"
  2. Threaded - does not block Mail.app while announcing
Examples:
  • New mail: from Michael.
  • New mail: From 3 different senders ! 2 from Erik. 3 junk. 1 from John.
  • New mail: From 5 different senders !

The script has to be saved as a Stay-open script, as it needs to monitor Mail.app in the background. It will Quit itself when the announcement is done.

IMPORTANT: You need to save the script as a program, and check "Stay open" !


property announceJunk : false -- should junk mail be announced too ?
property senderCntThreshold : 2 -- more than this, and the count is announced
property senderCntMax : 4 -- more than this, and only the count is announced
property voiceVolume : "0.7"

property senderList : {}
property firstRun : true -- don't do anything at first run of idle

using terms from application "Mail"
	on perform mail action with messages theMessages
		repeat with thisMessage in theMessages
			set thisSender to extract name from sender of thisMessage
			set junk to junk mail status of thisMessage
			tell application "Mailmelding"
				-- We have to run ourselves :-/
				--  If we didn't use "tell" the run method would never be called...
				newMail(thisSender, junk)
			end tell
		end repeat
	end perform mail action with messages
end using terms from

on newMail(thisSender, junk)
	if junk then
		if not announceJunk then
			return
		end if
		set thisSender to " junk "
	end if
	set found to false
	repeat with x in my senderList
		if sender of x is equal to thisSender then
			set cnt of x to (cnt of x) + 1
			set found to true
			exit repeat
		end if
	end repeat
	if not found then
		copy {sender:thisSender, cnt:1} to end of my senderList
	end if
end newMail

on idle
	if firstRun then
		set firstRun to false
		return 2
	end if
	tell application "Mail"
		set mailIdle to background activity count = 0
	end tell
	if mailIdle then
		set senderCount to count of senderList
		if senderCount = 0 then
			set firstRun to true
			quit
			return 0
		end if
		
		set sayStr to "[[volm " & voiceVolume & "]]" & "New mail:" & space
		
		if senderCount > senderCntThreshold then
			set sayStr to sayStr & "From " & senderCount & " different senders !" & space
		end if
		if senderCount is less than or equal to senderCntMax then
			--  Report the findings
			repeat with x in senderList
				set thisSender to sender of x
				set cnt to cnt of x
				set sayStr to sayStr & spokenPrefix(senderCount, cnt) & space
				if thisSender is " junk " then
					set sayStr to sayStr & "junk." & space
				else
					set sayStr to sayStr & "from " & pickFirstPart(thisSender) & "." & space
				end if
			end repeat
		end if
		say sayStr
		set senderList to {}
		set firstRun to true
		quit
	end if -- mailIdle
	return 2 -- Call again every 2 seconds...
end idle

on spokenPrefix(senderCount, cnt)
	if senderCount = 1 and cnt = 1 then
		return ""
	else
		return (cnt as text)
	end if
end spokenPrefix

on pickFirstPart(emailOrName)
	set oldDelim to AppleScript's text item delimiters
	if emailOrName contains "@" then
		set AppleScript's text item delimiters to {"@"}
	else
		set AppleScript's text item delimiters to {" "}
	end if
	return first text item of emailOrName
	set AppleScript's text item delimiters to oldDelim
end pickFirstPart


[ Reply to This | # ]
Correction !!!!
Authored by: Hugin777 on Mar 25, '04 09:07:39AM
Whoops, you have to change the string "Mailmelding" to the name you choose for the script !

If you save the script as "Mail-announcer", then change this line:

tell application "Mailmelding"

to this:

tell application "Mail-announcer"


[ Reply to This | # ]
Enhanced, threaded version
Authored by: mikeall on Mar 29, '04 02:18:24AM

I tried to cut and paste this one and make it into an apple script but it won't compile in Jaguar using Script Editor 1.9.
The error says:
Expected "given", "into", "with", "without" or other parameter name but found identifier.

The script looks like it would be great so any help will be appreciated.

---
Mike
http://allbutt.homeip.net/



[ Reply to This | # ]
Enhanced, threaded version
Authored by: Hugin777 on Apr 18, '04 10:25:45AM

Sorry, I'm no AppleScript expert. It works in Panther as far as I know...



[ Reply to This | # ]
Speak the sender of a mail item
Authored by: glusk on Aug 13, '12 11:49:59AM
Here is a new version of the original hint that works for me in 10.8 Mountain Lion. Note that there is a new place for Mail scripts at ~/Library/Application Scripts/com.apple.mail/

using terms from application "Mail"
	on perform mail action with messages matching_messages
		tell application "Mail"
			repeat with thisMessage in matching_messages
				set AppleScript's text item delimiters to {""}
				set thisSender to sender of thisMessage as string
				set brkpos to offset of "<" in thisSender
				if (brkpos is greater than 1) then
					set thisSender to (text items 1 through (brkpos - 1)) of thisSender as string
					if thisSender contains "\"" then
						set AppleScript's text item delimiters to {"\""}
						set thisSender to text item 2 of thisSender as string
					end if
				else
					if (brkpos is equal to 1) then
						set thisSender to (text items 2 through -1) of thisSender as string
					end if
					set AppleScript's text item delimiters to {"@"}
					set thisSender to text item 1 of thisSender as string
				end if
				say "Mail from " & thisSender
			end repeat
		end tell
	end perform mail action with messages
end using terms from


[ Reply to This | # ]
Speak the sender of a mail item
Authored by: echo on Aug 18, '12 09:12:35PM

@glusk Thanks, works in mountain lion!



[ Reply to This | # ]